switch (what) {
case Source::kWhatPrepared:
{
+ int32_t err;
+ CHECK(msg->findInt32("err", &err));
+
sp<NuPlayerDriver> driver = mDriver.promote();
if (driver != NULL) {
- driver->notifyPrepareCompleted(OK);
+ driver->notifyPrepareCompleted(err);
}
break;
}
notify->post();
}
-void NuPlayer::Source::notifyPrepared() {
+void NuPlayer::Source::notifyPrepared(status_t err) {
sp<AMessage> notify = dupNotify();
notify->setInt32("what", kWhatPrepared);
+ notify->setInt32("err", err);
notify->post();
}
NuPlayerDriver::NuPlayerDriver()
: mState(STATE_IDLE),
+ mIsAsyncPrepare(false),
mAsyncResult(UNKNOWN_ERROR),
mSetSurfaceInProgress(false),
mDurationUs(-1),
switch (mState) {
case STATE_UNPREPARED:
mState = STATE_PREPARING;
+
+ // Make sure we're not posting any notifications, success or
+ // failure information is only communicated through our result
+ // code.
+ mIsAsyncPrepare = false;
mPlayer->prepareAsync();
while (mState == STATE_PREPARING) {
mCondition.wait(mLock);
switch (mState) {
case STATE_UNPREPARED:
mState = STATE_PREPARING;
+ mIsAsyncPrepare = true;
mPlayer->prepareAsync();
return OK;
default:
mAsyncResult = err;
if (err == OK) {
- notifyListener(MEDIA_PREPARED);
+ if (mIsAsyncPrepare) {
+ notifyListener(MEDIA_PREPARED);
+ }
mState = STATE_PREPARED;
} else {
+ if (mIsAsyncPrepare) {
+ notifyListener(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err);
+ }
mState = STATE_UNPREPARED;
}
State mState;
+ bool mIsAsyncPrepare;
status_t mAsyncResult;
// The following are protected through "mLock"
void notifyFlagsChanged(uint32_t flags);
void notifyVideoSizeChanged(int32_t width, int32_t height);
- void notifyPrepared();
+ void notifyPrepared(status_t err = OK);
private:
sp<AMessage> mNotify;
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() {
switch (what) {
case MyHandler::kWhatConnected:
+ {
onConnected();
+
+ notifyVideoSizeChanged(0, 0);
+
+ uint32_t flags = 0;
+
+ if (mHandler->isSeekable()) {
+ flags = FLAG_CAN_PAUSE | FLAG_CAN_SEEK;
+
+ // Seeking 10secs forward or backward is a very expensive
+ // operation for rtsp, so let's not enable that.
+ // The user can always use the seek bar.
+ }
+
+ notifyFlagsChanged(flags);
+ notifyPrepared();
break;
+ }
case MyHandler::kWhatDisconnected:
+ {
onDisconnected(msg);
break;
+ }
case MyHandler::kWhatSeekDone:
{
}
if (err != OK) {
+ if (mState == CONNECTING) {
+ // We're still in the preparation phase, signal that it
+ // failed.
+ notifyPrepared(err);
+ }
+
mState = DISCONNECTED;
mFinalResult = err;
mLooper->unregisterHandler(mHandler->id());
mHandler.clear();
+ if (mState == CONNECTING) {
+ // We're still in the preparation phase, signal that it
+ // failed.
+ notifyPrepared(err);
+ }
+
mState = DISCONNECTED;
mFinalResult = err;
msg->post();
}
+ bool isSeekable() const {
+ return mSeekable;
+ }
+
static void addRR(const sp<ABuffer> &buf) {
uint8_t *ptr = buf->data() + buf->size();
ptr[0] = 0x80 | 0;