#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