This patch refactors RDT packet header parsing so that it can be used in
authorRonald S. Bultje <rsbultje@gmail.com>
Wed, 1 Oct 2008 12:37:07 +0000 (12:37 +0000)
committerRonald S. Bultje <rsbultje@gmail.com>
Wed, 1 Oct 2008 12:37:07 +0000 (12:37 +0000)
rtsp.c to detect the ID of the packet source also in case of TCP streams.
This allows proper playback of RDT streams with multiple stream types, e.g.
audio + video. Accepted by LucaB in "RDT/Realmedia patches #2" thread on ML.

Originally committed as revision 15496 to svn://svn.ffmpeg.org/ffmpeg/trunk

libavformat/rdt.c
libavformat/rdt.h
libavformat/rtsp.c

index c1238b2d46c1dcf6f08d5c4776b683037b7f491b..0dd9a6ef8742eb33042b627aefce44d46272931c 100644 (file)
@@ -140,27 +140,25 @@ rdt_load_mdpr (rdt_data *rdt, AVStream *st, int rule_nr)
  * Actual data handling.
  */
 
-static int rdt_parse_header(struct RTPDemuxContext *s, const uint8_t *buf,
-                            int len, int *seq, uint32_t *timestamp, int *flags)
+int
+ff_rdt_parse_header(const uint8_t *buf, int len,
+                    int *sn, int *seq, int *rn, uint32_t *ts)
 {
-    rdt_data *rdt = s->dynamic_protocol_context;
-    int consumed = 0, sn;
+    int consumed = 10;
 
-    if (buf[0] < 0x40 || buf[0] > 0x42) {
+    if (len > 0 && (buf[0] < 0x40 || buf[0] > 0x42)) {
         buf += 9;
         len -= 9;
         consumed += 9;
     }
-    sn = (buf[0]>>1) & 0x1f;
-    *seq = AV_RB16(buf+1);
-    *timestamp = AV_RB32(buf+4);
-    if (!(buf[3] & 1) && (sn != rdt->prev_sn || *timestamp != rdt->prev_ts)) {
-        *flags |= PKT_FLAG_KEY;
-        rdt->prev_sn = sn;
-        rdt->prev_ts = *timestamp;
-    }
+    if (len < 10)
+        return -1;
+    if (sn)  *sn  = (buf[0]>>1) & 0x1f;
+    if (seq) *seq = AV_RB16(buf+1);
+    if (ts)  *ts  = AV_RB32(buf+4);
+    if (rn)  *rn  = buf[3] & 0x3f;
 
-    return consumed + 10;
+    return consumed;
 }
 
 /**< return 0 on packet, no more left, 1 on packet, 1 on partial packet... */
@@ -208,7 +206,8 @@ int
 ff_rdt_parse_packet(RTPDemuxContext *s, AVPacket *pkt,
                     const uint8_t *buf, int len)
 {
-    int seq, flags = 0;
+    rdt_data *rdt = s->dynamic_protocol_context;
+    int seq, flags = 0, rule, sn;
     uint32_t timestamp;
     int rv= 0;
 
@@ -221,9 +220,14 @@ ff_rdt_parse_packet(RTPDemuxContext *s, AVPacket *pkt,
 
     if (len < 12)
         return -1;
-    rv = rdt_parse_header(s, buf, len, &seq, &timestamp, &flags);
+    rv = ff_rdt_parse_header(buf, len, &sn, &seq, &rule, &timestamp);
     if (rv < 0)
         return rv;
+    if (!(rule & 1) && (sn != rdt->prev_sn || timestamp != rdt->prev_ts)) {
+        flags |= PKT_FLAG_KEY;
+        rdt->prev_sn = sn;
+        rdt->prev_ts = timestamp;
+    }
     buf += rv;
     len -= rv;
     s->seq = seq;
index 5a13127fb5274bbe712e1ce0741f5989dfb74627..2fe11873ac985fba10d0823bc0ea745d09e5c9a7 100644 (file)
@@ -56,6 +56,20 @@ void ff_rdt_subscribe_rule(char *cmd, int size,
 void ff_rdt_subscribe_rule2(RTPDemuxContext *s, char *cmd, int size,
                             int stream_nr, int rule_nr);
 
+/**
+ * Parse RDT-style packet header.
+ *
+ * @param buf input buffer
+ * @param len length of input buffer
+ * @param sn will be set to the stream number this packet belongs to
+ * @param seq will be set to the sequence number this packet belongs to
+ * @param rn will be set to the rule number this packet belongs to
+ * @param ts will be set to the timestamp of the packet
+ * @return the amount of bytes consumed, or <0 on error
+ */
+int ff_rdt_parse_header(const uint8_t *buf, int len,
+                        int *sn, int *seq, int *rn, uint32_t *ts);
+
 /**
  * Parse RDT-style packet data (header + media data).
  * Usage similar to rtp_parse_packet().
index b6013de267d9f1e2ba7be43ba6d1f99b15d5bf5a..254931cf3d55628746e0b0cb36bd08e459de5d8c 100644 (file)
@@ -1265,6 +1265,9 @@ static int tcp_read_packet(AVFormatContext *s, RTSPStream **prtsp_st,
     ret = url_readbuf(rt->rtsp_hd, buf, len);
     if (ret != len)
         return -1;
+    if (rt->transport == RTSP_TRANSPORT_RDT &&
+        ff_rdt_parse_header(buf, len, &id, NULL, NULL, NULL) < 0)
+        return -1;
 
     /* find the matching stream */
     for(i = 0; i < rt->nb_rtsp_streams; i++) {