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

Commit 73d0a798 authored by Andy Hung's avatar Andy Hung Committed by Android (Google) Code Review
Browse files

Merge "NuPlayer: wait for renderer flush before decoder shutdown" into lmp-dev

parents 5002d02e 8d121d41
Loading
Loading
Loading
Loading
+52 −49
Original line number Diff line number Diff line
@@ -174,6 +174,7 @@ NuPlayer::NuPlayer()
      mNumFramesDropped(0ll),
      mVideoScalingMode(NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW),
      mStarted(false) {
    clearFlushComplete();
}

NuPlayer::~NuPlayer() {
@@ -333,25 +334,6 @@ void NuPlayer::seekToAsync(int64_t seekTimeUs, bool needNotify) {
    msg->post();
}

// static
bool NuPlayer::IsFlushingState(FlushStatus state, bool *needShutdown) {
    switch (state) {
        case FLUSHING_DECODER:
            if (needShutdown != NULL) {
                *needShutdown = false;
            }
            return true;

        case FLUSHING_DECODER_SHUTDOWN:
            if (needShutdown != NULL) {
                *needShutdown = true;
            }
            return true;

        default:
            return false;
    }
}

void NuPlayer::writeTrackInfo(
        Parcel* reply, const sp<AMessage> format) const {
@@ -773,38 +755,9 @@ void NuPlayer::onMessageReceived(const sp<AMessage> &msg) {

                mRenderer->queueEOS(audio, err);
            } else if (what == Decoder::kWhatFlushCompleted) {
                bool needShutdown;

                if (audio) {
                    CHECK(IsFlushingState(mFlushingAudio, &needShutdown));
                    mFlushingAudio = FLUSHED;
                } else {
                    CHECK(IsFlushingState(mFlushingVideo, &needShutdown));
                    mFlushingVideo = FLUSHED;

                    mVideoLateByUs = 0;
                }

                ALOGV("decoder %s flush completed", audio ? "audio" : "video");

                if (needShutdown) {
                    ALOGV("initiating %s decoder shutdown",
                         audio ? "audio" : "video");

                    // Widevine source reads must stop before releasing the video decoder.
                    if (!audio && mSource != NULL && mSourceFlags & Source::FLAG_SECURE) {
                        mSource->stop();
                    }

                    getDecoder(audio)->initiateShutdown();

                    if (audio) {
                        mFlushingAudio = SHUTTING_DOWN_DECODER;
                    } else {
                        mFlushingVideo = SHUTTING_DOWN_DECODER;
                    }
                }

                handleFlushComplete(audio, true /* isDecoder */);
                finishFlushIfPossible();
            } else if (what == Decoder::kWhatOutputFormatChanged) {
                sp<AMessage> format;
@@ -957,6 +910,8 @@ void NuPlayer::onMessageReceived(const sp<AMessage> &msg) {
                CHECK(msg->findInt32("audio", &audio));

                ALOGV("renderer %s flush completed.", audio ? "audio" : "video");
                handleFlushComplete(audio, false /* isDecoder */);
                finishFlushIfPossible();
            } else if (what == Renderer::kWhatVideoRenderingStart) {
                notifyListener(MEDIA_INFO, MEDIA_INFO_RENDERING_START, 0);
            } else if (what == Renderer::kWhatMediaRenderingStart) {
@@ -1084,6 +1039,50 @@ bool NuPlayer::audioDecoderStillNeeded() {
    return ((mFlushingAudio != SHUT_DOWN) && (mFlushingAudio != SHUTTING_DOWN_DECODER));
}

void NuPlayer::handleFlushComplete(bool audio, bool isDecoder) {
    // We wait for both the decoder flush and the renderer flush to complete
    // before entering either the FLUSHED or the SHUTTING_DOWN_DECODER state.

    mFlushComplete[audio][isDecoder] = true;
    if (!mFlushComplete[audio][!isDecoder]) {
        return;
    }

    FlushStatus *state = audio ? &mFlushingAudio : &mFlushingVideo;
    switch (*state) {
        case FLUSHING_DECODER:
        {
            *state = FLUSHED;

            if (!audio) {
                mVideoLateByUs = 0;
            }
            break;
        }

        case FLUSHING_DECODER_SHUTDOWN:
        {
            *state = SHUTTING_DOWN_DECODER;

            ALOGV("initiating %s decoder shutdown", audio ? "audio" : "video");
            if (!audio) {
                mVideoLateByUs = 0;
                // Widevine source reads must stop before releasing the video decoder.
                if (mSource != NULL && mSourceFlags & Source::FLAG_SECURE) {
                    mSource->stop();
                }
            }
            getDecoder(audio)->initiateShutdown();
            break;
        }

        default:
            // decoder flush completes only occur in a flushing state.
            LOG_ALWAYS_FATAL_IF(isDecoder, "decoder flush in invalid state %d", *state);
            break;
    }
}

void NuPlayer::finishFlushIfPossible() {
    if (mFlushingAudio != NONE && mFlushingAudio != FLUSHED
            && mFlushingAudio != SHUT_DOWN) {
@@ -1116,6 +1115,8 @@ void NuPlayer::finishFlushIfPossible() {
    mFlushingAudio = NONE;
    mFlushingVideo = NONE;

    clearFlushComplete();

    processDeferredActions();
}

@@ -1720,6 +1721,8 @@ void NuPlayer::flushDecoder(
    FlushStatus newStatus =
        needShutdown ? FLUSHING_DECODER_SHUTDOWN : FLUSHING_DECODER;

    mFlushComplete[audio][false /* isDecoder */] = false;
    mFlushComplete[audio][true /* isDecoder */] = false;
    if (audio) {
        ALOGE_IF(mFlushingAudio != NONE,
                "audio flushDecoder() is called in state %d", mFlushingAudio);
+11 −2
Original line number Diff line number Diff line
@@ -164,6 +164,9 @@ private:
    // notion of time has changed.
    bool mTimeDiscontinuityPending;

    // Status of flush responses from the decoder and renderer.
    bool mFlushComplete[2][2];

    // Used by feedDecoderInputData to aggregate small buffers into
    // one large buffer.
    sp<ABuffer> mPendingAudioAccessUnit;
@@ -187,6 +190,13 @@ private:
        return audio ? mAudioDecoder : mVideoDecoder;
    }

    inline void clearFlushComplete() {
        mFlushComplete[0][0] = false;
        mFlushComplete[0][1] = false;
        mFlushComplete[1][0] = false;
        mFlushComplete[1][1] = false;
    }

    void openAudioSink(const sp<AMessage> &format, bool offloadOnly);
    void closeAudioSink();

@@ -201,6 +211,7 @@ private:

    void notifyListener(int msg, int ext1, int ext2, const Parcel *in = NULL);

    void handleFlushComplete(bool audio, bool isDecoder);
    void finishFlushIfPossible();

    bool audioDecoderStillNeeded();
@@ -209,8 +220,6 @@ private:
            bool audio, bool needShutdown, const sp<AMessage> &newFormat = NULL);
    void updateDecoderFormatWithoutFlush(bool audio, const sp<AMessage> &format);

    static bool IsFlushingState(FlushStatus state, bool *needShutdown = NULL);

    void postScanSources();

    void schedulePollDuration();
+1 −1
Original line number Diff line number Diff line
@@ -582,7 +582,7 @@ status_t NuPlayerDriver::getMetadata(
}

void NuPlayerDriver::notifyResetComplete() {
    ALOGI("notifyResetComplete(%p)", this);
    ALOGD("notifyResetComplete(%p)", this);
    Mutex::Autolock autoLock(mLock);

    CHECK_EQ(mState, STATE_RESET_IN_PROGRESS);