FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavformat/rtspdec.c
Date: 2024-11-20 23:03:26
Exec Total Coverage
Lines: 5 590 0.8%
Functions: 1 21 4.8%
Branches: 2 349 0.6%

Line Branch Exec Source
1 /*
2 * RTSP demuxer
3 * Copyright (c) 2002 Fabrice Bellard
4 *
5 * This file is part of FFmpeg.
6 *
7 * FFmpeg 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 * FFmpeg 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 FFmpeg; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
22 #include "config_components.h"
23
24 #include "libavutil/avstring.h"
25 #include "libavutil/intreadwrite.h"
26 #include "libavutil/mathematics.h"
27 #include "libavutil/mem.h"
28 #include "libavutil/random_seed.h"
29 #include "libavutil/time.h"
30 #include "avformat.h"
31 #include "demux.h"
32
33 #include "internal.h"
34 #include "network.h"
35 #include "os_support.h"
36 #include "rtpproto.h"
37 #include "rtsp.h"
38 #include "rdt.h"
39 #include "tls.h"
40 #include "url.h"
41 #include "version.h"
42
43 static const struct RTSPStatusMessage {
44 enum RTSPStatusCode code;
45 const char *message;
46 } status_messages[] = {
47 { RTSP_STATUS_OK, "OK" },
48 { RTSP_STATUS_METHOD, "Method Not Allowed" },
49 { RTSP_STATUS_BANDWIDTH, "Not Enough Bandwidth" },
50 { RTSP_STATUS_SESSION, "Session Not Found" },
51 { RTSP_STATUS_STATE, "Method Not Valid in This State" },
52 { RTSP_STATUS_AGGREGATE, "Aggregate operation not allowed" },
53 { RTSP_STATUS_ONLY_AGGREGATE, "Only aggregate operation allowed" },
54 { RTSP_STATUS_TRANSPORT, "Unsupported transport" },
55 { RTSP_STATUS_INTERNAL, "Internal Server Error" },
56 { RTSP_STATUS_SERVICE, "Service Unavailable" },
57 { RTSP_STATUS_VERSION, "RTSP Version not supported" },
58 { 0, "NULL" }
59 };
60
61 static int rtsp_read_close(AVFormatContext *s)
62 {
63 RTSPState *rt = s->priv_data;
64
65 if (!(rt->rtsp_flags & RTSP_FLAG_LISTEN))
66 ff_rtsp_send_cmd_async(s, "TEARDOWN", rt->control_uri, NULL);
67
68 ff_rtsp_close_streams(s);
69 ff_rtsp_close_connections(s);
70 ff_network_close();
71 rt->real_setup = NULL;
72 av_freep(&rt->real_setup_cache);
73 return 0;
74 }
75
76 static inline int read_line(AVFormatContext *s, char *rbuf, const int rbufsize,
77 int *rbuflen)
78 {
79 RTSPState *rt = s->priv_data;
80 int idx = 0;
81 int ret = 0;
82 *rbuflen = 0;
83
84 do {
85 ret = ffurl_read_complete(rt->rtsp_hd, rbuf + idx, 1);
86 if (ret <= 0)
87 return ret ? ret : AVERROR_EOF;
88 if (rbuf[idx] == '\r') {
89 /* Ignore */
90 } else if (rbuf[idx] == '\n') {
91 rbuf[idx] = '\0';
92 *rbuflen = idx;
93 return 0;
94 } else
95 idx++;
96 } while (idx < rbufsize);
97 av_log(s, AV_LOG_ERROR, "Message too long\n");
98 return AVERROR(EIO);
99 }
100
101 static int rtsp_send_reply(AVFormatContext *s, enum RTSPStatusCode code,
102 const char *extracontent, uint16_t seq)
103 {
104 RTSPState *rt = s->priv_data;
105 char message[MAX_URL_SIZE];
106 int index = 0;
107 while (status_messages[index].code) {
108 if (status_messages[index].code == code) {
109 snprintf(message, sizeof(message), "RTSP/1.0 %d %s\r\n",
110 code, status_messages[index].message);
111 break;
112 }
113 index++;
114 }
115 if (!status_messages[index].code)
116 return AVERROR(EINVAL);
117 av_strlcatf(message, sizeof(message), "CSeq: %d\r\n", seq);
118 av_strlcatf(message, sizeof(message), "Server: %s\r\n", LIBAVFORMAT_IDENT);
119 if (extracontent)
120 av_strlcat(message, extracontent, sizeof(message));
121 av_strlcat(message, "\r\n", sizeof(message));
122 av_log(s, AV_LOG_TRACE, "Sending response:\n%s", message);
123 ffurl_write(rt->rtsp_hd_out, message, strlen(message));
124
125 return 0;
126 }
127
128 static inline int check_sessionid(AVFormatContext *s,
129 RTSPMessageHeader *request)
130 {
131 RTSPState *rt = s->priv_data;
132 unsigned char *session_id = rt->session_id;
133 if (!session_id[0]) {
134 av_log(s, AV_LOG_WARNING, "There is no session-id at the moment\n");
135 return 0;
136 }
137 if (strcmp(session_id, request->session_id)) {
138 av_log(s, AV_LOG_ERROR, "Unexpected session-id %s\n",
139 request->session_id);
140 rtsp_send_reply(s, RTSP_STATUS_SESSION, NULL, request->seq);
141 return AVERROR_STREAM_NOT_FOUND;
142 }
143 return 0;
144 }
145
146 static inline int rtsp_read_request(AVFormatContext *s,
147 RTSPMessageHeader *request,
148 const char *method)
149 {
150 RTSPState *rt = s->priv_data;
151 char rbuf[MAX_URL_SIZE];
152 int rbuflen, ret;
153 do {
154 ret = read_line(s, rbuf, sizeof(rbuf), &rbuflen);
155 if (ret)
156 return ret;
157 if (rbuflen > 1) {
158 av_log(s, AV_LOG_TRACE, "Parsing[%d]: %s\n", rbuflen, rbuf);
159 ff_rtsp_parse_line(s, request, rbuf, rt, method);
160 }
161 } while (rbuflen > 0);
162 if (request->seq != rt->seq + 1) {
163 av_log(s, AV_LOG_ERROR, "Unexpected Sequence number %d\n",
164 request->seq);
165 return AVERROR(EINVAL);
166 }
167 if (rt->session_id[0] && strcmp(method, "OPTIONS")) {
168 ret = check_sessionid(s, request);
169 if (ret)
170 return ret;
171 }
172
173 return 0;
174 }
175
176 static int rtsp_read_announce(AVFormatContext *s)
177 {
178 RTSPState *rt = s->priv_data;
179 RTSPMessageHeader request = { 0 };
180 char *sdp;
181 int ret;
182
183 ret = rtsp_read_request(s, &request, "ANNOUNCE");
184 if (ret)
185 return ret;
186 rt->seq++;
187 if (strcmp(request.content_type, "application/sdp")) {
188 av_log(s, AV_LOG_ERROR, "Unexpected content type %s\n",
189 request.content_type);
190 rtsp_send_reply(s, RTSP_STATUS_SERVICE, NULL, request.seq);
191 return AVERROR_OPTION_NOT_FOUND;
192 }
193 if (request.content_length) {
194 sdp = av_malloc(request.content_length + 1);
195 if (!sdp)
196 return AVERROR(ENOMEM);
197
198 /* Read SDP */
199 if (ffurl_read_complete(rt->rtsp_hd, sdp, request.content_length)
200 < request.content_length) {
201 av_log(s, AV_LOG_ERROR,
202 "Unable to get complete SDP Description in ANNOUNCE\n");
203 rtsp_send_reply(s, RTSP_STATUS_INTERNAL, NULL, request.seq);
204 av_free(sdp);
205 return AVERROR(EIO);
206 }
207 sdp[request.content_length] = '\0';
208 av_log(s, AV_LOG_VERBOSE, "SDP: %s\n", sdp);
209 ret = ff_sdp_parse(s, sdp);
210 av_free(sdp);
211 if (ret)
212 return ret;
213 rtsp_send_reply(s, RTSP_STATUS_OK, NULL, request.seq);
214 return 0;
215 }
216 av_log(s, AV_LOG_ERROR,
217 "Content-Length header value exceeds sdp allocated buffer (4KB)\n");
218 rtsp_send_reply(s, RTSP_STATUS_INTERNAL,
219 "Content-Length exceeds buffer size", request.seq);
220 return AVERROR(EIO);
221 }
222
223 static int rtsp_read_options(AVFormatContext *s)
224 {
225 RTSPState *rt = s->priv_data;
226 RTSPMessageHeader request = { 0 };
227 int ret = 0;
228
229 /* Parsing headers */
230 ret = rtsp_read_request(s, &request, "OPTIONS");
231 if (ret)
232 return ret;
233 rt->seq++;
234 /* Send Reply */
235 rtsp_send_reply(s, RTSP_STATUS_OK,
236 "Public: ANNOUNCE, PAUSE, SETUP, TEARDOWN, RECORD\r\n",
237 request.seq);
238 return 0;
239 }
240
241 static int rtsp_read_setup(AVFormatContext *s, char* host, char *controlurl)
242 {
243 RTSPState *rt = s->priv_data;
244 RTSPMessageHeader request = { 0 };
245 int ret = 0;
246 char url[MAX_URL_SIZE];
247 RTSPStream *rtsp_st;
248 char responseheaders[MAX_URL_SIZE];
249 int localport = -1;
250 int transportidx = 0;
251 int streamid = 0;
252
253 ret = rtsp_read_request(s, &request, "SETUP");
254 if (ret)
255 return ret;
256 rt->seq++;
257 if (!request.nb_transports) {
258 av_log(s, AV_LOG_ERROR, "No transport defined in SETUP\n");
259 return AVERROR_INVALIDDATA;
260 }
261 for (transportidx = 0; transportidx < request.nb_transports;
262 transportidx++) {
263 if (!request.transports[transportidx].mode_record ||
264 (request.transports[transportidx].lower_transport !=
265 RTSP_LOWER_TRANSPORT_UDP &&
266 request.transports[transportidx].lower_transport !=
267 RTSP_LOWER_TRANSPORT_TCP)) {
268 av_log(s, AV_LOG_ERROR, "mode=record/receive not set or transport"
269 " protocol not supported (yet)\n");
270 return AVERROR_INVALIDDATA;
271 }
272 }
273 if (request.nb_transports > 1)
274 av_log(s, AV_LOG_WARNING, "More than one transport not supported, "
275 "using first of all\n");
276 for (streamid = 0; streamid < rt->nb_rtsp_streams; streamid++) {
277 if (!strcmp(rt->rtsp_streams[streamid]->control_url,
278 controlurl))
279 break;
280 }
281 if (streamid == rt->nb_rtsp_streams) {
282 av_log(s, AV_LOG_ERROR, "Unable to find requested track\n");
283 return AVERROR_STREAM_NOT_FOUND;
284 }
285 rtsp_st = rt->rtsp_streams[streamid];
286 localport = rt->rtp_port_min;
287
288 /* check if the stream has already been setup */
289 if (rtsp_st->transport_priv) {
290 if (CONFIG_RTPDEC && rt->transport == RTSP_TRANSPORT_RDT)
291 ff_rdt_parse_close(rtsp_st->transport_priv);
292 else if (CONFIG_RTPDEC && rt->transport == RTSP_TRANSPORT_RTP)
293 ff_rtp_parse_close(rtsp_st->transport_priv);
294 rtsp_st->transport_priv = NULL;
295 }
296 if (rtsp_st->rtp_handle)
297 ffurl_closep(&rtsp_st->rtp_handle);
298
299 if (request.transports[0].lower_transport == RTSP_LOWER_TRANSPORT_TCP) {
300 rt->lower_transport = RTSP_LOWER_TRANSPORT_TCP;
301 if ((ret = ff_rtsp_open_transport_ctx(s, rtsp_st))) {
302 rtsp_send_reply(s, RTSP_STATUS_TRANSPORT, NULL, request.seq);
303 return ret;
304 }
305 rtsp_st->interleaved_min = request.transports[0].interleaved_min;
306 rtsp_st->interleaved_max = request.transports[0].interleaved_max;
307 snprintf(responseheaders, sizeof(responseheaders), "Transport: "
308 "RTP/AVP/TCP;unicast;mode=record;interleaved=%d-%d"
309 "\r\n", request.transports[0].interleaved_min,
310 request.transports[0].interleaved_max);
311 } else {
312 do {
313 AVDictionary *opts = NULL;
314 av_dict_set_int(&opts, "buffer_size", rt->buffer_size, 0);
315 ff_url_join(url, sizeof(url), "rtp", NULL, host, localport, NULL);
316 av_log(s, AV_LOG_TRACE, "Opening: %s\n", url);
317 ret = ffurl_open_whitelist(&rtsp_st->rtp_handle, url, AVIO_FLAG_READ_WRITE,
318 &s->interrupt_callback, &opts,
319 s->protocol_whitelist, s->protocol_blacklist, NULL);
320 av_dict_free(&opts);
321 if (ret)
322 localport += 2;
323 } while (ret || localport > rt->rtp_port_max);
324 if (localport > rt->rtp_port_max) {
325 rtsp_send_reply(s, RTSP_STATUS_TRANSPORT, NULL, request.seq);
326 return ret;
327 }
328
329 av_log(s, AV_LOG_TRACE, "Listening on: %d\n",
330 ff_rtp_get_local_rtp_port(rtsp_st->rtp_handle));
331 if ((ret = ff_rtsp_open_transport_ctx(s, rtsp_st))) {
332 rtsp_send_reply(s, RTSP_STATUS_TRANSPORT, NULL, request.seq);
333 return ret;
334 }
335
336 localport = ff_rtp_get_local_rtp_port(rtsp_st->rtp_handle);
337 snprintf(responseheaders, sizeof(responseheaders), "Transport: "
338 "RTP/AVP/UDP;unicast;mode=record;source=%s;"
339 "client_port=%d-%d;server_port=%d-%d\r\n",
340 host, request.transports[0].client_port_min,
341 request.transports[0].client_port_max, localport,
342 localport + 1);
343 }
344
345 /* Establish sessionid if not previously set */
346 /* Put this in a function? */
347 /* RFC 2326: session id must be at least 8 digits */
348 while (strlen(rt->session_id) < 8)
349 av_strlcatf(rt->session_id, 512, "%u", av_get_random_seed());
350
351 av_strlcatf(responseheaders, sizeof(responseheaders), "Session: %s\r\n",
352 rt->session_id);
353 /* Send Reply */
354 rtsp_send_reply(s, RTSP_STATUS_OK, responseheaders, request.seq);
355
356 rt->state = RTSP_STATE_PAUSED;
357 return 0;
358 }
359
360 static int rtsp_read_record(AVFormatContext *s)
361 {
362 RTSPState *rt = s->priv_data;
363 RTSPMessageHeader request = { 0 };
364 int ret = 0;
365 char responseheaders[MAX_URL_SIZE];
366
367 ret = rtsp_read_request(s, &request, "RECORD");
368 if (ret)
369 return ret;
370 ret = check_sessionid(s, &request);
371 if (ret)
372 return ret;
373 rt->seq++;
374 snprintf(responseheaders, sizeof(responseheaders), "Session: %s\r\n",
375 rt->session_id);
376 rtsp_send_reply(s, RTSP_STATUS_OK, responseheaders, request.seq);
377
378 rt->state = RTSP_STATE_STREAMING;
379 return 0;
380 }
381
382 static inline int parse_command_line(AVFormatContext *s, const char *line,
383 int linelen, char *uri, int urisize,
384 char *method, int methodsize,
385 enum RTSPMethod *methodcode)
386 {
387 RTSPState *rt = s->priv_data;
388 const char *linept, *searchlinept;
389 linept = strchr(line, ' ');
390
391 if (!linept) {
392 av_log(s, AV_LOG_ERROR, "Error parsing method string\n");
393 return AVERROR_INVALIDDATA;
394 }
395
396 if (linept - line > methodsize - 1) {
397 av_log(s, AV_LOG_ERROR, "Method string too long\n");
398 return AVERROR(EIO);
399 }
400 memcpy(method, line, linept - line);
401 method[linept - line] = '\0';
402 linept++;
403 if (!strcmp(method, "ANNOUNCE"))
404 *methodcode = ANNOUNCE;
405 else if (!strcmp(method, "OPTIONS"))
406 *methodcode = OPTIONS;
407 else if (!strcmp(method, "RECORD"))
408 *methodcode = RECORD;
409 else if (!strcmp(method, "SETUP"))
410 *methodcode = SETUP;
411 else if (!strcmp(method, "PAUSE"))
412 *methodcode = PAUSE;
413 else if (!strcmp(method, "TEARDOWN"))
414 *methodcode = TEARDOWN;
415 else
416 *methodcode = UNKNOWN;
417 /* Check method with the state */
418 if (rt->state == RTSP_STATE_IDLE) {
419 if ((*methodcode != ANNOUNCE) && (*methodcode != OPTIONS)) {
420 av_log(s, AV_LOG_ERROR, "Unexpected command in Idle State %s\n",
421 line);
422 return AVERROR_PROTOCOL_NOT_FOUND;
423 }
424 } else if (rt->state == RTSP_STATE_PAUSED) {
425 if ((*methodcode != OPTIONS) && (*methodcode != RECORD)
426 && (*methodcode != SETUP)) {
427 av_log(s, AV_LOG_ERROR, "Unexpected command in Paused State %s\n",
428 line);
429 return AVERROR_PROTOCOL_NOT_FOUND;
430 }
431 } else if (rt->state == RTSP_STATE_STREAMING) {
432 if ((*methodcode != PAUSE) && (*methodcode != OPTIONS)
433 && (*methodcode != TEARDOWN)) {
434 av_log(s, AV_LOG_ERROR, "Unexpected command in Streaming State"
435 " %s\n", line);
436 return AVERROR_PROTOCOL_NOT_FOUND;
437 }
438 } else {
439 av_log(s, AV_LOG_ERROR, "Unexpected State [%d]\n", rt->state);
440 return AVERROR_BUG;
441 }
442
443 searchlinept = strchr(linept, ' ');
444 if (!searchlinept) {
445 av_log(s, AV_LOG_ERROR, "Error parsing message URI\n");
446 return AVERROR_INVALIDDATA;
447 }
448 if (searchlinept - linept > urisize - 1) {
449 av_log(s, AV_LOG_ERROR, "uri string length exceeded buffer size\n");
450 return AVERROR(EIO);
451 }
452 memcpy(uri, linept, searchlinept - linept);
453 uri[searchlinept - linept] = '\0';
454 if (strcmp(rt->control_uri, uri)) {
455 char host[128], path[512], auth[128];
456 int port;
457 char ctl_host[128], ctl_path[512], ctl_auth[128];
458 int ctl_port;
459 av_url_split(NULL, 0, auth, sizeof(auth), host, sizeof(host), &port,
460 path, sizeof(path), uri);
461 av_url_split(NULL, 0, ctl_auth, sizeof(ctl_auth), ctl_host,
462 sizeof(ctl_host), &ctl_port, ctl_path, sizeof(ctl_path),
463 rt->control_uri);
464 if (strcmp(host, ctl_host))
465 av_log(s, AV_LOG_INFO, "Host %s differs from expected %s\n",
466 host, ctl_host);
467 if (strcmp(path, ctl_path) && *methodcode != SETUP)
468 av_log(s, AV_LOG_WARNING, "WARNING: Path %s differs from expected"
469 " %s\n", path, ctl_path);
470 if (*methodcode == ANNOUNCE) {
471 av_log(s, AV_LOG_INFO,
472 "Updating control URI to %s\n", uri);
473 av_strlcpy(rt->control_uri, uri, sizeof(rt->control_uri));
474 }
475 }
476
477 linept = searchlinept + 1;
478 if (!av_strstart(linept, "RTSP/1.0", NULL)) {
479 av_log(s, AV_LOG_ERROR, "Error parsing protocol or version\n");
480 return AVERROR_PROTOCOL_NOT_FOUND;
481 }
482 return 0;
483 }
484
485 int ff_rtsp_parse_streaming_commands(AVFormatContext *s)
486 {
487 RTSPState *rt = s->priv_data;
488 unsigned char rbuf[MAX_URL_SIZE];
489 unsigned char method[10];
490 char uri[500];
491 int ret;
492 int rbuflen = 0;
493 RTSPMessageHeader request = { 0 };
494 enum RTSPMethod methodcode;
495
496 ret = read_line(s, rbuf, sizeof(rbuf), &rbuflen);
497 if (ret < 0)
498 return ret;
499 av_log(s, AV_LOG_TRACE, "Parsing[%d]: %s\n", rbuflen, rbuf);
500 ret = parse_command_line(s, rbuf, rbuflen, uri, sizeof(uri), method,
501 sizeof(method), &methodcode);
502 if (ret) {
503 av_log(s, AV_LOG_ERROR, "RTSP: Unexpected Command\n");
504 return ret;
505 }
506
507 ret = rtsp_read_request(s, &request, method);
508 if (ret)
509 return ret;
510 rt->seq++;
511 if (methodcode == PAUSE) {
512 rt->state = RTSP_STATE_PAUSED;
513 ret = rtsp_send_reply(s, RTSP_STATUS_OK, NULL , request.seq);
514 // TODO: Missing date header in response
515 } else if (methodcode == OPTIONS) {
516 ret = rtsp_send_reply(s, RTSP_STATUS_OK,
517 "Public: ANNOUNCE, PAUSE, SETUP, TEARDOWN, "
518 "RECORD\r\n", request.seq);
519 } else if (methodcode == TEARDOWN) {
520 rt->state = RTSP_STATE_IDLE;
521 ret = rtsp_send_reply(s, RTSP_STATUS_OK, NULL , request.seq);
522 }
523 return ret;
524 }
525
526 static int rtsp_read_play(AVFormatContext *s)
527 {
528 RTSPState *rt = s->priv_data;
529 RTSPMessageHeader reply1, *reply = &reply1;
530 int i;
531 char cmd[MAX_URL_SIZE];
532
533 av_log(s, AV_LOG_DEBUG, "hello state=%d\n", rt->state);
534 rt->nb_byes = 0;
535
536 if (rt->lower_transport == RTSP_LOWER_TRANSPORT_UDP) {
537 for (i = 0; i < rt->nb_rtsp_streams; i++) {
538 RTSPStream *rtsp_st = rt->rtsp_streams[i];
539 /* Try to initialize the connection state in a
540 * potential NAT router by sending dummy packets.
541 * RTP/RTCP dummy packets are used for RDT, too.
542 */
543 if (rtsp_st->rtp_handle &&
544 !(rt->server_type == RTSP_SERVER_WMS && i > 1))
545 ff_rtp_send_punch_packets(rtsp_st->rtp_handle);
546 }
547 }
548 if (!(rt->server_type == RTSP_SERVER_REAL && rt->need_subscription)) {
549 if (rt->transport == RTSP_TRANSPORT_RTP) {
550 for (i = 0; i < rt->nb_rtsp_streams; i++) {
551 RTSPStream *rtsp_st = rt->rtsp_streams[i];
552 RTPDemuxContext *rtpctx = rtsp_st->transport_priv;
553 if (!rtpctx)
554 continue;
555 ff_rtp_reset_packet_queue(rtpctx);
556 rtpctx->last_rtcp_ntp_time = AV_NOPTS_VALUE;
557 rtpctx->first_rtcp_ntp_time = AV_NOPTS_VALUE;
558 rtpctx->base_timestamp = 0;
559 rtpctx->timestamp = 0;
560 rtpctx->unwrapped_timestamp = 0;
561 rtpctx->rtcp_ts_offset = 0;
562 }
563 }
564 if (rt->state == RTSP_STATE_PAUSED) {
565 cmd[0] = 0;
566 } else {
567 snprintf(cmd, sizeof(cmd),
568 "Range: npt=%"PRId64".%03"PRId64"-\r\n",
569 rt->seek_timestamp / AV_TIME_BASE,
570 rt->seek_timestamp / (AV_TIME_BASE / 1000) % 1000);
571 }
572 ff_rtsp_send_cmd(s, "PLAY", rt->control_uri, cmd, reply, NULL);
573 if (reply->status_code != RTSP_STATUS_OK) {
574 return ff_rtsp_averror(reply->status_code, -1);
575 }
576 if (rt->transport == RTSP_TRANSPORT_RTP &&
577 reply->range_start != AV_NOPTS_VALUE) {
578 for (i = 0; i < rt->nb_rtsp_streams; i++) {
579 RTSPStream *rtsp_st = rt->rtsp_streams[i];
580 RTPDemuxContext *rtpctx = rtsp_st->transport_priv;
581 AVStream *st = NULL;
582 if (!rtpctx || rtsp_st->stream_index < 0)
583 continue;
584
585 st = s->streams[rtsp_st->stream_index];
586 rtpctx->range_start_offset =
587 av_rescale_q(reply->range_start, AV_TIME_BASE_Q,
588 st->time_base);
589 }
590 }
591 }
592 rt->state = RTSP_STATE_STREAMING;
593 return 0;
594 }
595
596 /* pause the stream */
597 static int rtsp_read_pause(AVFormatContext *s)
598 {
599 RTSPState *rt = s->priv_data;
600 RTSPMessageHeader reply1, *reply = &reply1;
601
602 if (rt->state != RTSP_STATE_STREAMING)
603 return 0;
604 else if (!(rt->server_type == RTSP_SERVER_REAL && rt->need_subscription)) {
605 ff_rtsp_send_cmd(s, "PAUSE", rt->control_uri, NULL, reply, NULL);
606 if (reply->status_code != RTSP_STATUS_OK) {
607 return ff_rtsp_averror(reply->status_code, -1);
608 }
609 }
610 rt->state = RTSP_STATE_PAUSED;
611 return 0;
612 }
613
614 int ff_rtsp_setup_input_streams(AVFormatContext *s, RTSPMessageHeader *reply)
615 {
616 RTSPState *rt = s->priv_data;
617 char cmd[MAX_URL_SIZE];
618 unsigned char *content = NULL;
619 int ret;
620
621 /* describe the stream */
622 snprintf(cmd, sizeof(cmd),
623 "Accept: application/sdp\r\n");
624 if (rt->server_type == RTSP_SERVER_REAL) {
625 /**
626 * The Require: attribute is needed for proper streaming from
627 * Realmedia servers.
628 */
629 av_strlcat(cmd,
630 "Require: com.real.retain-entity-for-setup\r\n",
631 sizeof(cmd));
632 }
633 ff_rtsp_send_cmd(s, "DESCRIBE", rt->control_uri, cmd, reply, &content);
634 if (reply->status_code != RTSP_STATUS_OK) {
635 av_freep(&content);
636 return ff_rtsp_averror(reply->status_code, AVERROR_INVALIDDATA);
637 }
638 if (!content)
639 return AVERROR_INVALIDDATA;
640
641 av_log(s, AV_LOG_VERBOSE, "SDP:\n%s\n", content);
642 /* now we got the SDP description, we parse it */
643 ret = ff_sdp_parse(s, (const char *)content);
644 av_freep(&content);
645 if (ret < 0)
646 return ret;
647
648 return 0;
649 }
650
651 static int rtsp_listen(AVFormatContext *s)
652 {
653 RTSPState *rt = s->priv_data;
654 char proto[128], host[128], path[512], auth[128];
655 char uri[500];
656 int port;
657 int default_port = RTSP_DEFAULT_PORT;
658 char tcpname[500];
659 const char *lower_proto = "tcp";
660 unsigned char rbuf[MAX_URL_SIZE];
661 unsigned char method[10];
662 int rbuflen = 0;
663 int ret;
664 enum RTSPMethod methodcode;
665
666 if (!ff_network_init())
667 return AVERROR(EIO);
668
669 /* extract hostname and port */
670 av_url_split(proto, sizeof(proto), auth, sizeof(auth), host, sizeof(host),
671 &port, path, sizeof(path), s->url);
672
673 /* ff_url_join. No authorization by now (NULL) */
674 ff_url_join(rt->control_uri, sizeof(rt->control_uri), proto, NULL, host,
675 port, "%s", path);
676
677 if (!strcmp(proto, "rtsps")) {
678 lower_proto = "tls";
679 default_port = RTSPS_DEFAULT_PORT;
680 }
681
682 if (port < 0)
683 port = default_port;
684
685 /* Create TCP connection */
686 ff_url_join(tcpname, sizeof(tcpname), lower_proto, NULL, host, port,
687 "?listen&listen_timeout=%d", rt->initial_timeout * 1000);
688
689 if (ret = ffurl_open_whitelist(&rt->rtsp_hd, tcpname, AVIO_FLAG_READ_WRITE,
690 &s->interrupt_callback, NULL,
691 s->protocol_whitelist, s->protocol_blacklist, NULL)) {
692 av_log(s, AV_LOG_ERROR, "Unable to open RTSP for listening\n");
693 goto fail;
694 }
695 rt->state = RTSP_STATE_IDLE;
696 rt->rtsp_hd_out = rt->rtsp_hd;
697 for (;;) { /* Wait for incoming RTSP messages */
698 ret = read_line(s, rbuf, sizeof(rbuf), &rbuflen);
699 if (ret < 0)
700 goto fail;
701 av_log(s, AV_LOG_TRACE, "Parsing[%d]: %s\n", rbuflen, rbuf);
702 ret = parse_command_line(s, rbuf, rbuflen, uri, sizeof(uri), method,
703 sizeof(method), &methodcode);
704 if (ret) {
705 av_log(s, AV_LOG_ERROR, "RTSP: Unexpected Command\n");
706 goto fail;
707 }
708
709 if (methodcode == ANNOUNCE) {
710 ret = rtsp_read_announce(s);
711 rt->state = RTSP_STATE_PAUSED;
712 } else if (methodcode == OPTIONS) {
713 ret = rtsp_read_options(s);
714 } else if (methodcode == RECORD) {
715 ret = rtsp_read_record(s);
716 if (!ret)
717 return 0; // We are ready for streaming
718 } else if (methodcode == SETUP)
719 ret = rtsp_read_setup(s, host, uri);
720 if (ret) {
721 ret = AVERROR_INVALIDDATA;
722 goto fail;
723 }
724 }
725 fail:
726 ff_rtsp_close_streams(s);
727 ff_rtsp_close_connections(s);
728 ff_network_close();
729 return ret;
730 }
731
732 3843 static int rtsp_probe(const AVProbeData *p)
733 {
734
1/2
✓ Branch 0 taken 3843 times.
✗ Branch 1 not taken.
3843 if (
735 #if CONFIG_TLS_PROTOCOL
736 av_strstart(p->filename, "rtsps:", NULL) ||
737 #endif
738
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3843 times.
7686 av_strstart(p->filename, "satip:", NULL) ||
739 3843 av_strstart(p->filename, "rtsp:", NULL))
740 return AVPROBE_SCORE_MAX;
741 3843 return 0;
742 }
743
744 static int rtsp_read_header(AVFormatContext *s)
745 {
746 RTSPState *rt = s->priv_data;
747 int ret;
748
749 if (rt->initial_timeout > 0)
750 rt->rtsp_flags |= RTSP_FLAG_LISTEN;
751
752 if (rt->rtsp_flags & RTSP_FLAG_LISTEN) {
753 ret = rtsp_listen(s);
754 if (ret)
755 return ret;
756 } else {
757 ret = ff_rtsp_connect(s);
758 if (ret)
759 return ret;
760
761 rt->real_setup_cache = !s->nb_streams ? NULL :
762 av_calloc(s->nb_streams, 2 * sizeof(*rt->real_setup_cache));
763 if (!rt->real_setup_cache && s->nb_streams) {
764 ret = AVERROR(ENOMEM);
765 goto fail;
766 }
767 rt->real_setup = rt->real_setup_cache + s->nb_streams;
768
769 if (rt->initial_pause) {
770 /* do not start immediately */
771 } else {
772 ret = rtsp_read_play(s);
773 if (ret < 0)
774 goto fail;
775 }
776 }
777
778 return 0;
779
780 fail:
781 rtsp_read_close(s);
782 return ret;
783 }
784
785 int ff_rtsp_tcp_read_packet(AVFormatContext *s, RTSPStream **prtsp_st,
786 uint8_t *buf, int buf_size)
787 {
788 RTSPState *rt = s->priv_data;
789 int id, len, i, ret;
790 RTSPStream *rtsp_st;
791
792 av_log(s, AV_LOG_TRACE, "tcp_read_packet:\n");
793 redo:
794 for (;;) {
795 RTSPMessageHeader reply;
796
797 ret = ff_rtsp_read_reply(s, &reply, NULL, 1, NULL);
798 if (ret < 0)
799 return ret;
800 if (ret == 1) /* received '$' */
801 break;
802 /* XXX: parse message */
803 if (rt->state != RTSP_STATE_STREAMING)
804 return 0;
805 }
806 ret = ffurl_read_complete(rt->rtsp_hd, buf, 3);
807 if (ret != 3)
808 return AVERROR(EIO);
809 id = buf[0];
810 len = AV_RB16(buf + 1);
811 av_log(s, AV_LOG_TRACE, "id=%d len=%d\n", id, len);
812 if (len > buf_size || len < 8)
813 goto redo;
814 /* get the data */
815 ret = ffurl_read_complete(rt->rtsp_hd, buf, len);
816 if (ret != len)
817 return AVERROR(EIO);
818 if (rt->transport == RTSP_TRANSPORT_RDT &&
819 (ret = ff_rdt_parse_header(buf, len, &id, NULL, NULL, NULL, NULL)) < 0)
820 return ret;
821
822 /* find the matching stream */
823 for (i = 0; i < rt->nb_rtsp_streams; i++) {
824 rtsp_st = rt->rtsp_streams[i];
825 if (id >= rtsp_st->interleaved_min &&
826 id <= rtsp_st->interleaved_max)
827 goto found;
828 }
829 goto redo;
830 found:
831 *prtsp_st = rtsp_st;
832 return len;
833 }
834
835 static int resetup_tcp(AVFormatContext *s)
836 {
837 RTSPState *rt = s->priv_data;
838 char host[1024];
839 int port;
840
841 av_url_split(NULL, 0, NULL, 0, host, sizeof(host), &port, NULL, 0,
842 s->url);
843 ff_rtsp_undo_setup(s, 0);
844 return ff_rtsp_make_setup_request(s, host, port, RTSP_LOWER_TRANSPORT_TCP,
845 rt->real_challenge);
846 }
847
848 static int rtsp_read_packet(AVFormatContext *s, AVPacket *pkt)
849 {
850 RTSPState *rt = s->priv_data;
851 int ret;
852 RTSPMessageHeader reply1, *reply = &reply1;
853 char cmd[MAX_URL_SIZE];
854
855 retry:
856 if (rt->server_type == RTSP_SERVER_REAL) {
857 int i;
858
859 for (i = 0; i < s->nb_streams; i++)
860 rt->real_setup[i] = s->streams[i]->discard;
861
862 if (!rt->need_subscription) {
863 if (memcmp (rt->real_setup, rt->real_setup_cache,
864 sizeof(enum AVDiscard) * s->nb_streams)) {
865 snprintf(cmd, sizeof(cmd),
866 "Unsubscribe: %s\r\n",
867 rt->last_subscription);
868 ff_rtsp_send_cmd(s, "SET_PARAMETER", rt->control_uri,
869 cmd, reply, NULL);
870 if (reply->status_code != RTSP_STATUS_OK)
871 return ff_rtsp_averror(reply->status_code, AVERROR_INVALIDDATA);
872 rt->need_subscription = 1;
873 }
874 }
875
876 if (rt->need_subscription) {
877 int r, rule_nr, first = 1;
878
879 memcpy(rt->real_setup_cache, rt->real_setup,
880 sizeof(enum AVDiscard) * s->nb_streams);
881 rt->last_subscription[0] = 0;
882
883 snprintf(cmd, sizeof(cmd),
884 "Subscribe: ");
885 for (i = 0; i < rt->nb_rtsp_streams; i++) {
886 rule_nr = 0;
887 for (r = 0; r < s->nb_streams; r++) {
888 if (s->streams[r]->id == i) {
889 if (s->streams[r]->discard != AVDISCARD_ALL) {
890 if (!first)
891 av_strlcat(rt->last_subscription, ",",
892 sizeof(rt->last_subscription));
893 ff_rdt_subscribe_rule(
894 rt->last_subscription,
895 sizeof(rt->last_subscription), i, rule_nr);
896 first = 0;
897 }
898 rule_nr++;
899 }
900 }
901 }
902 av_strlcatf(cmd, sizeof(cmd), "%s\r\n", rt->last_subscription);
903 ff_rtsp_send_cmd(s, "SET_PARAMETER", rt->control_uri,
904 cmd, reply, NULL);
905 if (reply->status_code != RTSP_STATUS_OK)
906 return ff_rtsp_averror(reply->status_code, AVERROR_INVALIDDATA);
907 rt->need_subscription = 0;
908
909 if (rt->state == RTSP_STATE_STREAMING)
910 rtsp_read_play (s);
911 }
912 }
913
914 ret = ff_rtsp_fetch_packet(s, pkt);
915 if (ret < 0) {
916 if (ret == AVERROR(ETIMEDOUT) && !rt->packets) {
917 if (rt->lower_transport == RTSP_LOWER_TRANSPORT_UDP &&
918 rt->lower_transport_mask & (1 << RTSP_LOWER_TRANSPORT_TCP)) {
919 RTSPMessageHeader reply1, *reply = &reply1;
920 av_log(s, AV_LOG_WARNING, "UDP timeout, retrying with TCP\n");
921 if (rtsp_read_pause(s) != 0)
922 return -1;
923 // TEARDOWN is required on Real-RTSP, but might make
924 // other servers close the connection.
925 if (rt->server_type == RTSP_SERVER_REAL)
926 ff_rtsp_send_cmd(s, "TEARDOWN", rt->control_uri, NULL,
927 reply, NULL);
928 rt->session_id[0] = '\0';
929 if (resetup_tcp(s) == 0) {
930 rt->state = RTSP_STATE_IDLE;
931 rt->need_subscription = 1;
932 if (rtsp_read_play(s) != 0)
933 return -1;
934 goto retry;
935 }
936 }
937 }
938 return ret;
939 }
940 rt->packets++;
941
942 if (!(rt->rtsp_flags & RTSP_FLAG_LISTEN)) {
943 /* send dummy request to keep TCP connection alive */
944 if ((av_gettime_relative() - rt->last_cmd_time) / 1000000 >= rt->timeout / 2 ||
945 rt->auth_state.stale) {
946 if (rt->server_type == RTSP_SERVER_WMS ||
947 (rt->server_type != RTSP_SERVER_REAL &&
948 rt->get_parameter_supported)) {
949 ff_rtsp_send_cmd_async(s, "GET_PARAMETER", rt->control_uri, NULL);
950 } else {
951 ff_rtsp_send_cmd_async(s, "OPTIONS", rt->control_uri, NULL);
952 }
953 /* The stale flag should be reset when creating the auth response in
954 * ff_rtsp_send_cmd_async, but reset it here just in case we never
955 * called the auth code (if we didn't have any credentials set). */
956 rt->auth_state.stale = 0;
957 }
958 }
959
960 return 0;
961 }
962
963 static int rtsp_read_seek(AVFormatContext *s, int stream_index,
964 int64_t timestamp, int flags)
965 {
966 RTSPState *rt = s->priv_data;
967 int ret;
968
969 rt->seek_timestamp = av_rescale_q(timestamp,
970 s->streams[stream_index]->time_base,
971 AV_TIME_BASE_Q);
972 switch(rt->state) {
973 default:
974 case RTSP_STATE_IDLE:
975 break;
976 case RTSP_STATE_STREAMING:
977 if ((ret = rtsp_read_pause(s)) != 0)
978 return ret;
979 rt->state = RTSP_STATE_SEEKING;
980 if ((ret = rtsp_read_play(s)) != 0)
981 return ret;
982 break;
983 case RTSP_STATE_PAUSED:
984 rt->state = RTSP_STATE_IDLE;
985 break;
986 }
987 return 0;
988 }
989
990 static const AVClass rtsp_demuxer_class = {
991 .class_name = "RTSP demuxer",
992 .item_name = av_default_item_name,
993 .option = ff_rtsp_options,
994 .version = LIBAVUTIL_VERSION_INT,
995 };
996
997 const FFInputFormat ff_rtsp_demuxer = {
998 .p.name = "rtsp",
999 .p.long_name = NULL_IF_CONFIG_SMALL("RTSP input"),
1000 .p.flags = AVFMT_NOFILE,
1001 .p.priv_class = &rtsp_demuxer_class,
1002 .priv_data_size = sizeof(RTSPState),
1003 .read_probe = rtsp_probe,
1004 .read_header = rtsp_read_header,
1005 .read_packet = rtsp_read_packet,
1006 .read_close = rtsp_read_close,
1007 .read_seek = rtsp_read_seek,
1008 .read_play = rtsp_read_play,
1009 .read_pause = rtsp_read_pause,
1010 };
1011