summaryrefslogtreecommitdiffstats
path: root/media
diff options
context:
space:
mode:
authorAndreas Huber <andih@google.com>2010-02-09 14:05:43 -0800
committerAndreas Huber <andih@google.com>2010-02-09 14:27:33 -0800
commitbd22c52280179b29eefac91ef7e7bbbc33d25904 (patch)
treebc50a007b5e4bed8e8f2ad13636c9e808e3bc7b2 /media
parent26bae54d7a3d04215eba34c62c349f1be6ab1493 (diff)
downloadframeworks_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.cpp124
-rw-r--r--media/libstagefright/include/AwesomePlayer.h9
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 &);