From d7d22eba3c1bb7212ccc566fedb16dbee44f51a2 Mon Sep 17 00:00:00 2001 From: Andreas Huber Date: Tue, 23 Feb 2010 13:45:33 -0800 Subject: [PATCH] Propagate errors all the way through the MediaSources and send either MEDIA_PLAYBACK_COMPLETE or MEDIA_ERROR depending on the final reason for running out of buffers to play back. related-to-bug: 2463749 --- include/media/stagefright/AudioPlayer.h | 3 ++- include/media/stagefright/OMXCodec.h | 1 + media/libstagefright/AudioPlayer.cpp | 8 ++++++- media/libstagefright/AwesomePlayer.cpp | 23 +++++++++++++++----- media/libstagefright/MPEG4Extractor.cpp | 8 +++++++ media/libstagefright/OMXCodec.cpp | 3 ++- media/libstagefright/Prefetcher.cpp | 4 +++- media/libstagefright/include/AwesomePlayer.h | 3 ++- 8 files changed, 42 insertions(+), 11 deletions(-) diff --git a/include/media/stagefright/AudioPlayer.h b/include/media/stagefright/AudioPlayer.h index 8e5f05f19deea..ea15a5c407cfa 100644 --- a/include/media/stagefright/AudioPlayer.h +++ b/include/media/stagefright/AudioPlayer.h @@ -61,7 +61,7 @@ public: status_t seekTo(int64_t time_us); bool isSeeking(); - bool reachedEOS(); + bool reachedEOS(status_t *finalStatus); private: sp mSource; @@ -81,6 +81,7 @@ private: bool mSeeking; bool mReachedEOS; + status_t mFinalStatus; int64_t mSeekTimeUs; bool mStarted; diff --git a/include/media/stagefright/OMXCodec.h b/include/media/stagefright/OMXCodec.h index 974075d91e6e1..24c2f46251ef9 100644 --- a/include/media/stagefright/OMXCodec.h +++ b/include/media/stagefright/OMXCodec.h @@ -132,6 +132,7 @@ private: PortStatus mPortStatus[2]; bool mInitialBufferSubmit; bool mSignalledEOS; + status_t mFinalStatus; bool mNoMoreOutputData; bool mOutputPortSettingsHaveChanged; int64_t mSeekTimeUs; diff --git a/media/libstagefright/AudioPlayer.cpp b/media/libstagefright/AudioPlayer.cpp index 7997cd64a1b27..57f58bedad867 100644 --- a/media/libstagefright/AudioPlayer.cpp +++ b/media/libstagefright/AudioPlayer.cpp @@ -38,6 +38,7 @@ AudioPlayer::AudioPlayer(const sp &audioSink) mPositionTimeRealUs(-1), mSeeking(false), mReachedEOS(false), + mFinalStatus(OK), mStarted(false), mAudioSink(audioSink) { } @@ -168,6 +169,7 @@ void AudioPlayer::stop() { mPositionTimeRealUs = -1; mSeeking = false; mReachedEOS = false; + mFinalStatus = OK; mStarted = false; } @@ -181,8 +183,11 @@ bool AudioPlayer::isSeeking() { return mSeeking; } -bool AudioPlayer::reachedEOS() { +bool AudioPlayer::reachedEOS(status_t *finalStatus) { + *finalStatus = OK; + Mutex::Autolock autoLock(mLock); + *finalStatus = mFinalStatus; return mReachedEOS; } @@ -245,6 +250,7 @@ size_t AudioPlayer::fillBuffer(void *data, size_t size) { if (err != OK) { mReachedEOS = true; + mFinalStatus = err; break; } diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp index b3a73b0aa4fda..ab65b4414e2ca 100644 --- a/media/libstagefright/AwesomePlayer.cpp +++ b/media/libstagefright/AwesomePlayer.cpp @@ -434,14 +434,22 @@ void AwesomePlayer::onStreamDone() { } mStreamDoneEventPending = false; - if (mFlags & LOOPING) { + if (mStreamDoneStatus == ERROR_END_OF_STREAM && (mFlags & LOOPING)) { seekTo_l(0); if (mVideoSource != NULL) { postVideoEvent_l(); } } else { - notifyListener_l(MEDIA_PLAYBACK_COMPLETE); + if (mStreamDoneStatus == ERROR_END_OF_STREAM) { + LOGV("MEDIA_PLAYBACK_COMPLETE"); + notifyListener_l(MEDIA_PLAYBACK_COMPLETE); + } else { + LOGV("MEDIA_ERROR %d", mStreamDoneStatus); + + notifyListener_l( + MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, mStreamDoneStatus); + } pause_l(); @@ -802,7 +810,7 @@ void AwesomePlayer::onVideoEvent() { continue; } - postStreamDoneEvent_l(); + postStreamDoneEvent_l(err); return; } @@ -904,11 +912,13 @@ void AwesomePlayer::postVideoEvent_l(int64_t delayUs) { mQueue.postEventWithDelay(mVideoEvent, delayUs < 0 ? 10000 : delayUs); } -void AwesomePlayer::postStreamDoneEvent_l() { +void AwesomePlayer::postStreamDoneEvent_l(status_t status) { if (mStreamDoneEventPending) { return; } mStreamDoneEventPending = true; + + mStreamDoneStatus = status; mQueue.postEvent(mStreamDoneEvent); } @@ -947,9 +957,10 @@ void AwesomePlayer::onCheckAudioStatus() { notifyListener_l(MEDIA_SEEK_COMPLETE); } - if (mWatchForAudioEOS && mAudioPlayer->reachedEOS()) { + status_t finalStatus; + if (mWatchForAudioEOS && mAudioPlayer->reachedEOS(&finalStatus)) { mWatchForAudioEOS = false; - postStreamDoneEvent_l(); + postStreamDoneEvent_l(finalStatus); } postCheckAudioStatusEvent_l(); diff --git a/media/libstagefright/MPEG4Extractor.cpp b/media/libstagefright/MPEG4Extractor.cpp index a6053b39d02ab..165ac09017976 100644 --- a/media/libstagefright/MPEG4Extractor.cpp +++ b/media/libstagefright/MPEG4Extractor.cpp @@ -1450,6 +1450,14 @@ status_t MPEG4Source::read( &sampleIndex, SampleTable::kSyncSample_Flag); if (err != OK) { + if (err == ERROR_OUT_OF_RANGE) { + // An attempt to seek past the end of the stream would + // normally cause this ERROR_OUT_OF_RANGE error. Propagating + // this all the way to the MediaPlayer would cause abnormal + // termination. Legacy behaviour appears to be to behave as if + // we had seeked to the end of stream, ending normally. + err = ERROR_END_OF_STREAM; + } return err; } diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp index 4075ec1b1377c..974413d2290c3 100644 --- a/media/libstagefright/OMXCodec.cpp +++ b/media/libstagefright/OMXCodec.cpp @@ -1933,6 +1933,7 @@ void OMXCodec::drainInputBuffer(BufferInfo *info) { CODEC_LOGV("signalling end of input stream."); flags |= OMX_BUFFERFLAG_EOS; + mFinalStatus = err; mSignalledEOS = true; } else { mNoMoreOutputData = false; @@ -2411,7 +2412,7 @@ status_t OMXCodec::read( } if (mFilledBuffers.empty()) { - return ERROR_END_OF_STREAM; + return mSignalledEOS ? mFinalStatus : ERROR_END_OF_STREAM; } if (mOutputPortSettingsHaveChanged) { diff --git a/media/libstagefright/Prefetcher.cpp b/media/libstagefright/Prefetcher.cpp index 363e12192032a..9c73f4a135a4a 100644 --- a/media/libstagefright/Prefetcher.cpp +++ b/media/libstagefright/Prefetcher.cpp @@ -55,6 +55,7 @@ private: size_t mIndex; bool mStarted; bool mReachedEOS; + status_t mFinalStatus; int64_t mSeekTimeUs; int64_t mCacheDurationUs; bool mPrefetcherStopped; @@ -306,7 +307,7 @@ status_t PrefetchedSource::read( } if (mCachedBuffers.empty()) { - return ERROR_END_OF_STREAM; + return mReachedEOS ? mFinalStatus : ERROR_END_OF_STREAM; } *out = *mCachedBuffers.begin(); @@ -353,6 +354,7 @@ void PrefetchedSource::cacheMore() { if (err != OK) { mReachedEOS = true; + mFinalStatus = err; mCondition.signal(); return; diff --git a/media/libstagefright/include/AwesomePlayer.h b/media/libstagefright/include/AwesomePlayer.h index ce8eeae8c63c5..3590987d0a13d 100644 --- a/media/libstagefright/include/AwesomePlayer.h +++ b/media/libstagefright/include/AwesomePlayer.h @@ -145,10 +145,11 @@ private: Condition mPreparedCondition; bool mIsAsyncPrepare; status_t mPrepareResult; + status_t mStreamDoneStatus; void postVideoEvent_l(int64_t delayUs = -1); void postBufferingEvent_l(); - void postStreamDoneEvent_l(); + void postStreamDoneEvent_l(status_t status); void postCheckAudioStatusEvent_l(); status_t getPosition_l(int64_t *positionUs); status_t play_l();