[Libav-user] I can't get audio decoding to work.

Bill Messenger apothemmusic at gmail.com
Wed Jun 22 22:58:40 CEST 2016


I added some code to check if it was crashing because dataSize is negative.
It's not. Also, I found out that dtSize in this instance is 4608, and no
matter what I do, sizeof(frame->data[0]) is always 8. Also, I tried
sizeof(frame->data) which returned 64.

int dtSize = av_samples_get_buffer_size(nullptr, codecCtx->channels,
frame->nb_samples, codecCtx->sample_fmt, 1);
wxGetApp().popUpErrorDialog("dtSize: " + std::to_string(dtSize));
dataSize = dtSize;

while(totalBufferSize + dataSize > estimatedBuffSize)
{
estimatedBuffSize *= 1.1;
sampleBuffer = (uint8_t*)std::realloc(sampleBuffer, estimatedBuffSize);
}
wxGetApp().popUpErrorDialog("sizeof(frame->data[0]): " +
std::to_string(sizeof(frame->data[0])));

std::memcpy(sampleBuffer + totalBufferSize, frame->data[0], dataSize);

totalBufferSize += dataSize;
totalSamples += frame->nb_samples;

On Mon, Jun 20, 2016 at 5:47 PM, Bill Messenger <apothemmusic at gmail.com>
wrote:

> This is the function I'm using to decode the audio file. My guess is that
> it's crashing because "dataSize" is larger than "frame->data[0]", but I'm
> pretty sure my calculation of dataSize is correct. Am I copying the frame
> data to "sampleBuffer" the wrong way?
>
> bool AudioDecoder::decodeFile(std::string* filename)
> {
> reset(); // if a file has already been decoded, free it from memory and
> reset
>
> AVFormatContext* formatCtx = avformat_alloc_context();
> if(avformat_open_input(&formatCtx, filename->c_str(), nullptr, nullptr) <
> 0)
> {
> wxGetApp().popUpErrorDialog("Couldn't open \"" + *filename + "\".");
> avformat_close_input(&formatCtx);
> return false;
> }
>
> if(avformat_find_stream_info(formatCtx, nullptr) < 0)
> {
> wxGetApp().popUpErrorDialog("Couldn't find file info for \"" + *filename +
> "\".");
> avformat_close_input(&formatCtx);
> return false;
> }
>
> av_dump_format(formatCtx, 0, filename->c_str(), false);
>
> int streamID = -1;
> for(int i = 0; i < formatCtx->nb_streams; i++)
> {
> if(formatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO)
> {
> streamID = i;
> break;
> }
> }
> if(streamID == -1)
> {
> wxGetApp().popUpErrorDialog("\"" + *filename + "\" does not contain
> audio.");
> avformat_close_input(&formatCtx);
> return false;
> }
>
> AVCodecContext* codecCtx = formatCtx->streams[streamID]->codec;
> AVCodec* codec = avcodec_find_decoder(codecCtx->codec_id);
> if(!codec)
> {
> wxGetApp().popUpErrorDialog("Couldn't find the codec for \"" + *filename +
> "\".");
> avformat_close_input(&formatCtx);
> return false;
> }
> if(avcodec_open2(codecCtx, codec, nullptr) < 0)
> {
> wxGetApp().popUpErrorDialog("Couldn't open the codec for\"" + *filename +
> "\".");
> avformat_close_input(&formatCtx);
> return false;
> }
>
> sampleFormat = codecCtx->sample_fmt;
> if(!(sampleFormat == AV_SAMPLE_FMT_U8 || sampleFormat == AV_SAMPLE_FMT_U8P
> ||
> sampleFormat == AV_SAMPLE_FMT_S16 || sampleFormat == AV_SAMPLE_FMT_S16P ||
> sampleFormat == AV_SAMPLE_FMT_S32 || sampleFormat == AV_SAMPLE_FMT_S32P ||
> sampleFormat == AV_SAMPLE_FMT_FLT || sampleFormat == AV_SAMPLE_FMT_FLTP ||
> sampleFormat == AV_SAMPLE_FMT_DBL || sampleFormat == AV_SAMPLE_FMT_DBLP))
> {
> wxGetApp().popUpErrorDialog("\"" + *filename + "\" uses an unsupported
> format.");
> avcodec_close(codecCtx);
> avformat_close_input(&formatCtx);
> return false;
> }
>
> planar = false;
> if(sampleFormat == AV_SAMPLE_FMT_U8P || sampleFormat == AV_SAMPLE_FMT_S16P
> ||
>   sampleFormat == AV_SAMPLE_FMT_S32P || sampleFormat == AV_SAMPLE_FMT_FLTP
> || sampleFormat == AV_SAMPLE_FMT_DBLP)
> {
> planar = true;
> }
>
> AVFrame* frame = av_frame_alloc();
> if(!frame)
> {
> wxGetApp().popUpErrorDialog("Failed to allocate an audio frame.");
> avcodec_close(codecCtx);
> avformat_close_input(&formatCtx);
> return false;
> }
>
> AVPacket packet;
> av_init_packet(&packet);
>
> duration = formatCtx->duration / (double)AV_TIME_BASE; // duration is
> defined in AudioDecoder.h as "double duration = 0;"
>
> uint64_t estimatedBuffSize = std::ceil(duration * codecCtx->sample_rate *
> av_get_bytes_per_sample(codecCtx->sample_fmt) * codecCtx->channels);
>
> sampleBuffer = (uint8_t*)std::malloc(estimatedBuffSize); // sampleBuffer
> is defined in AudioDecoder.h as "uint8_t* sampleBuffer = nullptr;"
> sampleBufferSet = true;
>
> int len;
> int gotFrame = 0;
> uint64_t dataSize;
> uint64_t totalBufferSize = 0;
> uint64_t totalSamples = 0;
> while(av_read_frame(formatCtx, &packet) == 0)
> {
> len = avcodec_decode_audio4(codecCtx, frame, &gotFrame, &packet);
> if(len < 0)
> {
> wxGetApp().popUpErrorDialog("Error while decoding.");
> std::free(sampleBuffer);
> sampleBufferSet = false;
> av_packet_unref(&packet);
> av_frame_free(&frame);
> avcodec_close(codecCtx);
> avformat_close_input(&formatCtx);
> return false;
> }
>
> if(gotFrame)
> {
> dataSize = av_samples_get_buffer_size(nullptr, codecCtx->channels,
> frame->nb_samples, codecCtx->sample_fmt, 1);
>
> while(totalBufferSize + dataSize > estimatedBuffSize)
> {
> estimatedBuffSize *= 1.1;
> sampleBuffer = (uint8_t*)std::realloc(sampleBuffer, estimatedBuffSize);
> }
>
> std::memcpy(sampleBuffer + totalBufferSize, frame->data[0], dataSize);
>
> totalBufferSize += dataSize;
> totalSamples += frame->nb_samples;
> }
>
> av_packet_unref(&packet);
> }
>
> sampleBuffer = (uint8_t*)std::realloc(sampleBuffer, totalBufferSize);
>
> numChannels = codecCtx->channels;
> sampleRate = codecCtx->sample_rate;
> numSamples = totalSamples;
> bufferSize = totalBufferSize;
>
> av_packet_unref(&packet);
> av_frame_free(&frame);
> avcodec_close(codecCtx);
> avformat_close_input(&formatCtx);
>
> didInit = true;
>
> return true;
> }
>
> On Fri, Jun 17, 2016 at 4:20 PM, Bill Messenger <apothemmusic at gmail.com>
> wrote:
>
>> Update: I found out that it only crashes in debug mode. When I build it
>> in release mode, it doesn't crash. It must be a bug in MSVC 2015 or
>> something.
>>
>> On Fri, Jun 17, 2016 at 4:06 PM, Bill Messenger <apothemmusic at gmail.com>
>> wrote:
>>
>>> I'm trying to create a class that uses FFmpeg to decode any audio file
>>> and store it into memory. Then it has a function that returns a float value
>>> of any sample in that buffer. The code I wrote works perfectly for wav and
>>> flac files, produces weird audio for mp3 and ogg files, and crashes on
>>> certain mp3 files. I spent days trying to figure out why it isn't working,
>>> but I can't come up with anything.
>>>
>>> I think the reason why the audio is weird for mp3 and ogg files is that
>>> it uses planar audio instead of interleaved audio, but I don't see what's
>>> wrong with the code I wrote. I may be missing something though. For
>>> example, to get a sample for 16 bit interleaved audio I use:
>>>
>>> int16_t tmp = ((int16_t*)sampleBuffer)[numChannels*sample + channel];
>>> rv = (float)tmp / 32767.0f;
>>>
>>> and to get a sample for 16 bit planar audio I use:
>>>
>>> int16_t tmp = ((int16_t*)sampleBuffer)[sample + numSamples*channel];
>>> rv = (float)tmp / 32767.0f;
>>>
>>> And I have no clue why it crashes on certain mp3 files. I paid close
>>> attention to make sure there is enough memory allocated in the buffer.
>>> What's even weirder is that the file I created "Chiptune 15 2.mp3" didn't
>>> crash, but when I renamed it to "test.mp3", it crashed! These crashes
>>> happen on line 139 of "AudioDecoder.cpp":
>>>
>>> std::memcpy(sampleBuffer + totalBufferSize, frame->extended_data[0],
>>> dataSize);
>>>
>>> with an "Access violation reading location" error in vcruntime140d.dll.
>>> It says it isn't with location 0x0000000000000000 or 0xFFFFFFFFFFFFFFFF
>>> though, it's a different random location.
>>>
>>> I attached a zip file with the c++ code and two mp3's. Oh yeah, I should
>>> also mention that I'm using MSVC 2015 Community in Windows 10.
>>>
>>
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://ffmpeg.org/pipermail/libav-user/attachments/20160622/395e8d45/attachment.html>


More information about the Libav-user mailing list