3 * Copyright (c) 2002 Fabrice Bellard
5 * This file is part of Libav.
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.
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.
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
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_out
, 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 AVDictionary
*opts
= NULL
;
292 snprintf(buf
, sizeof(buf
), "%d", rt
->buffer_size
);
293 av_dict_set(&opts
, "buffer_size", buf
, 0);
294 ff_url_join(url
, sizeof(url
), "rtp", NULL
, host
, localport
, NULL
);
295 av_dlog(s
, "Opening: %s", url
);
296 ret
= ffurl_open(&rtsp_st
->rtp_handle
, url
, AVIO_FLAG_READ_WRITE
,
297 &s
->interrupt_callback
, &opts
);
301 } while (ret
|| localport
> rt
->rtp_port_max
);
302 if (localport
> rt
->rtp_port_max
) {
303 rtsp_send_reply(s
, RTSP_STATUS_TRANSPORT
, NULL
, request
.seq
);
307 av_dlog(s
, "Listening on: %d",
308 ff_rtp_get_local_rtp_port(rtsp_st
->rtp_handle
));
309 if ((ret
= ff_rtsp_open_transport_ctx(s
, rtsp_st
))) {
310 rtsp_send_reply(s
, RTSP_STATUS_TRANSPORT
, NULL
, request
.seq
);
314 localport
= ff_rtp_get_local_rtp_port(rtsp_st
->rtp_handle
);
315 snprintf(responseheaders
, sizeof(responseheaders
), "Transport: "
316 "RTP/AVP/UDP;unicast;mode=receive;source=%s;"
317 "client_port=%d-%d;server_port=%d-%d\r\n",
318 host
, request
.transports
[0].client_port_min
,
319 request
.transports
[0].client_port_max
, localport
,
323 /* Establish sessionid if not previously set */
324 /* Put this in a function? */
325 /* RFC 2326: session id must be at least 8 digits */
326 while (strlen(rt
->session_id
) < 8)
327 av_strlcatf(rt
->session_id
, 512, "%u", av_get_random_seed());
329 av_strlcatf(responseheaders
, sizeof(responseheaders
), "Session: %s\r\n",
332 rtsp_send_reply(s
, RTSP_STATUS_OK
, responseheaders
, request
.seq
);
334 rt
->state
= RTSP_STATE_PAUSED
;
338 static int rtsp_read_record(AVFormatContext
*s
)
340 RTSPState
*rt
= s
->priv_data
;
341 RTSPMessageHeader request
= { 0 };
343 char responseheaders
[1024];
345 ret
= rtsp_read_request(s
, &request
, "RECORD");
348 ret
= check_sessionid(s
, &request
);
352 snprintf(responseheaders
, sizeof(responseheaders
), "Session: %s\r\n",
354 rtsp_send_reply(s
, RTSP_STATUS_OK
, responseheaders
, request
.seq
);
356 rt
->state
= RTSP_STATE_STREAMING
;
360 static inline int parse_command_line(AVFormatContext
*s
, const char *line
,
361 int linelen
, char *uri
, int urisize
,
362 char *method
, int methodsize
,
363 enum RTSPMethod
*methodcode
)
365 RTSPState
*rt
= s
->priv_data
;
366 const char *linept
, *searchlinept
;
367 linept
= strchr(line
, ' ');
370 return AVERROR_INVALIDDATA
;
372 if (linept
- line
> methodsize
- 1) {
373 av_log(s
, AV_LOG_ERROR
, "Method string too long\n");
376 memcpy(method
, line
, linept
- line
);
377 method
[linept
- line
] = '\0';
379 if (!strcmp(method
, "ANNOUNCE"))
380 *methodcode
= ANNOUNCE
;
381 else if (!strcmp(method
, "OPTIONS"))
382 *methodcode
= OPTIONS
;
383 else if (!strcmp(method
, "RECORD"))
384 *methodcode
= RECORD
;
385 else if (!strcmp(method
, "SETUP"))
387 else if (!strcmp(method
, "PAUSE"))
389 else if (!strcmp(method
, "TEARDOWN"))
390 *methodcode
= TEARDOWN
;
392 *methodcode
= UNKNOWN
;
393 /* Check method with the state */
394 if (rt
->state
== RTSP_STATE_IDLE
) {
395 if ((*methodcode
!= ANNOUNCE
) && (*methodcode
!= OPTIONS
)) {
396 av_log(s
, AV_LOG_ERROR
, "Unexpected command in Idle State %s\n",
398 return AVERROR_PROTOCOL_NOT_FOUND
;
400 } else if (rt
->state
== RTSP_STATE_PAUSED
) {
401 if ((*methodcode
!= OPTIONS
) && (*methodcode
!= RECORD
)
402 && (*methodcode
!= SETUP
)) {
403 av_log(s
, AV_LOG_ERROR
, "Unexpected command in Paused State %s\n",
405 return AVERROR_PROTOCOL_NOT_FOUND
;
407 } else if (rt
->state
== RTSP_STATE_STREAMING
) {
408 if ((*methodcode
!= PAUSE
) && (*methodcode
!= OPTIONS
)
409 && (*methodcode
!= TEARDOWN
)) {
410 av_log(s
, AV_LOG_ERROR
, "Unexpected command in Streaming State"
412 return AVERROR_PROTOCOL_NOT_FOUND
;
415 av_log(s
, AV_LOG_ERROR
, "Unexpected State [%d]\n", rt
->state
);
419 searchlinept
= strchr(linept
, ' ');
421 av_log(s
, AV_LOG_ERROR
, "Error parsing message URI\n");
422 return AVERROR_INVALIDDATA
;
424 if (searchlinept
- linept
> urisize
- 1) {
425 av_log(s
, AV_LOG_ERROR
, "uri string length exceeded buffer size\n");
428 memcpy(uri
, linept
, searchlinept
- linept
);
429 uri
[searchlinept
- linept
] = '\0';
430 if (strcmp(rt
->control_uri
, uri
)) {
431 char host
[128], path
[512], auth
[128];
433 char ctl_host
[128], ctl_path
[512], ctl_auth
[128];
435 av_url_split(NULL
, 0, auth
, sizeof(auth
), host
, sizeof(host
), &port
,
436 path
, sizeof(path
), uri
);
437 av_url_split(NULL
, 0, ctl_auth
, sizeof(ctl_auth
), ctl_host
,
438 sizeof(ctl_host
), &ctl_port
, ctl_path
, sizeof(ctl_path
),
440 if (strcmp(host
, ctl_host
))
441 av_log(s
, AV_LOG_INFO
, "Host %s differs from expected %s\n",
443 if (strcmp(path
, ctl_path
) && *methodcode
!= SETUP
)
444 av_log(s
, AV_LOG_WARNING
, "WARNING: Path %s differs from expected"
445 " %s\n", path
, ctl_path
);
446 if (*methodcode
== ANNOUNCE
) {
447 av_log(s
, AV_LOG_INFO
,
448 "Updating control URI to %s\n", uri
);
449 av_strlcpy(rt
->control_uri
, uri
, sizeof(rt
->control_uri
));
453 linept
= searchlinept
+ 1;
454 if (!av_strstart(linept
, "RTSP/1.0", NULL
)) {
455 av_log(s
, AV_LOG_ERROR
, "Error parsing protocol or version\n");
456 return AVERROR_PROTOCOL_NOT_FOUND
;
461 int ff_rtsp_parse_streaming_commands(AVFormatContext
*s
)
463 RTSPState
*rt
= s
->priv_data
;
464 unsigned char rbuf
[4096];
465 unsigned char method
[10];
469 RTSPMessageHeader request
= { 0 };
470 enum RTSPMethod methodcode
;
472 ret
= read_line(s
, rbuf
, sizeof(rbuf
), &rbuflen
);
475 ret
= parse_command_line(s
, rbuf
, rbuflen
, uri
, sizeof(uri
), method
,
476 sizeof(method
), &methodcode
);
478 av_log(s
, AV_LOG_ERROR
, "RTSP: Unexpected Command\n");
482 ret
= rtsp_read_request(s
, &request
, method
);
486 if (methodcode
== PAUSE
) {
487 rt
->state
= RTSP_STATE_PAUSED
;
488 ret
= rtsp_send_reply(s
, RTSP_STATUS_OK
, NULL
, request
.seq
);
489 // TODO: Missing date header in response
490 } else if (methodcode
== OPTIONS
) {
491 ret
= rtsp_send_reply(s
, RTSP_STATUS_OK
,
492 "Public: ANNOUNCE, PAUSE, SETUP, TEARDOWN, "
493 "RECORD\r\n", request
.seq
);
494 } else if (methodcode
== TEARDOWN
) {
495 rt
->state
= RTSP_STATE_IDLE
;
496 ret
= rtsp_send_reply(s
, RTSP_STATUS_OK
, NULL
, request
.seq
);
502 static int rtsp_read_play(AVFormatContext
*s
)
504 RTSPState
*rt
= s
->priv_data
;
505 RTSPMessageHeader reply1
, *reply
= &reply1
;
509 av_log(s
, AV_LOG_DEBUG
, "hello state=%d\n", rt
->state
);
512 if (rt
->lower_transport
== RTSP_LOWER_TRANSPORT_UDP
) {
513 for (i
= 0; i
< rt
->nb_rtsp_streams
; i
++) {
514 RTSPStream
*rtsp_st
= rt
->rtsp_streams
[i
];
515 /* Try to initialize the connection state in a
516 * potential NAT router by sending dummy packets.
517 * RTP/RTCP dummy packets are used for RDT, too.
519 if (rtsp_st
->rtp_handle
&&
520 !(rt
->server_type
== RTSP_SERVER_WMS
&& i
> 1))
521 ff_rtp_send_punch_packets(rtsp_st
->rtp_handle
);
524 if (!(rt
->server_type
== RTSP_SERVER_REAL
&& rt
->need_subscription
)) {
525 if (rt
->transport
== RTSP_TRANSPORT_RTP
) {
526 for (i
= 0; i
< rt
->nb_rtsp_streams
; i
++) {
527 RTSPStream
*rtsp_st
= rt
->rtsp_streams
[i
];
528 RTPDemuxContext
*rtpctx
= rtsp_st
->transport_priv
;
531 ff_rtp_reset_packet_queue(rtpctx
);
532 rtpctx
->last_rtcp_ntp_time
= AV_NOPTS_VALUE
;
533 rtpctx
->first_rtcp_ntp_time
= AV_NOPTS_VALUE
;
534 rtpctx
->base_timestamp
= 0;
535 rtpctx
->timestamp
= 0;
536 rtpctx
->unwrapped_timestamp
= 0;
537 rtpctx
->rtcp_ts_offset
= 0;
540 if (rt
->state
== RTSP_STATE_PAUSED
) {
543 snprintf(cmd
, sizeof(cmd
),
544 "Range: npt=%"PRId64
".%03"PRId64
"-\r\n",
545 rt
->seek_timestamp
/ AV_TIME_BASE
,
546 rt
->seek_timestamp
/ (AV_TIME_BASE
/ 1000) % 1000);
548 ff_rtsp_send_cmd(s
, "PLAY", rt
->control_uri
, cmd
, reply
, NULL
);
549 if (reply
->status_code
!= RTSP_STATUS_OK
) {
552 if (rt
->transport
== RTSP_TRANSPORT_RTP
&&
553 reply
->range_start
!= AV_NOPTS_VALUE
) {
554 for (i
= 0; i
< rt
->nb_rtsp_streams
; i
++) {
555 RTSPStream
*rtsp_st
= rt
->rtsp_streams
[i
];
556 RTPDemuxContext
*rtpctx
= rtsp_st
->transport_priv
;
558 if (!rtpctx
|| rtsp_st
->stream_index
< 0)
560 st
= s
->streams
[rtsp_st
->stream_index
];
561 rtpctx
->range_start_offset
=
562 av_rescale_q(reply
->range_start
, AV_TIME_BASE_Q
,
567 rt
->state
= RTSP_STATE_STREAMING
;
571 /* pause the stream */
572 static int rtsp_read_pause(AVFormatContext
*s
)
574 RTSPState
*rt
= s
->priv_data
;
575 RTSPMessageHeader reply1
, *reply
= &reply1
;
577 if (rt
->state
!= RTSP_STATE_STREAMING
)
579 else if (!(rt
->server_type
== RTSP_SERVER_REAL
&& rt
->need_subscription
)) {
580 ff_rtsp_send_cmd(s
, "PAUSE", rt
->control_uri
, NULL
, reply
, NULL
);
581 if (reply
->status_code
!= RTSP_STATUS_OK
) {
585 rt
->state
= RTSP_STATE_PAUSED
;
589 int ff_rtsp_setup_input_streams(AVFormatContext
*s
, RTSPMessageHeader
*reply
)
591 RTSPState
*rt
= s
->priv_data
;
593 unsigned char *content
= NULL
;
596 /* describe the stream */
597 snprintf(cmd
, sizeof(cmd
),
598 "Accept: application/sdp\r\n");
599 if (rt
->server_type
== RTSP_SERVER_REAL
) {
601 * The Require: attribute is needed for proper streaming from
605 "Require: com.real.retain-entity-for-setup\r\n",
608 ff_rtsp_send_cmd(s
, "DESCRIBE", rt
->control_uri
, cmd
, reply
, &content
);
610 return AVERROR_INVALIDDATA
;
611 if (reply
->status_code
!= RTSP_STATUS_OK
) {
613 return AVERROR_INVALIDDATA
;
616 av_log(s
, AV_LOG_VERBOSE
, "SDP:\n%s\n", content
);
617 /* now we got the SDP description, we parse it */
618 ret
= ff_sdp_parse(s
, (const char *)content
);
626 static int rtsp_listen(AVFormatContext
*s
)
628 RTSPState
*rt
= s
->priv_data
;
629 char proto
[128], host
[128], path
[512], auth
[128];
632 int default_port
= RTSP_DEFAULT_PORT
;
634 const char *lower_proto
= "tcp";
635 unsigned char rbuf
[4096];
636 unsigned char method
[10];
639 enum RTSPMethod methodcode
;
641 /* extract hostname and port */
642 av_url_split(proto
, sizeof(proto
), auth
, sizeof(auth
), host
, sizeof(host
),
643 &port
, path
, sizeof(path
), s
->filename
);
645 /* ff_url_join. No authorization by now (NULL) */
646 ff_url_join(rt
->control_uri
, sizeof(rt
->control_uri
), proto
, NULL
, host
,
649 if (!strcmp(proto
, "rtsps")) {
651 default_port
= RTSPS_DEFAULT_PORT
;
657 /* Create TCP connection */
658 ff_url_join(tcpname
, sizeof(tcpname
), lower_proto
, NULL
, host
, port
,
659 "?listen&listen_timeout=%d", rt
->initial_timeout
* 1000);
661 if (ret
= ffurl_open(&rt
->rtsp_hd
, tcpname
, AVIO_FLAG_READ_WRITE
,
662 &s
->interrupt_callback
, NULL
)) {
663 av_log(s
, AV_LOG_ERROR
, "Unable to open RTSP for listening\n");
666 rt
->state
= RTSP_STATE_IDLE
;
667 rt
->rtsp_hd_out
= rt
->rtsp_hd
;
668 for (;;) { /* Wait for incoming RTSP messages */
669 ret
= read_line(s
, rbuf
, sizeof(rbuf
), &rbuflen
);
672 ret
= parse_command_line(s
, rbuf
, rbuflen
, uri
, sizeof(uri
), method
,
673 sizeof(method
), &methodcode
);
675 av_log(s
, AV_LOG_ERROR
, "RTSP: Unexpected Command\n");
679 if (methodcode
== ANNOUNCE
) {
680 ret
= rtsp_read_announce(s
);
681 rt
->state
= RTSP_STATE_PAUSED
;
682 } else if (methodcode
== OPTIONS
) {
683 ret
= rtsp_read_options(s
);
684 } else if (methodcode
== RECORD
) {
685 ret
= rtsp_read_record(s
);
687 return 0; // We are ready for streaming
688 } else if (methodcode
== SETUP
)
689 ret
= rtsp_read_setup(s
, host
, uri
);
691 ffurl_close(rt
->rtsp_hd
);
692 return AVERROR_INVALIDDATA
;
698 static int rtsp_probe(AVProbeData
*p
)
701 #if CONFIG_TLS_PROTOCOL
702 av_strstart(p
->filename
, "rtsps:", NULL
) ||
704 av_strstart(p
->filename
, "rtsp:", NULL
))
705 return AVPROBE_SCORE_MAX
;
709 static int rtsp_read_header(AVFormatContext
*s
)
711 RTSPState
*rt
= s
->priv_data
;
714 if (rt
->initial_timeout
> 0)
715 rt
->rtsp_flags
|= RTSP_FLAG_LISTEN
;
717 if (rt
->rtsp_flags
& RTSP_FLAG_LISTEN
) {
718 ret
= rtsp_listen(s
);
722 ret
= ff_rtsp_connect(s
);
726 rt
->real_setup_cache
= !s
->nb_streams ? NULL
:
727 av_mallocz(2 * s
->nb_streams
* sizeof(*rt
->real_setup_cache
));
728 if (!rt
->real_setup_cache
&& s
->nb_streams
)
729 return AVERROR(ENOMEM
);
730 rt
->real_setup
= rt
->real_setup_cache
+ s
->nb_streams
;
732 if (rt
->initial_pause
) {
733 /* do not start immediately */
735 if (rtsp_read_play(s
) < 0) {
736 ff_rtsp_close_streams(s
);
737 ff_rtsp_close_connections(s
);
738 return AVERROR_INVALIDDATA
;
746 int ff_rtsp_tcp_read_packet(AVFormatContext
*s
, RTSPStream
**prtsp_st
,
747 uint8_t *buf
, int buf_size
)
749 RTSPState
*rt
= s
->priv_data
;
753 av_dlog(s
, "tcp_read_packet:\n");
756 RTSPMessageHeader reply
;
758 ret
= ff_rtsp_read_reply(s
, &reply
, NULL
, 1, NULL
);
761 if (ret
== 1) /* received '$' */
763 /* XXX: parse message */
764 if (rt
->state
!= RTSP_STATE_STREAMING
)
767 ret
= ffurl_read_complete(rt
->rtsp_hd
, buf
, 3);
771 len
= AV_RB16(buf
+ 1);
772 av_dlog(s
, "id=%d len=%d\n", id
, len
);
773 if (len
> buf_size
|| len
< 12)
776 ret
= ffurl_read_complete(rt
->rtsp_hd
, buf
, len
);
779 if (rt
->transport
== RTSP_TRANSPORT_RDT
&&
780 ff_rdt_parse_header(buf
, len
, &id
, NULL
, NULL
, NULL
, NULL
) < 0)
783 /* find the matching stream */
784 for (i
= 0; i
< rt
->nb_rtsp_streams
; i
++) {
785 rtsp_st
= rt
->rtsp_streams
[i
];
786 if (id
>= rtsp_st
->interleaved_min
&&
787 id
<= rtsp_st
->interleaved_max
)
796 static int resetup_tcp(AVFormatContext
*s
)
798 RTSPState
*rt
= s
->priv_data
;
802 av_url_split(NULL
, 0, NULL
, 0, host
, sizeof(host
), &port
, NULL
, 0,
804 ff_rtsp_undo_setup(s
, 0);
805 return ff_rtsp_make_setup_request(s
, host
, port
, RTSP_LOWER_TRANSPORT_TCP
,
809 static int rtsp_read_packet(AVFormatContext
*s
, AVPacket
*pkt
)
811 RTSPState
*rt
= s
->priv_data
;
813 RTSPMessageHeader reply1
, *reply
= &reply1
;
817 if (rt
->server_type
== RTSP_SERVER_REAL
) {
820 for (i
= 0; i
< s
->nb_streams
; i
++)
821 rt
->real_setup
[i
] = s
->streams
[i
]->discard
;
823 if (!rt
->need_subscription
) {
824 if (memcmp (rt
->real_setup
, rt
->real_setup_cache
,
825 sizeof(enum AVDiscard
) * s
->nb_streams
)) {
826 snprintf(cmd
, sizeof(cmd
),
827 "Unsubscribe: %s\r\n",
828 rt
->last_subscription
);
829 ff_rtsp_send_cmd(s
, "SET_PARAMETER", rt
->control_uri
,
831 if (reply
->status_code
!= RTSP_STATUS_OK
)
832 return AVERROR_INVALIDDATA
;
833 rt
->need_subscription
= 1;
837 if (rt
->need_subscription
) {
838 int r
, rule_nr
, first
= 1;
840 memcpy(rt
->real_setup_cache
, rt
->real_setup
,
841 sizeof(enum AVDiscard
) * s
->nb_streams
);
842 rt
->last_subscription
[0] = 0;
844 snprintf(cmd
, sizeof(cmd
),
846 for (i
= 0; i
< rt
->nb_rtsp_streams
; i
++) {
848 for (r
= 0; r
< s
->nb_streams
; r
++) {
849 if (s
->streams
[r
]->id
== i
) {
850 if (s
->streams
[r
]->discard
!= AVDISCARD_ALL
) {
852 av_strlcat(rt
->last_subscription
, ",",
853 sizeof(rt
->last_subscription
));
854 ff_rdt_subscribe_rule(
855 rt
->last_subscription
,
856 sizeof(rt
->last_subscription
), i
, rule_nr
);
863 av_strlcatf(cmd
, sizeof(cmd
), "%s\r\n", rt
->last_subscription
);
864 ff_rtsp_send_cmd(s
, "SET_PARAMETER", rt
->control_uri
,
866 if (reply
->status_code
!= RTSP_STATUS_OK
)
867 return AVERROR_INVALIDDATA
;
868 rt
->need_subscription
= 0;
870 if (rt
->state
== RTSP_STATE_STREAMING
)
875 ret
= ff_rtsp_fetch_packet(s
, pkt
);
877 if (ret
== AVERROR(ETIMEDOUT
) && !rt
->packets
) {
878 if (rt
->lower_transport
== RTSP_LOWER_TRANSPORT_UDP
&&
879 rt
->lower_transport_mask
& (1 << RTSP_LOWER_TRANSPORT_TCP
)) {
880 RTSPMessageHeader reply1
, *reply
= &reply1
;
881 av_log(s
, AV_LOG_WARNING
, "UDP timeout, retrying with TCP\n");
882 if (rtsp_read_pause(s
) != 0)
884 // TEARDOWN is required on Real-RTSP, but might make
885 // other servers close the connection.
886 if (rt
->server_type
== RTSP_SERVER_REAL
)
887 ff_rtsp_send_cmd(s
, "TEARDOWN", rt
->control_uri
, NULL
,
889 rt
->session_id
[0] = '\0';
890 if (resetup_tcp(s
) == 0) {
891 rt
->state
= RTSP_STATE_IDLE
;
892 rt
->need_subscription
= 1;
893 if (rtsp_read_play(s
) != 0)
903 if (!(rt
->rtsp_flags
& RTSP_FLAG_LISTEN
)) {
904 /* send dummy request to keep TCP connection alive */
905 if ((av_gettime_relative() - rt
->last_cmd_time
) / 1000000 >= rt
->timeout
/ 2 ||
906 rt
->auth_state
.stale
) {
907 if (rt
->server_type
== RTSP_SERVER_WMS
||
908 (rt
->server_type
!= RTSP_SERVER_REAL
&&
909 rt
->get_parameter_supported
)) {
910 ff_rtsp_send_cmd_async(s
, "GET_PARAMETER", rt
->control_uri
, NULL
);
912 ff_rtsp_send_cmd_async(s
, "OPTIONS", rt
->control_uri
, NULL
);
914 /* The stale flag should be reset when creating the auth response in
915 * ff_rtsp_send_cmd_async, but reset it here just in case we never
916 * called the auth code (if we didn't have any credentials set). */
917 rt
->auth_state
.stale
= 0;
924 static int rtsp_read_seek(AVFormatContext
*s
, int stream_index
,
925 int64_t timestamp
, int flags
)
927 RTSPState
*rt
= s
->priv_data
;
929 rt
->seek_timestamp
= av_rescale_q(timestamp
,
930 s
->streams
[stream_index
]->time_base
,
934 case RTSP_STATE_IDLE
:
936 case RTSP_STATE_STREAMING
:
937 if (rtsp_read_pause(s
) != 0)
939 rt
->state
= RTSP_STATE_SEEKING
;
940 if (rtsp_read_play(s
) != 0)
943 case RTSP_STATE_PAUSED
:
944 rt
->state
= RTSP_STATE_IDLE
;
950 static const AVClass rtsp_demuxer_class
= {
951 .class_name
= "RTSP demuxer",
952 .item_name
= av_default_item_name
,
953 .option
= ff_rtsp_options
,
954 .version
= LIBAVUTIL_VERSION_INT
,
957 AVInputFormat ff_rtsp_demuxer
= {
959 .long_name
= NULL_IF_CONFIG_SMALL("RTSP input"),
960 .priv_data_size
= sizeof(RTSPState
),
961 .read_probe
= rtsp_probe
,
962 .read_header
= rtsp_read_header
,
963 .read_packet
= rtsp_read_packet
,
964 .read_close
= rtsp_read_close
,
965 .read_seek
= rtsp_read_seek
,
966 .flags
= AVFMT_NOFILE
,
967 .read_play
= rtsp_read_play
,
968 .read_pause
= rtsp_read_pause
,
969 .priv_class
= &rtsp_demuxer_class
,