From dacaa73ae5010b66f4224d70a520945e5b653544 Mon Sep 17 00:00:00 2001 From: Andreas Huber Date: Mon, 7 Dec 2009 09:56:32 -0800 Subject: Initial check in of stagefright software AAC decoder based on PV source code. --- media/libstagefright/codecs/aacdec/AACDecoder.cpp | 202 ++++++++++++++++++++++ 1 file changed, 202 insertions(+) create mode 100644 media/libstagefright/codecs/aacdec/AACDecoder.cpp (limited to 'media/libstagefright/codecs/aacdec/AACDecoder.cpp') diff --git a/media/libstagefright/codecs/aacdec/AACDecoder.cpp b/media/libstagefright/codecs/aacdec/AACDecoder.cpp new file mode 100644 index 0000000..03ac88d --- /dev/null +++ b/media/libstagefright/codecs/aacdec/AACDecoder.cpp @@ -0,0 +1,202 @@ +#include "AACDecoder.h" + +#include "../../include/ESDS.h" + +#include "pvmp4audiodecoder_api.h" + +#include +#include +#include +#include + +namespace android { + +AACDecoder::AACDecoder(const sp &source) + : mSource(source), + mStarted(false), + mBufferGroup(NULL), + mConfig(new tPVMP4AudioDecoderExternal), + mDecoderBuf(NULL), + mLastSeekTimeUs(0), + mNumSamplesOutput(0), + mInputBuffer(NULL) { +} + +AACDecoder::~AACDecoder() { + if (mStarted) { + stop(); + } + + delete mConfig; + mConfig = NULL; +} + +status_t AACDecoder::start(MetaData *params) { + CHECK(!mStarted); + + mBufferGroup = new MediaBufferGroup; + mBufferGroup->add_buffer(new MediaBuffer(2048 * 2)); + + mConfig->outputFormat = OUTPUTFORMAT_16PCM_INTERLEAVED; + mConfig->aacPlusUpsamplingFactor = 0; + mConfig->aacPlusEnabled = false; + + int32_t numChannels; + CHECK(mSource->getFormat()->findInt32(kKeyChannelCount, &numChannels)); + mConfig->desiredChannels = numChannels; + + UInt32 memRequirements = PVMP4AudioDecoderGetMemRequirements(); + mDecoderBuf = malloc(memRequirements); + + CHECK_EQ(PVMP4AudioDecoderInitLibrary(mConfig, mDecoderBuf), + MP4AUDEC_SUCCESS); + + uint32_t type; + const void *data; + size_t size; + if (mSource->getFormat()->findData(kKeyESDS, &type, &data, &size)) { + ESDS esds((const char *)data, size); + CHECK_EQ(esds.InitCheck(), OK); + + const void *codec_specific_data; + size_t codec_specific_data_size; + esds.getCodecSpecificInfo( + &codec_specific_data, &codec_specific_data_size); + + mConfig->pInputBuffer = (UChar *)codec_specific_data; + mConfig->inputBufferCurrentLength = codec_specific_data_size; + mConfig->inputBufferMaxLength = 0; + mConfig->inputBufferUsedLength = 0; + mConfig->remainderBits = 0; + + mConfig->pOutputBuffer = NULL; + mConfig->pOutputBuffer_plus = NULL; + mConfig->repositionFlag = false; + + CHECK_EQ(PVMP4AudioDecoderConfig(mConfig, mDecoderBuf), + MP4AUDEC_SUCCESS); + } + + mSource->start(); + + mLastSeekTimeUs = 0; + mNumSamplesOutput = 0; + mStarted = true; + + return OK; +} + +status_t AACDecoder::stop() { + CHECK(mStarted); + + if (mInputBuffer) { + mInputBuffer->release(); + mInputBuffer = NULL; + } + + free(mDecoderBuf); + mDecoderBuf = NULL; + + delete mBufferGroup; + mBufferGroup = NULL; + + mSource->stop(); + + mStarted = false; + + return OK; +} + +sp AACDecoder::getFormat() { + sp srcFormat = mSource->getFormat(); + + int32_t numChannels; + int32_t sampleRate; + CHECK(srcFormat->findInt32(kKeyChannelCount, &numChannels)); + CHECK(srcFormat->findInt32(kKeySampleRate, &sampleRate)); + + sp meta = new MetaData; + meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_RAW); + meta->setInt32(kKeyChannelCount, numChannels); + meta->setInt32(kKeySampleRate, sampleRate); + + return meta; +} + +status_t AACDecoder::read( + MediaBuffer **out, const ReadOptions *options) { + status_t err; + + *out = NULL; + + int64_t seekTimeUs; + if (options && options->getSeekTo(&seekTimeUs)) { + CHECK(seekTimeUs >= 0); + + mNumSamplesOutput = 0; + + if (mInputBuffer) { + mInputBuffer->release(); + mInputBuffer = NULL; + } + } else { + seekTimeUs = -1; + } + + if (mInputBuffer == NULL) { + err = mSource->read(&mInputBuffer, options); + + if (err != OK) { + return err; + } + + if (seekTimeUs >= 0) { + CHECK(mInputBuffer->meta_data()->findInt64( + kKeyTime, &mLastSeekTimeUs)); + + mNumSamplesOutput = 0; + } + } + + MediaBuffer *buffer; + CHECK_EQ(mBufferGroup->acquire_buffer(&buffer), OK); + + mConfig->pInputBuffer = + (UChar *)mInputBuffer->data() + mInputBuffer->range_offset(); + + mConfig->inputBufferCurrentLength = mInputBuffer->range_length(); + mConfig->inputBufferMaxLength = 0; + mConfig->inputBufferUsedLength = 0; + mConfig->remainderBits = 0; + + mConfig->pOutputBuffer = static_cast(buffer->data()); + mConfig->pOutputBuffer_plus = NULL; + mConfig->repositionFlag = false; + + CHECK_EQ(PVMP4AudioDecodeFrame(mConfig, mDecoderBuf), MP4AUDEC_SUCCESS); + + buffer->set_range( + 0, mConfig->frameLength * sizeof(int16_t) * mConfig->desiredChannels); + + mInputBuffer->set_range( + mInputBuffer->range_offset() + mConfig->inputBufferUsedLength, + mInputBuffer->range_length() - mConfig->inputBufferUsedLength); + + if (mInputBuffer->range_length() == 0) { + mInputBuffer->release(); + mInputBuffer = NULL; + } + + buffer->meta_data()->setInt64( + kKeyTime, + mLastSeekTimeUs + + (mNumSamplesOutput * 1000000) / mConfig->samplingRate); + + mNumSamplesOutput += mConfig->frameLength; + + *out = buffer; + + return OK; +} + +} // namespace android -- cgit v1.1