From 3690ff300828e78d05bd9765295754ef3838aa68 Mon Sep 17 00:00:00 2001 From: Jean-Yves Avenard Date: Tue, 11 Jun 2013 12:00:53 +1000 Subject: [PATCH] Small refactor of AC3 encoder. It can now be initialised many times (not that it's ever used that way). Also let FFmpeg allocates the required memory automatically rather than using a fixed size buffer --- .../audio/audiooutputdigitalencoder.cpp | 90 ++++++++----------- .../libmyth/audio/audiooutputdigitalencoder.h | 7 +- 2 files changed, 38 insertions(+), 59 deletions(-) diff --git a/mythtv/libs/libmyth/audio/audiooutputdigitalencoder.cpp b/mythtv/libs/libmyth/audio/audiooutputdigitalencoder.cpp index d224aa4e81d..95c628e8279 100644 --- a/mythtv/libs/libmyth/audio/audiooutputdigitalencoder.cpp +++ b/mythtv/libs/libmyth/audio/audiooutputdigitalencoder.cpp @@ -28,34 +28,22 @@ AudioOutputDigitalEncoder::AudioOutputDigitalEncoder(void) : samples_per_frame(0), m_spdifenc(NULL) { - out = (outbuf_t *)av_malloc(OUTBUFSIZE); + out = (outbuf_t *)av_mallocz(OUTBUFSIZE); if (out) { out_size = OUTBUFSIZE; } - in = (inbuf_t *)av_malloc(INBUFSIZE); + in = (inbuf_t *)av_mallocz(INBUFSIZE); if (in) { in_size = INBUFSIZE; } - inp = (inbuf_t *)av_malloc(INBUFSIZE); - - for (int i = 0; i < FF_MIN_BUFFER_SIZE; i++) - m_encodebuffer[i] = 0; + inp = (inbuf_t *)av_mallocz(INBUFSIZE); } AudioOutputDigitalEncoder::~AudioOutputDigitalEncoder() { - Dispose(); -} - -void AudioOutputDigitalEncoder::Dispose() -{ - if (av_context) - { - avcodec_close(av_context); - av_freep(&av_context); - } + Reset(); if (out) { av_freep(&out); @@ -70,11 +58,19 @@ void AudioOutputDigitalEncoder::Dispose() { av_freep(&inp); } - if (m_spdifenc) +} + +void AudioOutputDigitalEncoder::Reset(void) +{ + if (av_context) { - delete m_spdifenc; - m_spdifenc = NULL; + avcodec_close(av_context); + av_freep(&av_context); } + delete m_spdifenc; + m_spdifenc = NULL; + + clear(); } void *AudioOutputDigitalEncoder::realloc(void *ptr, @@ -106,6 +102,15 @@ bool AudioOutputDigitalEncoder::Init( .arg(ff_codec_id_string(codec_id)) .arg(bitrate) .arg(samplerate) .arg(channels)); + if (!(in || inp || out)) + { + LOG(VB_GENERAL, LOG_ERR, LOC + "Memory allocation failed"); + return false; + } + + // Clear digital encoder from all existing content + Reset(); + // We need to do this when called from mythmusic avcodeclock->lock(); avcodec_register_all(); @@ -123,49 +128,22 @@ bool AudioOutputDigitalEncoder::Init( av_context->bit_rate = bitrate; av_context->sample_rate = samplerate; av_context->channels = channels; - switch (channels) - { - case 1: - av_context->channel_layout = AV_CH_LAYOUT_MONO; - break; - case 2: - av_context->channel_layout = AV_CH_LAYOUT_STEREO; - break; - case 3: - av_context->channel_layout = AV_CH_LAYOUT_SURROUND; - break; - case 4: - av_context->channel_layout = AV_CH_LAYOUT_4POINT0; - break; - case 5: - av_context->channel_layout = AV_CH_LAYOUT_5POINT0; - break; - default: - av_context->channel_layout = AV_CH_LAYOUT_5POINT1; - break; - } + av_context->channel_layout = av_get_default_channel_layout(channels); av_context->sample_fmt = AV_SAMPLE_FMT_S16P; -// open it + // open it ret = avcodec_open2(av_context, codec, NULL); if (ret < 0) { LOG(VB_GENERAL, LOG_ERR, LOC + "Could not open codec, invalid bitrate or samplerate"); - Dispose(); return false; } - if (m_spdifenc) - { - delete m_spdifenc; - } - m_spdifenc = new SPDIFEncoder("spdif", AV_CODEC_ID_AC3); if (!m_spdifenc->Succeeded()) { - Dispose(); LOG(VB_GENERAL, LOG_ERR, LOC + "Could not create spdif muxer"); return false; } @@ -188,8 +166,9 @@ size_t AudioOutputDigitalEncoder::Encode(void *buf, int len, AudioFormat format) } // Check if there is enough space in incoming buffer - int required_len = inlen + len / sampleSize * - AudioOutputSettings::SampleSize(FORMAT_S16); + int required_len = inlen + + len * AudioOutputSettings::SampleSize(FORMAT_S16) / sampleSize; + if (required_len > (int)in_size) { required_len = ((required_len / INBUFSIZE) + 1) * INBUFSIZE; @@ -243,8 +222,8 @@ size_t AudioOutputDigitalEncoder::Encode(void *buf, int len, AudioFormat format) { AVPacket pkt; av_init_packet(&pkt); - pkt.data = (uint8_t *)m_encodebuffer; - pkt.size = sizeof(m_encodebuffer); + pkt.data = NULL; + pkt.size = 0; int got_packet = 0; AudioOutputUtil::DeinterleaveSamples( @@ -255,7 +234,6 @@ size_t AudioOutputDigitalEncoder::Encode(void *buf, int len, AudioFormat format) int ret = avcodec_encode_audio2(av_context, &pkt, frame, &got_packet); - int outsize = pkt.size; if (ret < 0) { @@ -266,13 +244,15 @@ size_t AudioOutputDigitalEncoder::Encode(void *buf, int len, AudioFormat format) i++; if (!got_packet) continue; - av_free_packet(&pkt); if (!m_spdifenc) { m_spdifenc = new SPDIFEncoder("spdif", AV_CODEC_ID_AC3); } - m_spdifenc->WriteFrame((uint8_t *)m_encodebuffer, outsize); + + m_spdifenc->WriteFrame((uint8_t *)pkt.data, pkt.size); + av_free_packet(&pkt); + // Check if output buffer is big enough required_len = outlen + m_spdifenc->GetProcessedSize(); if (required_len > (int)out_size) diff --git a/mythtv/libs/libmyth/audio/audiooutputdigitalencoder.h b/mythtv/libs/libmyth/audio/audiooutputdigitalencoder.h index c4ebef3e0aa..6da648d07fc 100644 --- a/mythtv/libs/libmyth/audio/audiooutputdigitalencoder.h +++ b/mythtv/libs/libmyth/audio/audiooutputdigitalencoder.h @@ -21,15 +21,15 @@ class AudioOutputDigitalEncoder ~AudioOutputDigitalEncoder(); bool Init(CodecID codec_id, int bitrate, int samplerate, int channels); - void Dispose(void); size_t Encode(void *buf, int len, AudioFormat format); size_t GetFrames(void *ptr, int maxlen); int Buffered(void) const { return inlen / sizeof(inbuf_t) / av_context->channels; } - void clear(); + void clear(); private: - void *realloc(void *ptr, size_t old_size, size_t new_size); + void Reset(void); + void *realloc(void *ptr, size_t old_size, size_t new_size); AVCodecContext *av_context; outbuf_t *out; @@ -39,7 +39,6 @@ class AudioOutputDigitalEncoder int outlen; int inlen; size_t samples_per_frame; - int16_t m_encodebuffer[FF_MIN_BUFFER_SIZE]; SPDIFEncoder *m_spdifenc; };