[FFmpeg-devel] [PATCH] fix ffmpeg crash on reading "non-interleved" DV type 1 AVI files

Michael Niedermayer michaelni
Thu Jan 14 20:23:56 CET 2010


On Thu, Jan 14, 2010 at 06:38:37PM +0200, Maksym Veremeyenko wrote:
> Michael Niedermayer ???????(??):
> [...]
>> i dont know what you are trying to do here, so i cannot make any 
>> suggestions
>> for a correct solution but i do know your patch is wrong
>> full bugreport and explanation of why a random piece of the non 
>> interleaved
>> handling should be skiped is missing
>
> During decode 18Gb avi file in _DV type 1_ format i got a Segmentation 
> fault of ffmpeg. Gdb says:
>
> [root at diva-proxy ffmpeg-r21211]# gdb --tty /dev/pts/5 --args ./ffmpeg_g 
> -debug 3 -i "/home/lowres/lost+found/Amer001.AVI" -vcodec copy -an -f 
> rawvideo -y /tmp/test.dv
> GNU gdb Fedora (6.8-32.fc10)
> Copyright (C) 2008 Free Software Foundation, Inc.
> License GPLv3+: GNU GPL version 3 or later 
> <http://gnu.org/licenses/gpl.html>
> This is free software: you are free to change and redistribute it.
> There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
> and "show warranty" for details.
> This GDB was configured as "i386-redhat-linux-gnu"...
> (gdb) r
> Starting program: /opt/enctools/src/ffmpeg-r21211/ffmpeg_g -debug 3 -i 
> /home/lowres/lost+found/Amer001.AVI -vcodec copy -an -f rawvideo -y 
> /tmp/test.dv
> [Thread debugging using libthread_db enabled]
> [New Thread 0xb7ff58d0 (LWP 25599)]
>
> Program received signal SIGSEGV, Segmentation fault.
> avi_read_packet (s=0x806a390, pkt=0xbfffe390) at libavformat/avidec.c:691
> 691	            int64_t ts= ast->frame_offset;
> Missing separate debuginfos, use: debuginfo-install glibc-2.9-3.i686 
> zlib-1.2.3-18.fc9.i386
> (gdb) bt
> #0  avi_read_packet (s=0x806a390, pkt=0xbfffe390) at 
> libavformat/avidec.c:691
> #1  0x00a07443 in av_read_packet (s=0x806a390, pkt=0xbfffe390) at 
> libavformat/utils.c:598
> #2  0x00a0906e in av_read_frame_internal (s=0x806a390, pkt=0xbffff57c) at 
> libavformat/utils.c:1018
> #3  0x080521bc in av_encode (output_files=0x805e1c0, nb_output_files=1, 
> input_files=0x805cde0, nb_input_files=1,
>     stream_maps=0x805e880, nb_stream_maps=0) at ffmpeg.c:2253
> #4  0x08052dab in main (argc=Cannot access memory at address 0x0
> ) at ffmpeg.c:4016
> (gdb) print ast
> $1 = (AVIStream *) 0x0
> (gdb) print i
> $2 = 1
>
> The problem happens on accessing AVIStream's frame_offset on uninitialized 
> *ast* (that is taken from st->priv_data). Stream's private data been 
> initialized only for one track:
>
> libavformat/avidec.c:
> [...]
>  366                s->nb_streams = 0;
>  367                if (CONFIG_DV_DEMUXER) {
>  368                    avi->dv_demux = dv_init_demux(s);
>  369                    if (!avi->dv_demux)
>  370                        goto fail;
>  371                }
>  372                s->streams[0]->priv_data = ast;
>                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>  373                url_fskip(pb, 3 * 4);
>  374                ast->scale = get_le32(pb);
>  375                ast->rate = get_le32(pb);
> [...]
>
> and second track (audio track) seems been added dynamically in 
> dv_produce_packet->dv_extract_audio_info call and private data for this 
> stream will not be initialized.
>
> So the solution was to disable code:
>
> --- avidec.c	2010-01-14 17:17:04.000000000 +0200
> +++ avidec.c.fixA	2010-01-14 16:12:52.000000000 +0200
> @@ -678,7 +678,7 @@
>              return size;
>      }
>
> -    if(avi->non_interleaved){
> +    if(avi->non_interleaved && !(CONFIG_DV_DEMUXER && avi->dv_demux)){
>          int best_stream_index = 0;
>          AVStream *best_st= NULL;
>          AVIStream *best_ast;
>
> because of /comments/ meaning bellow in libavformat/avidec.c:
>
> [...]
> 1092    if (CONFIG_DV_DEMUXER && avi->dv_demux) {
> 1093        /* One and only one real stream for DV in AVI, and it has video 
>  */
> 1094        /* offsets. Calling with other stream indexes should have 
> failed */
> 1095        /* the av_index_search_timestamp call above.      */
> 1096        assert(stream_index == 0);
> 1097
> 1098        /* Feed the DV video stream version of the timestamp to the */
> 1099        /* DV demux so it can synthesize correct timestamps.        */
> 1100        dv_offset_reset(avi->dv_demux, timestamp);
> 1101
> 1102        url_fseek(s->pb, pos, SEEK_SET);
> 1103        avi->stream_index= -1;
> 1104        return 0;
> 1105    }
> [...]
>
> Am i wrong?

the correct solution is to use chained demuxers,
failing that, a single stream cant be non_interleaved whatever sets it
is likely wrong

[...]
-- 
Michael     GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB

Its not that you shouldnt use gotos but rather that you should write
readable code and code with gotos often but not always is less readable
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: Digital signature
URL: <http://lists.mplayerhq.hu/pipermail/ffmpeg-devel/attachments/20100114/3204c5b6/attachment.pgp>



More information about the ffmpeg-devel mailing list