summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Andreas Huber <andih@google.com> 2010-10-08 15:21:08 -0700
committer Andreas Huber <andih@google.com> 2010-10-08 15:25:19 -0700
commit0c46b69f612da61ed39b32823d2d6baf2e8215e9 (patch)
tree2489d267e3df8585551b12c19c9eb87f6354646e
parent0fd4e216e7d6045528d5d1010f8b5f01581efb10 (diff)
RTSP seeking is now asynchronous, MediaPlayer is not notified that the seek is complete until it actually is. Ignore seek requests on live streams.
Change-Id: Ie61230cd60dd6c682baf72529100369ad6291189 related-to-bug: 3073955
-rw-r--r--media/libstagefright/AwesomePlayer.cpp15
-rw-r--r--media/libstagefright/include/ARTSPController.h7
-rw-r--r--media/libstagefright/include/AwesomePlayer.h3
-rw-r--r--media/libstagefright/rtsp/ARTSPController.cpp41
-rw-r--r--media/libstagefright/rtsp/MyHandler.h32
5 files changed, 87 insertions, 11 deletions
diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp
index 53543b374c0f..ff28f3b86769 100644
--- a/media/libstagefright/AwesomePlayer.cpp
+++ b/media/libstagefright/AwesomePlayer.cpp
@@ -876,12 +876,19 @@ status_t AwesomePlayer::seekTo(int64_t timeUs) {
return OK;
}
+// static
+void AwesomePlayer::OnRTSPSeekDoneWrapper(void *cookie) {
+ static_cast<AwesomePlayer *>(cookie)->onRTSPSeekDone();
+}
+
+void AwesomePlayer::onRTSPSeekDone() {
+ notifyListener_l(MEDIA_SEEK_COMPLETE);
+ mSeekNotificationSent = true;
+}
+
status_t AwesomePlayer::seekTo_l(int64_t timeUs) {
if (mRTSPController != NULL) {
- mRTSPController->seek(timeUs);
-
- notifyListener_l(MEDIA_SEEK_COMPLETE);
- mSeekNotificationSent = true;
+ mRTSPController->seekAsync(timeUs, OnRTSPSeekDoneWrapper, this);
return OK;
}
diff --git a/media/libstagefright/include/ARTSPController.h b/media/libstagefright/include/ARTSPController.h
index c2f3090b03a4..ce7ffe5c2352 100644
--- a/media/libstagefright/include/ARTSPController.h
+++ b/media/libstagefright/include/ARTSPController.h
@@ -33,7 +33,7 @@ struct ARTSPController : public MediaExtractor {
status_t connect(const char *url);
void disconnect();
- void seek(int64_t timeUs);
+ void seekAsync(int64_t timeUs, void (*seekDoneCb)(void *), void *cookie);
virtual size_t countTracks();
virtual sp<MediaSource> getTrack(size_t index);
@@ -61,6 +61,7 @@ private:
enum {
kWhatConnectDone = 'cdon',
kWhatDisconnectDone = 'ddon',
+ kWhatSeekDone = 'sdon',
};
enum State {
@@ -79,6 +80,10 @@ private:
sp<MyHandler> mHandler;
sp<AHandlerReflector<ARTSPController> > mReflector;
+ void (*mSeekDoneCb)(void *);
+ void *mSeekDoneCookie;
+ int64_t mLastSeekCompletedTimeUs;
+
DISALLOW_EVIL_CONSTRUCTORS(ARTSPController);
};
diff --git a/media/libstagefright/include/AwesomePlayer.h b/media/libstagefright/include/AwesomePlayer.h
index bbf482d48f66..079adcabca80 100644
--- a/media/libstagefright/include/AwesomePlayer.h
+++ b/media/libstagefright/include/AwesomePlayer.h
@@ -251,6 +251,9 @@ private:
static bool ContinuePreparation(void *cookie);
+ static void OnRTSPSeekDoneWrapper(void *cookie);
+ void onRTSPSeekDone();
+
AwesomePlayer(const AwesomePlayer &);
AwesomePlayer &operator=(const AwesomePlayer &);
};
diff --git a/media/libstagefright/rtsp/ARTSPController.cpp b/media/libstagefright/rtsp/ARTSPController.cpp
index 4c53639a9e8e..a7563ff93b3d 100644
--- a/media/libstagefright/rtsp/ARTSPController.cpp
+++ b/media/libstagefright/rtsp/ARTSPController.cpp
@@ -27,7 +27,10 @@ namespace android {
ARTSPController::ARTSPController(const sp<ALooper> &looper)
: mState(DISCONNECTED),
- mLooper(looper) {
+ mLooper(looper),
+ mSeekDoneCb(NULL),
+ mSeekDoneCookie(NULL),
+ mLastSeekCompletedTimeUs(-1) {
mReflector = new AHandlerReflector<ARTSPController>(this);
looper->registerHandler(mReflector);
}
@@ -80,14 +83,31 @@ void ARTSPController::disconnect() {
mHandler.clear();
}
-void ARTSPController::seek(int64_t timeUs) {
+void ARTSPController::seekAsync(
+ int64_t timeUs,
+ void (*seekDoneCb)(void *), void *cookie) {
Mutex::Autolock autoLock(mLock);
- if (mState != CONNECTED) {
+ CHECK(seekDoneCb != NULL);
+ CHECK(mSeekDoneCb == NULL);
+
+ // Ignore seek requests that are too soon after the previous one has
+ // completed, we don't want to swamp the server.
+
+ bool tooEarly =
+ mLastSeekCompletedTimeUs >= 0
+ && ALooper::GetNowUs() < mLastSeekCompletedTimeUs + 500000ll;
+
+ if (mState != CONNECTED || tooEarly) {
+ (*seekDoneCb)(cookie);
return;
}
- mHandler->seek(timeUs);
+ mSeekDoneCb = seekDoneCb;
+ mSeekDoneCookie = cookie;
+
+ sp<AMessage> msg = new AMessage(kWhatSeekDone, mReflector->id());
+ mHandler->seek(timeUs, msg);
}
size_t ARTSPController::countTracks() {
@@ -132,6 +152,19 @@ void ARTSPController::onMessageReceived(const sp<AMessage> &msg) {
break;
}
+ case kWhatSeekDone:
+ {
+ LOGI("seek done");
+
+ mLastSeekCompletedTimeUs = ALooper::GetNowUs();
+
+ void (*seekDoneCb)(void *) = mSeekDoneCb;
+ mSeekDoneCb = NULL;
+
+ (*seekDoneCb)(mSeekDoneCookie);
+ break;
+ }
+
default:
TRESPASS();
break;
diff --git a/media/libstagefright/rtsp/MyHandler.h b/media/libstagefright/rtsp/MyHandler.h
index 2c9cfd3be81e..05dd61b9ac86 100644
--- a/media/libstagefright/rtsp/MyHandler.h
+++ b/media/libstagefright/rtsp/MyHandler.h
@@ -88,7 +88,8 @@ struct MyHandler : public AHandler {
mCheckPending(false),
mCheckGeneration(0),
mTryTCPInterleaving(false),
- mReceivedFirstRTCPPacket(false) {
+ mReceivedFirstRTCPPacket(false),
+ mSeekable(false) {
mNetLooper->setName("rtsp net");
mNetLooper->start(false /* runOnCallingThread */,
false /* canCallJava */,
@@ -115,9 +116,10 @@ struct MyHandler : public AHandler {
(new AMessage('abor', id()))->post();
}
- void seek(int64_t timeUs) {
+ void seek(int64_t timeUs, const sp<AMessage> &doneMsg) {
sp<AMessage> msg = new AMessage('seek', id());
msg->setInt64("time", timeUs);
+ msg->setMessage("doneMsg", doneMsg);
msg->post();
}
@@ -379,6 +381,7 @@ struct MyHandler : public AHandler {
mFirstAccessUnitNTP = 0;
mNumAccessUnitsReceived = 0;
mReceivedFirstRTCPPacket = false;
+ mSeekable = false;
sp<AMessage> reply = new AMessage('tear', id());
@@ -551,7 +554,17 @@ struct MyHandler : public AHandler {
case 'seek':
{
+ sp<AMessage> doneMsg;
+ CHECK(msg->findMessage("doneMsg", &doneMsg));
+
if (mSeekPending) {
+ doneMsg->post();
+ break;
+ }
+
+ if (!mSeekable) {
+ LOGW("This is a live stream, ignoring seek request.");
+ doneMsg->post();
break;
}
@@ -577,6 +590,7 @@ struct MyHandler : public AHandler {
sp<AMessage> reply = new AMessage('see1', id());
reply->setInt64("time", timeUs);
+ reply->setMessage("doneMsg", doneMsg);
mConn->sendRequest(request.c_str(), reply);
break;
}
@@ -605,7 +619,11 @@ struct MyHandler : public AHandler {
request.append("\r\n");
+ sp<AMessage> doneMsg;
+ CHECK(msg->findMessage("doneMsg", &doneMsg));
+
sp<AMessage> reply = new AMessage('see2', id());
+ reply->setMessage("doneMsg", doneMsg);
mConn->sendRequest(request.c_str(), reply);
break;
}
@@ -644,6 +662,11 @@ struct MyHandler : public AHandler {
}
mSeekPending = false;
+
+ sp<AMessage> doneMsg;
+ CHECK(msg->findMessage("doneMsg", &doneMsg));
+
+ doneMsg->post();
break;
}
@@ -714,6 +737,8 @@ struct MyHandler : public AHandler {
}
void parsePlayResponse(const sp<ARTSPResponse> &response) {
+ mSeekable = false;
+
ssize_t i = response->mHeaders.indexOfKey("range");
if (i < 0) {
// Server doesn't even tell use what range it is going to
@@ -777,6 +802,8 @@ struct MyHandler : public AHandler {
++n;
}
+
+ mSeekable = true;
}
sp<APacketSource> getPacketSource(size_t index) {
@@ -808,6 +835,7 @@ private:
int32_t mCheckGeneration;
bool mTryTCPInterleaving;
bool mReceivedFirstRTCPPacket;
+ bool mSeekable;
struct TrackInfo {
AString mURL;