Support for a "preparation" state that can take care of lengthy
operations in NuPlayer and its sources. Sources also can publish their
flags now and the mediaplayer UI will be able to pick up on these.
Change-Id: I4f2b7e5d105dcb4b6c9132cd0e8799efa0c6a14b
diff --git a/media/libmediaplayerservice/nuplayer/GenericSource.cpp b/media/libmediaplayerservice/nuplayer/GenericSource.cpp
index 450fae5..b04e7a6 100644
--- a/media/libmediaplayerservice/nuplayer/GenericSource.cpp
+++ b/media/libmediaplayerservice/nuplayer/GenericSource.cpp
@@ -106,6 +106,26 @@
NuPlayer::GenericSource::~GenericSource() {
}
+void NuPlayer::GenericSource::prepareAsync() {
+ if (mVideoTrack.mSource != NULL) {
+ sp<MetaData> meta = mVideoTrack.mSource->getFormat();
+
+ int32_t width, height;
+ CHECK(meta->findInt32(kKeyWidth, &width));
+ CHECK(meta->findInt32(kKeyHeight, &height));
+
+ notifyVideoSizeChanged(width, height);
+ }
+
+ notifyFlagsChanged(
+ FLAG_CAN_PAUSE
+ | FLAG_CAN_SEEK_BACKWARD
+ | FLAG_CAN_SEEK_FORWARD
+ | FLAG_CAN_SEEK);
+
+ notifyPrepared();
+}
+
void NuPlayer::GenericSource::start() {
ALOGI("start");
@@ -262,8 +282,4 @@
}
}
-uint32_t NuPlayer::GenericSource::flags() const {
- return FLAG_SEEKABLE;
-}
-
} // namespace android
diff --git a/media/libmediaplayerservice/nuplayer/GenericSource.h b/media/libmediaplayerservice/nuplayer/GenericSource.h
index e59ea3a..2da680c 100644
--- a/media/libmediaplayerservice/nuplayer/GenericSource.h
+++ b/media/libmediaplayerservice/nuplayer/GenericSource.h
@@ -42,6 +42,8 @@
const sp<AMessage> ¬ify,
int fd, int64_t offset, int64_t length);
+ virtual void prepareAsync();
+
virtual void start();
virtual status_t feedMoreTSData();
@@ -51,8 +53,6 @@
virtual status_t getDuration(int64_t *durationUs);
virtual status_t seekTo(int64_t seekTimeUs);
- virtual uint32_t flags() const;
-
protected:
virtual ~GenericSource();
diff --git a/media/libmediaplayerservice/nuplayer/HTTPLiveSource.cpp b/media/libmediaplayerservice/nuplayer/HTTPLiveSource.cpp
index d38ee62..ae67906 100644
--- a/media/libmediaplayerservice/nuplayer/HTTPLiveSource.cpp
+++ b/media/libmediaplayerservice/nuplayer/HTTPLiveSource.cpp
@@ -66,7 +66,7 @@
}
}
-void NuPlayer::HTTPLiveSource::start() {
+void NuPlayer::HTTPLiveSource::prepareAsync() {
mLiveLooper = new ALooper;
mLiveLooper->setName("http live");
mLiveLooper->start();
@@ -81,6 +81,26 @@
mURL.c_str(), mExtraHeaders.isEmpty() ? NULL : &mExtraHeaders);
mTSParser = new ATSParser;
+
+ notifyVideoSizeChanged(0, 0);
+
+ uint32_t flags = FLAG_CAN_PAUSE;
+ if (mLiveSession->isSeekable()) {
+ flags |= FLAG_CAN_SEEK;
+ flags |= FLAG_CAN_SEEK_BACKWARD;
+ flags |= FLAG_CAN_SEEK_FORWARD;
+ }
+
+ if (mLiveSession->hasDynamicDuration()) {
+ flags |= FLAG_DYNAMIC_DURATION;
+ }
+
+ notifyFlagsChanged(flags);
+
+ notifyPrepared();
+}
+
+void NuPlayer::HTTPLiveSource::start() {
}
sp<MetaData> NuPlayer::HTTPLiveSource::getFormatMeta(bool audio) {
@@ -194,18 +214,5 @@
return OK;
}
-uint32_t NuPlayer::HTTPLiveSource::flags() const {
- uint32_t flags = 0;
- if (mLiveSession->isSeekable()) {
- flags |= FLAG_SEEKABLE;
- }
-
- if (mLiveSession->hasDynamicDuration()) {
- flags |= FLAG_DYNAMIC_DURATION;
- }
-
- return flags;
-}
-
} // namespace android
diff --git a/media/libmediaplayerservice/nuplayer/HTTPLiveSource.h b/media/libmediaplayerservice/nuplayer/HTTPLiveSource.h
index 4a217af..269f3c0 100644
--- a/media/libmediaplayerservice/nuplayer/HTTPLiveSource.h
+++ b/media/libmediaplayerservice/nuplayer/HTTPLiveSource.h
@@ -34,6 +34,7 @@
bool uidValid = false,
uid_t uid = 0);
+ virtual void prepareAsync();
virtual void start();
virtual status_t feedMoreTSData();
@@ -43,8 +44,6 @@
virtual status_t getDuration(int64_t *durationUs);
virtual status_t seekTo(int64_t seekTimeUs);
- virtual uint32_t flags() const;
-
protected:
virtual ~HTTPLiveSource();
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
index 0736fbe..78b94ba 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
@@ -112,6 +112,7 @@
NuPlayer::NuPlayer()
: mUIDValid(false),
+ mSourceFlags(0),
mVideoIsAVC(false),
mAudioEOS(false),
mVideoEOS(false),
@@ -142,7 +143,7 @@
mDriver = driver;
}
-void NuPlayer::setDataSource(const sp<IStreamSource> &source) {
+void NuPlayer::setDataSourceAsync(const sp<IStreamSource> &source) {
sp<AMessage> msg = new AMessage(kWhatSetDataSource, id());
sp<AMessage> notify = new AMessage(kWhatSourceNotify, id());
@@ -174,7 +175,7 @@
return false;
}
-void NuPlayer::setDataSource(
+void NuPlayer::setDataSourceAsync(
const char *url, const KeyedVector<String8, String8> *headers) {
sp<AMessage> msg = new AMessage(kWhatSetDataSource, id());
size_t len = strlen(url);
@@ -199,7 +200,7 @@
msg->post();
}
-void NuPlayer::setDataSource(int fd, int64_t offset, int64_t length) {
+void NuPlayer::setDataSourceAsync(int fd, int64_t offset, int64_t length) {
sp<AMessage> msg = new AMessage(kWhatSetDataSource, id());
sp<AMessage> notify = new AMessage(kWhatSourceNotify, id());
@@ -209,6 +210,10 @@
msg->post();
}
+void NuPlayer::prepareAsync() {
+ (new AMessage(kWhatPrepare, id()))->post();
+}
+
void NuPlayer::setVideoSurfaceTextureAsync(
const sp<IGraphicBufferProducer> &bufferProducer) {
sp<AMessage> msg = new AMessage(kWhatSetVideoNativeWindow, id());
@@ -287,6 +292,18 @@
mSource = static_cast<Source *>(obj.get());
looper()->registerHandler(mSource);
+
+ CHECK(mDriver != NULL);
+ sp<NuPlayerDriver> driver = mDriver.promote();
+ if (driver != NULL) {
+ driver->notifySetDataSourceCompleted(OK);
+ }
+ break;
+ }
+
+ case kWhatPrepare:
+ {
+ mSource->prepareAsync();
break;
}
@@ -403,9 +420,7 @@
&& (mAudioDecoder != NULL || mVideoDecoder != NULL)) {
// This is the first time we've found anything playable.
- uint32_t flags = mSource->flags();
-
- if (flags & Source::FLAG_DYNAMIC_DURATION) {
+ if (mSourceFlags & Source::FLAG_DYNAMIC_DURATION) {
schedulePollDuration();
}
}
@@ -730,7 +745,7 @@
case kWhatSourceNotify:
{
- TRESPASS(); // TBD
+ onSourceNotify(msg);
break;
}
@@ -1233,8 +1248,76 @@
}
}
+void NuPlayer::onSourceNotify(const sp<AMessage> &msg) {
+ int32_t what;
+ CHECK(msg->findInt32("what", &what));
+
+ switch (what) {
+ case Source::kWhatPrepared:
+ {
+ sp<NuPlayerDriver> driver = mDriver.promote();
+ if (driver != NULL) {
+ driver->notifyPrepareCompleted(OK);
+ }
+ break;
+ }
+
+ case Source::kWhatFlagsChanged:
+ {
+ uint32_t flags;
+ CHECK(msg->findInt32("flags", (int32_t *)&flags));
+
+ if ((mSourceFlags & Source::FLAG_DYNAMIC_DURATION)
+ && (!(flags & Source::FLAG_DYNAMIC_DURATION))) {
+ cancelPollDuration();
+ } else if (!(mSourceFlags & Source::FLAG_DYNAMIC_DURATION)
+ && (flags & Source::FLAG_DYNAMIC_DURATION)
+ && (mAudioDecoder != NULL || mVideoDecoder != NULL)) {
+ schedulePollDuration();
+ }
+
+ mSourceFlags = flags;
+ break;
+ }
+
+ case Source::kWhatVideoSizeChanged:
+ {
+ int32_t width, height;
+ CHECK(msg->findInt32("width", &width));
+ CHECK(msg->findInt32("height", &height));
+
+ notifyListener(MEDIA_SET_VIDEO_SIZE, width, height);
+ break;
+ }
+
+ default:
+ TRESPASS();
+ }
+}
+
////////////////////////////////////////////////////////////////////////////////
+void NuPlayer::Source::notifyFlagsChanged(uint32_t flags) {
+ sp<AMessage> notify = dupNotify();
+ notify->setInt32("what", kWhatFlagsChanged);
+ notify->setInt32("flags", flags);
+ notify->post();
+}
+
+void NuPlayer::Source::notifyVideoSizeChanged(int32_t width, int32_t height) {
+ sp<AMessage> notify = dupNotify();
+ notify->setInt32("what", kWhatVideoSizeChanged);
+ notify->setInt32("width", width);
+ notify->setInt32("height", height);
+ notify->post();
+}
+
+void NuPlayer::Source::notifyPrepared() {
+ sp<AMessage> notify = dupNotify();
+ notify->setInt32("what", kWhatPrepared);
+ notify->post();
+}
+
void NuPlayer::Source::onMessageReceived(const sp<AMessage> &msg) {
TRESPASS();
}
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.h b/media/libmediaplayerservice/nuplayer/NuPlayer.h
index 0ff6089..50d0462 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.h
@@ -35,12 +35,14 @@
void setDriver(const wp<NuPlayerDriver> &driver);
- void setDataSource(const sp<IStreamSource> &source);
+ void setDataSourceAsync(const sp<IStreamSource> &source);
- void setDataSource(
+ void setDataSourceAsync(
const char *url, const KeyedVector<String8, String8> *headers);
- void setDataSource(int fd, int64_t offset, int64_t length);
+ void setDataSourceAsync(int fd, int64_t offset, int64_t length);
+
+ void prepareAsync();
void setVideoSurfaceTextureAsync(
const sp<IGraphicBufferProducer> &bufferProducer);
@@ -82,6 +84,7 @@
enum {
kWhatSetDataSource = '=DaS',
+ kWhatPrepare = 'prep',
kWhatSetVideoNativeWindow = '=NaW',
kWhatSetAudioSink = '=AuS',
kWhatMoreDataQueued = 'more',
@@ -102,6 +105,7 @@
bool mUIDValid;
uid_t mUID;
sp<Source> mSource;
+ uint32_t mSourceFlags;
sp<NativeWindowWrapper> mNativeWindow;
sp<MediaPlayerBase::AudioSink> mAudioSink;
sp<Decoder> mVideoDecoder;
@@ -173,6 +177,8 @@
void performScanSources();
void performSetSurface(const sp<NativeWindowWrapper> &wrapper);
+ void onSourceNotify(const sp<AMessage> &msg);
+
DISALLOW_EVIL_CONSTRUCTORS(NuPlayer);
};
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
index 7043404..ab7b4e8 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
@@ -21,21 +21,24 @@
#include "NuPlayerDriver.h"
#include "NuPlayer.h"
+#include "NuPlayerSource.h"
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/foundation/ALooper.h>
+#include <media/stagefright/MetaData.h>
namespace android {
NuPlayerDriver::NuPlayerDriver()
- : mResetInProgress(false),
+ : mState(STATE_IDLE),
+ mAsyncResult(UNKNOWN_ERROR),
mSetSurfaceInProgress(false),
mDurationUs(-1),
mPositionUs(-1),
mNumFramesTotal(0),
mNumFramesDropped(0),
mLooper(new ALooper),
- mState(UNINITIALIZED),
+ mPlayerFlags(0),
mAtEOS(false),
mStartupSeekTimeUs(-1) {
mLooper->setName("NuPlayerDriver Looper");
@@ -67,43 +70,76 @@
status_t NuPlayerDriver::setDataSource(
const char *url, const KeyedVector<String8, String8> *headers) {
- CHECK_EQ((int)mState, (int)UNINITIALIZED);
+ Mutex::Autolock autoLock(mLock);
- mPlayer->setDataSource(url, headers);
+ if (mState != STATE_IDLE) {
+ return INVALID_OPERATION;
+ }
- mState = STOPPED;
+ mState = STATE_SET_DATASOURCE_PENDING;
- return OK;
+ mPlayer->setDataSourceAsync(url, headers);
+
+ while (mState == STATE_SET_DATASOURCE_PENDING) {
+ mCondition.wait(mLock);
+ }
+
+ return mAsyncResult;
}
status_t NuPlayerDriver::setDataSource(int fd, int64_t offset, int64_t length) {
- CHECK_EQ((int)mState, (int)UNINITIALIZED);
+ Mutex::Autolock autoLock(mLock);
- mPlayer->setDataSource(fd, offset, length);
+ if (mState != STATE_IDLE) {
+ return INVALID_OPERATION;
+ }
- mState = STOPPED;
+ mState = STATE_SET_DATASOURCE_PENDING;
- return OK;
+ mPlayer->setDataSourceAsync(fd, offset, length);
+
+ while (mState == STATE_SET_DATASOURCE_PENDING) {
+ mCondition.wait(mLock);
+ }
+
+ return mAsyncResult;
}
status_t NuPlayerDriver::setDataSource(const sp<IStreamSource> &source) {
- CHECK_EQ((int)mState, (int)UNINITIALIZED);
+ Mutex::Autolock autoLock(mLock);
- mPlayer->setDataSource(source);
+ if (mState != STATE_IDLE) {
+ return INVALID_OPERATION;
+ }
- mState = STOPPED;
+ mState = STATE_SET_DATASOURCE_PENDING;
- return OK;
+ mPlayer->setDataSourceAsync(source);
+
+ while (mState == STATE_SET_DATASOURCE_PENDING) {
+ mCondition.wait(mLock);
+ }
+
+ return mAsyncResult;
}
status_t NuPlayerDriver::setVideoSurfaceTexture(
const sp<IGraphicBufferProducer> &bufferProducer) {
Mutex::Autolock autoLock(mLock);
- if (mResetInProgress) {
+ if (mSetSurfaceInProgress) {
return INVALID_OPERATION;
}
+ switch (mState) {
+ case STATE_SET_DATASOURCE_PENDING:
+ case STATE_RESET_IN_PROGRESS:
+ return INVALID_OPERATION;
+
+ default:
+ break;
+ }
+
mSetSurfaceInProgress = true;
mPlayer->setVideoSurfaceTextureAsync(bufferProducer);
@@ -116,23 +152,55 @@
}
status_t NuPlayerDriver::prepare() {
- sendEvent(MEDIA_SET_VIDEO_SIZE, 0, 0);
- return OK;
+ Mutex::Autolock autoLock(mLock);
+ return prepare_l();
+}
+
+status_t NuPlayerDriver::prepare_l() {
+ switch (mState) {
+ case STATE_UNPREPARED:
+ mState = STATE_PREPARING;
+ mPlayer->prepareAsync();
+ while (mState == STATE_PREPARING) {
+ mCondition.wait(mLock);
+ }
+ return (mState == STATE_PREPARED) ? OK : UNKNOWN_ERROR;
+ default:
+ return INVALID_OPERATION;
+ };
}
status_t NuPlayerDriver::prepareAsync() {
- status_t err = prepare();
+ Mutex::Autolock autoLock(mLock);
- notifyListener(MEDIA_PREPARED);
-
- return err;
+ switch (mState) {
+ case STATE_UNPREPARED:
+ mState = STATE_PREPARING;
+ mPlayer->prepareAsync();
+ return OK;
+ default:
+ return INVALID_OPERATION;
+ };
}
status_t NuPlayerDriver::start() {
+ Mutex::Autolock autoLock(mLock);
+
switch (mState) {
- case UNINITIALIZED:
- return INVALID_OPERATION;
- case STOPPED:
+ case STATE_UNPREPARED:
+ {
+ status_t err = prepare_l();
+
+ if (err != OK) {
+ return err;
+ }
+
+ CHECK_EQ(mState, STATE_PREPARED);
+
+ // fall through
+ }
+
+ case STATE_PREPARED:
{
mAtEOS = false;
mPlayer->start();
@@ -146,21 +214,23 @@
mStartupSeekTimeUs = -1;
}
-
break;
}
- case PLAYING:
- return OK;
- default:
- {
- CHECK_EQ((int)mState, (int)PAUSED);
+ case STATE_RUNNING:
+ break;
+
+ case STATE_PAUSED:
+ {
mPlayer->resume();
break;
}
+
+ default:
+ return INVALID_OPERATION;
}
- mState = PLAYING;
+ mState = STATE_RUNNING;
return OK;
}
@@ -170,43 +240,44 @@
}
status_t NuPlayerDriver::pause() {
+ Mutex::Autolock autoLock(mLock);
+
switch (mState) {
- case UNINITIALIZED:
- return INVALID_OPERATION;
- case STOPPED:
+ case STATE_PAUSED:
+ case STATE_PREPARED:
return OK;
- case PLAYING:
+
+ case STATE_RUNNING:
mPlayer->pause();
break;
+
default:
- {
- CHECK_EQ((int)mState, (int)PAUSED);
- return OK;
- }
+ return INVALID_OPERATION;
}
- mState = PAUSED;
+ mState = STATE_PAUSED;
return OK;
}
bool NuPlayerDriver::isPlaying() {
- return mState == PLAYING && !mAtEOS;
+ return mState == STATE_RUNNING && !mAtEOS;
}
status_t NuPlayerDriver::seekTo(int msec) {
+ Mutex::Autolock autoLock(mLock);
+
int64_t seekTimeUs = msec * 1000ll;
switch (mState) {
- case UNINITIALIZED:
- return INVALID_OPERATION;
- case STOPPED:
+ case STATE_PREPARED:
{
mStartupSeekTimeUs = seekTimeUs;
break;
}
- case PLAYING:
- case PAUSED:
+
+ case STATE_RUNNING:
+ case STATE_PAUSED:
{
mAtEOS = false;
mPlayer->seekToAsync(seekTimeUs);
@@ -214,8 +285,7 @@
}
default:
- TRESPASS();
- break;
+ return INVALID_OPERATION;
}
return OK;
@@ -247,17 +317,28 @@
status_t NuPlayerDriver::reset() {
Mutex::Autolock autoLock(mLock);
- mResetInProgress = true;
+ switch (mState) {
+ case STATE_IDLE:
+ return OK;
+
+ case STATE_SET_DATASOURCE_PENDING:
+ case STATE_RESET_IN_PROGRESS:
+ return INVALID_OPERATION;
+
+ default:
+ break;
+ }
+
+ mState = STATE_RESET_IN_PROGRESS;
mPlayer->resetAsync();
- while (mResetInProgress) {
+ while (mState == STATE_RESET_IN_PROGRESS) {
mCondition.wait(mLock);
}
mDurationUs = -1;
mPositionUs = -1;
- mState = UNINITIALIZED;
mStartupSeekTimeUs = -1;
return OK;
@@ -311,20 +392,45 @@
status_t NuPlayerDriver::getMetadata(
const media::Metadata::Filter& ids, Parcel *records) {
- return INVALID_OPERATION;
+ Mutex::Autolock autoLock(mLock);
+
+ using media::Metadata;
+
+ Metadata meta(records);
+
+ meta.appendBool(
+ Metadata::kPauseAvailable,
+ mPlayerFlags & NuPlayer::Source::FLAG_CAN_PAUSE);
+
+ meta.appendBool(
+ Metadata::kSeekBackwardAvailable,
+ mPlayerFlags & NuPlayer::Source::FLAG_CAN_SEEK_BACKWARD);
+
+ meta.appendBool(
+ Metadata::kSeekForwardAvailable,
+ mPlayerFlags & NuPlayer::Source::FLAG_CAN_SEEK_FORWARD);
+
+ meta.appendBool(
+ Metadata::kSeekAvailable,
+ mPlayerFlags & NuPlayer::Source::FLAG_CAN_SEEK);
+
+ return OK;
}
void NuPlayerDriver::notifyResetComplete() {
Mutex::Autolock autoLock(mLock);
- CHECK(mResetInProgress);
- mResetInProgress = false;
+
+ CHECK_EQ(mState, STATE_RESET_IN_PROGRESS);
+ mState = STATE_IDLE;
mCondition.broadcast();
}
void NuPlayerDriver::notifySetSurfaceComplete() {
Mutex::Autolock autoLock(mLock);
+
CHECK(mSetSurfaceInProgress);
mSetSurfaceInProgress = false;
+
mCondition.broadcast();
}
@@ -376,4 +482,37 @@
sendEvent(msg, ext1, ext2);
}
+void NuPlayerDriver::notifySetDataSourceCompleted(status_t err) {
+ Mutex::Autolock autoLock(mLock);
+
+ CHECK_EQ(mState, STATE_SET_DATASOURCE_PENDING);
+
+ mAsyncResult = err;
+ mState = (err == OK) ? STATE_UNPREPARED : STATE_IDLE;
+ mCondition.broadcast();
+}
+
+void NuPlayerDriver::notifyPrepareCompleted(status_t err) {
+ Mutex::Autolock autoLock(mLock);
+
+ CHECK_EQ(mState, STATE_PREPARING);
+
+ mAsyncResult = err;
+
+ if (err == OK) {
+ notifyListener(MEDIA_PREPARED);
+ mState = STATE_PREPARED;
+ } else {
+ mState = STATE_UNPREPARED;
+ }
+
+ mCondition.broadcast();
+}
+
+void NuPlayerDriver::notifyFlagsChanged(uint32_t flags) {
+ Mutex::Autolock autoLock(mLock);
+
+ mPlayerFlags = flags;
+}
+
} // namespace android
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h
index 553c406..49b8ed2 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h
@@ -61,6 +61,8 @@
virtual status_t dump(int fd, const Vector<String16> &args) const;
+ void notifySetDataSourceCompleted(status_t err);
+ void notifyPrepareCompleted(status_t err);
void notifyResetComplete();
void notifySetSurfaceComplete();
void notifyDuration(int64_t durationUs);
@@ -68,17 +70,32 @@
void notifySeekComplete();
void notifyFrameStats(int64_t numFramesTotal, int64_t numFramesDropped);
void notifyListener(int msg, int ext1 = 0, int ext2 = 0);
+ void notifyFlagsChanged(uint32_t flags);
protected:
virtual ~NuPlayerDriver();
private:
+ enum State {
+ STATE_IDLE,
+ STATE_SET_DATASOURCE_PENDING,
+ STATE_UNPREPARED,
+ STATE_PREPARING,
+ STATE_PREPARED,
+ STATE_RUNNING,
+ STATE_PAUSED,
+ STATE_RESET_IN_PROGRESS,
+ };
+
mutable Mutex mLock;
Condition mCondition;
+ State mState;
+
+ status_t mAsyncResult;
+
// The following are protected through "mLock"
// >>>
- bool mResetInProgress;
bool mSetSurfaceInProgress;
int64_t mDurationUs;
int64_t mPositionUs;
@@ -88,19 +105,14 @@
sp<ALooper> mLooper;
sp<NuPlayer> mPlayer;
+ uint32_t mPlayerFlags;
- enum State {
- UNINITIALIZED,
- STOPPED,
- PLAYING,
- PAUSED
- };
-
- State mState;
bool mAtEOS;
int64_t mStartupSeekTimeUs;
+ status_t prepare_l();
+
DISALLOW_EVIL_CONSTRUCTORS(NuPlayerDriver);
};
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerSource.h b/media/libmediaplayerservice/nuplayer/NuPlayerSource.h
index a3201cf..53c7c12 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerSource.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerSource.h
@@ -25,11 +25,21 @@
namespace android {
struct ABuffer;
+struct MetaData;
struct NuPlayer::Source : public AHandler {
enum Flags {
- FLAG_SEEKABLE = 1,
- FLAG_DYNAMIC_DURATION = 2,
+ FLAG_CAN_PAUSE = 1,
+ FLAG_CAN_SEEK_BACKWARD = 2, // the "10 sec back button"
+ FLAG_CAN_SEEK_FORWARD = 4, // the "10 sec forward button"
+ FLAG_CAN_SEEK = 8, // the "seek bar"
+ FLAG_DYNAMIC_DURATION = 16,
+ };
+
+ enum {
+ kWhatPrepared,
+ kWhatFlagsChanged,
+ kWhatVideoSizeChanged,
};
// The provides message is used to notify the player about various
@@ -38,6 +48,8 @@
: mNotify(notify) {
}
+ virtual void prepareAsync() = 0;
+
virtual void start() = 0;
virtual void stop() {}
@@ -58,8 +70,6 @@
return INVALID_OPERATION;
}
- virtual uint32_t flags() const = 0;
-
protected:
virtual ~Source() {}
@@ -69,6 +79,10 @@
sp<AMessage> dupNotify() const { return mNotify->dup(); }
+ void notifyFlagsChanged(uint32_t flags);
+ void notifyVideoSizeChanged(int32_t width, int32_t height);
+ void notifyPrepared();
+
private:
sp<AMessage> mNotify;
diff --git a/media/libmediaplayerservice/nuplayer/RTSPSource.cpp b/media/libmediaplayerservice/nuplayer/RTSPSource.cpp
index 3035589..e4d72d9 100644
--- a/media/libmediaplayerservice/nuplayer/RTSPSource.cpp
+++ b/media/libmediaplayerservice/nuplayer/RTSPSource.cpp
@@ -65,7 +65,7 @@
mLooper->stop();
}
-void NuPlayer::RTSPSource::start() {
+void NuPlayer::RTSPSource::prepareAsync() {
if (mLooper == NULL) {
mLooper = new ALooper;
mLooper->setName("rtsp");
@@ -88,13 +88,27 @@
(mFlags & kFlagIncognito) ? SDPLoader::kFlagIncognito : 0,
mUIDValid, mUID);
- mSDPLoader->load(mURL.c_str(), mExtraHeaders.isEmpty() ? NULL : &mExtraHeaders);
+ mSDPLoader->load(
+ mURL.c_str(), mExtraHeaders.isEmpty() ? NULL : &mExtraHeaders);
} else {
mHandler = new MyHandler(mURL.c_str(), notify, mUIDValid, mUID);
mLooper->registerHandler(mHandler);
mHandler->connect();
}
+
+ notifyVideoSizeChanged(0, 0);
+
+ notifyFlagsChanged(
+ FLAG_CAN_PAUSE
+ | FLAG_CAN_SEEK_BACKWARD
+ | FLAG_CAN_SEEK_FORWARD
+ | FLAG_CAN_SEEK);
+
+ notifyPrepared();
+}
+
+void NuPlayer::RTSPSource::start() {
}
void NuPlayer::RTSPSource::stop() {
@@ -225,10 +239,6 @@
mHandler->seek(seekTimeUs);
}
-uint32_t NuPlayer::RTSPSource::flags() const {
- return FLAG_SEEKABLE;
-}
-
void NuPlayer::RTSPSource::onMessageReceived(const sp<AMessage> &msg) {
if (msg->what() == kWhatDisconnect) {
uint32_t replyID;
diff --git a/media/libmediaplayerservice/nuplayer/RTSPSource.h b/media/libmediaplayerservice/nuplayer/RTSPSource.h
index b2a7dae..cbb6f90 100644
--- a/media/libmediaplayerservice/nuplayer/RTSPSource.h
+++ b/media/libmediaplayerservice/nuplayer/RTSPSource.h
@@ -40,6 +40,7 @@
uid_t uid = 0,
bool isSDP = false);
+ virtual void prepareAsync();
virtual void start();
virtual void stop();
@@ -50,8 +51,6 @@
virtual status_t getDuration(int64_t *durationUs);
virtual status_t seekTo(int64_t seekTimeUs);
- virtual uint32_t flags() const;
-
void onMessageReceived(const sp<AMessage> &msg);
protected:
diff --git a/media/libmediaplayerservice/nuplayer/StreamingSource.cpp b/media/libmediaplayerservice/nuplayer/StreamingSource.cpp
index 9b04833..df03f86 100644
--- a/media/libmediaplayerservice/nuplayer/StreamingSource.cpp
+++ b/media/libmediaplayerservice/nuplayer/StreamingSource.cpp
@@ -43,6 +43,12 @@
NuPlayer::StreamingSource::~StreamingSource() {
}
+void NuPlayer::StreamingSource::prepareAsync() {
+ notifyVideoSizeChanged(0, 0);
+ notifyFlagsChanged(0);
+ notifyPrepared();
+}
+
void NuPlayer::StreamingSource::start() {
mStreamListener = new NuPlayerStreamListener(mSource, 0);
@@ -176,9 +182,5 @@
return err;
}
-uint32_t NuPlayer::StreamingSource::flags() const {
- return 0;
-}
-
} // namespace android
diff --git a/media/libmediaplayerservice/nuplayer/StreamingSource.h b/media/libmediaplayerservice/nuplayer/StreamingSource.h
index dc616f7..80b061c 100644
--- a/media/libmediaplayerservice/nuplayer/StreamingSource.h
+++ b/media/libmediaplayerservice/nuplayer/StreamingSource.h
@@ -31,14 +31,13 @@
const sp<AMessage> ¬ify,
const sp<IStreamSource> &source);
+ virtual void prepareAsync();
virtual void start();
virtual status_t feedMoreTSData();
virtual status_t dequeueAccessUnit(bool audio, sp<ABuffer> *accessUnit);
- virtual uint32_t flags() const;
-
protected:
virtual ~StreamingSource();
diff --git a/media/libmediaplayerservice/nuplayer/mp4/MP4Source.cpp b/media/libmediaplayerservice/nuplayer/mp4/MP4Source.cpp
index d659b73..d31d947 100644
--- a/media/libmediaplayerservice/nuplayer/mp4/MP4Source.cpp
+++ b/media/libmediaplayerservice/nuplayer/mp4/MP4Source.cpp
@@ -117,6 +117,12 @@
MP4Source::~MP4Source() {
}
+void MP4Source::prepareAsync() {
+ notifyVideoSizeChanged(0, 0);
+ notifyFlagsChanged(0);
+ notifyPrepared();
+}
+
void MP4Source::start() {
mLooper->start(false /* runOnCallingThread */);
mParser->start(new StreamSource(mSource));
@@ -135,8 +141,4 @@
return mParser->dequeueAccessUnit(audio, accessUnit);
}
-uint32_t MP4Source::flags() const {
- return 0;
-}
-
} // namespace android
diff --git a/media/libmediaplayerservice/nuplayer/mp4/MP4Source.h b/media/libmediaplayerservice/nuplayer/mp4/MP4Source.h
index b16a111..a6ef622 100644
--- a/media/libmediaplayerservice/nuplayer/mp4/MP4Source.h
+++ b/media/libmediaplayerservice/nuplayer/mp4/MP4Source.h
@@ -26,6 +26,7 @@
struct MP4Source : public NuPlayer::Source {
MP4Source(const sp<AMessage> ¬ify, const sp<IStreamSource> &source);
+ virtual void prepareAsync();
virtual void start();
virtual status_t feedMoreTSData();
@@ -35,8 +36,6 @@
virtual status_t dequeueAccessUnit(
bool audio, sp<ABuffer> *accessUnit);
- virtual uint32_t flags() const;
-
protected:
virtual ~MP4Source();