[FFmpeg-devel] [PATCH] rmdec.c: parse INDX chunk

Ronald S. Bultje rsbultje
Fri Mar 13 14:40:41 CET 2009


Hi,

On Wed, Mar 11, 2009 at 3:54 PM, Ronald S. Bultje <rsbultje at gmail.com> wrote:
> On Wed, Mar 11, 2009 at 2:55 PM, Kostya <kostya.shishkov at gmail.com> wrote:
>> Run seektest first, it no regressions - very good.
>> If some values got changed - better understand why and update seek.ref
>> or redo the patch in case of bad values (IIRC, -1 instead of large numbers)
>
> Gotcha, will do.

Seektest caught a nice little bug hidden inside my patch, with that
fixed, it passed with no changes. See attached. I tried cat file.rm |
./ffplay pipe://0 (containing an index, which is obviously not read),
and it worked just fine, but w/o seeking of course.

See attached for my patch which is essentially still the same.

Ronald
-------------- next part --------------
Index: ffmpeg-svn/libavformat/rmdec.c
===================================================================
--- ffmpeg-svn.orig/libavformat/rmdec.c	2009-03-13 09:25:49.000000000 -0400
+++ ffmpeg-svn/libavformat/rmdec.c	2009-03-13 09:32:12.000000000 -0400
@@ -292,6 +292,49 @@
     return 0;
 }
 
+/** this function assumes that the demuxer has already seeked to the start
+ * of the INDX chunk, and will bail out if not. */
+static int rm_read_index(AVFormatContext *s)
+{
+    ByteIOContext *pb = s->pb;
+    unsigned int size, n_pkts, str_id, next_off, n, pos, pts;
+    AVStream *st;
+
+    do {
+        if (get_le32(pb) != MKTAG('I','N','D','X'))
+            return -1;
+        size     = get_be32(pb);
+        if (size < 20)
+            return -1;
+        url_fskip(pb, 2);
+        n_pkts   = get_be32(pb);
+        str_id   = get_be16(pb);
+        next_off = get_be32(pb);
+        for (n = 0; n < s->nb_streams; n++)
+            if (s->streams[n]->id == str_id) {
+                st = s->streams[n];
+                break;
+            }
+        if (n == s->nb_streams)
+            goto skip;
+
+        for (n = 0; n < n_pkts; n++) {
+            url_fskip(pb, 2);
+            pts = get_be32(pb);
+            pos = get_be32(pb);
+            url_fskip(pb, 4); /* packet no. */
+
+            av_add_index_entry(st, pos, pts, 0, 0, AVINDEX_KEYFRAME);
+        }
+
+skip:
+        if (next_off && url_ftell(pb) != next_off &&
+            url_fseek(pb, next_off, SEEK_SET) < 0)
+            return -1;
+    } while (next_off);
+
+    return 0;
+}
 
 static int rm_read_header_old(AVFormatContext *s, AVFormatParameters *ap)
 {
@@ -314,6 +357,7 @@
     unsigned int tag;
     int tag_size;
     unsigned int start_time, duration;
+    unsigned int data_off = 0, indx_off = 0;
     char buf[128];
     int flags = 0;
 
@@ -357,8 +401,8 @@
             get_be32(pb); /* nb packets */
             get_be32(pb); /* duration */
             get_be32(pb); /* preroll */
-            get_be32(pb); /* index offset */
-            get_be32(pb); /* data offset */
+            indx_off = get_be32(pb); /* index offset */
+            data_off = get_be32(pb); /* data offset */
             get_be16(pb); /* nb streams */
             flags = get_be16(pb); /* flags */
             break;
@@ -400,6 +444,14 @@
     if (!rm->nb_packets && (flags & 4))
         rm->nb_packets = 3600 * 25;
     get_be32(pb); /* next data header */
+
+    if (!data_off)
+        data_off = url_ftell(pb) - 18;
+    if (indx_off && url_fseek(pb, indx_off, SEEK_SET) >= 0) {
+        rm_read_index(s);
+        url_fseek(pb, data_off + 18, SEEK_SET);
+    }
+
     return 0;
 }
 



More information about the ffmpeg-devel mailing list