Loading media/libstagefright/codecs/aacdec/SoftAAC2.cpp +197 −126 Original line number Diff line number Diff line Loading @@ -14,8 +14,8 @@ * limitations under the License. */ #define LOG_TAG "SoftAAC2" //#define LOG_NDEBUG 0 #define LOG_TAG "SoftAAC2" #include <utils/Log.h> #include "SoftAAC2.h" Loading Loading @@ -68,7 +68,6 @@ SoftAAC2::SoftAAC2( mOutputBufferCount(0), mSignalledError(false), mLastInHeader(NULL), mCurrentInputTime(0), mOutputPortSettingsChange(NONE) { initPorts(); CHECK_EQ(initDecoder(), (status_t)OK); Loading Loading @@ -610,9 +609,24 @@ void SoftAAC2::onQueueFilled(OMX_U32 /* portIndex */) { notify(OMX_EventError, OMX_ErrorStreamCorrupt, ERROR_MALFORMED, NULL); return; } // insert buffer size and time stamp mBufferSizes.add(inBufferLength[0]); if (mLastInHeader != inHeader) { mBufferTimestamps.add(inHeader->nTimeStamp); mLastInHeader = inHeader; } else { int64_t currentTime = mBufferTimestamps.top(); currentTime += mStreamInfo->aacSamplesPerFrame * 1000000ll / mStreamInfo->sampleRate; mBufferTimestamps.add(currentTime); } } else { inBuffer[0] = inHeader->pBuffer + inHeader->nOffset; inBufferLength[0] = inHeader->nFilledLen; mLastInHeader = inHeader; mBufferTimestamps.add(inHeader->nTimeStamp); mBufferSizes.add(inHeader->nFilledLen); } // Fill and decode Loading @@ -621,18 +635,6 @@ void SoftAAC2::onQueueFilled(OMX_U32 /* portIndex */) { INT prevSampleRate = mStreamInfo->sampleRate; INT prevNumChannels = mStreamInfo->numChannels; if (inHeader != mLastInHeader) { mLastInHeader = inHeader; mCurrentInputTime = inHeader->nTimeStamp; } else { if (mStreamInfo->sampleRate) { mCurrentInputTime += mStreamInfo->aacSamplesPerFrame * 1000000ll / mStreamInfo->sampleRate; } else { ALOGW("no sample rate yet"); } } mAnchorTimes.add(mCurrentInputTime); aacDecoder_Fill(mAACDecoder, inBuffer, inBufferLength, Loading @@ -642,21 +644,35 @@ void SoftAAC2::onQueueFilled(OMX_U32 /* portIndex */) { mDrcWrap.submitStreamData(mStreamInfo); mDrcWrap.update(); AAC_DECODER_ERROR decoderErr = aacDecoder_DecodeFrame(mAACDecoder, UINT inBufferUsedLength = inBufferLength[0] - bytesValid[0]; inHeader->nFilledLen -= inBufferUsedLength; inHeader->nOffset += inBufferUsedLength; AAC_DECODER_ERROR decoderErr; do { if (outputDelayRingBufferSamplesLeft() < (mStreamInfo->frameSize * mStreamInfo->numChannels)) { ALOGV("skipping decode: not enough space left in ringbuffer"); break; } int numconsumed = mStreamInfo->numTotalBytes + mStreamInfo->numBadBytes; decoderErr = aacDecoder_DecodeFrame(mAACDecoder, tmpOutBuffer, 2048 * MAX_CHANNEL_COUNT, 0 /* flags */); if (decoderErr != AAC_DEC_OK) { ALOGW("aacDecoder_DecodeFrame decoderErr = 0x%4.4x", decoderErr); numconsumed = (mStreamInfo->numTotalBytes + mStreamInfo->numBadBytes) - numconsumed; if (numconsumed != 0) { mDecodedSizes.add(numconsumed); } if (decoderErr == AAC_DEC_NOT_ENOUGH_BITS) { ALOGE("AAC_DEC_NOT_ENOUGH_BITS should never happen"); mSignalledError = true; notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL); return; break; } if (decoderErr != AAC_DEC_OK) { ALOGW("aacDecoder_DecodeFrame decoderErr = 0x%4.4x", decoderErr); } if (bytesValid[0] != 0) { Loading @@ -676,9 +692,6 @@ void SoftAAC2::onQueueFilled(OMX_U32 /* portIndex */) { notify(OMX_EventError, OMX_ErrorUndefined, decoderErr, NULL); return; } UINT inBufferUsedLength = inBufferLength[0] - bytesValid[0]; inHeader->nFilledLen -= inBufferUsedLength; inHeader->nOffset += inBufferUsedLength; } else { ALOGW("AAC decoder returned error 0x%4.4x, substituting silence", decoderErr); Loading Loading @@ -740,7 +753,7 @@ void SoftAAC2::onQueueFilled(OMX_U32 /* portIndex */) { notify(OMX_EventError, OMX_ErrorUndefined, decoderErr, NULL); return; } if (inHeader->nFilledLen == 0) { if (inHeader && inHeader->nFilledLen == 0) { inInfo->mOwnedByUs = false; mInputBufferCount++; inQueue.erase(inQueue.begin()); Loading @@ -749,8 +762,9 @@ void SoftAAC2::onQueueFilled(OMX_U32 /* portIndex */) { notifyEmptyBufferDone(inHeader); inHeader = NULL; } else { ALOGV("inHeader->nFilledLen = %d", inHeader->nFilledLen); ALOGV("inHeader->nFilledLen = %d", inHeader ? inHeader->nFilledLen : 0); } } while (decoderErr == AAC_DEC_OK); } int32_t outputDelay = mStreamInfo->outputDelay * mStreamInfo->numChannels; Loading Loading @@ -809,8 +823,9 @@ void SoftAAC2::onQueueFilled(OMX_U32 /* portIndex */) { INT_PCM *outBuffer = reinterpret_cast<INT_PCM *>(outHeader->pBuffer + outHeader->nOffset); int samplesize = mStreamInfo->numChannels * sizeof(int16_t); if (outHeader->nOffset + mStreamInfo->frameSize * mStreamInfo->numChannels * sizeof(int16_t) + mStreamInfo->frameSize * samplesize > outHeader->nAllocLen) { ALOGE("buffer overflow"); mSignalledError = true; Loading @@ -818,17 +833,67 @@ void SoftAAC2::onQueueFilled(OMX_U32 /* portIndex */) { return; } int32_t ns = outputDelayRingBufferGetSamples(outBuffer, mStreamInfo->frameSize * mStreamInfo->numChannels); // TODO: check for overflow if (ns != mStreamInfo->frameSize * mStreamInfo->numChannels) { int available = outputDelayRingBufferSamplesAvailable(); int numSamples = outHeader->nAllocLen / sizeof(int16_t); if (numSamples > available) { numSamples = available; } int64_t currentTime = 0; if (available) { int numFrames = numSamples / (mStreamInfo->frameSize * mStreamInfo->numChannels); numSamples = numFrames * (mStreamInfo->frameSize * mStreamInfo->numChannels); ALOGV("%d samples available (%d), or %d frames", numSamples, available, numFrames); int64_t *nextTimeStamp = &mBufferTimestamps.editItemAt(0); currentTime = *nextTimeStamp; int32_t *currentBufLeft = &mBufferSizes.editItemAt(0); for (int i = 0; i < numFrames; i++) { int32_t decodedSize = mDecodedSizes.itemAt(0); mDecodedSizes.removeAt(0); ALOGV("decoded %d of %d", decodedSize, *currentBufLeft); if (*currentBufLeft > decodedSize) { // adjust/interpolate next time stamp *currentBufLeft -= decodedSize; *nextTimeStamp += mStreamInfo->aacSamplesPerFrame * 1000000ll / mStreamInfo->sampleRate; ALOGV("adjusted nextTimeStamp/size to %lld/%d", *nextTimeStamp, *currentBufLeft); } else { // move to next timestamp in list if (mBufferTimestamps.size() > 0) { mBufferTimestamps.removeAt(0); nextTimeStamp = &mBufferTimestamps.editItemAt(0); mBufferSizes.removeAt(0); currentBufLeft = &mBufferSizes.editItemAt(0); ALOGV("moved to next time/size: %lld/%d", *nextTimeStamp, *currentBufLeft); } // try to limit output buffer size to match input buffers // (e.g when an input buffer contained 4 "sub" frames, output // at most 4 decoded units in the corresponding output buffer) // This is optional. Remove the next three lines to fill the output // buffer with as many units as available. numFrames = i + 1; numSamples = numFrames * mStreamInfo->frameSize * mStreamInfo->numChannels; break; } } ALOGV("getting %d from ringbuffer", numSamples); int32_t ns = outputDelayRingBufferGetSamples(outBuffer, numSamples); if (ns != numSamples) { ALOGE("not a complete frame of samples available"); mSignalledError = true; notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL); return; } } outHeader->nFilledLen = numSamples * sizeof(int16_t); outHeader->nFilledLen = mStreamInfo->frameSize * mStreamInfo->numChannels * sizeof(int16_t); if (mEndOfInput && !outQueue.empty() && outputDelayRingBufferSamplesAvailable() == 0) { outHeader->nFlags = OMX_BUFFERFLAG_EOS; mEndOfOutput = true; Loading @@ -836,13 +901,13 @@ void SoftAAC2::onQueueFilled(OMX_U32 /* portIndex */) { outHeader->nFlags = 0; } outHeader->nTimeStamp = mAnchorTimes.isEmpty() ? 0 : mAnchorTimes.itemAt(0); mAnchorTimes.removeAt(0); outHeader->nTimeStamp = currentTime; mOutputBufferCount++; outInfo->mOwnedByUs = false; outQueue.erase(outQueue.begin()); outInfo = NULL; ALOGV("out timestamp %lld / %d", outHeader->nTimeStamp, outHeader->nFilledLen); notifyFillBufferDone(outHeader); outHeader = NULL; } Loading Loading @@ -877,8 +942,10 @@ void SoftAAC2::onQueueFilled(OMX_U32 /* portIndex */) { outHeader->nFilledLen = 0; outHeader->nFlags = OMX_BUFFERFLAG_EOS; outHeader->nTimeStamp = mAnchorTimes.itemAt(0); mAnchorTimes.removeAt(0); outHeader->nTimeStamp = mBufferTimestamps.itemAt(0); mBufferTimestamps.clear(); mBufferSizes.clear(); mDecodedSizes.clear(); mOutputBufferCount++; outInfo->mOwnedByUs = false; Loading @@ -899,7 +966,9 @@ void SoftAAC2::onPortFlushCompleted(OMX_U32 portIndex) { // depend on fragments from the last one decoded. // drain all existing data drainDecoder(); mAnchorTimes.clear(); mBufferTimestamps.clear(); mBufferSizes.clear(); mDecodedSizes.clear(); mLastInHeader = NULL; } else { while (outputDelayRingBufferSamplesAvailable() > 0) { Loading Loading @@ -955,7 +1024,9 @@ void SoftAAC2::onReset() { mOutputDelayRingBufferReadPos = 0; mEndOfInput = false; mEndOfOutput = false; mAnchorTimes.clear(); mBufferTimestamps.clear(); mBufferSizes.clear(); mDecodedSizes.clear(); mLastInHeader = NULL; // To make the codec behave the same before and after a reset, we need to invalidate the Loading media/libstagefright/codecs/aacdec/SoftAAC2.h +3 −2 Original line number Diff line number Diff line Loading @@ -59,8 +59,9 @@ private: size_t mOutputBufferCount; bool mSignalledError; OMX_BUFFERHEADERTYPE *mLastInHeader; int64_t mCurrentInputTime; Vector<int64_t> mAnchorTimes; Vector<int32_t> mBufferSizes; Vector<int32_t> mDecodedSizes; Vector<int64_t> mBufferTimestamps; CDrcPresModeWrapper mDrcWrap; Loading Loading
media/libstagefright/codecs/aacdec/SoftAAC2.cpp +197 −126 Original line number Diff line number Diff line Loading @@ -14,8 +14,8 @@ * limitations under the License. */ #define LOG_TAG "SoftAAC2" //#define LOG_NDEBUG 0 #define LOG_TAG "SoftAAC2" #include <utils/Log.h> #include "SoftAAC2.h" Loading Loading @@ -68,7 +68,6 @@ SoftAAC2::SoftAAC2( mOutputBufferCount(0), mSignalledError(false), mLastInHeader(NULL), mCurrentInputTime(0), mOutputPortSettingsChange(NONE) { initPorts(); CHECK_EQ(initDecoder(), (status_t)OK); Loading Loading @@ -610,9 +609,24 @@ void SoftAAC2::onQueueFilled(OMX_U32 /* portIndex */) { notify(OMX_EventError, OMX_ErrorStreamCorrupt, ERROR_MALFORMED, NULL); return; } // insert buffer size and time stamp mBufferSizes.add(inBufferLength[0]); if (mLastInHeader != inHeader) { mBufferTimestamps.add(inHeader->nTimeStamp); mLastInHeader = inHeader; } else { int64_t currentTime = mBufferTimestamps.top(); currentTime += mStreamInfo->aacSamplesPerFrame * 1000000ll / mStreamInfo->sampleRate; mBufferTimestamps.add(currentTime); } } else { inBuffer[0] = inHeader->pBuffer + inHeader->nOffset; inBufferLength[0] = inHeader->nFilledLen; mLastInHeader = inHeader; mBufferTimestamps.add(inHeader->nTimeStamp); mBufferSizes.add(inHeader->nFilledLen); } // Fill and decode Loading @@ -621,18 +635,6 @@ void SoftAAC2::onQueueFilled(OMX_U32 /* portIndex */) { INT prevSampleRate = mStreamInfo->sampleRate; INT prevNumChannels = mStreamInfo->numChannels; if (inHeader != mLastInHeader) { mLastInHeader = inHeader; mCurrentInputTime = inHeader->nTimeStamp; } else { if (mStreamInfo->sampleRate) { mCurrentInputTime += mStreamInfo->aacSamplesPerFrame * 1000000ll / mStreamInfo->sampleRate; } else { ALOGW("no sample rate yet"); } } mAnchorTimes.add(mCurrentInputTime); aacDecoder_Fill(mAACDecoder, inBuffer, inBufferLength, Loading @@ -642,21 +644,35 @@ void SoftAAC2::onQueueFilled(OMX_U32 /* portIndex */) { mDrcWrap.submitStreamData(mStreamInfo); mDrcWrap.update(); AAC_DECODER_ERROR decoderErr = aacDecoder_DecodeFrame(mAACDecoder, UINT inBufferUsedLength = inBufferLength[0] - bytesValid[0]; inHeader->nFilledLen -= inBufferUsedLength; inHeader->nOffset += inBufferUsedLength; AAC_DECODER_ERROR decoderErr; do { if (outputDelayRingBufferSamplesLeft() < (mStreamInfo->frameSize * mStreamInfo->numChannels)) { ALOGV("skipping decode: not enough space left in ringbuffer"); break; } int numconsumed = mStreamInfo->numTotalBytes + mStreamInfo->numBadBytes; decoderErr = aacDecoder_DecodeFrame(mAACDecoder, tmpOutBuffer, 2048 * MAX_CHANNEL_COUNT, 0 /* flags */); if (decoderErr != AAC_DEC_OK) { ALOGW("aacDecoder_DecodeFrame decoderErr = 0x%4.4x", decoderErr); numconsumed = (mStreamInfo->numTotalBytes + mStreamInfo->numBadBytes) - numconsumed; if (numconsumed != 0) { mDecodedSizes.add(numconsumed); } if (decoderErr == AAC_DEC_NOT_ENOUGH_BITS) { ALOGE("AAC_DEC_NOT_ENOUGH_BITS should never happen"); mSignalledError = true; notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL); return; break; } if (decoderErr != AAC_DEC_OK) { ALOGW("aacDecoder_DecodeFrame decoderErr = 0x%4.4x", decoderErr); } if (bytesValid[0] != 0) { Loading @@ -676,9 +692,6 @@ void SoftAAC2::onQueueFilled(OMX_U32 /* portIndex */) { notify(OMX_EventError, OMX_ErrorUndefined, decoderErr, NULL); return; } UINT inBufferUsedLength = inBufferLength[0] - bytesValid[0]; inHeader->nFilledLen -= inBufferUsedLength; inHeader->nOffset += inBufferUsedLength; } else { ALOGW("AAC decoder returned error 0x%4.4x, substituting silence", decoderErr); Loading Loading @@ -740,7 +753,7 @@ void SoftAAC2::onQueueFilled(OMX_U32 /* portIndex */) { notify(OMX_EventError, OMX_ErrorUndefined, decoderErr, NULL); return; } if (inHeader->nFilledLen == 0) { if (inHeader && inHeader->nFilledLen == 0) { inInfo->mOwnedByUs = false; mInputBufferCount++; inQueue.erase(inQueue.begin()); Loading @@ -749,8 +762,9 @@ void SoftAAC2::onQueueFilled(OMX_U32 /* portIndex */) { notifyEmptyBufferDone(inHeader); inHeader = NULL; } else { ALOGV("inHeader->nFilledLen = %d", inHeader->nFilledLen); ALOGV("inHeader->nFilledLen = %d", inHeader ? inHeader->nFilledLen : 0); } } while (decoderErr == AAC_DEC_OK); } int32_t outputDelay = mStreamInfo->outputDelay * mStreamInfo->numChannels; Loading Loading @@ -809,8 +823,9 @@ void SoftAAC2::onQueueFilled(OMX_U32 /* portIndex */) { INT_PCM *outBuffer = reinterpret_cast<INT_PCM *>(outHeader->pBuffer + outHeader->nOffset); int samplesize = mStreamInfo->numChannels * sizeof(int16_t); if (outHeader->nOffset + mStreamInfo->frameSize * mStreamInfo->numChannels * sizeof(int16_t) + mStreamInfo->frameSize * samplesize > outHeader->nAllocLen) { ALOGE("buffer overflow"); mSignalledError = true; Loading @@ -818,17 +833,67 @@ void SoftAAC2::onQueueFilled(OMX_U32 /* portIndex */) { return; } int32_t ns = outputDelayRingBufferGetSamples(outBuffer, mStreamInfo->frameSize * mStreamInfo->numChannels); // TODO: check for overflow if (ns != mStreamInfo->frameSize * mStreamInfo->numChannels) { int available = outputDelayRingBufferSamplesAvailable(); int numSamples = outHeader->nAllocLen / sizeof(int16_t); if (numSamples > available) { numSamples = available; } int64_t currentTime = 0; if (available) { int numFrames = numSamples / (mStreamInfo->frameSize * mStreamInfo->numChannels); numSamples = numFrames * (mStreamInfo->frameSize * mStreamInfo->numChannels); ALOGV("%d samples available (%d), or %d frames", numSamples, available, numFrames); int64_t *nextTimeStamp = &mBufferTimestamps.editItemAt(0); currentTime = *nextTimeStamp; int32_t *currentBufLeft = &mBufferSizes.editItemAt(0); for (int i = 0; i < numFrames; i++) { int32_t decodedSize = mDecodedSizes.itemAt(0); mDecodedSizes.removeAt(0); ALOGV("decoded %d of %d", decodedSize, *currentBufLeft); if (*currentBufLeft > decodedSize) { // adjust/interpolate next time stamp *currentBufLeft -= decodedSize; *nextTimeStamp += mStreamInfo->aacSamplesPerFrame * 1000000ll / mStreamInfo->sampleRate; ALOGV("adjusted nextTimeStamp/size to %lld/%d", *nextTimeStamp, *currentBufLeft); } else { // move to next timestamp in list if (mBufferTimestamps.size() > 0) { mBufferTimestamps.removeAt(0); nextTimeStamp = &mBufferTimestamps.editItemAt(0); mBufferSizes.removeAt(0); currentBufLeft = &mBufferSizes.editItemAt(0); ALOGV("moved to next time/size: %lld/%d", *nextTimeStamp, *currentBufLeft); } // try to limit output buffer size to match input buffers // (e.g when an input buffer contained 4 "sub" frames, output // at most 4 decoded units in the corresponding output buffer) // This is optional. Remove the next three lines to fill the output // buffer with as many units as available. numFrames = i + 1; numSamples = numFrames * mStreamInfo->frameSize * mStreamInfo->numChannels; break; } } ALOGV("getting %d from ringbuffer", numSamples); int32_t ns = outputDelayRingBufferGetSamples(outBuffer, numSamples); if (ns != numSamples) { ALOGE("not a complete frame of samples available"); mSignalledError = true; notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL); return; } } outHeader->nFilledLen = numSamples * sizeof(int16_t); outHeader->nFilledLen = mStreamInfo->frameSize * mStreamInfo->numChannels * sizeof(int16_t); if (mEndOfInput && !outQueue.empty() && outputDelayRingBufferSamplesAvailable() == 0) { outHeader->nFlags = OMX_BUFFERFLAG_EOS; mEndOfOutput = true; Loading @@ -836,13 +901,13 @@ void SoftAAC2::onQueueFilled(OMX_U32 /* portIndex */) { outHeader->nFlags = 0; } outHeader->nTimeStamp = mAnchorTimes.isEmpty() ? 0 : mAnchorTimes.itemAt(0); mAnchorTimes.removeAt(0); outHeader->nTimeStamp = currentTime; mOutputBufferCount++; outInfo->mOwnedByUs = false; outQueue.erase(outQueue.begin()); outInfo = NULL; ALOGV("out timestamp %lld / %d", outHeader->nTimeStamp, outHeader->nFilledLen); notifyFillBufferDone(outHeader); outHeader = NULL; } Loading Loading @@ -877,8 +942,10 @@ void SoftAAC2::onQueueFilled(OMX_U32 /* portIndex */) { outHeader->nFilledLen = 0; outHeader->nFlags = OMX_BUFFERFLAG_EOS; outHeader->nTimeStamp = mAnchorTimes.itemAt(0); mAnchorTimes.removeAt(0); outHeader->nTimeStamp = mBufferTimestamps.itemAt(0); mBufferTimestamps.clear(); mBufferSizes.clear(); mDecodedSizes.clear(); mOutputBufferCount++; outInfo->mOwnedByUs = false; Loading @@ -899,7 +966,9 @@ void SoftAAC2::onPortFlushCompleted(OMX_U32 portIndex) { // depend on fragments from the last one decoded. // drain all existing data drainDecoder(); mAnchorTimes.clear(); mBufferTimestamps.clear(); mBufferSizes.clear(); mDecodedSizes.clear(); mLastInHeader = NULL; } else { while (outputDelayRingBufferSamplesAvailable() > 0) { Loading Loading @@ -955,7 +1024,9 @@ void SoftAAC2::onReset() { mOutputDelayRingBufferReadPos = 0; mEndOfInput = false; mEndOfOutput = false; mAnchorTimes.clear(); mBufferTimestamps.clear(); mBufferSizes.clear(); mDecodedSizes.clear(); mLastInHeader = NULL; // To make the codec behave the same before and after a reset, we need to invalidate the Loading
media/libstagefright/codecs/aacdec/SoftAAC2.h +3 −2 Original line number Diff line number Diff line Loading @@ -59,8 +59,9 @@ private: size_t mOutputBufferCount; bool mSignalledError; OMX_BUFFERHEADERTYPE *mLastInHeader; int64_t mCurrentInputTime; Vector<int64_t> mAnchorTimes; Vector<int32_t> mBufferSizes; Vector<int32_t> mDecodedSizes; Vector<int64_t> mBufferTimestamps; CDrcPresModeWrapper mDrcWrap; Loading