Skip to content

Commit

Permalink
Small refactor of AC3 encoder.
Browse files Browse the repository at this point in the history
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
  • Loading branch information
jyavenard committed Jun 18, 2013
1 parent 7cd3a05 commit 3690ff3
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 59 deletions.
90 changes: 35 additions & 55 deletions mythtv/libs/libmyth/audio/audiooutputdigitalencoder.cpp
Expand Up @@ -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);
Expand All @@ -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,
Expand Down Expand Up @@ -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();
Expand 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;
}
Expand All @@ -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;
Expand Down Expand Up @@ -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(
Expand All @@ -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)
{
Expand All @@ -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)
Expand Down
7 changes: 3 additions & 4 deletions mythtv/libs/libmyth/audio/audiooutputdigitalencoder.h
Expand Up @@ -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;
Expand All @@ -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;
};

Expand Down

0 comments on commit 3690ff3

Please sign in to comment.