[FFmpeg-trac] #369(avcodec:new): Multichannel encoding with the native aac encoder crashes

FFmpeg trac at avcodec.org
Fri Jul 29 13:50:24 CEST 2011


#369: Multichannel encoding with the native aac encoder crashes
---------------------------+----------------------
Reporter:  cehoyos         |       Owner:
    Type:  defect          |      Status:  new
Priority:  important       |   Component:  avcodec
 Version:  git-master      |  Resolution:
Keywords:  aac regression  |  Blocked By:
Blocking:                  |  Reproduced:  0
Analyzed:  0               |
---------------------------+----------------------

Comment (by danijel):

 I recreated your crash, but for me it ended up in a different place.
 Nevertheless I think I know what might be a problem. This is the gdb dump
 in my case:
 {{{
 (gdb)  r -i Canyon-5.1-48khz-448kbit.ac3 -strict experimental out.aac
 Starting program: /home/guest/ffmpeg/test/bin/ffmpeg -i Canyon-5.1-48khz-
 448kbit
 .ac3 -strict experimental out.aac
 [Thread debugging using libthread_db enabled]
 ffmpeg version N-31617-g4095fa9, Copyright (c) 2000-2011 the FFmpeg
 developers
   built on Jul 29 2011 12:42:33 with gcc 4.6.1
   configuration: --prefix=/home/guest/ffmpeg/test --pkg-config=pkg-config
 --enab
 le-shared --disable-static --enable-runtime-cpudetect --enable-debug=3
 --disable
 -optimizations --disable-stripping
   libavutil    51. 11. 0 / 51. 11. 0
   libavcodec   53.  8. 0 / 53.  8. 0
   libavformat  53.  6. 0 / 53.  6. 0
   libavdevice  53.  2. 0 / 53.  2. 0
   libavfilter   2. 27. 2 /  2. 27. 2
   libswscale    2.  0. 0 /  2.  0. 0
 [ac3 @ 0x806a380] max_analyze_duration 5000000 reached at 5024000
 [ac3 @ 0x806a380] Estimating duration from bitrate, this may be inaccurate
 Input #0, ac3, from 'Canyon-5.1-48khz-448kbit.ac3':
   Duration: 00:00:37.98, start: 0.000000, bitrate: 448 kb/s
     Stream #0.0: Audio: ac3, 48000 Hz, 5.1, s16, 448 kb/s
 File 'out.aac' already exists. Overwrite ? [y/N] y
 Output #0, adts, to 'out.aac':
   Metadata:
     encoder         : Lavf53.6.0
     Stream #0.0: Audio: aac, 48000 Hz, 5.1, s16, 64 kb/s
 Stream mapping:
   Stream #0.0 -> #0.0
 Press [q] to stop, [?] for help

 Program received signal SIGSEGV, Segmentation fault.
 0xb731384f in psy_3gpp_analyze_channel (ctx=0x80668ec, channel=6,
     coefs=0xb65e62c0, wi=0xbfffe554) at libavcodec/aacpsy.c:599
 599             bands[g].thr   = FFMAX(bands[g].thr,    bands[g-1].thr *
 coeffs[
 g].spread_hi[0]);
 }}}

 The code in question being:
 {{{
 (gdb) list 576,603
 576     for (w = 0; w < wi->num_windows*16; w += 16) {
 577         for (g = 0; g < num_bands; g++) {
 578             AacPsyBand *band = &pch->band[w+g];
 579
 580             float form_factor = 0.0f;
 581             band->energy = 0.0f;
 582             for (i = 0; i < band_sizes[g]; i++) {
 583                 band->energy += coefs[start+i] * coefs[start+i];
 584                 form_factor  += sqrtf(fabs(coefs[start+i]));
 585             }
 586             band->thr      = band->energy * 0.001258925f;
 587             band->nz_lines = form_factor / powf(band->energy /
 band_sizes[g], 0.25f);
 588
 589             start += band_sizes[g];
 590         }
 591     }
 592     //modify thresholds and energies - spread, threshold in quiet,
 pre-e---Type <return> to continue, or q <return> to quit---
 cho control
 593     for (w = 0; w < wi->num_windows*16; w += 16) {
 594         AacPsyBand *bands = &pch->band[w];
 595
 596         //5.4.2.3 "Spreading" & 5.4.3 "Spreaded Energy Calculation"
 597         spread_en[0] = bands[0].energy;
 598         for (g = 1; g < num_bands; g++) {
 599             bands[g].thr   = FFMAX(bands[g].thr,    bands[g-1].thr *
 coeffs[g].spread_hi[0]);
 600             spread_en[w+g] = FFMAX(bands[g].energy, spread_en[w+g-1] *
 coeffs[g].spread_hi[1]);
 601         }
 602         for (g = num_bands - 2; g >= 0; g--) {
 603             bands[g].thr   = FFMAX(bands[g].thr,   bands[g+1].thr *
 coeffs[g].spread_low[0]);
 }}}

 My error is in line 599 and yours in 583. I will now show how I analyzed
 my bug and you can do the same yourself to confirm the error.

 If I print the bands variable it turns out to be NULL:
 {{{
 (gdb) p bands
 $8 = (AacPsyBand *) 0x0
 }}}

 Which is strange since it's being set properly to {{{AacPsyBand *bands =
 &pch->band[w];}}} a few lines earlier and not changed anywhere else in
 that loop. If we print the second half of that expression we get a valid
 pointer:
 {{{
 (gdb) p &pch->band[w]
 $10 = (AacPsyBand *) 0x80f1f28
 }}}

 Clearly the error is some sort of a memory leak causing overwriting local
 variables. If we look at what's really happening we can see that
 {{{bands}}} is set to a certain offset of {{{pch->band}}} array
 ({{{&pch->band[w]}}} is the same as {{{pch->band+w}}}) where the array is
 set to a static size of 128 as shown under this link:
 http://ffmpeg.org/doxygen/trunk/structAacPsyChannel.html

 This array is then iterated from the starting offset of 96 (as shown by
 command {{{p w}}}) and increased for {{{num_bands}}} times which is 49.
 Since 96+49 is more than 128, we get a memory leak. In fact, the SEGFAULT
 happens way too late, since on my machine {{{g}}} is at value 44 when the
 OS realizes the error:
 {{{
 (gdb) p w
 $12 = 96
 (gdb) p num_bands
 $13 = 49
 (gdb) p g
 $14 = 44
 }}}

 I guess you could try and increase the static size of the {{{bands}}}
 array to at least 596 (a bit more to make sure) in AacPsyChannel structure
 located in libavcodec/aacpsy.c:117, but I'm not sure if that's how the
 code is supposed to work. My conclusion is meerly by looking at the code.
 I don't really know what it does. I think there is just a bad bug in here
 somewhere cause the code seems to assume that num_bands is <16 and
 wi->num_windows is <8.

-- 
Ticket URL: <https://ffmpeg.org/trac/ffmpeg/ticket/369#comment:1>
FFmpeg <http://ffmpeg.org>
FFmpeg issue tracker


More information about the FFmpeg-trac mailing list