FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavformat/rtspdec.c
Date: 2026-04-29 05:33:45
Exec Total Coverage
Lines: 5 656 0.8%
Functions: 1 26 3.8%
Branches: 2 375 0.5%

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