3 * Copyright (c) 2002 Fabrice Bellard
5 * This file is part of FFmpeg.
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.
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.
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
22 #include "libavutil/avstring.h"
23 #include "libavutil/intreadwrite.h"
24 #include "libavutil/mathematics.h"
25 #include "libavutil/random_seed.h"
26 #include "libavutil/time.h"
31 #include "os_support.h"
37 static const struct RTSPStatusMessage
{
38 enum RTSPStatusCode code
;
40 } status_messages
[] = {
41 { RTSP_STATUS_OK
, "OK" },
42 { RTSP_STATUS_METHOD
, "Method Not Allowed" },
43 { RTSP_STATUS_BANDWIDTH
, "Not Enough Bandwidth" },
44 { RTSP_STATUS_SESSION
, "Session Not Found" },
45 { RTSP_STATUS_STATE
, "Method Not Valid in This State" },
46 { RTSP_STATUS_AGGREGATE
, "Aggregate operation not allowed" },
47 { RTSP_STATUS_ONLY_AGGREGATE
, "Only aggregate operation allowed" },
48 { RTSP_STATUS_TRANSPORT
, "Unsupported transport" },
49 { RTSP_STATUS_INTERNAL
, "Internal Server Error" },
50 { RTSP_STATUS_SERVICE
, "Service Unavailable" },
51 { RTSP_STATUS_VERSION
, "RTSP Version not supported" },
55 static int rtsp_read_close(AVFormatContext
*s
)
57 RTSPState
*rt
= s
->priv_data
;
59 if (!(rt
->rtsp_flags
& RTSP_FLAG_LISTEN
))
60 ff_rtsp_send_cmd_async(s
, "TEARDOWN", rt
->control_uri
, NULL
);
62 ff_rtsp_close_streams(s
);
63 ff_rtsp_close_connections(s
);
65 rt
->real_setup
= NULL
;
66 av_freep(&rt
->real_setup_cache
);
70 static inline int read_line(AVFormatContext
*s
, char *rbuf
, const int rbufsize
,
73 RTSPState
*rt
= s
->priv_data
;
79 ret
= ffurl_read_complete(rt
->rtsp_hd
, rbuf
+ idx
, 1);
81 return ret
? ret
: AVERROR_EOF
;
82 if (rbuf
[idx
] == '\r') {
84 } else if (rbuf
[idx
] == '\n') {
90 } while (idx
< rbufsize
);
91 av_log(s
, AV_LOG_ERROR
, "Message too long\n");
95 static int rtsp_send_reply(AVFormatContext
*s
, enum RTSPStatusCode code
,
96 const char *extracontent
, uint16_t seq
)
98 RTSPState
*rt
= s
->priv_data
;
101 while (status_messages
[index
].code
) {
102 if (status_messages
[index
].code
== code
) {
103 snprintf(message
, sizeof(message
), "RTSP/1.0 %d %s\r\n",
104 code
, status_messages
[index
].message
);
109 if (!status_messages
[index
].code
)
110 return AVERROR(EINVAL
);
111 av_strlcatf(message
, sizeof(message
), "CSeq: %d\r\n", seq
);
112 av_strlcatf(message
, sizeof(message
), "Server: %s\r\n", LIBAVFORMAT_IDENT
);
114 av_strlcat(message
, extracontent
, sizeof(message
));
115 av_strlcat(message
, "\r\n", sizeof(message
));
116 av_dlog(s
, "Sending response:\n%s", message
);
117 ffurl_write(rt
->rtsp_hd
, message
, strlen(message
));
122 static inline int check_sessionid(AVFormatContext
*s
,
123 RTSPMessageHeader
*request
)
125 RTSPState
*rt
= s
->priv_data
;
126 unsigned char *session_id
= rt
->session_id
;
127 if (!session_id
[0]) {
128 av_log(s
, AV_LOG_WARNING
, "There is no session-id at the moment\n");
131 if (strcmp(session_id
, request
->session_id
)) {
132 av_log(s
, AV_LOG_ERROR
, "Unexpected session-id %s\n",
133 request
->session_id
);
134 rtsp_send_reply(s
, RTSP_STATUS_SESSION
, NULL
, request
->seq
);
135 return AVERROR_STREAM_NOT_FOUND
;
140 static inline int rtsp_read_request(AVFormatContext
*s
,
141 RTSPMessageHeader
*request
,
144 RTSPState
*rt
= s
->priv_data
;
148 ret
= read_line(s
, rbuf
, sizeof(rbuf
), &rbuflen
);
152 av_dlog(s
, "Parsing[%d]: %s\n", rbuflen
, rbuf
);
153 ff_rtsp_parse_line(request
, rbuf
, rt
, method
);
155 } while (rbuflen
> 0);
156 if (request
->seq
!= rt
->seq
+ 1) {
157 av_log(s
, AV_LOG_ERROR
, "Unexpected Sequence number %d\n",
159 return AVERROR(EINVAL
);
161 if (rt
->session_id
[0] && strcmp(method
, "OPTIONS")) {
162 ret
= check_sessionid(s
, request
);
170 static int rtsp_read_announce(AVFormatContext
*s
)
172 RTSPState
*rt
= s
->priv_data
;
173 RTSPMessageHeader request
= { 0 };
177 ret
= rtsp_read_request(s
, &request
, "ANNOUNCE");
181 if (strcmp(request
.content_type
, "application/sdp")) {
182 av_log(s
, AV_LOG_ERROR
, "Unexpected content type %s\n",
183 request
.content_type
);
184 rtsp_send_reply(s
, RTSP_STATUS_SERVICE
, NULL
, request
.seq
);
185 return AVERROR_OPTION_NOT_FOUND
;
187 if (request
.content_length
&& request
.content_length
< sizeof(sdp
) - 1) {
189 if (ffurl_read_complete(rt
->rtsp_hd
, sdp
, request
.content_length
)
190 < request
.content_length
) {
191 av_log(s
, AV_LOG_ERROR
,
192 "Unable to get complete SDP Description in ANNOUNCE\n");
193 rtsp_send_reply(s
, RTSP_STATUS_INTERNAL
, NULL
, request
.seq
);
196 sdp
[request
.content_length
] = '\0';
197 av_log(s
, AV_LOG_VERBOSE
, "SDP: %s\n", sdp
);
198 ret
= ff_sdp_parse(s
, sdp
);
201 rtsp_send_reply(s
, RTSP_STATUS_OK
, NULL
, request
.seq
);
204 av_log(s
, AV_LOG_ERROR
,
205 "Content-Length header value exceeds sdp allocated buffer (4KB)\n");
206 rtsp_send_reply(s
, RTSP_STATUS_INTERNAL
,
207 "Content-Length exceeds buffer size", request
.seq
);
211 static int rtsp_read_options(AVFormatContext
*s
)
213 RTSPState
*rt
= s
->priv_data
;
214 RTSPMessageHeader request
= { 0 };
217 /* Parsing headers */
218 ret
= rtsp_read_request(s
, &request
, "OPTIONS");
223 rtsp_send_reply(s
, RTSP_STATUS_OK
,
224 "Public: ANNOUNCE, PAUSE, SETUP, TEARDOWN, RECORD\r\n",
229 static int rtsp_read_setup(AVFormatContext
*s
, char* host
, char *controlurl
)
231 RTSPState
*rt
= s
->priv_data
;
232 RTSPMessageHeader request
= { 0 };
236 char responseheaders
[1024];
238 int transportidx
= 0;
241 ret
= rtsp_read_request(s
, &request
, "SETUP");
245 if (!request
.nb_transports
) {
246 av_log(s
, AV_LOG_ERROR
, "No transport defined in SETUP\n");
247 return AVERROR_INVALIDDATA
;
249 for (transportidx
= 0; transportidx
< request
.nb_transports
;
251 if (!request
.transports
[transportidx
].mode_record
||
252 (request
.transports
[transportidx
].lower_transport
!=
253 RTSP_LOWER_TRANSPORT_UDP
&&
254 request
.transports
[transportidx
].lower_transport
!=
255 RTSP_LOWER_TRANSPORT_TCP
)) {
256 av_log(s
, AV_LOG_ERROR
, "mode=record/receive not set or transport"
257 " protocol not supported (yet)\n");
258 return AVERROR_INVALIDDATA
;
261 if (request
.nb_transports
> 1)
262 av_log(s
, AV_LOG_WARNING
, "More than one transport not supported, "
263 "using first of all\n");
264 for (streamid
= 0; streamid
< rt
->nb_rtsp_streams
; streamid
++) {
265 if (!strcmp(rt
->rtsp_streams
[streamid
]->control_url
,
269 if (streamid
== rt
->nb_rtsp_streams
) {
270 av_log(s
, AV_LOG_ERROR
, "Unable to find requested track\n");
271 return AVERROR_STREAM_NOT_FOUND
;
273 rtsp_st
= rt
->rtsp_streams
[streamid
];
274 localport
= rt
->rtp_port_min
;
276 if (request
.transports
[0].lower_transport
== RTSP_LOWER_TRANSPORT_TCP
) {
277 rt
->lower_transport
= RTSP_LOWER_TRANSPORT_TCP
;
278 if ((ret
= ff_rtsp_open_transport_ctx(s
, rtsp_st
))) {
279 rtsp_send_reply(s
, RTSP_STATUS_TRANSPORT
, NULL
, request
.seq
);
282 rtsp_st
->interleaved_min
= request
.transports
[0].interleaved_min
;
283 rtsp_st
->interleaved_max
= request
.transports
[0].interleaved_max
;
284 snprintf(responseheaders
, sizeof(responseheaders
), "Transport: "
285 "RTP/AVP/TCP;unicast;mode=receive;interleaved=%d-%d"
286 "\r\n", request
.transports
[0].interleaved_min
,
287 request
.transports
[0].interleaved_max
);
290 ff_url_join(url
, sizeof(url
), "rtp", NULL
, host
, localport
, NULL
);
291 av_dlog(s
, "Opening: %s", url
);
292 ret
= ffurl_open(&rtsp_st
->rtp_handle
, url
, AVIO_FLAG_READ_WRITE
,
293 &s
->interrupt_callback
, NULL
);
296 } while (ret
|| localport
> rt
->rtp_port_max
);
297 if (localport
> rt
->rtp_port_max
) {
298 rtsp_send_reply(s
, RTSP_STATUS_TRANSPORT
, NULL
, request
.seq
);
302 av_dlog(s
, "Listening on: %d",
303 ff_rtp_get_local_rtp_port(rtsp_st
->rtp_handle
));
304 if ((ret
= ff_rtsp_open_transport_ctx(s
, rtsp_st
))) {
305 rtsp_send_reply(s
, RTSP_STATUS_TRANSPORT
, NULL
, request
.seq
);
309 localport
= ff_rtp_get_local_rtp_port(rtsp_st
->rtp_handle
);
310 snprintf(responseheaders
, sizeof(responseheaders
), "Transport: "
311 "RTP/AVP/UDP;unicast;mode=receive;source=%s;"
312 "client_port=%d-%d;server_port=%d-%d\r\n",
313 host
, request
.transports
[0].client_port_min
,
314 request
.transports
[0].client_port_max
, localport
,
318 /* Establish sessionid if not previously set */
319 /* Put this in a function? */
320 /* RFC 2326: session id must be at least 8 digits */
321 while (strlen(rt
->session_id
) < 8)
322 av_strlcatf(rt
->session_id
, 512, "%u", av_get_random_seed());
324 av_strlcatf(responseheaders
, sizeof(responseheaders
), "Session: %s\r\n",
327 rtsp_send_reply(s
, RTSP_STATUS_OK
, responseheaders
, request
.seq
);
329 rt
->state
= RTSP_STATE_PAUSED
;
333 static int rtsp_read_record(AVFormatContext
*s
)
335 RTSPState
*rt
= s
->priv_data
;
336 RTSPMessageHeader request
= { 0 };
338 char responseheaders
[1024];
340 ret
= rtsp_read_request(s
, &request
, "RECORD");
343 ret
= check_sessionid(s
, &request
);
347 snprintf(responseheaders
, sizeof(responseheaders
), "Session: %s\r\n",
349 rtsp_send_reply(s
, RTSP_STATUS_OK
, responseheaders
, request
.seq
);
351 rt
->state
= RTSP_STATE_STREAMING
;
355 static inline int parse_command_line(AVFormatContext
*s
, const char *line
,
356 int linelen
, char *uri
, int urisize
,
357 char *method
, int methodsize
,
358 enum RTSPMethod
*methodcode
)
360 RTSPState
*rt
= s
->priv_data
;
361 const char *linept
, *searchlinept
;
362 linept
= strchr(line
, ' ');
365 av_log(s
, AV_LOG_ERROR
, "Error parsing method string\n");
366 return AVERROR_INVALIDDATA
;
369 if (linept
- line
> methodsize
- 1) {
370 av_log(s
, AV_LOG_ERROR
, "Method string too long\n");
373 memcpy(method
, line
, linept
- line
);
374 method
[linept
- line
] = '\0';
376 if (!strcmp(method
, "ANNOUNCE"))
377 *methodcode
= ANNOUNCE
;
378 else if (!strcmp(method
, "OPTIONS"))
379 *methodcode
= OPTIONS
;
380 else if (!strcmp(method
, "RECORD"))
381 *methodcode
= RECORD
;
382 else if (!strcmp(method
, "SETUP"))
384 else if (!strcmp(method
, "PAUSE"))
386 else if (!strcmp(method
, "TEARDOWN"))
387 *methodcode
= TEARDOWN
;
389 *methodcode
= UNKNOWN
;
390 /* Check method with the state */
391 if (rt
->state
== RTSP_STATE_IDLE
) {
392 if ((*methodcode
!= ANNOUNCE
) && (*methodcode
!= OPTIONS
)) {
393 av_log(s
, AV_LOG_ERROR
, "Unexpected command in Idle State %s\n",
395 return AVERROR_PROTOCOL_NOT_FOUND
;
397 } else if (rt
->state
== RTSP_STATE_PAUSED
) {
398 if ((*methodcode
!= OPTIONS
) && (*methodcode
!= RECORD
)
399 && (*methodcode
!= SETUP
)) {
400 av_log(s
, AV_LOG_ERROR
, "Unexpected command in Paused State %s\n",
402 return AVERROR_PROTOCOL_NOT_FOUND
;
404 } else if (rt
->state
== RTSP_STATE_STREAMING
) {
405 if ((*methodcode
!= PAUSE
) && (*methodcode
!= OPTIONS
)
406 && (*methodcode
!= TEARDOWN
)) {
407 av_log(s
, AV_LOG_ERROR
, "Unexpected command in Streaming State"
409 return AVERROR_PROTOCOL_NOT_FOUND
;
412 av_log(s
, AV_LOG_ERROR
, "Unexpected State [%d]\n", rt
->state
);
416 searchlinept
= strchr(linept
, ' ');
418 av_log(s
, AV_LOG_ERROR
, "Error parsing message URI\n");
419 return AVERROR_INVALIDDATA
;
421 if (searchlinept
- linept
> urisize
- 1) {
422 av_log(s
, AV_LOG_ERROR
, "uri string length exceeded buffer size\n");
425 memcpy(uri
, linept
, searchlinept
- linept
);
426 uri
[searchlinept
- linept
] = '\0';
427 if (strcmp(rt
->control_uri
, uri
)) {
428 char host
[128], path
[512], auth
[128];
430 char ctl_host
[128], ctl_path
[512], ctl_auth
[128];
432 av_url_split(NULL
, 0, auth
, sizeof(auth
), host
, sizeof(host
), &port
,
433 path
, sizeof(path
), uri
);
434 av_url_split(NULL
, 0, ctl_auth
, sizeof(ctl_auth
), ctl_host
,
435 sizeof(ctl_host
), &ctl_port
, ctl_path
, sizeof(ctl_path
),
437 if (strcmp(host
, ctl_host
))
438 av_log(s
, AV_LOG_INFO
, "Host %s differs from expected %s\n",
440 if (strcmp(path
, ctl_path
) && *methodcode
!= SETUP
)
441 av_log(s
, AV_LOG_WARNING
, "WARNING: Path %s differs from expected"
442 " %s\n", path
, ctl_path
);
443 if (*methodcode
== ANNOUNCE
) {
444 av_log(s
, AV_LOG_INFO
,
445 "Updating control URI to %s\n", uri
);
446 av_strlcpy(rt
->control_uri
, uri
, sizeof(rt
->control_uri
));
450 linept
= searchlinept
+ 1;
451 if (!av_strstart(linept
, "RTSP/1.0", NULL
)) {
452 av_log(s
, AV_LOG_ERROR
, "Error parsing protocol or version\n");
453 return AVERROR_PROTOCOL_NOT_FOUND
;
458 int ff_rtsp_parse_streaming_commands(AVFormatContext
*s
)
460 RTSPState
*rt
= s
->priv_data
;
461 unsigned char rbuf
[4096];
462 unsigned char method
[10];
466 RTSPMessageHeader request
= { 0 };
467 enum RTSPMethod methodcode
;
469 ret
= read_line(s
, rbuf
, sizeof(rbuf
), &rbuflen
);
472 ret
= parse_command_line(s
, rbuf
, rbuflen
, uri
, sizeof(uri
), method
,
473 sizeof(method
), &methodcode
);
475 av_log(s
, AV_LOG_ERROR
, "RTSP: Unexpected Command\n");
479 ret
= rtsp_read_request(s
, &request
, method
);
483 if (methodcode
== PAUSE
) {
484 rt
->state
= RTSP_STATE_PAUSED
;
485 ret
= rtsp_send_reply(s
, RTSP_STATUS_OK
, NULL
, request
.seq
);
486 // TODO: Missing date header in response
487 } else if (methodcode
== OPTIONS
) {
488 ret
= rtsp_send_reply(s
, RTSP_STATUS_OK
,
489 "Public: ANNOUNCE, PAUSE, SETUP, TEARDOWN, "
490 "RECORD\r\n", request
.seq
);
491 } else if (methodcode
== TEARDOWN
) {
492 rt
->state
= RTSP_STATE_IDLE
;
493 ret
= rtsp_send_reply(s
, RTSP_STATUS_OK
, NULL
, request
.seq
);
499 static int rtsp_read_play(AVFormatContext
*s
)
501 RTSPState
*rt
= s
->priv_data
;
502 RTSPMessageHeader reply1
, *reply
= &reply1
;
506 av_log(s
, AV_LOG_DEBUG
, "hello state=%d\n", rt
->state
);
509 if (!(rt
->server_type
== RTSP_SERVER_REAL
&& rt
->need_subscription
)) {
510 if (rt
->transport
== RTSP_TRANSPORT_RTP
) {
511 for (i
= 0; i
< rt
->nb_rtsp_streams
; i
++) {
512 RTSPStream
*rtsp_st
= rt
->rtsp_streams
[i
];
513 RTPDemuxContext
*rtpctx
= rtsp_st
->transport_priv
;
516 ff_rtp_reset_packet_queue(rtpctx
);
517 rtpctx
->last_rtcp_ntp_time
= AV_NOPTS_VALUE
;
518 rtpctx
->first_rtcp_ntp_time
= AV_NOPTS_VALUE
;
519 rtpctx
->base_timestamp
= 0;
520 rtpctx
->timestamp
= 0;
521 rtpctx
->unwrapped_timestamp
= 0;
522 rtpctx
->rtcp_ts_offset
= 0;
525 if (rt
->state
== RTSP_STATE_PAUSED
) {
528 snprintf(cmd
, sizeof(cmd
),
529 "Range: npt=%"PRId64
".%03"PRId64
"-\r\n",
530 rt
->seek_timestamp
/ AV_TIME_BASE
,
531 rt
->seek_timestamp
/ (AV_TIME_BASE
/ 1000) % 1000);
533 ff_rtsp_send_cmd(s
, "PLAY", rt
->control_uri
, cmd
, reply
, NULL
);
534 if (reply
->status_code
!= RTSP_STATUS_OK
) {
535 return ff_rtsp_averror(reply
->status_code
, -1);
537 if (rt
->transport
== RTSP_TRANSPORT_RTP
&&
538 reply
->range_start
!= AV_NOPTS_VALUE
) {
539 for (i
= 0; i
< rt
->nb_rtsp_streams
; i
++) {
540 RTSPStream
*rtsp_st
= rt
->rtsp_streams
[i
];
541 RTPDemuxContext
*rtpctx
= rtsp_st
->transport_priv
;
543 if (!rtpctx
|| rtsp_st
->stream_index
< 0)
545 st
= s
->streams
[rtsp_st
->stream_index
];
546 rtpctx
->range_start_offset
=
547 av_rescale_q(reply
->range_start
, AV_TIME_BASE_Q
,
552 rt
->state
= RTSP_STATE_STREAMING
;
556 /* pause the stream */
557 static int rtsp_read_pause(AVFormatContext
*s
)
559 RTSPState
*rt
= s
->priv_data
;
560 RTSPMessageHeader reply1
, *reply
= &reply1
;
562 if (rt
->state
!= RTSP_STATE_STREAMING
)
564 else if (!(rt
->server_type
== RTSP_SERVER_REAL
&& rt
->need_subscription
)) {
565 ff_rtsp_send_cmd(s
, "PAUSE", rt
->control_uri
, NULL
, reply
, NULL
);
566 if (reply
->status_code
!= RTSP_STATUS_OK
) {
567 return ff_rtsp_averror(reply
->status_code
, -1);
570 rt
->state
= RTSP_STATE_PAUSED
;
574 int ff_rtsp_setup_input_streams(AVFormatContext
*s
, RTSPMessageHeader
*reply
)
576 RTSPState
*rt
= s
->priv_data
;
578 unsigned char *content
= NULL
;
581 /* describe the stream */
582 snprintf(cmd
, sizeof(cmd
),
583 "Accept: application/sdp\r\n");
584 if (rt
->server_type
== RTSP_SERVER_REAL
) {
586 * The Require: attribute is needed for proper streaming from
590 "Require: com.real.retain-entity-for-setup\r\n",
593 ff_rtsp_send_cmd(s
, "DESCRIBE", rt
->control_uri
, cmd
, reply
, &content
);
594 if (reply
->status_code
!= RTSP_STATUS_OK
) {
596 return ff_rtsp_averror(reply
->status_code
, AVERROR_INVALIDDATA
);
599 return AVERROR_INVALIDDATA
;
601 av_log(s
, AV_LOG_VERBOSE
, "SDP:\n%s\n", content
);
602 /* now we got the SDP description, we parse it */
603 ret
= ff_sdp_parse(s
, (const char *)content
);
611 static int rtsp_listen(AVFormatContext
*s
)
613 RTSPState
*rt
= s
->priv_data
;
614 char proto
[128], host
[128], path
[512], auth
[128];
617 int default_port
= RTSP_DEFAULT_PORT
;
619 const char *lower_proto
= "tcp";
620 unsigned char rbuf
[4096];
621 unsigned char method
[10];
624 enum RTSPMethod methodcode
;
626 /* extract hostname and port */
627 av_url_split(proto
, sizeof(proto
), auth
, sizeof(auth
), host
, sizeof(host
),
628 &port
, path
, sizeof(path
), s
->filename
);
630 /* ff_url_join. No authorization by now (NULL) */
631 ff_url_join(rt
->control_uri
, sizeof(rt
->control_uri
), proto
, NULL
, host
,
634 if (!strcmp(proto
, "rtsps")) {
636 default_port
= RTSPS_DEFAULT_PORT
;
642 /* Create TCP connection */
643 ff_url_join(tcpname
, sizeof(tcpname
), lower_proto
, NULL
, host
, port
,
644 "?listen&listen_timeout=%d", rt
->initial_timeout
* 1000);
646 if (ret
= ffurl_open(&rt
->rtsp_hd
, tcpname
, AVIO_FLAG_READ_WRITE
,
647 &s
->interrupt_callback
, NULL
)) {
648 av_log(s
, AV_LOG_ERROR
, "Unable to open RTSP for listening\n");
651 rt
->state
= RTSP_STATE_IDLE
;
652 rt
->rtsp_hd_out
= rt
->rtsp_hd
;
653 for (;;) { /* Wait for incoming RTSP messages */
654 ret
= read_line(s
, rbuf
, sizeof(rbuf
), &rbuflen
);
657 ret
= parse_command_line(s
, rbuf
, rbuflen
, uri
, sizeof(uri
), method
,
658 sizeof(method
), &methodcode
);
660 av_log(s
, AV_LOG_ERROR
, "RTSP: Unexpected Command\n");
664 if (methodcode
== ANNOUNCE
) {
665 ret
= rtsp_read_announce(s
);
666 rt
->state
= RTSP_STATE_PAUSED
;
667 } else if (methodcode
== OPTIONS
) {
668 ret
= rtsp_read_options(s
);
669 } else if (methodcode
== RECORD
) {
670 ret
= rtsp_read_record(s
);
672 return 0; // We are ready for streaming
673 } else if (methodcode
== SETUP
)
674 ret
= rtsp_read_setup(s
, host
, uri
);
676 ffurl_close(rt
->rtsp_hd
);
677 return AVERROR_INVALIDDATA
;
683 static int rtsp_probe(AVProbeData
*p
)
686 #if CONFIG_TLS_PROTOCOL
687 av_strstart(p
->filename
, "rtsps:", NULL
) ||
689 av_strstart(p
->filename
, "rtsp:", NULL
))
690 return AVPROBE_SCORE_MAX
;
694 static int rtsp_read_header(AVFormatContext
*s
)
696 RTSPState
*rt
= s
->priv_data
;
699 if (rt
->initial_timeout
> 0)
700 rt
->rtsp_flags
|= RTSP_FLAG_LISTEN
;
702 if (rt
->rtsp_flags
& RTSP_FLAG_LISTEN
) {
703 ret
= rtsp_listen(s
);
707 ret
= ff_rtsp_connect(s
);
711 rt
->real_setup_cache
= !s
->nb_streams
? NULL
:
712 av_mallocz_array(s
->nb_streams
, 2 * sizeof(*rt
->real_setup_cache
));
713 if (!rt
->real_setup_cache
&& s
->nb_streams
)
714 return AVERROR(ENOMEM
);
715 rt
->real_setup
= rt
->real_setup_cache
+ s
->nb_streams
;
717 if (rt
->initial_pause
) {
718 /* do not start immediately */
720 if ((ret
= rtsp_read_play(s
)) < 0) {
721 ff_rtsp_close_streams(s
);
722 ff_rtsp_close_connections(s
);
731 int ff_rtsp_tcp_read_packet(AVFormatContext
*s
, RTSPStream
**prtsp_st
,
732 uint8_t *buf
, int buf_size
)
734 RTSPState
*rt
= s
->priv_data
;
738 av_dlog(s
, "tcp_read_packet:\n");
741 RTSPMessageHeader reply
;
743 ret
= ff_rtsp_read_reply(s
, &reply
, NULL
, 1, NULL
);
746 if (ret
== 1) /* received '$' */
748 /* XXX: parse message */
749 if (rt
->state
!= RTSP_STATE_STREAMING
)
752 ret
= ffurl_read_complete(rt
->rtsp_hd
, buf
, 3);
756 len
= AV_RB16(buf
+ 1);
757 av_dlog(s
, "id=%d len=%d\n", id
, len
);
758 if (len
> buf_size
|| len
< 8)
761 ret
= ffurl_read_complete(rt
->rtsp_hd
, buf
, len
);
764 if (rt
->transport
== RTSP_TRANSPORT_RDT
&&
765 ff_rdt_parse_header(buf
, len
, &id
, NULL
, NULL
, NULL
, NULL
) < 0)
768 /* find the matching stream */
769 for (i
= 0; i
< rt
->nb_rtsp_streams
; i
++) {
770 rtsp_st
= rt
->rtsp_streams
[i
];
771 if (id
>= rtsp_st
->interleaved_min
&&
772 id
<= rtsp_st
->interleaved_max
)
781 static int resetup_tcp(AVFormatContext
*s
)
783 RTSPState
*rt
= s
->priv_data
;
787 av_url_split(NULL
, 0, NULL
, 0, host
, sizeof(host
), &port
, NULL
, 0,
789 ff_rtsp_undo_setup(s
, 0);
790 return ff_rtsp_make_setup_request(s
, host
, port
, RTSP_LOWER_TRANSPORT_TCP
,
794 static int rtsp_read_packet(AVFormatContext
*s
, AVPacket
*pkt
)
796 RTSPState
*rt
= s
->priv_data
;
798 RTSPMessageHeader reply1
, *reply
= &reply1
;
802 if (rt
->server_type
== RTSP_SERVER_REAL
) {
805 for (i
= 0; i
< s
->nb_streams
; i
++)
806 rt
->real_setup
[i
] = s
->streams
[i
]->discard
;
808 if (!rt
->need_subscription
) {
809 if (memcmp (rt
->real_setup
, rt
->real_setup_cache
,
810 sizeof(enum AVDiscard
) * s
->nb_streams
)) {
811 snprintf(cmd
, sizeof(cmd
),
812 "Unsubscribe: %s\r\n",
813 rt
->last_subscription
);
814 ff_rtsp_send_cmd(s
, "SET_PARAMETER", rt
->control_uri
,
816 if (reply
->status_code
!= RTSP_STATUS_OK
)
817 return ff_rtsp_averror(reply
->status_code
, AVERROR_INVALIDDATA
);
818 rt
->need_subscription
= 1;
822 if (rt
->need_subscription
) {
823 int r
, rule_nr
, first
= 1;
825 memcpy(rt
->real_setup_cache
, rt
->real_setup
,
826 sizeof(enum AVDiscard
) * s
->nb_streams
);
827 rt
->last_subscription
[0] = 0;
829 snprintf(cmd
, sizeof(cmd
),
831 for (i
= 0; i
< rt
->nb_rtsp_streams
; i
++) {
833 for (r
= 0; r
< s
->nb_streams
; r
++) {
834 if (s
->streams
[r
]->id
== i
) {
835 if (s
->streams
[r
]->discard
!= AVDISCARD_ALL
) {
837 av_strlcat(rt
->last_subscription
, ",",
838 sizeof(rt
->last_subscription
));
839 ff_rdt_subscribe_rule(
840 rt
->last_subscription
,
841 sizeof(rt
->last_subscription
), i
, rule_nr
);
848 av_strlcatf(cmd
, sizeof(cmd
), "%s\r\n", rt
->last_subscription
);
849 ff_rtsp_send_cmd(s
, "SET_PARAMETER", rt
->control_uri
,
851 if (reply
->status_code
!= RTSP_STATUS_OK
)
852 return ff_rtsp_averror(reply
->status_code
, AVERROR_INVALIDDATA
);
853 rt
->need_subscription
= 0;
855 if (rt
->state
== RTSP_STATE_STREAMING
)
860 ret
= ff_rtsp_fetch_packet(s
, pkt
);
862 if (ret
== AVERROR(ETIMEDOUT
) && !rt
->packets
) {
863 if (rt
->lower_transport
== RTSP_LOWER_TRANSPORT_UDP
&&
864 rt
->lower_transport_mask
& (1 << RTSP_LOWER_TRANSPORT_TCP
)) {
865 RTSPMessageHeader reply1
, *reply
= &reply1
;
866 av_log(s
, AV_LOG_WARNING
, "UDP timeout, retrying with TCP\n");
867 if (rtsp_read_pause(s
) != 0)
869 // TEARDOWN is required on Real-RTSP, but might make
870 // other servers close the connection.
871 if (rt
->server_type
== RTSP_SERVER_REAL
)
872 ff_rtsp_send_cmd(s
, "TEARDOWN", rt
->control_uri
, NULL
,
874 rt
->session_id
[0] = '\0';
875 if (resetup_tcp(s
) == 0) {
876 rt
->state
= RTSP_STATE_IDLE
;
877 rt
->need_subscription
= 1;
878 if (rtsp_read_play(s
) != 0)
888 if (!(rt
->rtsp_flags
& RTSP_FLAG_LISTEN
)) {
889 /* send dummy request to keep TCP connection alive */
890 if ((av_gettime_relative() - rt
->last_cmd_time
) / 1000000 >= rt
->timeout
/ 2 ||
891 rt
->auth_state
.stale
) {
892 if (rt
->server_type
== RTSP_SERVER_WMS
||
893 (rt
->server_type
!= RTSP_SERVER_REAL
&&
894 rt
->get_parameter_supported
)) {
895 ff_rtsp_send_cmd_async(s
, "GET_PARAMETER", rt
->control_uri
, NULL
);
897 ff_rtsp_send_cmd_async(s
, "OPTIONS", rt
->control_uri
, NULL
);
899 /* The stale flag should be reset when creating the auth response in
900 * ff_rtsp_send_cmd_async, but reset it here just in case we never
901 * called the auth code (if we didn't have any credentials set). */
902 rt
->auth_state
.stale
= 0;
909 static int rtsp_read_seek(AVFormatContext
*s
, int stream_index
,
910 int64_t timestamp
, int flags
)
912 RTSPState
*rt
= s
->priv_data
;
915 rt
->seek_timestamp
= av_rescale_q(timestamp
,
916 s
->streams
[stream_index
]->time_base
,
920 case RTSP_STATE_IDLE
:
922 case RTSP_STATE_STREAMING
:
923 if ((ret
= rtsp_read_pause(s
)) != 0)
925 rt
->state
= RTSP_STATE_SEEKING
;
926 if ((ret
= rtsp_read_play(s
)) != 0)
929 case RTSP_STATE_PAUSED
:
930 rt
->state
= RTSP_STATE_IDLE
;
936 static const AVClass rtsp_demuxer_class
= {
937 .class_name
= "RTSP demuxer",
938 .item_name
= av_default_item_name
,
939 .option
= ff_rtsp_options
,
940 .version
= LIBAVUTIL_VERSION_INT
,
943 AVInputFormat ff_rtsp_demuxer
= {
945 .long_name
= NULL_IF_CONFIG_SMALL("RTSP input"),
946 .priv_data_size
= sizeof(RTSPState
),
947 .read_probe
= rtsp_probe
,
948 .read_header
= rtsp_read_header
,
949 .read_packet
= rtsp_read_packet
,
950 .read_close
= rtsp_read_close
,
951 .read_seek
= rtsp_read_seek
,
952 .flags
= AVFMT_NOFILE
,
953 .read_play
= rtsp_read_play
,
954 .read_pause
= rtsp_read_pause
,
955 .priv_class
= &rtsp_demuxer_class
,