Opened 6 years ago

Closed 5 years ago

Last modified 5 years ago

#1834 closed defect (invalid)

swr_convert() results in integer division by zero exception

Reported by: mbradshaw Owned by: michael
Priority: normal Component: swresample
Version: git-master Keywords:
Cc: Blocked By:
Blocking: Reproduced by developer: no
Analyzed by developer: no

Description

Summary of the bug:
When I call swr_convert() I get an integer division by zero exception at 0x707c86ee. The disassembly around 0x707c86ee, should it help, is:

707C86AB  je          707C86E4  
707C86AD  mov         edx,dword ptr [ebx+4E8h]  
707C86B3  test        edx,edx  
707C86B5  jne         707C8743  
707C86BB  mov         dword ptr [esp+0Ch],edi  
707C86BF  mov         dword ptr [esp+8],ebp  
707C86C3  mov         dword ptr [esp+4],esi  
707C86C7  mov         dword ptr [esp],eax  
707C86CA  mov         dword ptr [esp+2Ch],ecx  
707C86CE  call        707C2AF4  
707C86D3  mov         ecx,dword ptr [esp+2Ch]  
707C86D7  mov         eax,ecx  
707C86D9  add         esp,3Ch  
707C86DC  pop         ebx  
707C86DD  pop         esi  
707C86DE  pop         edi  
707C86DF  pop         ebp  
707C86E0  ret  
707C86E1  lea         esi,[esi]  
707C86E4  test        edi,edi  
707C86E6  js          707C873C  
707C86E8  mov         eax,3FFFFFFFh  
707C86ED  cdq  
707C86EE  idiv        eax,dword ptr [ebx+1B4h]  
707C86F4  cdq  
707C86F5  idiv        eax,dword ptr [ebx+1B0h]  
707C86FB  cmp         edi,eax  
707C86FD  jg          707C873C  
707C86FF  cmp         edi,dword ptr [ebx+1B8h]  
707C8705  jle         707C8724  
707C8707  lea         eax,[ebx+12Ch]  
707C870D  mov         edx,edi  
707C870F  mov         dword ptr [esp+2Ch],ecx  
707C8713  call        707C77C8  
707C8718  test        eax,eax  
707C871A  mov         ecx,dword ptr [esp+2Ch]  
707C871E  jns         707C8724  
707C8720  mov         ecx,eax  
707C8722  jmp         707C86D7  
707C8724  mov         dword ptr [esp+54h],edi  
707C8728  mov         dword ptr [esp+50h],ebp  
707C872C  mov         edx,esi  
707C872E  mov         eax,ebx  
707C8730  add         esp,3Ch  
707C8733  pop         ebx  
707C8734  pop         esi  
707C8735  pop         edi  
707C8736  pop         ebp  
707C8737  jmp         707C80B4  
707C873C  mov         ecx,0FFFFFFEAh  

This happens with more than just the attached sample file, but I've attached a file just in case. The very first call to swr_convert() results in this division by zero exception.

How to reproduce: (some lame sample code just to show when it's happening)

#include <iostream>

extern "C"
{
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libswresample/swresample.h>
};

int main()
{
    av_register_all();

    AVFrame* frame = avcodec_alloc_frame();
    if (!frame)
    {
        std::cout << "Error allocating the frame" << std::endl;
        return 1;
    }

    AVFormatContext* formatContext = NULL;
    if (avformat_open_input(&formatContext, "C:/Users/mbradshaw/Desktop/samples/TimeCode.mov", NULL, NULL) != 0)
    {
        av_free(frame);
        std::cout << "Error opening the file" << std::endl;
        return 1;
    }

    if (avformat_find_stream_info(formatContext, NULL) < 0)
    {
        av_free(frame);
        av_close_input_file(formatContext);
        std::cout << "Error finding the stream info" << std::endl;
        return 1;
    }

    AVStream* audioStream = NULL;
    for (unsigned int i = 0; i < formatContext->nb_streams; ++i)
    {
        if (formatContext->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO)
        {
            audioStream = formatContext->streams[i];
            break;
        }
    }

    if (audioStream == NULL)
    {
        av_free(frame);
        av_close_input_file(formatContext);
        std::cout << "Could not find any audio stream in the file" << std::endl;
        return 1;
    }

    AVCodecContext* codecContext = audioStream->codec;

    codecContext->codec = avcodec_find_decoder(codecContext->codec_id);
    if (codecContext->codec == NULL)
    {
        av_free(frame);
        av_close_input_file(formatContext);
        std::cout << "Couldn't find a proper decoder" << std::endl;
        return 1;
    }
    else if (avcodec_open2(codecContext, codecContext->codec, NULL) != 0)
    {
        av_free(frame);
        av_close_input_file(formatContext);
        std::cout << "Couldn't open the context with the decoder" << std::endl;
        return 1;
    }

    SwrContext* swrContext = NULL;
    swrContext = swr_alloc_set_opts(swrContext,
        codecContext->channel_layout, // out channel layout
        codecContext->sample_fmt, // out sample format
        codecContext->sample_rate, // out sample rate
        codecContext->channel_layout, // in channel layout
        codecContext->sample_fmt, // in sample format
        codecContext->sample_rate, // in sample rate
        0, // log offset
        NULL); // log context

    if (!swrContext)
    {
        av_free(frame);
        avcodec_close(codecContext);
        av_close_input_file(formatContext);
        std::cout << "Couldn't allocate and set the resampling context" << std::endl;
        return 1;
    }

    int bufSize = av_samples_get_buffer_size(NULL, codecContext->channels, codecContext->sample_rate, codecContext->sample_fmt, 0);
    uint8_t* buf = new uint8_t[bufSize];

    AVPacket packet;
    av_init_packet(&packet);

    int packetCount = 0;
    int decodedFrameCount = 0;
    while (av_read_frame(formatContext, &packet) == 0)
    {
        ++packetCount;
        if (packet.stream_index == audioStream->index)
        {
            int frameFinished = 0;
            avcodec_decode_audio4(codecContext, frame, &frameFinished, &packet);

            if (frameFinished)
            {
                const uint8_t** in = (const uint8_t**)frame->extended_data;
                uint8_t* out[SWR_CH_MAX] = {buf, NULL};

                std::cout << "converted: " << swr_convert(swrContext, out, codecContext->sample_rate, in, frame->nb_samples) << std::endl;
            }
        }

        av_free_packet(&packet);
    }

    delete [] buf;
    swr_free(&swrContext);
    av_free(frame);
    avcodec_close(codecContext);
    av_close_input_file(formatContext);
}

Attachments (1)

TimeCode.mov (2.1 MB) - added by mbradshaw 6 years ago.

Change History (8)

Changed 6 years ago by mbradshaw

comment:1 in reply to: ↑ description ; follow-up: Changed 6 years ago by cehoyos

Replying to mbradshaw:

Summary of the bug:
When I call swr_convert() I get an integer division by zero exception at 0x707c86ee. The disassembly around 0x707c86ee, should it help, is:

The disassembly looks very odd, did you read http://ffmpeg.org/bugreports.html ?

Is the FPE reproducible with ffmpeg (the application)? If not, do you know why?

comment:2 in reply to: ↑ 1 Changed 6 years ago by mbradshaw

Replying to cehoyos:

Replying to mbradshaw:

Summary of the bug:
When I call swr_convert() I get an integer division by zero exception at 0x707c86ee. The disassembly around 0x707c86ee, should it help, is:

The disassembly looks very odd, did you read http://ffmpeg.org/bugreports.html ?

Heh, sorry, I forgot it was Intel syntax and not AT&T syntax. I've re-run the program (on OS X 10.6) with gdb and got the following:

Program received signal EXC_ARITHMETIC, Arithmetic exception.
0x0000000100632ba8 in realloc_audio (a=0x10185f9d0, count=1024) at libswresample/swresample.c:359
359	    if(count < 0 || count > INT_MAX/2/a->bps/a->ch_count)

It looks like a->bps and a->ch_count are both zero.

(gdb) p *a
$5 = {
  ch = {0x0 <repeats 32 times>}, 
  data = 0x0, 
  ch_count = 0, 
  bps = 0, 
  count = 0, 
  planar = 0, 
  fmt = AV_SAMPLE_FMT_U8
}

Backtrace is (I'm not entirely sure why it says there's only two frames...):

(gdb) bt
#0  0x0000000100632ba8 in realloc_audio (a=0x10185f9d0, count=1024) at libswresample/swresample.c:359
#1  0x00000001006334de in swr_convert_internal (s=0x400, out=0x10185fd30, out_count=0, in=0x0, in_count=25557456) at libswresample/swresample.c:535

I can post the disassembly of realloc_audio if needed, but I don't think that's necessary.


Is the FPE reproducible with ffmpeg (the application)? If not, do you know why?

No (or at least I haven't found a way to trigger it). Doing ffmpeg -i TimeCode.mov -strict -2 -af "aconvert=s16:stereo" out.mp4 (or mono) did not result in any errors. I've no clue why my code gets the floating point exception but ffmpeg does not. file reports both my program and ffmpeg as "Mach-O 64-bit executable x86_64". However, I get this same crash on Windows 7 64-bit (using 32-bit ffmpeg in a 32-bit application).

I probably should've added this: the video file info is:

$ ffmpeg -i TimeCode.mov 
ffmpeg version N-45342-g6efe1ed Copyright (c) 2000-2012 the FFmpeg developers
  built on Oct 13 2012 10:34:47 with gcc 4.2.1 (GCC) (Apple Inc. build 5666) (dot 3)
  configuration: --enable-libopenjpeg --enable-libx264 --enable-gpl
  libavutil      51. 74.100 / 51. 74.100
  libavcodec     54. 65.100 / 54. 65.100
  libavformat    54. 32.100 / 54. 32.100
  libavdevice    54.  3.100 / 54.  3.100
  libavfilter     3. 19.102 /  3. 19.102
  libswscale      2.  1.101 /  2.  1.101
  libswresample   0. 16.100 /  0. 16.100
  libpostproc    52.  1.100 / 52.  1.100
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'TimeCode.mov':
  Metadata:
    major_brand     : qt  
    minor_version   : 537199360
    compatible_brands: qt  
    creation_time   : 2011-06-13 20:22:03
  Duration: 00:00:15.04, start: 0.038345, bitrate: 1173 kb/s
    Stream #0:0(eng): Audio: aac (mp4a / 0x6134706D), 44100 Hz, stereo, s16, 157 kb/s
    Metadata:
      creation_time   : 2011-06-13 20:22:03
      handler_name    : Apple Alias Data Handler
    Stream #0:1(eng): Video: h264 (Baseline) (avc1 / 0x31637661), yuv420p, 852x480 [SAR 1:1 DAR 71:40], 1003 kb/s, 23.98 fps, 24 tbr, 600 tbn, 47.95 tbc
    Metadata:
      creation_time   : 2011-06-13 20:22:03
      handler_name    : Apple Alias Data Handler

comment:3 Changed 6 years ago by mbradshaw

  • Resolution set to invalid
  • Status changed from new to closed

*Sigh*

I wasn't calling swr_init().

comment:4 Changed 5 years ago by TheSHEEEP

  • Resolution invalid deleted
  • Status changed from closed to reopened

Hey.

I do have the same problem as the OP, but mine did not go away after calling swr_init() as I did so from the beginning.

Here is how I initialize the context:

SwrContext* swrContext = swr_alloc_set_opts(NULL, 
                audioCodecContext->channel_layout, AV_SAMPLE_FMT_S16P, audioCodecContext->sample_rate,
                audioCodecContext->channel_layout, audioCodecContext->sample_fmt, audioCodecContext->sample_rate, 
                0, NULL);
int result = swr_init(swrContext);

// Create destination sample buffer
uint8_t* destBuffer = NULL;
int destBufferLinesize;
av_samples_alloc(   &destBuffer,
                        &destBufferLinesize,
                        videoInfo.audioNumChannels,
                        2048,
                        AV_SAMPLE_FMT_S16P,
                        0);

And here is the call to convert:

int outputSamples = swr_convert(p_swrContext, 
                                &p_destBuffer, 2048, 
                                (const uint8_t**)p_frame->extended_data, p_frame->nb_samples);

I also tried using AV_SAMPLE_FMT_S16 (non-planar, as that is what OpenAL wants AFAIK), but it yields the same crash (division by 0 because of what OP said).

Also, I do not get any FFmpeg errors in the log and av_samples_alloc, swr_alloc_set_opts and swr_init do not return any errors, either.

Last edited 5 years ago by TheSHEEEP (previous) (diff)

comment:5 Changed 5 years ago by cehoyos

  • Resolution set to invalid
  • Status changed from reopened to closed

Please do not reopen ancient tickets and please understand that this is a bug tracker, not a support forum.

comment:6 Changed 5 years ago by TheSHEEEP

Should I open a new one instead? This really does seem like a bug to me (or at least a missing error log).

comment:7 Changed 5 years ago by cehoyos

If there is a bug, then a report would be (very) welcome.

Can you reproduce the crash with ffmpeg (the application)? If not, please consider to find out why before opening a new ticket. I also believe that you should give other readers of libav-user a little more time to answer.

Note: See TracTickets for help on using tickets.