diff options
author | Andreas Huber <andih@google.com> | 2010-02-09 14:05:43 -0800 |
---|---|---|
committer | Andreas Huber <andih@google.com> | 2010-02-09 14:27:33 -0800 |
commit | bd22c52280179b29eefac91ef7e7bbbc33d25904 (patch) | |
tree | bc50a007b5e4bed8e8f2ad13636c9e808e3bc7b2 /media | |
parent | 26bae54d7a3d04215eba34c62c349f1be6ab1493 (diff) | |
download | frameworks_av-bd22c52280179b29eefac91ef7e7bbbc33d25904.zip frameworks_av-bd22c52280179b29eefac91ef7e7bbbc33d25904.tar.gz frameworks_av-bd22c52280179b29eefac91ef7e7bbbc33d25904.tar.bz2 |
Defer actual work of setDataSource given a URI to the prepare phase in order to not block the calling thread for any significant amount of time...
related-to-bug: 2431117
Diffstat (limited to 'media')
-rw-r--r-- | media/libstagefright/AwesomePlayer.cpp | 124 | ||||
-rw-r--r-- | media/libstagefright/include/AwesomePlayer.h | 9 |
2 files changed, 109 insertions, 24 deletions
diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp index c0a2f5b..a13b242 100644 --- a/media/libstagefright/AwesomePlayer.cpp +++ b/media/libstagefright/AwesomePlayer.cpp @@ -111,6 +111,7 @@ private: AwesomePlayer::AwesomePlayer() : mTimeSource(NULL), mAudioPlayer(NULL), + mFlags(0), mLastVideoBuffer(NULL), mVideoBuffer(NULL) { CHECK_EQ(mClient.connect(), OK); @@ -167,23 +168,17 @@ status_t AwesomePlayer::setDataSource( reset_l(); - sp<DataSource> dataSource = DataSource::CreateFromURI(uri, headers); + mUri = uri; - if (dataSource == NULL) { - return UNKNOWN_ERROR; + if (headers) { + mUriHeaders = *headers; } - sp<MediaExtractor> extractor = MediaExtractor::Create(dataSource); - - if (extractor == NULL) { - return UNKNOWN_ERROR; - } - - if (dataSource->flags() & DataSource::kWantsPrefetching) { - mPrefetcher = new Prefetcher; - } + // The actual work will be done during preparation in the call to + // ::finishSetDataSource_l to avoid blocking the calling thread in + // setDataSource for any significant time. - return setDataSource_l(extractor); + return OK; } status_t AwesomePlayer::setDataSource( @@ -242,6 +237,10 @@ void AwesomePlayer::reset() { } void AwesomePlayer::reset_l() { + while (mFlags & PREPARING) { + mPreparedCondition.wait(mLock); + } + cancelPlayerEvents(); mVideoRenderer.clear(); @@ -290,6 +289,9 @@ void AwesomePlayer::reset_l() { mSeekTimeUs = 0; mPrefetcher.clear(); + + mUri.setTo(""); + mUriHeaders.clear(); } void AwesomePlayer::notifyListener_l(int msg, int ext1, int ext2) { @@ -350,6 +352,14 @@ status_t AwesomePlayer::play() { return OK; } + if (!(mFlags & PREPARED)) { + status_t err = prepare_l(); + + if (err != OK) { + return err; + } + } + mFlags |= PLAYING; mFlags |= FIRST_FRAME; @@ -815,30 +825,49 @@ void AwesomePlayer::onCheckAudioStatus() { status_t AwesomePlayer::prepare() { Mutex::Autolock autoLock(mLock); + return prepare_l(); +} +status_t AwesomePlayer::prepare_l() { + if (mFlags & PREPARED) { + return OK; + } + + if (mFlags & PREPARING) { + return UNKNOWN_ERROR; + } + + mIsAsyncPrepare = false; status_t err = prepareAsync_l(); if (err != OK) { return err; } - while (mAsyncPrepareEvent != NULL) { + while (mFlags & PREPARING) { mPreparedCondition.wait(mLock); } - return OK; + return mPrepareResult; } status_t AwesomePlayer::prepareAsync() { Mutex::Autolock autoLock(mLock); + + if (mFlags & PREPARING) { + return UNKNOWN_ERROR; // async prepare already pending + } + + mIsAsyncPrepare = true; return prepareAsync_l(); } status_t AwesomePlayer::prepareAsync_l() { - if (mAsyncPrepareEvent != NULL) { - return UNKNOWN_ERROR; // async prepare already pending. + if (mFlags & PREPARING) { + return UNKNOWN_ERROR; // async prepare already pending } + mFlags |= PREPARING; mAsyncPrepareEvent = new AwesomeEvent( this, &AwesomePlayer::onPrepareAsyncEvent); @@ -847,7 +876,49 @@ status_t AwesomePlayer::prepareAsync_l() { return OK; } +status_t AwesomePlayer::finishSetDataSource_l() { + sp<DataSource> dataSource = + DataSource::CreateFromURI(mUri.string(), &mUriHeaders); + + if (dataSource == NULL) { + return UNKNOWN_ERROR; + } + + sp<MediaExtractor> extractor = MediaExtractor::Create(dataSource); + + if (extractor == NULL) { + return UNKNOWN_ERROR; + } + + if (dataSource->flags() & DataSource::kWantsPrefetching) { + mPrefetcher = new Prefetcher; + } + + return setDataSource_l(extractor); +} + void AwesomePlayer::onPrepareAsyncEvent() { + { + Mutex::Autolock autoLock(mLock); + + if (mUri.size() > 0) { + status_t err = finishSetDataSource_l(); + + if (err != OK) { + if (mIsAsyncPrepare) { + notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err); + } + + mPrepareResult = err; + mFlags &= ~PREPARING; + mAsyncPrepareEvent = NULL; + mPreparedCondition.broadcast(); + + return; + } + } + } + sp<Prefetcher> prefetcher; { @@ -861,16 +932,21 @@ void AwesomePlayer::onPrepareAsyncEvent() { Mutex::Autolock autoLock(mLock); - if (mVideoWidth < 0 || mVideoHeight < 0) { - notifyListener_l(MEDIA_SET_VIDEO_SIZE, 0, 0); - } else { - notifyListener_l(MEDIA_SET_VIDEO_SIZE, mVideoWidth, mVideoHeight); - } + if (mIsAsyncPrepare) { + if (mVideoWidth < 0 || mVideoHeight < 0) { + notifyListener_l(MEDIA_SET_VIDEO_SIZE, 0, 0); + } else { + notifyListener_l(MEDIA_SET_VIDEO_SIZE, mVideoWidth, mVideoHeight); + } - notifyListener_l(MEDIA_PREPARED); + notifyListener_l(MEDIA_PREPARED); + } + mPrepareResult = OK; + mFlags &= ~PREPARING; + mFlags |= PREPARED; mAsyncPrepareEvent = NULL; - mPreparedCondition.signal(); + mPreparedCondition.broadcast(); } } // namespace android diff --git a/media/libstagefright/include/AwesomePlayer.h b/media/libstagefright/include/AwesomePlayer.h index 651b910..a19784b 100644 --- a/media/libstagefright/include/AwesomePlayer.h +++ b/media/libstagefright/include/AwesomePlayer.h @@ -58,6 +58,7 @@ struct AwesomePlayer { void reset(); status_t prepare(); + status_t prepare_l(); status_t prepareAsync(); status_t prepareAsync_l(); @@ -84,6 +85,8 @@ private: PLAYING = 1, LOOPING = 2, FIRST_FRAME = 4, + PREPARING = 8, + PREPARED = 16, }; mutable Mutex mLock; @@ -97,6 +100,9 @@ private: TimeSource *mTimeSource; + String8 mUri; + KeyedVector<String8, String8> mUriHeaders; + sp<MediaSource> mVideoSource; sp<AwesomeRenderer> mVideoRenderer; @@ -127,6 +133,8 @@ private: sp<TimedEventQueue::Event> mAsyncPrepareEvent; Condition mPreparedCondition; + bool mIsAsyncPrepare; + status_t mPrepareResult; void postVideoEvent_l(int64_t delayUs = -1); void postBufferingEvent_l(); @@ -158,6 +166,7 @@ private: void onBufferingUpdate(); void onCheckAudioStatus(); void onPrepareAsyncEvent(); + status_t finishSetDataSource_l(); AwesomePlayer(const AwesomePlayer &); AwesomePlayer &operator=(const AwesomePlayer &); |