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

Commit cf31f1ee authored by Andy Hung's avatar Andy Hung
Browse files

NuPlayer: Fix decoder error handling

Upon error, release MediaCodec after flushing data.
Report errors when they occur with ALOGE.
Fix onInputBufferFilled mInputBufferIsDequeued check.

Bug: 17423087
Bug: 17622642
Change-Id: I316601a19d5ec95cf8e14f5bc0418a05ec423041
parent 80ec934a
Loading
Loading
Loading
Loading
+13 −6
Original line number Diff line number Diff line
@@ -832,24 +832,31 @@ void NuPlayer::onMessageReceived(const sp<AMessage> &msg) {

                finishFlushIfPossible();
            } else if (what == Decoder::kWhatError) {
                ALOGE("Received error from %s decoder, aborting playback.",
                     audio ? "audio" : "video");

                status_t err;
                if (!msg->findInt32("err", &err)) {
                    err = UNKNOWN_ERROR;
                }
                mRenderer->queueEOS(audio, err);
                ALOGE("received error from %s decoder %#x", audio ? "audio" : "video", err);

                ALOGI("shutting down %s", audio ? "audio" : "video");
                if (audio && mFlushingAudio != NONE) {
                    mRenderer->queueEOS(audio, err);
                    mAudioDecoder.clear();
                    ++mAudioDecoderGeneration;
                    mFlushingAudio = SHUT_DOWN;
                    finishFlushIfPossible();
                } else if (!audio && mFlushingVideo != NONE) {
                    mRenderer->queueEOS(audio, err);
                    mVideoDecoder.clear();
                    ++mVideoDecoderGeneration;
                    mFlushingVideo = SHUT_DOWN;
                }
                    finishFlushIfPossible();
                }  else {
                    mDeferredActions.push_back(
                            new ShutdownDecoderAction(audio, !audio /* video */));
                    processDeferredActions();
                    notifyListener(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err);
                }
            } else if (what == Decoder::kWhatDrainThisBuffer) {
                renderBuffer(audio, msg);
            } else {
+26 −8
Original line number Diff line number Diff line
@@ -223,7 +223,11 @@ status_t NuPlayer::Decoder::getInputBuffers(Vector<sp<ABuffer> > *buffers) const

void NuPlayer::Decoder::handleError(int32_t err)
{
    mCodec->release();
    // We cannot immediately release the codec due to buffers still outstanding
    // in the renderer.  We signal to the player the error so it can shutdown/release the
    // decoder after flushing and increment the generation to discard unnecessary messages.

    ++mBufferGeneration;

    sp<AMessage> notify = mNotify->dup();
    notify->setInt32("what", kWhatError);
@@ -238,6 +242,8 @@ bool NuPlayer::Decoder::handleAnInputBuffer() {
            mComponentName.c_str(), res == OK ? (int)bufferIx : res);
    if (res != OK) {
        if (res != -EAGAIN) {
            ALOGE("Failed to dequeue input buffer for %s (err=%d)",
                    mComponentName.c_str(), res);
            handleError(res);
        }
        return false;
@@ -311,7 +317,7 @@ void android::NuPlayer::Decoder::onInputBufferFilled(const sp<AMessage> &msg) {
        }
    }

    mInputBufferIsDequeued.editItemAt(bufferIx) = false;


    if (buffer == NULL /* includes !hasBuffer */) {
        int32_t streamErr = ERROR_END_OF_STREAM;
@@ -329,12 +335,18 @@ void android::NuPlayer::Decoder::onInputBufferFilled(const sp<AMessage> &msg) {
                0,
                0,
                MediaCodec::BUFFER_FLAG_EOS);
        if (streamErr == ERROR_END_OF_STREAM && err != OK) {
        if (err == OK) {
            mInputBufferIsDequeued.editItemAt(bufferIx) = false;
        } else if (streamErr == ERROR_END_OF_STREAM) {
            streamErr = err;
            // err will not be ERROR_END_OF_STREAM
        }

        if (streamErr != ERROR_END_OF_STREAM) {
            ALOGE("Stream error for %s (err=%d), EOS %s queued",
                    mComponentName.c_str(),
                    streamErr,
                    err == OK ? "successfully" : "unsuccessfully");
            handleError(streamErr);
        }
    } else {
@@ -364,17 +376,21 @@ void android::NuPlayer::Decoder::onInputBufferFilled(const sp<AMessage> &msg) {
                        timeUs,
                        flags);
        if (err != OK) {
            if (mediaBuffer != NULL) {
                mediaBuffer->release();
            }
            ALOGE("Failed to queue input buffer for %s (err=%d)",
                    mComponentName.c_str(), err);
            handleError(err);
        }

        } else {
            mInputBufferIsDequeued.editItemAt(bufferIx) = false;
            if (mediaBuffer != NULL) {
                CHECK(mMediaBuffers[bufferIx] == NULL);
                mMediaBuffers.editItemAt(bufferIx) = mediaBuffer;
            }
        }
    }
}

bool NuPlayer::Decoder::handleAnOutputBuffer() {
    size_t bufferIx = -1;
@@ -422,6 +438,8 @@ bool NuPlayer::Decoder::handleAnOutputBuffer() {
        return true;
    } else if (res != OK) {
        if (res != -EAGAIN) {
            ALOGE("Failed to dequeue output buffer for %s (err=%d)",
                    mComponentName.c_str(), res);
            handleError(res);
        }
        return false;
+1 −1
Original line number Diff line number Diff line
@@ -485,7 +485,7 @@ AString AMessage::debugString(int32_t indent) const {
            {
                sp<ABuffer> buffer = static_cast<ABuffer *>(item.u.refValue);

                if (buffer != NULL && buffer->size() <= 64) {
                if (buffer != NULL && buffer->data() != NULL && buffer->size() <= 64) {
                    tmp = StringPrintf("Buffer %s = {\n", item.mName);
                    hexdump(buffer->data(), buffer->size(), indent + 4, &tmp);
                    appendIndent(&tmp, indent + 2);