Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9404fa6a authored by Marco Nelissen's avatar Marco Nelissen Committed by Android (Google) Code Review
Browse files

Merge "Fix decoder EOS handling" into klp-dev

parents 96be8bb7 9da36a6c
Loading
Loading
Loading
Loading
+102 −115
Original line number Diff line number Diff line
@@ -58,6 +58,8 @@ SoftAAC2::SoftAAC2(
      mIsADTS(false),
      mInputBufferCount(0),
      mSignalledError(false),
      mSawInputEos(false),
      mSignalledOutputEos(false),
      mAnchorTimeUs(0),
      mNumSamplesOutput(0),
      mOutputPortSettingsChange(NONE) {
@@ -350,65 +352,30 @@ void SoftAAC2::onQueueFilled(OMX_U32 portIndex) {
        return;
    }

    while (!inQueue.empty() && !outQueue.empty()) {
        BufferInfo *inInfo = *inQueue.begin();
        OMX_BUFFERHEADERTYPE *inHeader = inInfo->mHeader;
    while ((!inQueue.empty() || (mSawInputEos && !mSignalledOutputEos)) && !outQueue.empty()) {
        BufferInfo *inInfo = NULL;
        OMX_BUFFERHEADERTYPE *inHeader = NULL;
        if (!inQueue.empty()) {
            inInfo = *inQueue.begin();
            inHeader = inInfo->mHeader;
        }

        BufferInfo *outInfo = *outQueue.begin();
        OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader;
        outHeader->nFlags = 0;

        if (inHeader) {
            if (inHeader->nFlags & OMX_BUFFERFLAG_EOS) {
            inQueue.erase(inQueue.begin());
            inInfo->mOwnedByUs = false;
            notifyEmptyBufferDone(inHeader);

            if (mDecoderHasData) {
                // flush out the decoder's delayed data by calling DecodeFrame
                // one more time, with the AACDEC_FLUSH flag set
                INT_PCM *outBuffer =
                        reinterpret_cast<INT_PCM *>(
                                outHeader->pBuffer + outHeader->nOffset);

                AAC_DECODER_ERROR decoderErr =
                    aacDecoder_DecodeFrame(mAACDecoder,
                                           outBuffer,
                                           outHeader->nAllocLen,
                                           AACDEC_FLUSH);
                mDecoderHasData = false;

                if (decoderErr != AAC_DEC_OK) {
                    mSignalledError = true;

                    notify(OMX_EventError, OMX_ErrorUndefined, decoderErr,
                           NULL);

                    return;
                mSawInputEos = true;
            }

                outHeader->nFilledLen =
                        mStreamInfo->frameSize
                            * sizeof(int16_t)
                            * mStreamInfo->numChannels;
            } else {
                // we never submitted any data to the decoder, so there's nothing to flush out
                outHeader->nFilledLen = 0;
            }

            outHeader->nFlags = OMX_BUFFERFLAG_EOS;

            outQueue.erase(outQueue.begin());
            outInfo->mOwnedByUs = false;
            notifyFillBufferDone(outHeader);
            return;
        }

        if (inHeader->nOffset == 0) {
            if (inHeader->nOffset == 0 && inHeader->nFilledLen) {
                mAnchorTimeUs = inHeader->nTimeStamp;
                mNumSamplesOutput = 0;
            }

        size_t adtsHeaderSize = 0;
            if (mIsADTS) {
                size_t adtsHeaderSize = 0;
                // skip 30 bits, aac_frame_length follows.
                // ssssssss ssssiiip ppffffPc ccohCCll llllllll lll?????

@@ -460,6 +427,9 @@ void SoftAAC2::onQueueFilled(OMX_U32 portIndex) {
                inBuffer[0] = inHeader->pBuffer + inHeader->nOffset;
                inBufferLength[0] = inHeader->nFilledLen;
            }
        } else {
            inBufferLength[0] = 0;
        }

        // Fill and decode
        INT_PCM *outBuffer = reinterpret_cast<INT_PCM *>(
@@ -471,26 +441,41 @@ void SoftAAC2::onQueueFilled(OMX_U32 portIndex) {
        int prevNumChannels = mStreamInfo->numChannels;

        AAC_DECODER_ERROR decoderErr = AAC_DEC_NOT_ENOUGH_BITS;
        while (bytesValid[0] > 0 && decoderErr == AAC_DEC_NOT_ENOUGH_BITS) {
        while ((bytesValid[0] > 0 || mSawInputEos) && decoderErr == AAC_DEC_NOT_ENOUGH_BITS) {
            mDecoderHasData |= (bytesValid[0] > 0);
            aacDecoder_Fill(mAACDecoder,
                            inBuffer,
                            inBufferLength,
                            bytesValid);
            mDecoderHasData = true;

            decoderErr = aacDecoder_DecodeFrame(mAACDecoder,
                                                outBuffer,
                                                outHeader->nAllocLen,
                                                0 /* flags */);

            if (decoderErr == AAC_DEC_NOT_ENOUGH_BITS) {
                if (mSawInputEos && bytesValid[0] <= 0) {
                    if (mDecoderHasData) {
                        // flush out the decoder's delayed data by calling DecodeFrame
                        // one more time, with the AACDEC_FLUSH flag set
                        decoderErr = aacDecoder_DecodeFrame(mAACDecoder,
                                                            outBuffer,
                                                            outHeader->nAllocLen,
                                                            AACDEC_FLUSH);
                        mDecoderHasData = false;
                    }
                    outHeader->nFlags = OMX_BUFFERFLAG_EOS;
                    mSignalledOutputEos = true;
                    break;
                } else {
                    ALOGW("Not enough bits, bytesValid %d", bytesValid[0]);
                }
            }
        }

        size_t numOutBytes =
            mStreamInfo->frameSize * sizeof(int16_t) * mStreamInfo->numChannels;

        if (inHeader) {
            if (decoderErr == AAC_DEC_OK) {
                UINT inBufferUsedLength = inBufferLength[0] - bytesValid[0];
                inHeader->nFilledLen -= inBufferUsedLength;
@@ -516,6 +501,7 @@ void SoftAAC2::onQueueFilled(OMX_U32 portIndex) {
                notifyEmptyBufferDone(inHeader);
                inHeader = NULL;
            }
        }

        /*
         * AAC+/eAAC+ streams can be signalled in two ways: either explicitly
@@ -555,7 +541,6 @@ void SoftAAC2::onQueueFilled(OMX_U32 portIndex) {
            // we've previously decoded valid data, in the latter case
            // (decode failed) we'll output a silent frame.
            outHeader->nFilledLen = numOutBytes;
            outHeader->nFlags = 0;

            outHeader->nTimeStamp =
                mAnchorTimeUs
@@ -606,6 +591,8 @@ void SoftAAC2::onReset() {
    mStreamInfo->sampleRate = 0;

    mSignalledError = false;
    mSawInputEos = false;
    mSignalledOutputEos = false;
    mOutputPortSettingsChange = NONE;
}

+2 −0
Original line number Diff line number Diff line
@@ -55,6 +55,8 @@ private:
    bool mDecoderHasData;
    size_t mInputBufferCount;
    bool mSignalledError;
    bool mSawInputEos;
    bool mSignalledOutputEos;
    int64_t mAnchorTimeUs;
    int64_t mNumSamplesOutput;

+61 −53
Original line number Diff line number Diff line
@@ -49,6 +49,8 @@ SoftMP3::SoftMP3(
      mNumChannels(2),
      mSamplingRate(44100),
      mSignalledError(false),
      mSawInputEos(false),
      mSignalledOutputEos(false),
      mOutputPortSettingsChange(NONE) {
    initPorts();
    initDecoder();
@@ -194,48 +196,36 @@ void SoftMP3::onQueueFilled(OMX_U32 portIndex) {
    List<BufferInfo *> &inQueue = getPortQueue(0);
    List<BufferInfo *> &outQueue = getPortQueue(1);

    while (!inQueue.empty() && !outQueue.empty()) {
        BufferInfo *inInfo = *inQueue.begin();
        OMX_BUFFERHEADERTYPE *inHeader = inInfo->mHeader;
    while ((!inQueue.empty() || (mSawInputEos && !mSignalledOutputEos)) && !outQueue.empty()) {
        BufferInfo *inInfo = NULL;
        OMX_BUFFERHEADERTYPE *inHeader = NULL;
        if (!inQueue.empty()) {
            inInfo = *inQueue.begin();
            inHeader = inInfo->mHeader;
        }

        BufferInfo *outInfo = *outQueue.begin();
        OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader;
        outHeader->nFlags = 0;

        if (inHeader->nFlags & OMX_BUFFERFLAG_EOS) {
            inQueue.erase(inQueue.begin());
            inInfo->mOwnedByUs = false;
            notifyEmptyBufferDone(inHeader);

            if (!mIsFirst) {
                // pad the end of the stream with 529 samples, since that many samples
                // were trimmed off the beginning when decoding started
                outHeader->nFilledLen =
                    kPVMP3DecoderDelay * mNumChannels * sizeof(int16_t);

                memset(outHeader->pBuffer, 0, outHeader->nFilledLen);
            } else {
                // Since we never discarded frames from the start, we won't have
                // to add any padding at the end either.
                outHeader->nFilledLen = 0;
            }

            outHeader->nFlags = OMX_BUFFERFLAG_EOS;

            outQueue.erase(outQueue.begin());
            outInfo->mOwnedByUs = false;
            notifyFillBufferDone(outHeader);
            return;
        }

        if (inHeader->nOffset == 0) {
        if (inHeader) {
            if (inHeader->nOffset == 0 && inHeader->nFilledLen) {
                mAnchorTimeUs = inHeader->nTimeStamp;
                mNumFramesOutput = 0;
            }

            if (inHeader->nFlags & OMX_BUFFERFLAG_EOS) {
                mSawInputEos = true;
            }

            mConfig->pInputBuffer =
                inHeader->pBuffer + inHeader->nOffset;

            mConfig->inputBufferCurrentLength = inHeader->nFilledLen;
        } else {
            mConfig->pInputBuffer = NULL;
            mConfig->inputBufferCurrentLength = 0;
        }
        mConfig->inputBufferMaxLength = 0;
        mConfig->inputBufferUsedLength = 0;

@@ -262,13 +252,28 @@ void SoftMP3::onQueueFilled(OMX_U32 portIndex) {
                mConfig->outputFrameSize = kOutputBufferSize / sizeof(int16_t);
            }

            if (decoderErr == NO_ENOUGH_MAIN_DATA_ERROR && mSawInputEos) {
                if (!mIsFirst) {
                    // pad the end of the stream with 529 samples, since that many samples
                    // were trimmed off the beginning when decoding started
                    outHeader->nOffset = 0;
                    outHeader->nFilledLen = kPVMP3DecoderDelay * mNumChannels * sizeof(int16_t);

                    memset(outHeader->pBuffer, 0, outHeader->nFilledLen);
                }
                outHeader->nFlags = OMX_BUFFERFLAG_EOS;
                mSignalledOutputEos = true;
            } else {
                // This is recoverable, just ignore the current frame and
                // play silence instead.
                memset(outHeader->pBuffer,
                       0,
                       mConfig->outputFrameSize * sizeof(int16_t));

                if (inHeader) {
                    mConfig->inputBufferUsedLength = inHeader->nFilledLen;
                }
            }
        } else if (mConfig->samplingRate != mSamplingRate
                || mConfig->num_channels != mNumChannels) {
            mSamplingRate = mConfig->samplingRate;
@@ -289,7 +294,7 @@ void SoftMP3::onQueueFilled(OMX_U32 portIndex) {

            outHeader->nFilledLen =
                mConfig->outputFrameSize * sizeof(int16_t) - outHeader->nOffset;
        } else {
        } else if (!mSignalledOutputEos) {
            outHeader->nOffset = 0;
            outHeader->nFilledLen = mConfig->outputFrameSize * sizeof(int16_t);
        }
@@ -298,14 +303,12 @@ void SoftMP3::onQueueFilled(OMX_U32 portIndex) {
            mAnchorTimeUs
                + (mNumFramesOutput * 1000000ll) / mConfig->samplingRate;

        outHeader->nFlags = 0;

        if (inHeader) {
            CHECK_GE(inHeader->nFilledLen, mConfig->inputBufferUsedLength);

            inHeader->nOffset += mConfig->inputBufferUsedLength;
            inHeader->nFilledLen -= mConfig->inputBufferUsedLength;

        mNumFramesOutput += mConfig->outputFrameSize / mNumChannels;

            if (inHeader->nFilledLen == 0) {
                inInfo->mOwnedByUs = false;
@@ -314,6 +317,9 @@ void SoftMP3::onQueueFilled(OMX_U32 portIndex) {
                notifyEmptyBufferDone(inHeader);
                inHeader = NULL;
            }
        }

        mNumFramesOutput += mConfig->outputFrameSize / mNumChannels;

        outInfo->mOwnedByUs = false;
        outQueue.erase(outQueue.begin());
@@ -362,6 +368,8 @@ void SoftMP3::onReset() {
    pvmp3_InitDecoder(mConfig, mDecoderBuf);
    mIsFirst = true;
    mSignalledError = false;
    mSawInputEos = false;
    mSignalledOutputEos = false;
    mOutputPortSettingsChange = NONE;
}

+2 −0
Original line number Diff line number Diff line
@@ -61,6 +61,8 @@ private:

    bool mIsFirst;
    bool mSignalledError;
    bool mSawInputEos;
    bool mSignalledOutputEos;

    enum {
        NONE,
+39 −34
Original line number Diff line number Diff line
@@ -54,6 +54,8 @@ SoftVorbis::SoftVorbis(
      mAnchorTimeUs(0),
      mNumFramesOutput(0),
      mNumFramesLeftOnPage(-1),
      mSawInputEos(false),
      mSignalledOutputEos(false),
      mOutputPortSettingsChange(NONE) {
    initPorts();
    CHECK_EQ(initDecoder(), (status_t)OK);
@@ -290,48 +292,47 @@ void SoftVorbis::onQueueFilled(OMX_U32 portIndex) {
        return;
    }

    while (!inQueue.empty() && !outQueue.empty()) {
        BufferInfo *inInfo = *inQueue.begin();
        OMX_BUFFERHEADERTYPE *inHeader = inInfo->mHeader;
    while ((!inQueue.empty() || (mSawInputEos && !mSignalledOutputEos)) && !outQueue.empty()) {
        BufferInfo *inInfo = NULL;
        OMX_BUFFERHEADERTYPE *inHeader = NULL;
        if (!inQueue.empty()) {
            inInfo = *inQueue.begin();
            inHeader = inInfo->mHeader;
        }

        BufferInfo *outInfo = *outQueue.begin();
        OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader;

        if (inHeader->nFlags & OMX_BUFFERFLAG_EOS) {
            inQueue.erase(inQueue.begin());
            inInfo->mOwnedByUs = false;
            notifyEmptyBufferDone(inHeader);

            outHeader->nFilledLen = 0;
            outHeader->nFlags = OMX_BUFFERFLAG_EOS;
        int32_t numPageSamples = 0;

            outQueue.erase(outQueue.begin());
            outInfo->mOwnedByUs = false;
            notifyFillBufferDone(outHeader);
            return;
        if (inHeader) {
            if (inHeader->nFlags & OMX_BUFFERFLAG_EOS) {
                mSawInputEos = true;
            }

        int32_t numPageSamples;
            if (inHeader->nFilledLen || !mSawInputEos) {
                CHECK_GE(inHeader->nFilledLen, sizeof(numPageSamples));
                memcpy(&numPageSamples,
                       inHeader->pBuffer
                        + inHeader->nOffset + inHeader->nFilledLen - 4,
                       sizeof(numPageSamples));

        if (numPageSamples >= 0) {
            mNumFramesLeftOnPage = numPageSamples;
        }

                if (inHeader->nOffset == 0) {
                    mAnchorTimeUs = inHeader->nTimeStamp;
                    mNumFramesOutput = 0;
                }

                inHeader->nFilledLen -= sizeof(numPageSamples);;
            }
        }

        if (numPageSamples >= 0) {
            mNumFramesLeftOnPage = numPageSamples;
        }

        ogg_buffer buf;
        buf.data = inHeader->pBuffer + inHeader->nOffset;
        buf.size = inHeader->nFilledLen;
        buf.data = inHeader ? inHeader->pBuffer + inHeader->nOffset : NULL;
        buf.size = inHeader ? inHeader->nFilledLen : 0;
        buf.refcount = 1;
        buf.ptr.owner = NULL;

@@ -384,11 +385,13 @@ void SoftVorbis::onQueueFilled(OMX_U32 portIndex) {

        mNumFramesOutput += numFrames;

        if (inHeader) {
            inInfo->mOwnedByUs = false;
            inQueue.erase(inQueue.begin());
            inInfo = NULL;
            notifyEmptyBufferDone(inHeader);
            inHeader = NULL;
        }

        outInfo->mOwnedByUs = false;
        outQueue.erase(outQueue.begin());
@@ -425,6 +428,8 @@ void SoftVorbis::onReset() {
        mVi = NULL;
    }

    mSawInputEos = false;
    mSignalledOutputEos = false;
    mOutputPortSettingsChange = NONE;
}

Loading