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
This commit is contained in:
@@ -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);
|
||||
// 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.
|
||||
|
||||
if (extractor == NULL) {
|
||||
return UNKNOWN_ERROR;
|
||||
}
|
||||
|
||||
if (dataSource->flags() & DataSource::kWantsPrefetching) {
|
||||
mPrefetcher = new Prefetcher;
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
@@ -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 &);
|
||||
|
||||
Reference in New Issue
Block a user