Hi,

Here is a first attempt at RTCP BYE support, in bite-size patches.

0001 - Replace hardcoded RTCP packet types with an enum.

0002 - Reinstate rtp_get_file_handles function that is slated for
removal at the next major bump. We need to be able to get the RTCP fd
from the rtpproto.

0003 - Read RTCP packets from the RTSP demuxer. This might not be
strictly necessary, but it guarantees we'll read a RTCP packet if one
is available (without the availability of a RTP data packet).

0004 - According to RFC 3550, RTCP is always sent in
compound/aggregate form, starting with either a SR or RR packet, with
the other types (eg, BYE) following. This patch enables reading past
the first SR packet.

0005 - Actual BYE support. This is really kinda incomplete. It only
returns EOF, whereas we should be selectively removing the stream
(theoretically we could have concurrent streams playing, and one BYEs
while the others keep going). In the case where we get a BYE with only
one stream left, perhaps an EOF would be appropriate then.

Right now, not much happens since the EOF is propagated back to the
application layer. FFplay pretty much ignores it, although I suppose
it could (should?) be patched to call av_close_input_stream, so it
sends a proper TEARDOWN.

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 cf7b9a757415bc6311231a25efc88629383cbaef Mon Sep 17 00:00:00 2001
From: Josh Allmann <[email protected]>
Date: Sat, 7 Aug 2010 01:48:09 -0700
Subject: [PATCH 2/5] Reinstate rtp_get_file_handles function; we need this to read RTCP.

---
 libavformat/rtpdec.h   |    2 --
 libavformat/rtpproto.c |    2 --
 2 files changed, 0 insertions(+), 4 deletions(-)

diff --git a/libavformat/rtpdec.h b/libavformat/rtpdec.h
index 5389bcc..4dcf8d3 100644
--- a/libavformat/rtpdec.h
+++ b/libavformat/rtpdec.h
@@ -48,9 +48,7 @@ int rtp_get_local_rtp_port(URLContext *h);
 int rtp_get_local_rtcp_port(URLContext *h);
 
 int rtp_set_remote_url(URLContext *h, const char *uri);
-#if (LIBAVFORMAT_VERSION_MAJOR <= 52)
 void rtp_get_file_handles(URLContext *h, int *prtp_fd, int *prtcp_fd);
-#endif
 
 /**
  * Send a dummy packet on both port pairs to set up the connection
diff --git a/libavformat/rtpproto.c b/libavformat/rtpproto.c
index 289a253..e3852c9 100644
--- a/libavformat/rtpproto.c
+++ b/libavformat/rtpproto.c
@@ -351,7 +351,6 @@ int rtp_get_local_rtcp_port(URLContext *h)
     return udp_get_local_port(s->rtcp_hd);
 }
 
-#if (LIBAVFORMAT_VERSION_MAJOR <= 52)
 /**
  * Return the rtp and rtcp file handles for select() usage to wait for
  * several RTP streams at the same time.
@@ -365,7 +364,6 @@ void rtp_get_file_handles(URLContext *h, int *prtp_fd, int *prtcp_fd)
     *prtp_fd = s->rtp_fd;
     *prtcp_fd = s->rtcp_fd;
 }
-#endif
 
 static int rtp_get_file_handle(URLContext *h)
 {
-- 
1.7.0.4

From 88b8e59ed29673319ff32183f0a21357b3c56e61 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 |   15 +++++++--------
 1 files changed, 7 insertions(+), 8 deletions(-)

diff --git a/libavformat/rtsp.c b/libavformat/rtsp.c
index 36fe753..0a7dae1 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,11 @@ 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;
+                rtp_get_file_handles(rtsp_st->rtp_handle, &fd, &fd_rtcp);
+                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;
@@ -1675,8 +1674,8 @@ 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) {
-                    fd = url_get_file_handle(rtsp_st->rtp_handle);
-                    if (FD_ISSET(fd, &rfds)) {
+                    rtp_get_file_handles(rtsp_st->rtp_handle, &fd, &fd_rtcp);
+                    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 3dd328395a926a6e291e26dbc27487aeff847b76 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 d8a81220e76f8d254eb0844ae5151f3d2d33448a 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   |    3 ++-
 2 files changed, 5 insertions(+), 3 deletions(-)

diff --git a/libavformat/rtpdec.c b/libavformat/rtpdec.c
index 5860bc2..c441346 100644
--- a/libavformat/rtpdec.c
+++ b/libavformat/rtpdec.c
@@ -91,6 +91,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;
         }
@@ -449,8 +451,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 0a7dae1..1f9a3df 100644
--- a/libavformat/rtsp.c
+++ b/libavformat/rtsp.c
@@ -1820,7 +1820,8 @@ static int rtsp_fetch_packet(AVFormatContext *s, AVPacket *pkt)
                         rtpctx2->first_rtcp_ntp_time = rtpctx->first_rtcp_ntp_time;
                 }
             }
-        }
+        } else if (ret == RTCP_BYE)
+            return AVERROR_EOF;
     }
     if (ret < 0)
         goto redo;
-- 
1.7.0.4

_______________________________________________
FFmpeg-soc mailing list
[email protected]
https://lists.mplayerhq.hu/mailman/listinfo/ffmpeg-soc

Reply via email to