rtspdec.c
Go to the documentation of this file.
1 /*
2  * RTSP demuxer
3  * Copyright (c) 2002 Fabrice Bellard
4  *
5  * This file is part of Libav.
6  *
7  * Libav is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * Libav is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with Libav; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20  */
21 
22 #include "libavutil/avstring.h"
23 #include "libavutil/intreadwrite.h"
24 #include "libavutil/mathematics.h"
25 #include "avformat.h"
26 
27 #include "internal.h"
28 #include "network.h"
29 #include "os_support.h"
30 #include "rtsp.h"
31 #include "rdt.h"
32 #include "url.h"
33 
35 {
36  RTSPState *rt = s->priv_data;
37  RTSPMessageHeader reply1, *reply = &reply1;
38  int i;
39  char cmd[1024];
40 
41  av_log(s, AV_LOG_DEBUG, "hello state=%d\n", rt->state);
42  rt->nb_byes = 0;
43 
44  if (!(rt->server_type == RTSP_SERVER_REAL && rt->need_subscription)) {
45  if (rt->transport == RTSP_TRANSPORT_RTP) {
46  for (i = 0; i < rt->nb_rtsp_streams; i++) {
47  RTSPStream *rtsp_st = rt->rtsp_streams[i];
48  RTPDemuxContext *rtpctx = rtsp_st->transport_priv;
49  if (!rtpctx)
50  continue;
54  rtpctx->base_timestamp = 0;
55  rtpctx->timestamp = 0;
56  rtpctx->unwrapped_timestamp = 0;
57  rtpctx->rtcp_ts_offset = 0;
58  }
59  }
60  if (rt->state == RTSP_STATE_PAUSED) {
61  cmd[0] = 0;
62  } else {
63  snprintf(cmd, sizeof(cmd),
64  "Range: npt=%"PRId64".%03"PRId64"-\r\n",
66  rt->seek_timestamp / (AV_TIME_BASE / 1000) % 1000);
67  }
68  ff_rtsp_send_cmd(s, "PLAY", rt->control_uri, cmd, reply, NULL);
69  if (reply->status_code != RTSP_STATUS_OK) {
70  return -1;
71  }
72  if (rt->transport == RTSP_TRANSPORT_RTP &&
73  reply->range_start != AV_NOPTS_VALUE) {
74  for (i = 0; i < rt->nb_rtsp_streams; i++) {
75  RTSPStream *rtsp_st = rt->rtsp_streams[i];
76  RTPDemuxContext *rtpctx = rtsp_st->transport_priv;
77  AVStream *st = NULL;
78  if (!rtpctx || rtsp_st->stream_index < 0)
79  continue;
80  st = s->streams[rtsp_st->stream_index];
81  rtpctx->range_start_offset =
83  st->time_base);
84  }
85  }
86  }
88  return 0;
89 }
90 
91 /* pause the stream */
93 {
94  RTSPState *rt = s->priv_data;
95  RTSPMessageHeader reply1, *reply = &reply1;
96 
97  if (rt->state != RTSP_STATE_STREAMING)
98  return 0;
99  else if (!(rt->server_type == RTSP_SERVER_REAL && rt->need_subscription)) {
100  ff_rtsp_send_cmd(s, "PAUSE", rt->control_uri, NULL, reply, NULL);
101  if (reply->status_code != RTSP_STATUS_OK) {
102  return -1;
103  }
104  }
105  rt->state = RTSP_STATE_PAUSED;
106  return 0;
107 }
108 
110 {
111  RTSPState *rt = s->priv_data;
112  char cmd[1024];
113  unsigned char *content = NULL;
114  int ret;
115 
116  /* describe the stream */
117  snprintf(cmd, sizeof(cmd),
118  "Accept: application/sdp\r\n");
119  if (rt->server_type == RTSP_SERVER_REAL) {
124  av_strlcat(cmd,
125  "Require: com.real.retain-entity-for-setup\r\n",
126  sizeof(cmd));
127  }
128  ff_rtsp_send_cmd(s, "DESCRIBE", rt->control_uri, cmd, reply, &content);
129  if (!content)
130  return AVERROR_INVALIDDATA;
131  if (reply->status_code != RTSP_STATUS_OK) {
132  av_freep(&content);
133  return AVERROR_INVALIDDATA;
134  }
135 
136  av_log(s, AV_LOG_VERBOSE, "SDP:\n%s\n", content);
137  /* now we got the SDP description, we parse it */
138  ret = ff_sdp_parse(s, (const char *)content);
139  av_freep(&content);
140  if (ret < 0)
141  return ret;
142 
143  return 0;
144 }
145 
146 static int rtsp_probe(AVProbeData *p)
147 {
148  if (av_strstart(p->filename, "rtsp:", NULL))
149  return AVPROBE_SCORE_MAX;
150  return 0;
151 }
152 
154  AVFormatParameters *ap)
155 {
156  RTSPState *rt = s->priv_data;
157  int ret;
158 
159  ret = ff_rtsp_connect(s);
160  if (ret)
161  return ret;
162 
163  rt->real_setup_cache = av_mallocz(2 * s->nb_streams * sizeof(*rt->real_setup_cache));
164  if (!rt->real_setup_cache)
165  return AVERROR(ENOMEM);
166  rt->real_setup = rt->real_setup_cache + s->nb_streams;
167 
168  if (rt->initial_pause) {
169  /* do not start immediately */
170  } else {
171  if (rtsp_read_play(s) < 0) {
174  return AVERROR_INVALIDDATA;
175  }
176  }
177 
178  return 0;
179 }
180 
182  uint8_t *buf, int buf_size)
183 {
184  RTSPState *rt = s->priv_data;
185  int id, len, i, ret;
186  RTSPStream *rtsp_st;
187 
188  av_dlog(s, "tcp_read_packet:\n");
189 redo:
190  for (;;) {
191  RTSPMessageHeader reply;
192 
193  ret = ff_rtsp_read_reply(s, &reply, NULL, 1, NULL);
194  if (ret < 0)
195  return ret;
196  if (ret == 1) /* received '$' */
197  break;
198  /* XXX: parse message */
199  if (rt->state != RTSP_STATE_STREAMING)
200  return 0;
201  }
202  ret = ffurl_read_complete(rt->rtsp_hd, buf, 3);
203  if (ret != 3)
204  return -1;
205  id = buf[0];
206  len = AV_RB16(buf + 1);
207  av_dlog(s, "id=%d len=%d\n", id, len);
208  if (len > buf_size || len < 12)
209  goto redo;
210  /* get the data */
211  ret = ffurl_read_complete(rt->rtsp_hd, buf, len);
212  if (ret != len)
213  return -1;
214  if (rt->transport == RTSP_TRANSPORT_RDT &&
215  ff_rdt_parse_header(buf, len, &id, NULL, NULL, NULL, NULL) < 0)
216  return -1;
217 
218  /* find the matching stream */
219  for (i = 0; i < rt->nb_rtsp_streams; i++) {
220  rtsp_st = rt->rtsp_streams[i];
221  if (id >= rtsp_st->interleaved_min &&
222  id <= rtsp_st->interleaved_max)
223  goto found;
224  }
225  goto redo;
226 found:
227  *prtsp_st = rtsp_st;
228  return len;
229 }
230 
232 {
233  RTSPState *rt = s->priv_data;
234  char host[1024];
235  int port;
236 
237  av_url_split(NULL, 0, NULL, 0, host, sizeof(host), &port, NULL, 0,
238  s->filename);
241  rt->real_challenge);
242 }
243 
245 {
246  RTSPState *rt = s->priv_data;
247  int ret;
248  RTSPMessageHeader reply1, *reply = &reply1;
249  char cmd[1024];
250 
251 retry:
252  if (rt->server_type == RTSP_SERVER_REAL) {
253  int i;
254 
255  for (i = 0; i < s->nb_streams; i++)
256  rt->real_setup[i] = s->streams[i]->discard;
257 
258  if (!rt->need_subscription) {
259  if (memcmp (rt->real_setup, rt->real_setup_cache,
260  sizeof(enum AVDiscard) * s->nb_streams)) {
261  snprintf(cmd, sizeof(cmd),
262  "Unsubscribe: %s\r\n",
263  rt->last_subscription);
264  ff_rtsp_send_cmd(s, "SET_PARAMETER", rt->control_uri,
265  cmd, reply, NULL);
266  if (reply->status_code != RTSP_STATUS_OK)
267  return AVERROR_INVALIDDATA;
268  rt->need_subscription = 1;
269  }
270  }
271 
272  if (rt->need_subscription) {
273  int r, rule_nr, first = 1;
274 
275  memcpy(rt->real_setup_cache, rt->real_setup,
276  sizeof(enum AVDiscard) * s->nb_streams);
277  rt->last_subscription[0] = 0;
278 
279  snprintf(cmd, sizeof(cmd),
280  "Subscribe: ");
281  for (i = 0; i < rt->nb_rtsp_streams; i++) {
282  rule_nr = 0;
283  for (r = 0; r < s->nb_streams; r++) {
284  if (s->streams[r]->id == i) {
285  if (s->streams[r]->discard != AVDISCARD_ALL) {
286  if (!first)
287  av_strlcat(rt->last_subscription, ",",
288  sizeof(rt->last_subscription));
290  rt->last_subscription,
291  sizeof(rt->last_subscription), i, rule_nr);
292  first = 0;
293  }
294  rule_nr++;
295  }
296  }
297  }
298  av_strlcatf(cmd, sizeof(cmd), "%s\r\n", rt->last_subscription);
299  ff_rtsp_send_cmd(s, "SET_PARAMETER", rt->control_uri,
300  cmd, reply, NULL);
301  if (reply->status_code != RTSP_STATUS_OK)
302  return AVERROR_INVALIDDATA;
303  rt->need_subscription = 0;
304 
305  if (rt->state == RTSP_STATE_STREAMING)
306  rtsp_read_play (s);
307  }
308  }
309 
310  ret = ff_rtsp_fetch_packet(s, pkt);
311  if (ret < 0) {
312  if (ret == AVERROR(ETIMEDOUT) && !rt->packets) {
315  RTSPMessageHeader reply1, *reply = &reply1;
316  av_log(s, AV_LOG_WARNING, "UDP timeout, retrying with TCP\n");
317  if (rtsp_read_pause(s) != 0)
318  return -1;
319  // TEARDOWN is required on Real-RTSP, but might make
320  // other servers close the connection.
321  if (rt->server_type == RTSP_SERVER_REAL)
322  ff_rtsp_send_cmd(s, "TEARDOWN", rt->control_uri, NULL,
323  reply, NULL);
324  rt->session_id[0] = '\0';
325  if (resetup_tcp(s) == 0) {
326  rt->state = RTSP_STATE_IDLE;
327  rt->need_subscription = 1;
328  if (rtsp_read_play(s) != 0)
329  return -1;
330  goto retry;
331  }
332  }
333  }
334  return ret;
335  }
336  rt->packets++;
337 
338  /* send dummy request to keep TCP connection alive */
339  if ((av_gettime() - rt->last_cmd_time) / 1000000 >= rt->timeout / 2) {
340  if (rt->server_type == RTSP_SERVER_WMS ||
341  (rt->server_type != RTSP_SERVER_REAL &&
343  ff_rtsp_send_cmd_async(s, "GET_PARAMETER", rt->control_uri, NULL);
344  } else {
345  ff_rtsp_send_cmd_async(s, "OPTIONS", "*", NULL);
346  }
347  }
348 
349  return 0;
350 }
351 
352 static int rtsp_read_seek(AVFormatContext *s, int stream_index,
353  int64_t timestamp, int flags)
354 {
355  RTSPState *rt = s->priv_data;
356 
357  rt->seek_timestamp = av_rescale_q(timestamp,
358  s->streams[stream_index]->time_base,
360  switch(rt->state) {
361  default:
362  case RTSP_STATE_IDLE:
363  break;
365  if (rtsp_read_pause(s) != 0)
366  return -1;
368  if (rtsp_read_play(s) != 0)
369  return -1;
370  break;
371  case RTSP_STATE_PAUSED:
372  rt->state = RTSP_STATE_IDLE;
373  break;
374  }
375  return 0;
376 }
377 
379 {
380  RTSPState *rt = s->priv_data;
381 
382  ff_rtsp_send_cmd_async(s, "TEARDOWN", rt->control_uri, NULL);
383 
387  rt->real_setup = NULL;
389  return 0;
390 }
391 
393  .class_name = "RTSP demuxer",
394  .item_name = av_default_item_name,
395  .option = ff_rtsp_options,
396  .version = LIBAVUTIL_VERSION_INT,
397 };
398 
400  .name = "rtsp",
401  .long_name = NULL_IF_CONFIG_SMALL("RTSP input format"),
402  .priv_data_size = sizeof(RTSPState),
408  .flags = AVFMT_NOFILE,
409  .read_play = rtsp_read_play,
410  .read_pause = rtsp_read_pause,
411  .priv_class = &rtsp_demuxer_class,
412 };