summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndreas Huber <andih@google.com>2010-10-10 19:13:48 -0700
committerAndroid Git Automerger <android-git-automerger@android.com>2010-10-10 19:13:48 -0700
commit250e051e564e3b6f5a88314379d5e145a2b5615f (patch)
treea74d98e42412b7b1b75df245c06087d1b3a05856
parente31aa743466972764f9db5a88a713621ff0a29ae (diff)
parentb4ff90196e0bff3d80bb922933cd646381c2d1b4 (diff)
downloadframeworks_av-250e051e564e3b6f5a88314379d5e145a2b5615f.zip
frameworks_av-250e051e564e3b6f5a88314379d5e145a2b5615f.tar.gz
frameworks_av-250e051e564e3b6f5a88314379d5e145a2b5615f.tar.bz2
am cac43e8a: am beffefa2: Merge "RTSP seeking is now asynchronous, MediaPlayer is not notified that the seek is complete until it actually is. Ignore seek requests on live streams." into gingerbread
Merge commit 'cac43e8a2ce59c1151d5a2028330b2a769591d22' * commit 'cac43e8a2ce59c1151d5a2028330b2a769591d22': RTSP seeking is now asynchronous, MediaPlayer is not notified that the seek is complete until it actually is. Ignore seek requests on live streams.
-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 cd26bd6..fcc3e81 100644
--- a/media/libstagefright/AwesomePlayer.cpp
+++ b/media/libstagefright/AwesomePlayer.cpp
@@ -896,12 +896,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 c2f3090..ce7ffe5 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 6ebf4ce..8efe634 100644
--- a/media/libstagefright/include/AwesomePlayer.h
+++ b/media/libstagefright/include/AwesomePlayer.h
@@ -254,6 +254,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 4c53639..a7563ff 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 9fb5f2a..846d1d5 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;