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
diff --git a/include/media/stagefright/AudioPlayer.h b/include/media/stagefright/AudioPlayer.h
index 8e5f05f..ea15a5c 100644
--- a/include/media/stagefright/AudioPlayer.h
+++ b/include/media/stagefright/AudioPlayer.h
@@ -61,7 +61,7 @@
status_t seekTo(int64_t time_us);
bool isSeeking();
- bool reachedEOS();
+ bool reachedEOS(status_t *finalStatus);
private:
sp<MediaSource> mSource;
@@ -81,6 +81,7 @@
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 974075d..24c2f46 100644
--- a/include/media/stagefright/OMXCodec.h
+++ b/include/media/stagefright/OMXCodec.h
@@ -132,6 +132,7 @@
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 7997cd6..57f58be 100644
--- a/media/libstagefright/AudioPlayer.cpp
+++ b/media/libstagefright/AudioPlayer.cpp
@@ -38,6 +38,7 @@
mPositionTimeRealUs(-1),
mSeeking(false),
mReachedEOS(false),
+ mFinalStatus(OK),
mStarted(false),
mAudioSink(audioSink) {
}
@@ -168,6 +169,7 @@
mPositionTimeRealUs = -1;
mSeeking = false;
mReachedEOS = false;
+ mFinalStatus = OK;
mStarted = false;
}
@@ -181,8 +183,11 @@
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 @@
if (err != OK) {
mReachedEOS = true;
+ mFinalStatus = err;
break;
}
diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp
index b3a73b0..ab65b44 100644
--- a/media/libstagefright/AwesomePlayer.cpp
+++ b/media/libstagefright/AwesomePlayer.cpp
@@ -434,14 +434,22 @@
}
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 @@
continue;
}
- postStreamDoneEvent_l();
+ postStreamDoneEvent_l(err);
return;
}
@@ -904,11 +912,13 @@
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 @@
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 a6053b3..165ac09 100644
--- a/media/libstagefright/MPEG4Extractor.cpp
+++ b/media/libstagefright/MPEG4Extractor.cpp
@@ -1450,6 +1450,14 @@
&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 4075ec1..974413d 100644
--- a/media/libstagefright/OMXCodec.cpp
+++ b/media/libstagefright/OMXCodec.cpp
@@ -1933,6 +1933,7 @@
CODEC_LOGV("signalling end of input stream.");
flags |= OMX_BUFFERFLAG_EOS;
+ mFinalStatus = err;
mSignalledEOS = true;
} else {
mNoMoreOutputData = false;
@@ -2411,7 +2412,7 @@
}
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 363e121..9c73f4a 100644
--- a/media/libstagefright/Prefetcher.cpp
+++ b/media/libstagefright/Prefetcher.cpp
@@ -55,6 +55,7 @@
size_t mIndex;
bool mStarted;
bool mReachedEOS;
+ status_t mFinalStatus;
int64_t mSeekTimeUs;
int64_t mCacheDurationUs;
bool mPrefetcherStopped;
@@ -306,7 +307,7 @@
}
if (mCachedBuffers.empty()) {
- return ERROR_END_OF_STREAM;
+ return mReachedEOS ? mFinalStatus : ERROR_END_OF_STREAM;
}
*out = *mCachedBuffers.begin();
@@ -353,6 +354,7 @@
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 ce8eeae..3590987 100644
--- a/media/libstagefright/include/AwesomePlayer.h
+++ b/media/libstagefright/include/AwesomePlayer.h
@@ -145,10 +145,11 @@
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();