From f3bd1972e039c6ded5154db715e5a32f1813a239 Mon Sep 17 00:00:00 2001 From: Marco Nelissen Date: Tue, 9 Apr 2013 14:57:38 -0700 Subject: Fix MediaCodec.flush() There were two problems here. One was that the skip/cut buffer wasn't cleared when it should be, and the second was that we were always sending the first buffer of encoded data to the AAC decoder twice. b/8543366 Change-Id: Ic040edabf16cccd1f6ef8c9e5c9cfbacbdd8a089 --- media/libstagefright/codecs/aacdec/SoftAAC2.cpp | 103 +++++++++++------------- media/libstagefright/codecs/aacdec/SoftAAC2.h | 3 +- 2 files changed, 51 insertions(+), 55 deletions(-) (limited to 'media/libstagefright/codecs') diff --git a/media/libstagefright/codecs/aacdec/SoftAAC2.cpp b/media/libstagefright/codecs/aacdec/SoftAAC2.cpp index a8ab2ac..8ba2afb 100644 --- a/media/libstagefright/codecs/aacdec/SoftAAC2.cpp +++ b/media/libstagefright/codecs/aacdec/SoftAAC2.cpp @@ -118,7 +118,7 @@ status_t SoftAAC2::initDecoder() { status = OK; } } - mIsFirst = true; + mDecoderHasData = false; // for streams that contain metadata, use the mobile profile DRC settings unless overridden // by platform properties: @@ -327,6 +327,7 @@ void SoftAAC2::onQueueFilled(OMX_U32 portIndex) { notify(OMX_EventError, OMX_ErrorUndefined, decoderErr, NULL); return; } + inQueue.erase(inQueue.begin()); info->mOwnedByUs = false; notifyEmptyBufferDone(header); @@ -358,7 +359,7 @@ void SoftAAC2::onQueueFilled(OMX_U32 portIndex) { inInfo->mOwnedByUs = false; notifyEmptyBufferDone(inHeader); - if (!mIsFirst) { + if (mDecoderHasData) { // flush out the decoder's delayed data by calling DecodeFrame // one more time, with the AACDEC_FLUSH flag set INT_PCM *outBuffer = @@ -370,6 +371,7 @@ void SoftAAC2::onQueueFilled(OMX_U32 portIndex) { outBuffer, outHeader->nAllocLen, AACDEC_FLUSH); + mDecoderHasData = false; if (decoderErr != AAC_DEC_OK) { mSignalledError = true; @@ -385,9 +387,7 @@ void SoftAAC2::onQueueFilled(OMX_U32 portIndex) { * sizeof(int16_t) * mStreamInfo->numChannels; } else { - // Since we never discarded frames from the start, we won't have - // to add any padding at the end either. - + // we never submitted any data to the decoder, so there's nothing to flush out outHeader->nFilledLen = 0; } @@ -473,6 +473,7 @@ void SoftAAC2::onQueueFilled(OMX_U32 portIndex) { inBuffer, inBufferLength, bytesValid); + mDecoderHasData = true; decoderErr = aacDecoder_DecodeFrame(mAACDecoder, outBuffer, @@ -484,6 +485,35 @@ void SoftAAC2::onQueueFilled(OMX_U32 portIndex) { } } + size_t numOutBytes = + mStreamInfo->frameSize * sizeof(int16_t) * mStreamInfo->numChannels; + + if (decoderErr == AAC_DEC_OK) { + UINT inBufferUsedLength = inBufferLength[0] - bytesValid[0]; + inHeader->nFilledLen -= inBufferUsedLength; + inHeader->nOffset += inBufferUsedLength; + } else { + ALOGW("AAC decoder returned error %d, substituting silence", + decoderErr); + + memset(outHeader->pBuffer + outHeader->nOffset, 0, numOutBytes); + + // Discard input buffer. + inHeader->nFilledLen = 0; + + aacDecoder_SetParam(mAACDecoder, AAC_TPDEC_CLEAR_BUFFER, 1); + + // fall through + } + + if (inHeader->nFilledLen == 0) { + inInfo->mOwnedByUs = false; + inQueue.erase(inQueue.begin()); + inInfo = NULL; + notifyEmptyBufferDone(inHeader); + inHeader = NULL; + } + /* * AAC+/eAAC+ streams can be signalled in two ways: either explicitly * or implicitly, according to MPEG4 spec. AAC+/eAAC+ is a dual @@ -502,15 +532,9 @@ void SoftAAC2::onQueueFilled(OMX_U32 portIndex) { if (mStreamInfo->sampleRate != prevSampleRate || mStreamInfo->numChannels != prevNumChannels) { maybeConfigureDownmix(); - ALOGI("Reconfiguring decoder: %d Hz, %d channels", - mStreamInfo->sampleRate, - mStreamInfo->numChannels); - - // We're going to want to revisit this input buffer, but - // may have already advanced the offset. Undo that if - // necessary. - inHeader->nOffset -= adtsHeaderSize; - inHeader->nFilledLen += adtsHeaderSize; + ALOGI("Reconfiguring decoder: %d->%d Hz, %d->%d channels", + prevSampleRate, mStreamInfo->sampleRate, + prevNumChannels, mStreamInfo->numChannels); notify(OMX_EventPortSettingsChanged, 1, 0, NULL); mOutputPortSettingsChange = AWAITING_DISABLED; @@ -523,38 +547,10 @@ void SoftAAC2::onQueueFilled(OMX_U32 portIndex) { return; } - size_t numOutBytes = - mStreamInfo->frameSize * sizeof(int16_t) * mStreamInfo->numChannels; - - if (decoderErr == AAC_DEC_OK) { - UINT inBufferUsedLength = inBufferLength[0] - bytesValid[0]; - inHeader->nFilledLen -= inBufferUsedLength; - inHeader->nOffset += inBufferUsedLength; - } else { - ALOGW("AAC decoder returned error %d, substituting silence", - decoderErr); - - memset(outHeader->pBuffer + outHeader->nOffset, 0, numOutBytes); - - // Discard input buffer. - inHeader->nFilledLen = 0; - - aacDecoder_SetParam(mAACDecoder, AAC_TPDEC_CLEAR_BUFFER, 1); - - // fall through - } - if (decoderErr == AAC_DEC_OK || mNumSamplesOutput > 0) { // We'll only output data if we successfully decoded it or // we've previously decoded valid data, in the latter case // (decode failed) we'll output a silent frame. - if (mIsFirst) { - mIsFirst = false; - // the first decoded frame should be discarded to account - // for decoder delay - numOutBytes = 0; - } - outHeader->nFilledLen = numOutBytes; outHeader->nFlags = 0; @@ -571,14 +567,6 @@ void SoftAAC2::onQueueFilled(OMX_U32 portIndex) { outHeader = NULL; } - if (inHeader->nFilledLen == 0) { - inInfo->mOwnedByUs = false; - inQueue.erase(inQueue.begin()); - inInfo = NULL; - notifyEmptyBufferDone(inHeader); - inHeader = NULL; - } - if (decoderErr == AAC_DEC_OK) { ++mInputBufferCount; } @@ -589,14 +577,21 @@ void SoftAAC2::onPortFlushCompleted(OMX_U32 portIndex) { if (portIndex == 0) { // Make sure that the next buffer output does not still // depend on fragments from the last one decoded. - aacDecoder_SetParam(mAACDecoder, AAC_TPDEC_CLEAR_BUFFER, 1); - mIsFirst = true; + // drain all existing data + drainDecoder(); } } -void SoftAAC2::onReset() { +void SoftAAC2::drainDecoder() { + short buf [2048]; + aacDecoder_DecodeFrame(mAACDecoder, buf, 4096, AACDEC_FLUSH | AACDEC_CLRHIST | AACDEC_INTR); + aacDecoder_DecodeFrame(mAACDecoder, buf, 4096, AACDEC_FLUSH | AACDEC_CLRHIST | AACDEC_INTR); aacDecoder_SetParam(mAACDecoder, AAC_TPDEC_CLEAR_BUFFER, 1); - mIsFirst = true; + mDecoderHasData = false; +} + +void SoftAAC2::onReset() { + drainDecoder(); } void SoftAAC2::onPortEnableCompleted(OMX_U32 portIndex, bool enabled) { diff --git a/media/libstagefright/codecs/aacdec/SoftAAC2.h b/media/libstagefright/codecs/aacdec/SoftAAC2.h index 6957ade..2d960ab 100644 --- a/media/libstagefright/codecs/aacdec/SoftAAC2.h +++ b/media/libstagefright/codecs/aacdec/SoftAAC2.h @@ -52,7 +52,7 @@ private: HANDLE_AACDECODER mAACDecoder; CStreamInfo *mStreamInfo; bool mIsADTS; - bool mIsFirst; + bool mDecoderHasData; size_t mInputBufferCount; bool mSignalledError; int64_t mAnchorTimeUs; @@ -68,6 +68,7 @@ private: status_t initDecoder(); bool isConfigured() const; void maybeConfigureDownmix() const; + void drainDecoder(); DISALLOW_EVIL_CONSTRUCTORS(SoftAAC2); }; -- cgit v1.1