From 50aef03b24d949249b020226dffa3a78077f1056 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Wed, 30 Oct 2013 19:12:45 +0200 Subject: [PATCH] rtspenc: Make sure BYE packets are sent before TEARDOWN MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Also make sure the BYE packets are sent at all when using TCP interleaved transport. Signed-off-by: Martin Storsjö --- libavformat/rtsp.c | 8 +++++--- libavformat/rtsp.h | 7 ++++++- libavformat/rtspdec.c | 2 +- libavformat/rtspenc.c | 9 +++++++-- 4 files changed, 19 insertions(+), 7 deletions(-) diff --git a/libavformat/rtsp.c b/libavformat/rtsp.c index 16b5d416f2..70f8e2104e 100644 --- a/libavformat/rtsp.c +++ b/libavformat/rtsp.c @@ -638,7 +638,7 @@ int ff_sdp_parse(AVFormatContext *s, const char *content) } #endif /* CONFIG_RTPDEC */ -void ff_rtsp_undo_setup(AVFormatContext *s) +void ff_rtsp_undo_setup(AVFormatContext *s, int send_packets) { RTSPState *rt = s->priv_data; int i; @@ -653,6 +653,8 @@ void ff_rtsp_undo_setup(AVFormatContext *s) av_write_trailer(rtpctx); if (rt->lower_transport == RTSP_LOWER_TRANSPORT_TCP) { uint8_t *ptr; + if (CONFIG_RTSP_MUXER && rtpctx->pb && send_packets) + ff_rtsp_tcp_write_packet(s, rtsp_st); avio_close_dyn_buf(rtpctx->pb, &ptr); av_free(ptr); } else { @@ -678,7 +680,7 @@ void ff_rtsp_close_streams(AVFormatContext *s) int i, j; RTSPStream *rtsp_st; - ff_rtsp_undo_setup(s); + ff_rtsp_undo_setup(s, 0); for (i = 0; i < rt->nb_rtsp_streams; i++) { rtsp_st = rt->rtsp_streams[i]; if (rtsp_st) { @@ -1549,7 +1551,7 @@ int ff_rtsp_make_setup_request(AVFormatContext *s, const char *host, int port, return 0; fail: - ff_rtsp_undo_setup(s); + ff_rtsp_undo_setup(s, 0); return err; } diff --git a/libavformat/rtsp.h b/libavformat/rtsp.h index c6f2ffae4b..7a910b06db 100644 --- a/libavformat/rtsp.h +++ b/libavformat/rtsp.h @@ -587,6 +587,11 @@ int ff_sdp_parse(AVFormatContext *s, const char *content); int ff_rtsp_tcp_read_packet(AVFormatContext *s, RTSPStream **prtsp_st, uint8_t *buf, int buf_size); +/** + * Send buffered packets over TCP. + */ +int ff_rtsp_tcp_write_packet(AVFormatContext *s, RTSPStream *rtsp_st); + /** * Receive one packet from the RTSPStreams set up in the AVFormatContext * (which should contain a RTSPState struct as priv_data). @@ -605,7 +610,7 @@ int ff_rtsp_make_setup_request(AVFormatContext *s, const char *host, int port, * Undo the effect of ff_rtsp_make_setup_request, close the * transport_priv and rtp_handle fields. */ -void ff_rtsp_undo_setup(AVFormatContext *s); +void ff_rtsp_undo_setup(AVFormatContext *s, int send_packets); /** * Open RTSP transport context. diff --git a/libavformat/rtspdec.c b/libavformat/rtspdec.c index 43dcb47ac1..160d49bb3d 100644 --- a/libavformat/rtspdec.c +++ b/libavformat/rtspdec.c @@ -769,7 +769,7 @@ static int resetup_tcp(AVFormatContext *s) av_url_split(NULL, 0, NULL, 0, host, sizeof(host), &port, NULL, 0, s->filename); - ff_rtsp_undo_setup(s); + ff_rtsp_undo_setup(s, 0); return ff_rtsp_make_setup_request(s, host, port, RTSP_LOWER_TRANSPORT_TCP, rt->real_challenge); } diff --git a/libavformat/rtspenc.c b/libavformat/rtspenc.c index d8e5b0e212..8a334ec49b 100644 --- a/libavformat/rtspenc.c +++ b/libavformat/rtspenc.c @@ -136,7 +136,7 @@ static int rtsp_write_header(AVFormatContext *s) return 0; } -static int tcp_write_packet(AVFormatContext *s, RTSPStream *rtsp_st) +int ff_rtsp_tcp_write_packet(AVFormatContext *s, RTSPStream *rtsp_st) { RTSPState *rt = s->priv_data; AVFormatContext *rtpctx = rtsp_st->transport_priv; @@ -217,7 +217,7 @@ static int rtsp_write_packet(AVFormatContext *s, AVPacket *pkt) * packets, so we need to send them out on the TCP connection separately. */ if (!ret && rt->lower_transport == RTSP_LOWER_TRANSPORT_TCP) - ret = tcp_write_packet(s, rtsp_st); + ret = ff_rtsp_tcp_write_packet(s, rtsp_st); return ret; } @@ -225,6 +225,11 @@ static int rtsp_write_close(AVFormatContext *s) { RTSPState *rt = s->priv_data; + // If we want to send RTCP_BYE packets, these are sent by av_write_trailer. + // Thus call this on all streams before doing the teardown. This is + // done within ff_rtsp_undo_setup. + ff_rtsp_undo_setup(s, 1); + ff_rtsp_send_cmd_async(s, "TEARDOWN", rt->control_uri, NULL); ff_rtsp_close_streams(s);