From: Andy Hung Date: Fri, 3 Oct 2014 16:53:53 +0000 (-0700) Subject: NuPlayer: wait for renderer flush before decoder shutdown X-Git-Tag: android-x86-6.0-r1~852^2~202^2~2^2~2^2^2^2^2^2~2^2^2 X-Git-Url: http://git.osdn.net/view?a=commitdiff_plain;h=e96fced473bc98364106d975fb64728c4fd28ccc;p=android-x86%2Fframeworks-av.git NuPlayer: wait for renderer flush before decoder shutdown Bug: 17679341 Change-Id: Ie3883686891e7ee6fb45ceb01af1eb60b559d3a0 --- diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp index 53eec91c22..1c7399588a 100644 --- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp +++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp @@ -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 format) const { @@ -773,38 +755,9 @@ void NuPlayer::onMessageReceived(const sp &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 format; @@ -957,6 +910,8 @@ void NuPlayer::onMessageReceived(const sp &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); diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.h b/media/libmediaplayerservice/nuplayer/NuPlayer.h index 81577336db..1b9a756785 100644 --- a/media/libmediaplayerservice/nuplayer/NuPlayer.h +++ b/media/libmediaplayerservice/nuplayer/NuPlayer.h @@ -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 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 &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 &newFormat = NULL); void updateDecoderFormatWithoutFlush(bool audio, const sp &format); - static bool IsFlushingState(FlushStatus state, bool *needShutdown = NULL); - void postScanSources(); void schedulePollDuration(); diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp index 1a01d52804..c57955d7ae 100644 --- a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp +++ b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp @@ -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);