[FFmpeg-devel] [PATCH] rmdec.c: correctly skip indexes

Ronald S. Bultje rsbultje
Mon Mar 9 14:49:42 CET 2009


Hi,

2008/12/30 Michael Niedermayer <michaelni at gmx.at>:
> On Tue, Dec 30, 2008 at 02:07:31PM -0500, Ronald S. Bultje wrote:
>> @@ -445,9 +445,11 @@
>> ? ? ? ? ? ? ?state= (state<<8) + get_byte(pb);
>>
>> ? ? ? ? ? ? ?if(state == MKBETAG('I', 'N', 'D', 'X')){
>> - ? ? ? ? ? ? ? ?len = get_be16(pb) - 6;
>> - ? ? ? ? ? ? ? ?if(len<0)
>> - ? ? ? ? ? ? ? ? ? ?continue;
>> + ? ? ? ? ? ? ? ?int size, n_pkts;
>> + ? ? ? ? ? ? ? ?size = get_be32(pb);
>> + ? ? ? ? ? ? ? ?url_fskip(pb, 4);
>> + ? ? ? ? ? ? ? ?n_pkts = get_be16(pb);
>> + ? ? ? ? ? ? ? ?len = size - 14 + n_pkts * 14;
>> ? ? ? ? ? ? ? ? ?goto skip;
>> ? ? ? ? ? ? ?}
[..]
> besides you change a 16bit BE to a 32bit BE read, its hard to imagine how
> both could have made sense, you should explain this assuming your code
> does make any sense.

So I wanted to look at this again. So the question here is, why does
index-skipping not work for some files? Here's the two typical
examples I've found (both taken from the same fle, the first DBZ movie
on samples.mplayerhq.hu):

1:
024935E0   3B B9 C9 57  D2 C2 7E 06  1D 5A FA 90  B9 FC 49 4E  ;..W..~..Z....IN
024935F0   44 58 00 00  1D 1E 00 00  00 00 02 13  00 00 02 49  DX.............I
02493600   53 0C 00 00  00 00 00 00  00 00 01 B2  00 00 00 00  S...............

Index size here is clearly not the two-bytes after INDEX, so I'm quite
sure that's a typo in the current code. It's always 32-bit (see
mplayer, gst, etc., as referenced before). However, the size is the
size of the total code, because the next index starts exactly at this
offset (24935EE+1D1E=249530C). Let's look at this one:

2:
02495300   00 12 67 1C  02 48 DA 8D  00 01 0F 76  49 4E 44 58  ..g..H.....vINDX
02495310   00 00 00 14  00 00 00 00  03 0C 00 01  00 00 00 00  ................
02495320   00 00 00 00  00 21 00 00  25 F4 00 00  00 0E 00 00  .....!..%.......

The length of all examples I've looked at so far is 0x14, which is not
even enough space to fit a single INDEX chunk (14 bytes header minimum
+ 14 bytes per chunk). It seems that for any of these chunks where the
"size" is 0x14, the actual size is 0x14 (index header) + n_pkts * 14.

Attached patch implements this and correctly skips indexes for me.
Behaviour before at end of file (add a printf directly inside the if
state == MKTAG(INDX), and another printf directly after the skip:
tag):

==
Index, len=-6
Skip
Skip
Skip
Skip
Skip
Skip
Skip
Skip
EOF reached
==

After:
==
Index, len=7446
Skip
Index, len=10926
Skip
EOF reached
==

I'll apply the patch unless people have obvious complaints. I'll do
actual index reading in a separate patch, I'll probably implement
seeking along with it (not yet done).

Ronald
-------------- next part --------------
Index: ffmpeg-svn/libavformat/rmdec.c
===================================================================
--- ffmpeg-svn.orig/libavformat/rmdec.c	2009-03-09 09:45:42.000000000 -0400
+++ ffmpeg-svn/libavformat/rmdec.c	2009-03-09 09:48:09.000000000 -0400
@@ -440,7 +440,15 @@
             state= (state<<8) + get_byte(pb);
 
             if(state == MKBETAG('I', 'N', 'D', 'X')){
-                len = get_be16(pb) - 6;
+                int size, n_pkts;
+                size = get_be32(pb);
+                if (size >= 28) {
+                    len = size - 8;
+                } else {
+                    url_fskip(pb, 2);
+                    n_pkts = get_be32(pb);
+                    len = size - 14 + n_pkts * 14;
+                }
                 if(len<0)
                     continue;
                 goto skip;



More information about the ffmpeg-devel mailing list