On 16 August 2010 07:53, Ronald S. Bultje <[email protected]> wrote: > Hi, > > On Mon, Aug 16, 2010 at 10:46 AM, Martin Storsjö <[email protected]> wrote: >> On Mon, 16 Aug 2010, Ronald S. Bultje wrote: >>> On Mon, Aug 16, 2010 at 10:38 AM, Martin Storsjö <[email protected]> wrote: >>> > Is RDT received over rtp:// URLContexts? If that's the case, this patch >>> > itself still is ok, you just won't ever get any data on the RTCP socket. >>> >>> Yeah, RDT stuff is interleaved within the stream. Kind of ugly, I >>> guess. TCP has its own mechanism, I'm sure, can you look into that >>> also? >> >> Yeah, I think it should all work just fine. This particular issue was for >> UDP where the packets are sent on a separate socket, that we need to >> include in the select(). For TCP they all come in the same stream, and are >> already properly passed to rtpdec, where the new code would do the right >> thing. > > Right. You'll notice that we do in fact open the socket for RTCP, even > for RDT streams. So you can just add it. It should just never receive > any data. >
I might be missing something, but I don't see any particular RDT handling code in rtsp_fetch_packet other than rdt_parse_packet. Do I still need to do something? Attached patches address all comments so far: -Add in rtp_get_rtcp_file_handle function, preserving the deprecation of rtp_get_file_handles -Counter for the number of BYEs received, which is reset after a seek. If nb_byes == nb_streams, we return EOF. As mentioned earlier, this is probably not the correct behavior. Autoexit does not trip under my tests, perhaps because with this patch, the EOF never makes it back to ffplay. Instead, av_read_frame_internal tries to return some (bogus?) final packets (utils.c:1119). Josh
From f5aacfa066c021c698b4f55720464020544d0f57 Mon Sep 17 00:00:00 2001 From: Josh Allmann <[email protected]> Date: Mon, 2 Aug 2010 23:15:23 -0700 Subject: [PATCH 1/5] Replace hard-coded RTCP packet types with defines. --- libavformat/rtp.h | 9 +++++++++ libavformat/rtpdec.c | 10 +++++----- libavformat/rtpenc.c | 2 +- libavformat/rtpproto.c | 2 +- libavformat/rtspenc.c | 2 +- 5 files changed, 17 insertions(+), 8 deletions(-) diff --git a/libavformat/rtp.h b/libavformat/rtp.h index 333ed33..f550ad7 100644 --- a/libavformat/rtp.h +++ b/libavformat/rtp.h @@ -82,4 +82,13 @@ enum CodecID ff_rtp_codec_id(const char *buf, enum AVMediaType codec_type); */ #define RTP_XIPH_IDENT 0xfecdba +/* RTCP packet types */ +enum RTCPType { + RTCP_SR = 200, + RTCP_RR, // 201 + RTCP_SDES, // 202 + RTCP_BYE, // 203 + RTCP_APP // 204 +}; + #endif /* AVFORMAT_RTP_H */ diff --git a/libavformat/rtpdec.c b/libavformat/rtpdec.c index fb58a9d..649ed2b 100644 --- a/libavformat/rtpdec.c +++ b/libavformat/rtpdec.c @@ -73,7 +73,7 @@ void av_register_rtp_dynamic_payload_handlers(void) static int rtcp_parse_packet(RTPDemuxContext *s, const unsigned char *buf, int len) { - if (buf[1] != 200) + if (buf[1] != RTCP_SR) return -1; s->last_rtcp_ntp_time = AV_RB64(buf + 8); if (s->first_rtcp_ntp_time == AV_NOPTS_VALUE) @@ -208,7 +208,7 @@ int rtp_check_and_send_back_rr(RTPDemuxContext *s, int count) // Receiver Report put_byte(pb, (RTP_VERSION << 6) + 1); /* 1 report block */ - put_byte(pb, 201); + put_byte(pb, RTCP_RR); put_be16(pb, 7); /* length in words - 1 */ put_be32(pb, s->ssrc); // our own SSRC put_be32(pb, s->ssrc); // XXX: should be the server's here! @@ -246,7 +246,7 @@ int rtp_check_and_send_back_rr(RTPDemuxContext *s, int count) // CNAME put_byte(pb, (RTP_VERSION << 6) + 1); /* 1 report block */ - put_byte(pb, 202); + put_byte(pb, RTCP_SDES); len = strlen(s->hostname); put_be16(pb, (6 + len + 3) / 4); /* length in words - 1 */ put_be32(pb, s->ssrc); @@ -297,7 +297,7 @@ void rtp_send_punch_packets(URLContext* rtp_handle) return; put_byte(pb, (RTP_VERSION << 6)); - put_byte(pb, 201); /* receiver report */ + put_byte(pb, RTCP_RR); /* receiver report */ put_be16(pb, 1); /* length in words - 1 */ put_be32(pb, 0); /* our own SSRC */ @@ -432,7 +432,7 @@ int rtp_parse_packet(RTPDemuxContext *s, AVPacket *pkt, if ((buf[0] & 0xc0) != (RTP_VERSION << 6)) return -1; - if (buf[1] >= 200 && buf[1] <= 204) { + if (buf[1] >= RTCP_SR && buf[1] <= RTCP_APP) { rtcp_parse_packet(s, buf, len); return -1; } diff --git a/libavformat/rtpenc.c b/libavformat/rtpenc.c index 9335e8c..892d7cf 100644 --- a/libavformat/rtpenc.c +++ b/libavformat/rtpenc.c @@ -187,7 +187,7 @@ static void rtcp_send_sr(AVFormatContext *s1, int64_t ntp_time) rtp_ts = av_rescale_q(ntp_time - s->first_rtcp_ntp_time, (AVRational){1, 1000000}, s1->streams[0]->time_base) + s->base_timestamp; put_byte(s1->pb, (RTP_VERSION << 6)); - put_byte(s1->pb, 200); + put_byte(s1->pb, RTCP_SR); put_be16(s1->pb, 6); /* length in words - 1 */ put_be32(s1->pb, s->ssrc); put_be32(s1->pb, ntp_time / 1000000); diff --git a/libavformat/rtpproto.c b/libavformat/rtpproto.c index 46511ba..289a253 100644 --- a/libavformat/rtpproto.c +++ b/libavformat/rtpproto.c @@ -285,7 +285,7 @@ static int rtp_write(URLContext *h, const uint8_t *buf, int size) int ret; URLContext *hd; - if (buf[1] >= 200 && buf[1] <= 204) { + if (buf[1] >= RTCP_SR && buf[1] <= RTCP_APP) { /* RTCP payload type */ hd = s->rtcp_hd; } else { diff --git a/libavformat/rtspenc.c b/libavformat/rtspenc.c index a4c7fd9..9a9fa5a 100644 --- a/libavformat/rtspenc.c +++ b/libavformat/rtspenc.c @@ -85,7 +85,7 @@ static int tcp_write_packet(AVFormatContext *s, RTSPStream *rtsp_st) size -= 4; if (packet_len > size || packet_len < 2) break; - if (ptr[1] >= 200 && ptr[1] <= 204) + if (ptr[1] >= RTCP_SR && ptr[1] <= RTCP_APP) id = rtsp_st->interleaved_max; /* RTCP */ else id = rtsp_st->interleaved_min; /* RTP */ -- 1.7.0.4
From c7bd172e496aac1393a3b144448e2b21c7a4bc98 Mon Sep 17 00:00:00 2001 From: Josh Allmann <[email protected]> Date: Tue, 17 Aug 2010 23:40:35 -0700 Subject: [PATCH 2/5] Add rtp_get_rtcp_file_handle functon. --- libavformat/rtpdec.h | 5 +++++ libavformat/rtpproto.c | 5 +++++ 2 files changed, 10 insertions(+), 0 deletions(-) diff --git a/libavformat/rtpdec.h b/libavformat/rtpdec.h index 5389bcc..8548459 100644 --- a/libavformat/rtpdec.h +++ b/libavformat/rtpdec.h @@ -72,6 +72,11 @@ void rtp_send_punch_packets(URLContext* rtp_handle); */ int rtp_check_and_send_back_rr(RTPDemuxContext *s, int count); +/** + * Get the file handle for the RTCP socket. + */ +int rtp_get_rtcp_file_handle(URLContext *h); + // these statistics are used for rtcp receiver reports... typedef struct { uint16_t max_seq; ///< highest sequence number seen diff --git a/libavformat/rtpproto.c b/libavformat/rtpproto.c index 289a253..ef4602d 100644 --- a/libavformat/rtpproto.c +++ b/libavformat/rtpproto.c @@ -373,6 +373,11 @@ static int rtp_get_file_handle(URLContext *h) return s->rtp_fd; } +int rtp_get_rtcp_file_handle(URLContext *h) { + RTPContext *s = h->priv_data; + return s->rtcp_fd; +} + URLProtocol rtp_protocol = { "rtp", rtp_open, -- 1.7.0.4
From 09d3166f5df3ca25a5257285700d61a0b20f0e9b Mon Sep 17 00:00:00 2001 From: Josh Allmann <[email protected]> Date: Fri, 13 Aug 2010 15:09:44 -0700 Subject: [PATCH 3/5] Read RTCP packets in RTSP demuxer. --- libavformat/rtsp.c | 13 +++++++------ 1 files changed, 7 insertions(+), 6 deletions(-) diff --git a/libavformat/rtsp.c b/libavformat/rtsp.c index 36fe753..509434a 100644 --- a/libavformat/rtsp.c +++ b/libavformat/rtsp.c @@ -1642,7 +1642,7 @@ static int udp_read_packet(AVFormatContext *s, RTSPStream **prtsp_st, RTSPState *rt = s->priv_data; RTSPStream *rtsp_st; fd_set rfds; - int fd, fd_max, n, i, ret, tcp_fd, timeout_cnt = 0; + int fd, fd_rtcp, fd_max, n, i, ret, tcp_fd, timeout_cnt = 0; struct timeval tv; for (;;) { @@ -1659,12 +1659,12 @@ static int udp_read_packet(AVFormatContext *s, RTSPStream **prtsp_st, for (i = 0; i < rt->nb_rtsp_streams; i++) { rtsp_st = rt->rtsp_streams[i]; if (rtsp_st->rtp_handle) { - /* currently, we cannot probe RTCP handle because of - * blocking restrictions */ fd = url_get_file_handle(rtsp_st->rtp_handle); - if (fd > fd_max) - fd_max = fd; + fd_rtcp = rtp_get_rtcp_file_handle(rtsp_st->rtp_handle); + if (FFMAX(fd, fd_rtcp) > fd_max) + fd_max = FFMAX(fd, fd_rtcp); FD_SET(fd, &rfds); + FD_SET(fd_rtcp, &rfds); } } tv.tv_sec = 0; @@ -1676,7 +1676,8 @@ static int udp_read_packet(AVFormatContext *s, RTSPStream **prtsp_st, rtsp_st = rt->rtsp_streams[i]; if (rtsp_st->rtp_handle) { fd = url_get_file_handle(rtsp_st->rtp_handle); - if (FD_ISSET(fd, &rfds)) { + fd_rtcp = rtp_get_rtcp_file_handle(rtsp_st->rtp_handle); + if (FD_ISSET(fd_rtcp, &rfds) || FD_ISSET(fd, &rfds)) { ret = url_read(rtsp_st->rtp_handle, buf, buf_size); if (ret > 0) { *prtsp_st = rtsp_st; -- 1.7.0.4
From 0253dc1db8dc8eb7971fa2cbbac200eaf314d5f0 Mon Sep 17 00:00:00 2001 From: Josh Allmann <[email protected]> Date: Sat, 14 Aug 2010 23:24:07 -0700 Subject: [PATCH 4/5] Read RTCP compound packets. --- libavformat/rtpdec.c | 28 ++++++++++++++++++++++------ 1 files changed, 22 insertions(+), 6 deletions(-) diff --git a/libavformat/rtpdec.c b/libavformat/rtpdec.c index 649ed2b..5860bc2 100644 --- a/libavformat/rtpdec.c +++ b/libavformat/rtpdec.c @@ -73,12 +73,28 @@ void av_register_rtp_dynamic_payload_handlers(void) static int rtcp_parse_packet(RTPDemuxContext *s, const unsigned char *buf, int len) { - if (buf[1] != RTCP_SR) - return -1; - s->last_rtcp_ntp_time = AV_RB64(buf + 8); - if (s->first_rtcp_ntp_time == AV_NOPTS_VALUE) - s->first_rtcp_ntp_time = s->last_rtcp_ntp_time; - s->last_rtcp_timestamp = AV_RB32(buf + 16); + int payload_len; + while (len) { + switch (buf[1]) { + case RTCP_SR: + if (len < 16) { + av_log(NULL, AV_LOG_ERROR, "Invalid length for RTCP SR packet\n"); + return AVERROR_INVALIDDATA; + } + payload_len = (AV_RB16(buf + 2) + 1) * 4; + + s->last_rtcp_ntp_time = AV_RB64(buf + 8); + if (s->first_rtcp_ntp_time == AV_NOPTS_VALUE) + s->first_rtcp_ntp_time = s->last_rtcp_ntp_time; + s->last_rtcp_timestamp = AV_RB32(buf + 16); + + buf += payload_len; + len -= payload_len; + break; + default: + return -1; + } + } return 0; } -- 1.7.0.4
From 4f4811d9d3065292ce8469dcdb2e053dd690a8a5 Mon Sep 17 00:00:00 2001 From: Josh Allmann <[email protected]> Date: Sun, 15 Aug 2010 01:10:11 -0700 Subject: [PATCH 5/5] Add in RTCP BYE support. --- libavformat/rtpdec.c | 5 +++-- libavformat/rtsp.c | 11 +++++++++++ libavformat/rtsp.h | 5 +++++ 3 files changed, 19 insertions(+), 2 deletions(-) diff --git a/libavformat/rtpdec.c b/libavformat/rtpdec.c index 6b7ed48..8199cca 100644 --- a/libavformat/rtpdec.c +++ b/libavformat/rtpdec.c @@ -92,6 +92,8 @@ static int rtcp_parse_packet(RTPDemuxContext *s, const unsigned char *buf, int l buf += payload_len; len -= payload_len; break; + case RTCP_BYE: + return RTCP_BYE; default: return -1; } @@ -450,8 +452,7 @@ int rtp_parse_packet(RTPDemuxContext *s, AVPacket *pkt, if ((buf[0] & 0xc0) != (RTP_VERSION << 6)) return -1; if (buf[1] >= RTCP_SR && buf[1] <= RTCP_APP) { - rtcp_parse_packet(s, buf, len); - return -1; + return rtcp_parse_packet(s, buf, len); } payload_type = buf[1] & 0x7f; if (buf[1] & 0x80) diff --git a/libavformat/rtsp.c b/libavformat/rtsp.c index 509434a..098daef 100644 --- a/libavformat/rtsp.c +++ b/libavformat/rtsp.c @@ -1375,6 +1375,7 @@ int ff_rtsp_connect(AVFormatContext *s) return AVERROR(EIO); redirect: rt->control_transport = RTSP_MODE_PLAIN; + rt->nb_byes = 0; /* extract hostname and port */ av_url_split(NULL, 0, auth, sizeof(auth), host, sizeof(host), &port, path, sizeof(path), s->filename); @@ -1822,6 +1823,15 @@ static int rtsp_fetch_packet(AVFormatContext *s, AVPacket *pkt) rtpctx2->first_rtcp_ntp_time = rtpctx->first_rtcp_ntp_time; } } + } else if (ret == RTCP_BYE) { + rt->nb_byes++; + + av_log(s, AV_LOG_DEBUG, "Received BYE for stream %d (%d/%d)\n", + rtsp_st->stream_index, rt->nb_byes, rt->nb_rtsp_streams); + + if (rt->nb_byes == rt->nb_rtsp_streams) { + return AVERROR_EOF; + } } } if (ret < 0) @@ -1950,6 +1960,7 @@ static int rtsp_read_seek(AVFormatContext *s, int stream_index, rt->state = RTSP_STATE_SEEKING; if (rtsp_read_play(s) != 0) return -1; + rt->nb_byes = 0; break; case RTSP_STATE_PAUSED: rt->state = RTSP_STATE_IDLE; diff --git a/libavformat/rtsp.h b/libavformat/rtsp.h index 814d8d8..3ee1dc5 100644 --- a/libavformat/rtsp.h +++ b/libavformat/rtsp.h @@ -303,6 +303,11 @@ typedef struct RTSPState { /** RTSP transport mode, such as plain or tunneled. */ enum RTSPControlTransport control_transport; + + /* Number of RTCP BYE packets the RTSP session has received. + * An EOF is propagated back if nb_byes == nb_streams. + * This is reset after a seek. */ + int nb_byes; } RTSPState; /** -- 1.7.0.4
_______________________________________________ FFmpeg-soc mailing list [email protected] https://lists.mplayerhq.hu/mailman/listinfo/ffmpeg-soc
