[FFmpeg-devel] [PATCH] Multipart RM support (work-in-progress).

Ronald S. Bultje rsbultje
Tue Feb 1 03:38:30 CET 2011


---
 libavformat/rmdec.c |   59 ++++++++++++++++++++++++++++++++++++++++++++++----
 1 files changed, 54 insertions(+), 5 deletions(-)

diff --git a/libavformat/rmdec.c b/libavformat/rmdec.c
index da7e6b2..a920fad 100644
--- a/libavformat/rmdec.c
+++ b/libavformat/rmdec.c
@@ -47,6 +47,16 @@ typedef struct {
     int remaining_len;
     int audio_stream_num; ///< Stream number for audio packets
     int audio_pkt_cnt; ///< Output packet counter
+
+    /* only valid for multirate files, unused otherwise */
+    struct {
+        int64_t last_pts;    ///< timestamp of last RM packet
+        uint64_t cur_offset; ///< file offset of data in next RM packet
+        uint64_t start_off;  ///< offset of first packet in this data chunk
+        unsigned int size;   ///< size of the data chunk
+    } data_chunks[MAX_STREAMS];
+    int n_data_chunks;       ///< number of data chunks, >1 for multirate files
+    int cur_data_chunk;      ///< index of data chunk of last packet
 } RMDemuxContext;
 
 static const unsigned char sipr_swaps[38][2] = {
@@ -390,7 +400,7 @@ static int rm_read_header(AVFormatContext *s, AVFormatParameters *ap)
     ByteIOContext *pb = s->pb;
     unsigned int tag;
     int tag_size;
-    unsigned int start_time, duration;
+    unsigned int start_time, duration, next_data_header;
     unsigned int data_off = 0, indx_off = 0;
     char buf[128];
     int flags = 0;
@@ -477,7 +487,21 @@ static int rm_read_header(AVFormatContext *s, AVFormatParameters *ap)
     rm->nb_packets = get_be32(pb); /* number of packets */
     if (!rm->nb_packets && (flags & 4))
         rm->nb_packets = 3600 * 25;
-    get_be32(pb); /* next data header */
+    do {
+        rm->data_chunks[rm->n_data_chunks].size = FFMAX(0, tag_size - 18);
+        next_data_header = get_be32(pb);
+        rm->data_chunks[rm->n_data_chunks].start_off =
+            rm->data_chunks[rm->n_data_chunks].cur_offset = url_ftell(pb);
+        rm->n_data_chunks++;
+        if (!next_data_header ||
+            url_fseek(pb, next_data_header, SEEK_SET) < 0 ||
+            get_le32(pb) != MKTAG('D','A','T','A'))
+            break;
+        tag_size = get_be32(pb);
+        url_fskip(pb, 6); // flags, n_packets
+    } while (rm->n_data_chunks < MAX_STREAMS);
+    if (rm->n_data_chunks > 1)
+        url_fseek(pb, rm->data_chunks[0].start_off, SEEK_SET);
 
     if (!data_off)
         data_off = url_ftell(pb) - 18;
@@ -524,6 +548,23 @@ static int sync(AVFormatContext *s, int64_t *timestamp, int *flags, int *stream_
             *timestamp = AV_NOPTS_VALUE;
             *flags= 0;
         }else{
+            int cnt, cur_chunk = -1;
+
+            for (cnt = 0; cnt < rm->n_data_chunks; cnt++)
+                if ((cur_chunk == -1 ||
+                     rm->data_chunks[cnt].last_pts <
+                         rm->data_chunks[cur_chunk].last_pts) &&
+                    !(rm->data_chunks[cnt].size > 0 &&
+                      rm->data_chunks[cnt].cur_offset >=
+                          rm->data_chunks[cnt].start_off +
+                          rm->data_chunks[cnt].size))
+                    cur_chunk = cnt;
+            if (cur_chunk == -1) return -1; //EOF
+            if (cur_chunk != rm->cur_data_chunk) {
+                url_fseek(pb, rm->data_chunks[cur_chunk].cur_offset, SEEK_SET);
+                rm->cur_data_chunk = cur_chunk;
+            }
+
             state= (state<<8) + get_byte(pb);
 
             if(state == MKBETAG('I', 'N', 'D', 'X')){
@@ -548,15 +589,23 @@ static int sync(AVFormatContext *s, int64_t *timestamp, int *flags, int *stream_
                        "DATA tag in middle of chunk, file may be broken.\n");
             }
 
-            if(state > (unsigned)0xFFFF || state <= 12)
+            if(state > 0x1FFFF+12 || state <= 12)
                 continue;
-            len=state - 12;
-            state= 0xFFFFFFFF;
+            len=(state - 12)&0xFFFF;
 
             num = get_be16(pb);
             *timestamp = get_be32(pb);
             get_byte(pb); /* reserved */
             *flags = get_byte(pb); /* flags */
+
+             if (state >> 16 == 1) {
+                 url_fskip(pb, 1);
+                 len--;
+             }
+ 
+             state= 0xFFFFFFFF;
+             rm->data_chunks[cur_chunk].last_pts = *timestamp;
+             rm->data_chunks[cur_chunk].cur_offset = url_ftell(pb)+len;
         }
         for(i=0;i<s->nb_streams;i++) {
             st = s->streams[i];
-- 
1.7.2.1




More information about the ffmpeg-devel mailing list