Skip to content

Commit

Permalink
Fix audio decoding following FFmpeg resync
Browse files Browse the repository at this point in the history
We can't assume that decoded data is on a single plane.
Also, we do need to allocate 4 times the maximum audio buffer as potentially data could grow by a factor of 4 (uint8_t -> float)
An error was introduced for passthrough audio ; would have affected mythtranscode with passthrough enabled.
Potentially, audio buffer wouldn't have been 16 bytes aligned.
  • Loading branch information
jyavenard committed May 9, 2012
1 parent ea65b58 commit 579fdcf
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 56 deletions.
105 changes: 50 additions & 55 deletions mythtv/libs/libmythtv/avformatdecoder.cpp
Expand Up @@ -302,8 +302,6 @@ AvFormatDecoder::AvFormatDecoder(MythPlayer *parent,
// Interactive TV
itv(NULL),
// Audio
m_audioFrame(NULL),
audioSamples(NULL),
disable_passthru(false),
m_fps(0.0f),
codec_is_mpeg(false)
Expand All @@ -312,7 +310,8 @@ AvFormatDecoder::AvFormatDecoder(MythPlayer *parent,
memset(ccX08_in_pmt, 0, sizeof(ccX08_in_pmt));
memset(ccX08_in_tracks, 0, sizeof(ccX08_in_tracks));

m_audioFrame = avcodec_alloc_frame();
audioSamples = (uint8_t *)av_mallocz(AVCODEC_MAX_AUDIO_FRAME_SIZE *
sizeof(int32_t));
ccd608->SetIgnoreTimecode(true);

bool debug = VERBOSE_LEVEL_CHECK(VB_LIBAV, LOG_ANY);
Expand Down Expand Up @@ -346,7 +345,7 @@ AvFormatDecoder::~AvFormatDecoder()

sws_freeContext(sws_ctx);

av_free(m_audioFrame);
av_free(audioSamples);

if (avfRingBuffer)
delete avfRingBuffer;
Expand Down Expand Up @@ -4107,20 +4106,9 @@ bool AvFormatDecoder::ProcessAudioPacket(AVStream *curstream, AVPacket *pkt,
ctx->channels = m_audio->GetMaxChannels();
}

avcodec_get_frame_defaults(m_audioFrame);
int got_frame = 0;

ret = avcodec_decode_audio4(ctx, m_audioFrame, &got_frame,
&tmp_pkt);
if (ret > 0 && got_frame)
{
decoded_size = ret;
already_decoded = true;
data_size = av_samples_get_buffer_size(NULL, ctx->channels,
m_audioFrame->nb_samples,
ctx->sample_fmt, 1);
audioSamples = m_audioFrame->extended_data[0];
}
ret = DecodeAudio(ctx, audioSamples, data_size, &tmp_pkt);
decoded_size = data_size;
already_decoded = true;
reselectAudioTrack |= ctx->channels;
}

Expand Down Expand Up @@ -4167,30 +4155,16 @@ bool AvFormatDecoder::ProcessAudioPacket(AVStream *curstream, AVPacket *pkt,
{
if (!already_decoded)
{
decoded_size = -1;
if (m_audio->NeedDecodingBeforePassthrough())
{
avcodec_get_frame_defaults(m_audioFrame);
int got_frame = 0;

ret = avcodec_decode_audio4(ctx, m_audioFrame, &got_frame,
&tmp_pkt);
if (ret > 0 && got_frame)
{
decoded_size = ret;
data_size =
av_samples_get_buffer_size(NULL, ctx->channels,
m_audioFrame->nb_samples,
ctx->sample_fmt, 1);
audioSamples = m_audioFrame->extended_data[0];
}
ret = DecodeAudio(ctx, audioSamples, data_size, &tmp_pkt);
decoded_size = data_size;
}
else
decoded_size = -1;
}
else
{
audioSamples = tmp_pkt.data;
data_size = tmp_pkt.size;
}
memcpy(audioSamples, tmp_pkt.data, tmp_pkt.size);
data_size = tmp_pkt.size;
// We have processed all the data, there can't be any left
tmp_pkt.size = 0;
}
Expand All @@ -4207,20 +4181,8 @@ bool AvFormatDecoder::ProcessAudioPacket(AVStream *curstream, AVPacket *pkt,
else
ctx->request_channels = 0;

avcodec_get_frame_defaults(m_audioFrame);
int got_frame = 0;

ret = avcodec_decode_audio4(ctx, m_audioFrame, &got_frame,
&tmp_pkt);
if (ret > 0 && got_frame)
{
decoded_size = ret;
data_size =
av_samples_get_buffer_size(NULL, ctx->channels,
m_audioFrame->nb_samples,
ctx->sample_fmt, 1);
audioSamples = m_audioFrame->extended_data[0];
}
ret = DecodeAudio(ctx, audioSamples, data_size, &tmp_pkt);
decoded_size = data_size;
}

// When decoding some audio streams the number of
Expand Down Expand Up @@ -4253,9 +4215,9 @@ bool AvFormatDecoder::ProcessAudioPacket(AVStream *curstream, AVPacket *pkt,

long long temppts = lastapts;

if (audSubIdx != -1)
extract_mono_channel(audSubIdx, &audioOut, (char *)audioSamples,
data_size);
if (audSubIdx != -1 && !audioOut.do_passthru)
extract_mono_channel(audSubIdx, &audioOut,
(char *)audioSamples, data_size);

int frames = (ctx->channels <= 0 || decoded_size < 0) ? -1 :
decoded_size / (ctx->channels *
Expand Down Expand Up @@ -4285,6 +4247,39 @@ bool AvFormatDecoder::ProcessAudioPacket(AVStream *curstream, AVPacket *pkt,
return true;
}

int AvFormatDecoder::DecodeAudio(AVCodecContext *ctx,
uint8_t *buffer, int &data_size,
AVPacket *pkt)
{
AVFrame frame;
int got_frame = 0;

int ret = avcodec_decode_audio4(ctx, &frame, &got_frame, pkt);
if (ret < 0 || !got_frame)
{
data_size = 0;
return ret;
}

int plane_size;
int planar = av_sample_fmt_is_planar(ctx->sample_fmt);
data_size = av_samples_get_buffer_size(&plane_size, ctx->channels,
frame.nb_samples,
ctx->sample_fmt, 1);
memcpy(buffer, frame.extended_data[0], plane_size);

if (planar && ctx->channels > 1)
{
uint8_t *out = buffer + plane_size;
for (int i = 1; i < ctx->channels; i++)
{
memcpy(out, frame.extended_data[i], plane_size);
out += plane_size;
}
}
return ret;
}

// documented in decoderbase.h
bool AvFormatDecoder::GetFrame(DecodeType decodetype)
{
Expand Down
3 changes: 2 additions & 1 deletion mythtv/libs/libmythtv/avformatdecoder.h
Expand Up @@ -255,6 +255,8 @@ class AvFormatDecoder : public DecoderBase
virtual void StreamChangeCheck(void) { }
virtual void PostProcessTracks(void) { }

int DecodeAudio(AVCodecContext *ctx, uint8_t *buffer, int &data_size,
AVPacket *pkt);
PrivateDecoder *private_dec;

bool is_db_ignored;
Expand Down Expand Up @@ -346,7 +348,6 @@ class AvFormatDecoder : public DecoderBase
InteractiveTV *itv; ///< MHEG/MHP decoder

// Audio
AVFrame *m_audioFrame;
uint8_t *audioSamples;
bool disable_passthru;

Expand Down

0 comments on commit 579fdcf

Please sign in to comment.