diff options
author | Andreas Huber <andih@google.com> | 2010-02-12 10:42:02 -0800 |
---|---|---|
committer | Andreas Huber <andih@google.com> | 2010-02-12 12:43:34 -0800 |
commit | 7b3396acc702451be9bafb19d7fe26d55d43a316 (patch) | |
tree | eadd21b8b9142e7f0ece40c4f6b8b55323b5dd6d /media/libstagefright/AwesomePlayer.cpp | |
parent | 328901bdc7c00ab361c5ef16d0d69c94a0458e95 (diff) | |
download | frameworks_av-7b3396acc702451be9bafb19d7fe26d55d43a316.zip frameworks_av-7b3396acc702451be9bafb19d7fe26d55d43a316.tar.gz frameworks_av-7b3396acc702451be9bafb19d7fe26d55d43a316.tar.bz2 |
Squashed commit of the following:
commit 427e927298449826bb5b98327b0c05957aa051e6
Author: Andreas Huber <andih@google.com>
Date: Fri Feb 12 10:39:07 2010 -0800
Fixing a race condition in AwesomePlayer and support for suspend/resume.
commit 96201a04b6657b6bd69ec6100f4de66aebcaa0b4
Author: Andreas Huber <andih@google.com>
Date: Fri Feb 12 10:36:15 2010 -0800
Protect MPEG4Source's sanity by properly locking.
related-to-bug: 2231576
Diffstat (limited to 'media/libstagefright/AwesomePlayer.cpp')
-rw-r--r-- | media/libstagefright/AwesomePlayer.cpp | 140 |
1 files changed, 123 insertions, 17 deletions
diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp index 5d2127b..41e6911 100644 --- a/media/libstagefright/AwesomePlayer.cpp +++ b/media/libstagefright/AwesomePlayer.cpp @@ -169,7 +169,8 @@ AwesomePlayer::AwesomePlayer() mAudioPlayer(NULL), mFlags(0), mLastVideoBuffer(NULL), - mVideoBuffer(NULL) { + mVideoBuffer(NULL), + mSuspensionState(NULL) { CHECK_EQ(mClient.connect(), OK); DataSource::RegisterDefaultSniffers(); @@ -221,7 +222,11 @@ void AwesomePlayer::setListener(const wp<MediaPlayerBase> &listener) { status_t AwesomePlayer::setDataSource( const char *uri, const KeyedVector<String8, String8> *headers) { Mutex::Autolock autoLock(mLock); + return setDataSource_l(uri, headers); +} +status_t AwesomePlayer::setDataSource_l( + const char *uri, const KeyedVector<String8, String8> *headers) { reset_l(); mUri = uri; @@ -243,15 +248,22 @@ status_t AwesomePlayer::setDataSource( reset_l(); - sp<DataSource> source = new FileSource(fd, offset, length); + sp<DataSource> dataSource = new FileSource(fd, offset, length); - status_t err = source->initCheck(); + status_t err = dataSource->initCheck(); if (err != OK) { return err; } - sp<MediaExtractor> extractor = MediaExtractor::Create(source); + mFileSource = dataSource; + + return setDataSource_l(dataSource); +} + +status_t AwesomePlayer::setDataSource_l( + const sp<DataSource> &dataSource) { + sp<MediaExtractor> extractor = MediaExtractor::Create(dataSource); if (extractor == NULL) { return UNKNOWN_ERROR; @@ -299,6 +311,26 @@ void AwesomePlayer::reset_l() { cancelPlayerEvents(); + if (mPrefetcher != NULL) { + CHECK_EQ(mPrefetcher->getStrongCount(), 1); + } + mPrefetcher.clear(); + + // Shutdown audio first, so that the respone to the reset request + // appears to happen instantaneously as far as the user is concerned + // If we did this later, audio would continue playing while we + // shutdown the video-related resources and the player appear to + // not be as responsive to a reset request. + mAudioSource.clear(); + + if (mTimeSource != mAudioPlayer) { + delete mTimeSource; + } + mTimeSource = NULL; + + delete mAudioPlayer; + mAudioPlayer = NULL; + mVideoRenderer.clear(); if (mLastVideoBuffer) { @@ -325,16 +357,6 @@ void AwesomePlayer::reset_l() { IPCThreadState::self()->flushCommands(); } - mAudioSource.clear(); - - if (mTimeSource != mAudioPlayer) { - delete mTimeSource; - } - mTimeSource = NULL; - - delete mAudioPlayer; - mAudioPlayer = NULL; - mDurationUs = -1; mFlags = 0; mVideoWidth = mVideoHeight = -1; @@ -344,10 +366,13 @@ void AwesomePlayer::reset_l() { mSeeking = false; mSeekTimeUs = 0; - mPrefetcher.clear(); - mUri.setTo(""); mUriHeaders.clear(); + + mFileSource.clear(); + + delete mSuspensionState; + mSuspensionState = NULL; } void AwesomePlayer::notifyListener_l(int msg, int ext1, int ext2) { @@ -403,7 +428,10 @@ void AwesomePlayer::onStreamDone() { status_t AwesomePlayer::play() { Mutex::Autolock autoLock(mLock); + return play_l(); +} +status_t AwesomePlayer::play_l() { if (mFlags & PLAYING) { return OK; } @@ -579,7 +607,10 @@ status_t AwesomePlayer::getDuration(int64_t *durationUs) { status_t AwesomePlayer::getPosition(int64_t *positionUs) { Mutex::Autolock autoLock(mLock); + return getPosition_l(positionUs); +} +status_t AwesomePlayer::getPosition_l(int64_t *positionUs) { if (mVideoSource != NULL) { *positionUs = mVideoTimeUs; } else if (mAudioPlayer != NULL) { @@ -697,7 +728,11 @@ status_t AwesomePlayer::setVideoSource(sp<MediaSource> source) { void AwesomePlayer::onVideoEvent() { Mutex::Autolock autoLock(mLock); - + if (!mVideoEventPending) { + // The event has been cancelled in reset_l() but had already + // been scheduled for execution at that time. + return; + } mVideoEventPending = false; if (mSeeking) { @@ -985,6 +1020,7 @@ void AwesomePlayer::onPrepareAsyncEvent() { if (prefetcher != NULL) { prefetcher->prepare(); + prefetcher.clear(); } Mutex::Autolock autoLock(mLock); @@ -1006,5 +1042,75 @@ void AwesomePlayer::onPrepareAsyncEvent() { mPreparedCondition.broadcast(); } +status_t AwesomePlayer::suspend() { + LOGI("suspend"); + Mutex::Autolock autoLock(mLock); + + if (mSuspensionState != NULL) { + return INVALID_OPERATION; + } + + while (mFlags & PREPARING) { + mPreparedCondition.wait(mLock); + } + + SuspensionState *state = new SuspensionState; + state->mUri = mUri; + state->mUriHeaders = mUriHeaders; + state->mFileSource = mFileSource; + + state->mFlags = mFlags & (PLAYING | LOOPING); + getPosition_l(&state->mPositionUs); + + reset_l(); + + mSuspensionState = state; + + return OK; +} + +status_t AwesomePlayer::resume() { + LOGI("resume"); + Mutex::Autolock autoLock(mLock); + + if (mSuspensionState == NULL) { + return INVALID_OPERATION; + } + + SuspensionState *state = mSuspensionState; + mSuspensionState = NULL; + + status_t err; + if (state->mFileSource != NULL) { + err = setDataSource_l(state->mFileSource); + + if (err == OK) { + mFileSource = state->mFileSource; + } + } else { + err = setDataSource_l(state->mUri, &state->mUriHeaders); + } + + if (err != OK) { + delete state; + state = NULL; + + return err; + } + + seekTo_l(state->mPositionUs); + + mFlags = state->mFlags & LOOPING; + + if (state->mFlags & PLAYING) { + play_l(); + } + + delete state; + state = NULL; + + return OK; +} + } // namespace android |