diff options
author | Andreas Huber <andih@google.com> | 2011-01-04 14:01:29 -0800 |
---|---|---|
committer | Andreas Huber <andih@google.com> | 2011-01-04 14:07:58 -0800 |
commit | cbeaca7a819cc11724f6f34457dabf5bd55a84a1 (patch) | |
tree | d4601ae2e269aa16dfbd5c138c4d6bae285701dd /media/libmediaplayerservice/nuplayer | |
parent | 08a4186b1f0ca71aac94a24c1dbbdc0a84b8c705 (diff) | |
download | frameworks_base-cbeaca7a819cc11724f6f34457dabf5bd55a84a1.zip frameworks_base-cbeaca7a819cc11724f6f34457dabf5bd55a84a1.tar.gz frameworks_base-cbeaca7a819cc11724f6f34457dabf5bd55a84a1.tar.bz2 |
Properly shutdown the decoders on a reset() in NuPlayer's implementation.
related-to-bug: 3321470
Change-Id: Ida6d2171c5a3a407188d4633602b764f8fe7086a
Diffstat (limited to 'media/libmediaplayerservice/nuplayer')
5 files changed, 191 insertions, 61 deletions
diff --git a/media/libmediaplayerservice/nuplayer/HTTPLiveSource.cpp b/media/libmediaplayerservice/nuplayer/HTTPLiveSource.cpp index c656e69..29e4971 100644 --- a/media/libmediaplayerservice/nuplayer/HTTPLiveSource.cpp +++ b/media/libmediaplayerservice/nuplayer/HTTPLiveSource.cpp @@ -87,7 +87,7 @@ bool NuPlayer::HTTPLiveSource::feedMoreTSData() { break; } else if (n < 0) { LOGI("input data EOS reached."); - mTSParser->signalEOS(ERROR_END_OF_STREAM); + mTSParser->signalEOS(n); mEOS = true; break; } else { diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp index 24efa35..9a8cff3 100644 --- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp +++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp @@ -45,8 +45,11 @@ NuPlayer::NuPlayer() : mAudioEOS(false), mVideoEOS(false), mScanSourcesPending(false), + mScanSourcesGeneration(0), mFlushingAudio(NONE), - mFlushingVideo(NONE) { + mFlushingVideo(NONE), + mResetInProgress(false), + mResetPostponed(false) { } NuPlayer::~NuPlayer() { @@ -87,18 +90,22 @@ void NuPlayer::start() { (new AMessage(kWhatStart, id()))->post(); } +void NuPlayer::resetAsync() { + (new AMessage(kWhatReset, id()))->post(); +} + // static -bool NuPlayer::IsFlushingState(FlushStatus state, bool *formatChange) { +bool NuPlayer::IsFlushingState(FlushStatus state, bool *needShutdown) { switch (state) { case FLUSHING_DECODER: - if (formatChange != NULL) { - *formatChange = false; + if (needShutdown != NULL) { + *needShutdown = false; } return true; - case FLUSHING_DECODER_FORMATCHANGE: - if (formatChange != NULL) { - *formatChange = true; + case FLUSHING_DECODER_SHUTDOWN: + if (needShutdown != NULL) { + *needShutdown = true; } return true; @@ -111,7 +118,7 @@ void NuPlayer::onMessageReceived(const sp<AMessage> &msg) { switch (msg->what()) { case kWhatSetDataSource: { - LOGI("kWhatSetDataSource"); + LOGV("kWhatSetDataSource"); CHECK(mSource == NULL); @@ -124,7 +131,7 @@ void NuPlayer::onMessageReceived(const sp<AMessage> &msg) { case kWhatSetVideoSurface: { - LOGI("kWhatSetVideoSurface"); + LOGV("kWhatSetVideoSurface"); sp<RefBase> obj; CHECK(msg->findObject("surface", &obj)); @@ -135,7 +142,7 @@ void NuPlayer::onMessageReceived(const sp<AMessage> &msg) { case kWhatSetAudioSink: { - LOGI("kWhatSetAudioSink"); + LOGV("kWhatSetAudioSink"); sp<RefBase> obj; CHECK(msg->findObject("sink", &obj)); @@ -146,6 +153,9 @@ void NuPlayer::onMessageReceived(const sp<AMessage> &msg) { case kWhatStart: { + mAudioEOS = false; + mVideoEOS = false; + mSource->start(); mRenderer = new Renderer( @@ -154,13 +164,19 @@ void NuPlayer::onMessageReceived(const sp<AMessage> &msg) { looper()->registerHandler(mRenderer); - (new AMessage(kWhatScanSources, id()))->post(); - mScanSourcesPending = true; + postScanSources(); break; } case kWhatScanSources: { + int32_t generation; + CHECK(msg->findInt32("generation", &generation)); + if (generation != mScanSourcesGeneration) { + // Drop obsolete msg. + break; + } + mScanSourcesPending = false; instantiateDecoder(false, &mVideoDecoder); @@ -170,6 +186,11 @@ void NuPlayer::onMessageReceived(const sp<AMessage> &msg) { } if (!mSource->feedMoreTSData()) { + if (mAudioDecoder == NULL && mVideoDecoder == NULL) { + // We're not currently decoding anything (no audio or + // video tracks found) and we just ran out of input data. + notifyListener(MEDIA_PLAYBACK_COMPLETE, 0, 0); + } break; } @@ -203,20 +224,20 @@ void NuPlayer::onMessageReceived(const sp<AMessage> &msg) { } else if (what == ACodec::kWhatEOS) { mRenderer->queueEOS(audio, ERROR_END_OF_STREAM); } else if (what == ACodec::kWhatFlushCompleted) { - bool formatChange; + bool needShutdown; if (audio) { - CHECK(IsFlushingState(mFlushingAudio, &formatChange)); + CHECK(IsFlushingState(mFlushingAudio, &needShutdown)); mFlushingAudio = FLUSHED; } else { - CHECK(IsFlushingState(mFlushingVideo, &formatChange)); + CHECK(IsFlushingState(mFlushingVideo, &needShutdown)); mFlushingVideo = FLUSHED; } - LOGI("decoder %s flush completed", audio ? "audio" : "video"); + LOGV("decoder %s flush completed", audio ? "audio" : "video"); - if (formatChange) { - LOGI("initiating %s decoder shutdown", + if (needShutdown) { + LOGV("initiating %s decoder shutdown", audio ? "audio" : "video"); (audio ? mAudioDecoder : mVideoDecoder)->initiateShutdown(); @@ -238,7 +259,7 @@ void NuPlayer::onMessageReceived(const sp<AMessage> &msg) { int32_t sampleRate; CHECK(codecRequest->findInt32("sample-rate", &sampleRate)); - LOGI("Audio output format changed to %d Hz, %d channels", + LOGV("Audio output format changed to %d Hz, %d channels", sampleRate, numChannels); mAudioSink->close(); @@ -247,7 +268,7 @@ void NuPlayer::onMessageReceived(const sp<AMessage> &msg) { mRenderer->signalAudioSinkChanged(); } else if (what == ACodec::kWhatShutdownCompleted) { - LOGI("%s shutdown completed", audio ? "audio" : "video"); + LOGV("%s shutdown completed", audio ? "audio" : "video"); if (audio) { mAudioDecoder.clear(); @@ -285,7 +306,7 @@ void NuPlayer::onMessageReceived(const sp<AMessage> &msg) { mVideoEOS = true; } - LOGI("reached %s EOS", audio ? "audio" : "video"); + LOGV("reached %s EOS", audio ? "audio" : "video"); if ((mAudioEOS || mAudioDecoder == NULL) && (mVideoEOS || mVideoDecoder == NULL)) { @@ -297,7 +318,7 @@ void NuPlayer::onMessageReceived(const sp<AMessage> &msg) { int32_t audio; CHECK(msg->findInt32("audio", &audio)); - LOGI("renderer %s flush completed.", audio ? "audio" : "video"); + LOGV("renderer %s flush completed.", audio ? "audio" : "video"); } break; } @@ -307,6 +328,37 @@ void NuPlayer::onMessageReceived(const sp<AMessage> &msg) { break; } + case kWhatReset: + { + LOGV("kWhatReset"); + + if (mFlushingAudio != NONE || mFlushingVideo != NONE) { + // We're currently flushing, postpone the reset until that's + // completed. + + LOGV("postponing reset"); + + mResetPostponed = true; + break; + } + + if (mAudioDecoder == NULL && mVideoDecoder == NULL) { + finishReset(); + break; + } + + if (mAudioDecoder != NULL) { + flushDecoder(true /* audio */, true /* needShutdown */); + } + + if (mVideoDecoder != NULL) { + flushDecoder(false /* audio */, true /* needShutdown */); + } + + mResetInProgress = true; + break; + } + default: TRESPASS(); break; @@ -322,7 +374,7 @@ void NuPlayer::finishFlushIfPossible() { return; } - LOGI("both audio and video are flushed now."); + LOGV("both audio and video are flushed now."); mRenderer->signalTimeDiscontinuity(); @@ -343,10 +395,39 @@ void NuPlayer::finishFlushIfPossible() { mFlushingAudio = NONE; mFlushingVideo = NONE; - if (scanSourcesAgain && !mScanSourcesPending) { - mScanSourcesPending = true; - (new AMessage(kWhatScanSources, id()))->post(); + if (mResetInProgress) { + LOGV("reset completed"); + + mResetInProgress = false; + finishReset(); + } else if (mResetPostponed) { + (new AMessage(kWhatReset, id()))->post(); + mResetPostponed = false; + } else if (scanSourcesAgain) { + postScanSources(); + } +} + +void NuPlayer::finishReset() { + CHECK(mAudioDecoder == NULL); + CHECK(mVideoDecoder == NULL); + + mRenderer.clear(); + mSource.clear(); + + notifyListener(MEDIA_RESET_COMPLETE, 0, 0); +} + +void NuPlayer::postScanSources() { + if (mScanSourcesPending) { + return; } + + sp<AMessage> msg = new AMessage(kWhatScanSources, id()); + msg->setInt32("generation", mScanSourcesGeneration); + msg->post(); + + mScanSourcesPending = true; } status_t NuPlayer::instantiateDecoder(bool audio, sp<Decoder> *decoder) { @@ -396,37 +477,10 @@ status_t NuPlayer::feedDecoderInputData(bool audio, const sp<AMessage> &msg) { bool formatChange = type == ATSParser::DISCONTINUITY_FORMATCHANGE; - LOGI("%s discontinuity (formatChange=%d)", + LOGV("%s discontinuity (formatChange=%d)", audio ? "audio" : "video", formatChange); - (audio ? mAudioDecoder : mVideoDecoder)->signalFlush(); - mRenderer->flush(audio); - - if (audio) { - CHECK(mFlushingAudio == NONE - || mFlushingAudio == AWAITING_DISCONTINUITY); - - mFlushingAudio = formatChange - ? FLUSHING_DECODER_FORMATCHANGE : FLUSHING_DECODER; - - if (mFlushingVideo == NONE) { - mFlushingVideo = (mVideoDecoder != NULL) - ? AWAITING_DISCONTINUITY - : FLUSHED; - } - } else { - CHECK(mFlushingVideo == NONE - || mFlushingVideo == AWAITING_DISCONTINUITY); - - mFlushingVideo = formatChange - ? FLUSHING_DECODER_FORMATCHANGE : FLUSHING_DECODER; - - if (mFlushingAudio == NONE) { - mFlushingAudio = (mAudioDecoder != NULL) - ? AWAITING_DISCONTINUITY - : FLUSHED; - } - } + flushDecoder(audio, formatChange); } reply->setInt32("err", err); @@ -439,7 +493,7 @@ status_t NuPlayer::feedDecoderInputData(bool audio, const sp<AMessage> &msg) { #if 0 int64_t mediaTimeUs; CHECK(accessUnit->meta()->findInt64("timeUs", &mediaTimeUs)); - LOGI("feeding %s input buffer at media time %.2f secs", + LOGV("feeding %s input buffer at media time %.2f secs", audio ? "audio" : "video", mediaTimeUs / 1E6); #endif @@ -478,4 +532,39 @@ void NuPlayer::notifyListener(int msg, int ext1, int ext2) { listener->sendEvent(msg, ext1, ext2); } +void NuPlayer::flushDecoder(bool audio, bool needShutdown) { + // Make sure we don't continue to scan sources until we finish flushing. + ++mScanSourcesGeneration; + + (audio ? mAudioDecoder : mVideoDecoder)->signalFlush(); + mRenderer->flush(audio); + + FlushStatus newStatus = + needShutdown ? FLUSHING_DECODER_SHUTDOWN : FLUSHING_DECODER; + + if (audio) { + CHECK(mFlushingAudio == NONE + || mFlushingAudio == AWAITING_DISCONTINUITY); + + mFlushingAudio = newStatus; + + if (mFlushingVideo == NONE) { + mFlushingVideo = (mVideoDecoder != NULL) + ? AWAITING_DISCONTINUITY + : FLUSHED; + } + } else { + CHECK(mFlushingVideo == NONE + || mFlushingVideo == AWAITING_DISCONTINUITY); + + mFlushingVideo = newStatus; + + if (mFlushingAudio == NONE) { + mFlushingAudio = (mAudioDecoder != NULL) + ? AWAITING_DISCONTINUITY + : FLUSHED; + } + } +} + } // namespace android diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.h b/media/libmediaplayerservice/nuplayer/NuPlayer.h index 172a962..1cf2f60 100644 --- a/media/libmediaplayerservice/nuplayer/NuPlayer.h +++ b/media/libmediaplayerservice/nuplayer/NuPlayer.h @@ -40,6 +40,10 @@ struct NuPlayer : public AHandler { void setAudioSink(const sp<MediaPlayerBase::AudioSink> &sink); void start(); + // Will notify the listener that reset() has completed + // with code MEDIA_RESET_COMPLETE. + void resetAsync(); + protected: virtual ~NuPlayer(); @@ -63,6 +67,7 @@ private: kWhatVideoNotify, kWhatAudioNotify, kWhatRendererNotify, + kWhatReset, }; wp<MediaPlayerBase> mListener; @@ -73,17 +78,17 @@ private: sp<Decoder> mAudioDecoder; sp<Renderer> mRenderer; - bool mEOS; bool mAudioEOS; bool mVideoEOS; bool mScanSourcesPending; + int32_t mScanSourcesGeneration; enum FlushStatus { NONE, AWAITING_DISCONTINUITY, FLUSHING_DECODER, - FLUSHING_DECODER_FORMATCHANGE, + FLUSHING_DECODER_SHUTDOWN, SHUTTING_DOWN_DECODER, FLUSHED, SHUT_DOWN, @@ -91,6 +96,8 @@ private: FlushStatus mFlushingAudio; FlushStatus mFlushingVideo; + bool mResetInProgress; + bool mResetPostponed; status_t instantiateDecoder(bool audio, sp<Decoder> *decoder); @@ -101,7 +108,12 @@ private: void finishFlushIfPossible(); - static bool IsFlushingState(FlushStatus state, bool *formatChange = NULL); + void flushDecoder(bool audio, bool needShutdown); + + static bool IsFlushingState(FlushStatus state, bool *needShutdown = NULL); + + void finishReset(); + void postScanSources(); DISALLOW_EVIL_CONSTRUCTORS(NuPlayer); }; diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp index d21d4ff..4988d24 100644 --- a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp +++ b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp @@ -22,12 +22,14 @@ #include "NuPlayer.h" +#include <media/stagefright/foundation/ADebug.h> #include <media/stagefright/foundation/ALooper.h> namespace android { NuPlayerDriver::NuPlayerDriver() - : mLooper(new ALooper), + : mResetInProgress(false), + mLooper(new ALooper), mPlayer(false) { mLooper->setName("NuPlayerDriver Looper"); @@ -121,6 +123,15 @@ status_t NuPlayerDriver::getDuration(int *msec) { } status_t NuPlayerDriver::reset() { + Mutex::Autolock autoLock(mLock); + mResetInProgress = true; + + mPlayer->resetAsync(); + + while (mResetInProgress) { + mCondition.wait(mLock); + } + return OK; } @@ -145,4 +156,16 @@ status_t NuPlayerDriver::getMetadata( return INVALID_OPERATION; } +void NuPlayerDriver::sendEvent(int msg, int ext1, int ext2) { + if (msg != MEDIA_RESET_COMPLETE) { + MediaPlayerInterface::sendEvent(msg, ext1, ext2); + return; + } + + Mutex::Autolock autoLock(mLock); + CHECK(mResetInProgress); + mResetInProgress = false; + mCondition.broadcast(); +} + } // namespace android diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h index 44ae3bf..f153af4 100644 --- a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h +++ b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h @@ -54,10 +54,16 @@ struct NuPlayerDriver : public MediaPlayerInterface { virtual status_t getMetadata( const media::Metadata::Filter& ids, Parcel *records); + virtual void sendEvent(int msg, int ext1 = 0, int ext2 = 0); + protected: virtual ~NuPlayerDriver(); private: + Mutex mLock; + Condition mCondition; + bool mResetInProgress; + sp<ALooper> mLooper; sp<NuPlayer> mPlayer; bool mPlaying; |