summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndreas Huber <andih@google.com>2012-11-16 10:38:11 -0800
committerAndreas Huber <andih@google.com>2012-11-29 10:33:51 -0800
commit5131d127a042ee88f903370be88845dc8c9f8578 (patch)
treeb6c2153d94a2dd57b8dfaaa12742c60c4fec0187
parent79c56d3f17d3193a0a86eb3c9bfdea90b89ae3f9 (diff)
downloadframeworks_av-5131d127a042ee88f903370be88845dc8c9f8578.zip
frameworks_av-5131d127a042ee88f903370be88845dc8c9f8578.tar.gz
frameworks_av-5131d127a042ee88f903370be88845dc8c9f8578.tar.bz2
[wfd] Support a low(er) power state by triggering PAUSE/RESUME.
Change-Id: Ibe42bfa73816bbfeb7e652d435254d0171b89727 related-to-bug: 7638150
-rw-r--r--include/media/IRemoteDisplay.h3
-rw-r--r--media/libmedia/IRemoteDisplay.cpp31
-rw-r--r--media/libmediaplayerservice/RemoteDisplay.cpp8
-rw-r--r--media/libmediaplayerservice/RemoteDisplay.h2
-rw-r--r--media/libstagefright/wifi-display/source/MediaPuller.cpp34
-rw-r--r--media/libstagefright/wifi-display/source/MediaPuller.h6
-rw-r--r--media/libstagefright/wifi-display/source/PlaybackSession.cpp44
-rw-r--r--media/libstagefright/wifi-display/source/PlaybackSession.h3
-rw-r--r--media/libstagefright/wifi-display/source/WifiDisplaySource.cpp146
-rw-r--r--media/libstagefright/wifi-display/source/WifiDisplaySource.h20
10 files changed, 267 insertions, 30 deletions
diff --git a/include/media/IRemoteDisplay.h b/include/media/IRemoteDisplay.h
index a61704e..c8baae9 100644
--- a/include/media/IRemoteDisplay.h
+++ b/include/media/IRemoteDisplay.h
@@ -39,6 +39,9 @@ class IRemoteDisplay : public IInterface
public:
DECLARE_META_INTERFACE(RemoteDisplay);
+ virtual status_t pause() = 0;
+ virtual status_t resume() = 0;
+
// Disconnects the remote display and stops listening for new connections.
virtual status_t dispose() = 0;
};
diff --git a/media/libmedia/IRemoteDisplay.cpp b/media/libmedia/IRemoteDisplay.cpp
index da25a15..1e15434 100644
--- a/media/libmedia/IRemoteDisplay.cpp
+++ b/media/libmedia/IRemoteDisplay.cpp
@@ -23,6 +23,8 @@ namespace android {
enum {
DISPOSE = IBinder::FIRST_CALL_TRANSACTION,
+ PAUSE,
+ RESUME,
};
class BpRemoteDisplay: public BpInterface<IRemoteDisplay>
@@ -33,6 +35,20 @@ public:
{
}
+ virtual status_t pause() {
+ Parcel data, reply;
+ data.writeInterfaceToken(IRemoteDisplay::getInterfaceDescriptor());
+ remote()->transact(PAUSE, data, &reply);
+ return reply.readInt32();
+ }
+
+ virtual status_t resume() {
+ Parcel data, reply;
+ data.writeInterfaceToken(IRemoteDisplay::getInterfaceDescriptor());
+ remote()->transact(RESUME, data, &reply);
+ return reply.readInt32();
+ }
+
status_t dispose()
{
Parcel data, reply;
@@ -55,6 +71,21 @@ status_t BnRemoteDisplay::onTransact(
reply->writeInt32(dispose());
return NO_ERROR;
}
+
+ case PAUSE:
+ {
+ CHECK_INTERFACE(IRemoteDisplay, data, reply);
+ reply->writeInt32(pause());
+ return OK;
+ }
+
+ case RESUME:
+ {
+ CHECK_INTERFACE(IRemoteDisplay, data, reply);
+ reply->writeInt32(resume());
+ return OK;
+ }
+
default:
return BBinder::onTransact(code, data, reply, flags);
}
diff --git a/media/libmediaplayerservice/RemoteDisplay.cpp b/media/libmediaplayerservice/RemoteDisplay.cpp
index 5baa3ad..20e6513 100644
--- a/media/libmediaplayerservice/RemoteDisplay.cpp
+++ b/media/libmediaplayerservice/RemoteDisplay.cpp
@@ -40,6 +40,14 @@ RemoteDisplay::RemoteDisplay(
RemoteDisplay::~RemoteDisplay() {
}
+status_t RemoteDisplay::pause() {
+ return mSource->pause();
+}
+
+status_t RemoteDisplay::resume() {
+ return mSource->resume();
+}
+
status_t RemoteDisplay::dispose() {
mSource->stop();
diff --git a/media/libmediaplayerservice/RemoteDisplay.h b/media/libmediaplayerservice/RemoteDisplay.h
index 0d87250..bd8b684 100644
--- a/media/libmediaplayerservice/RemoteDisplay.h
+++ b/media/libmediaplayerservice/RemoteDisplay.h
@@ -33,6 +33,8 @@ struct WifiDisplaySource;
struct RemoteDisplay : public BnRemoteDisplay {
RemoteDisplay(const sp<IRemoteDisplayClient> &client, const char *iface);
+ virtual status_t pause();
+ virtual status_t resume();
virtual status_t dispose();
protected:
diff --git a/media/libstagefright/wifi-display/source/MediaPuller.cpp b/media/libstagefright/wifi-display/source/MediaPuller.cpp
index ab69c4a..189bea3 100644
--- a/media/libstagefright/wifi-display/source/MediaPuller.cpp
+++ b/media/libstagefright/wifi-display/source/MediaPuller.cpp
@@ -34,7 +34,8 @@ MediaPuller::MediaPuller(
: mSource(source),
mNotify(notify),
mPullGeneration(0),
- mIsAudio(false) {
+ mIsAudio(false),
+ mPaused(false) {
sp<MetaData> meta = source->getFormat();
const char *mime;
CHECK(meta->findCString(kKeyMIMEType, &mime));
@@ -71,6 +72,14 @@ void MediaPuller::stopAsync(const sp<AMessage> &notify) {
msg->post();
}
+void MediaPuller::pause() {
+ (new AMessage(kWhatPause, id()))->post();
+}
+
+void MediaPuller::resume() {
+ (new AMessage(kWhatResume, id()))->post();
+}
+
void MediaPuller::onMessageReceived(const sp<AMessage> &msg) {
switch (msg->what()) {
case kWhatStart:
@@ -95,7 +104,6 @@ void MediaPuller::onMessageReceived(const sp<AMessage> &msg) {
uint32_t replyID;
CHECK(msg->senderAwaitsResponse(&replyID));
-
response->postReply(replyID);
break;
}
@@ -130,6 +138,16 @@ void MediaPuller::onMessageReceived(const sp<AMessage> &msg) {
MediaBuffer *mbuf;
status_t err = mSource->read(&mbuf);
+ if (mPaused) {
+ if (err == OK) {
+ mbuf->release();
+ mbuf = NULL;
+ }
+
+ schedulePull();
+ break;
+ }
+
if (err != OK) {
if (err == ERROR_END_OF_STREAM) {
ALOGI("stream ended.");
@@ -176,6 +194,18 @@ void MediaPuller::onMessageReceived(const sp<AMessage> &msg) {
break;
}
+ case kWhatPause:
+ {
+ mPaused = true;
+ break;
+ }
+
+ case kWhatResume:
+ {
+ mPaused = false;
+ break;
+ }
+
default:
TRESPASS();
}
diff --git a/media/libstagefright/wifi-display/source/MediaPuller.h b/media/libstagefright/wifi-display/source/MediaPuller.h
index 728da7b..1291bb3 100644
--- a/media/libstagefright/wifi-display/source/MediaPuller.h
+++ b/media/libstagefright/wifi-display/source/MediaPuller.h
@@ -35,6 +35,9 @@ struct MediaPuller : public AHandler {
status_t start();
void stopAsync(const sp<AMessage> &notify);
+ void pause();
+ void resume();
+
protected:
virtual void onMessageReceived(const sp<AMessage> &msg);
virtual ~MediaPuller();
@@ -44,12 +47,15 @@ private:
kWhatStart,
kWhatStop,
kWhatPull,
+ kWhatPause,
+ kWhatResume,
};
sp<MediaSource> mSource;
sp<AMessage> mNotify;
int32_t mPullGeneration;
bool mIsAudio;
+ bool mPaused;
status_t postSynchronouslyAndReturnError(const sp<AMessage> &msg);
void schedulePull();
diff --git a/media/libstagefright/wifi-display/source/PlaybackSession.cpp b/media/libstagefright/wifi-display/source/PlaybackSession.cpp
index 4e5eb52..916f797 100644
--- a/media/libstagefright/wifi-display/source/PlaybackSession.cpp
+++ b/media/libstagefright/wifi-display/source/PlaybackSession.cpp
@@ -76,6 +76,9 @@ struct WifiDisplaySource::PlaybackSession::Track : public AHandler {
status_t start();
void stopAsync();
+ void pause();
+ void resume();
+
void queueAccessUnit(const sp<ABuffer> &accessUnit);
sp<ABuffer> dequeueAccessUnit();
@@ -208,6 +211,14 @@ void WifiDisplaySource::PlaybackSession::Track::stopAsync() {
}
}
+void WifiDisplaySource::PlaybackSession::Track::pause() {
+ mMediaPuller->pause();
+}
+
+void WifiDisplaySource::PlaybackSession::Track::resume() {
+ mMediaPuller->resume();
+}
+
void WifiDisplaySource::PlaybackSession::Track::onMessageReceived(
const sp<AMessage> &msg) {
switch (msg->what()) {
@@ -325,6 +336,7 @@ WifiDisplaySource::PlaybackSession::PlaybackSession(
mInterfaceAddr(interfaceAddr),
mHDCP(hdcp),
mWeAreDead(false),
+ mPaused(false),
mLastLifesignUs(),
mVideoTrackIndex(-1),
mPrevTimeUs(-1ll),
@@ -383,6 +395,8 @@ void WifiDisplaySource::PlaybackSession::updateLiveness() {
status_t WifiDisplaySource::PlaybackSession::play() {
updateLiveness();
+ (new AMessage(kWhatResume, id()))->post();
+
return OK;
}
@@ -413,6 +427,8 @@ status_t WifiDisplaySource::PlaybackSession::onFinishPlay2() {
status_t WifiDisplaySource::PlaybackSession::pause() {
updateLiveness();
+ (new AMessage(kWhatPause, id()))->post();
+
return OK;
}
@@ -590,6 +606,34 @@ void WifiDisplaySource::PlaybackSession::onMessageReceived(
break;
}
+ case kWhatPause:
+ {
+ if (mPaused) {
+ break;
+ }
+
+ for (size_t i = 0; i < mTracks.size(); ++i) {
+ mTracks.editValueAt(i)->pause();
+ }
+
+ mPaused = true;
+ break;
+ }
+
+ case kWhatResume:
+ {
+ if (!mPaused) {
+ break;
+ }
+
+ for (size_t i = 0; i < mTracks.size(); ++i) {
+ mTracks.editValueAt(i)->resume();
+ }
+
+ mPaused = false;
+ break;
+ }
+
default:
TRESPASS();
}
diff --git a/media/libstagefright/wifi-display/source/PlaybackSession.h b/media/libstagefright/wifi-display/source/PlaybackSession.h
index dabc1c4..b9d193b 100644
--- a/media/libstagefright/wifi-display/source/PlaybackSession.h
+++ b/media/libstagefright/wifi-display/source/PlaybackSession.h
@@ -84,6 +84,8 @@ private:
kWhatUpdateSurface,
kWhatFinishPlay,
kWhatPacketize,
+ kWhatPause,
+ kWhatResume,
};
sp<ANetworkSession> mNetSession;
@@ -93,6 +95,7 @@ private:
in_addr mInterfaceAddr;
sp<IHDCP> mHDCP;
bool mWeAreDead;
+ bool mPaused;
int64_t mLastLifesignUs;
diff --git a/media/libstagefright/wifi-display/source/WifiDisplaySource.cpp b/media/libstagefright/wifi-display/source/WifiDisplaySource.cpp
index 78d6e62..08f67f9 100644
--- a/media/libstagefright/wifi-display/source/WifiDisplaySource.cpp
+++ b/media/libstagefright/wifi-display/source/WifiDisplaySource.cpp
@@ -65,41 +65,50 @@ WifiDisplaySource::WifiDisplaySource(
WifiDisplaySource::~WifiDisplaySource() {
}
-status_t WifiDisplaySource::start(const char *iface) {
- CHECK_EQ(mState, INITIALIZED);
-
- sp<AMessage> msg = new AMessage(kWhatStart, id());
- msg->setString("iface", iface);
-
- sp<AMessage> response;
- status_t err = msg->postAndAwaitResponse(&response);
+static status_t PostAndAwaitResponse(
+ const sp<AMessage> &msg, sp<AMessage> *response) {
+ status_t err = msg->postAndAwaitResponse(response);
if (err != OK) {
return err;
}
- if (!response->findInt32("err", &err)) {
+ if (response == NULL || !(*response)->findInt32("err", &err)) {
err = OK;
}
return err;
}
+status_t WifiDisplaySource::start(const char *iface) {
+ CHECK_EQ(mState, INITIALIZED);
+
+ sp<AMessage> msg = new AMessage(kWhatStart, id());
+ msg->setString("iface", iface);
+
+ sp<AMessage> response;
+ return PostAndAwaitResponse(msg, &response);
+}
+
status_t WifiDisplaySource::stop() {
sp<AMessage> msg = new AMessage(kWhatStop, id());
sp<AMessage> response;
- status_t err = msg->postAndAwaitResponse(&response);
+ return PostAndAwaitResponse(msg, &response);
+}
- if (err != OK) {
- return err;
- }
+status_t WifiDisplaySource::pause() {
+ sp<AMessage> msg = new AMessage(kWhatPause, id());
- if (!response->findInt32("err", &err)) {
- err = OK;
- }
+ sp<AMessage> response;
+ return PostAndAwaitResponse(msg, &response);
+}
- return err;
+status_t WifiDisplaySource::resume() {
+ sp<AMessage> msg = new AMessage(kWhatResume, id());
+
+ sp<AMessage> response;
+ return PostAndAwaitResponse(msg, &response);
}
void WifiDisplaySource::onMessageReceived(const sp<AMessage> &msg) {
@@ -236,6 +245,20 @@ void WifiDisplaySource::onMessageReceived(const sp<AMessage> &msg) {
mClient->onDisplayError(
IRemoteDisplayClient::kDisplayErrorUnknown);
}
+
+#if 0
+ // testing only.
+ char val[PROPERTY_VALUE_MAX];
+ if (property_get("media.wfd.trigger", val, NULL)) {
+ if (!strcasecmp(val, "pause") && mState == PLAYING) {
+ mState = PLAYING_TO_PAUSED;
+ sendTrigger(mClientSessionID, TRIGGER_PAUSE);
+ } else if (!strcasecmp(val, "play") && mState == PAUSED) {
+ mState = PAUSED_TO_PLAYING;
+ sendTrigger(mClientSessionID, TRIGGER_PLAY);
+ }
+ }
+#endif
break;
}
@@ -254,8 +277,8 @@ void WifiDisplaySource::onMessageReceived(const sp<AMessage> &msg) {
if (mState >= AWAITING_CLIENT_PLAY) {
// We have a session, i.e. a previous SETUP succeeded.
- status_t err = sendM5(
- mClientSessionID, true /* requestShutdown */);
+ status_t err = sendTrigger(
+ mClientSessionID, TRIGGER_TEARDOWN);
if (err == OK) {
mState = AWAITING_CLIENT_TEARDOWN;
@@ -273,6 +296,46 @@ void WifiDisplaySource::onMessageReceived(const sp<AMessage> &msg) {
break;
}
+ case kWhatPause:
+ {
+ uint32_t replyID;
+ CHECK(msg->senderAwaitsResponse(&replyID));
+
+ status_t err = OK;
+
+ if (mState != PLAYING) {
+ err = INVALID_OPERATION;
+ } else {
+ mState = PLAYING_TO_PAUSED;
+ sendTrigger(mClientSessionID, TRIGGER_PAUSE);
+ }
+
+ sp<AMessage> response = new AMessage;
+ response->setInt32("err", err);
+ response->postReply(replyID);
+ break;
+ }
+
+ case kWhatResume:
+ {
+ uint32_t replyID;
+ CHECK(msg->senderAwaitsResponse(&replyID));
+
+ status_t err = OK;
+
+ if (mState != PAUSED) {
+ err = INVALID_OPERATION;
+ } else {
+ mState = PAUSED_TO_PLAYING;
+ sendTrigger(mClientSessionID, TRIGGER_PLAY);
+ }
+
+ sp<AMessage> response = new AMessage;
+ response->setInt32("err", err);
+ response->postReply(replyID);
+ break;
+ }
+
case kWhatReapDeadClients:
{
mReaperPending = false;
@@ -400,7 +463,7 @@ void WifiDisplaySource::onMessageReceived(const sp<AMessage> &msg) {
if (mSetupTriggerDeferred) {
mSetupTriggerDeferred = false;
- sendM5(mClientSessionID, false /* requestShutdown */);
+ sendTrigger(mClientSessionID, TRIGGER_SETUP);
}
break;
}
@@ -574,13 +637,25 @@ status_t WifiDisplaySource::sendM4(int32_t sessionID) {
return OK;
}
-status_t WifiDisplaySource::sendM5(int32_t sessionID, bool requestShutdown) {
+status_t WifiDisplaySource::sendTrigger(
+ int32_t sessionID, TriggerType triggerType) {
AString body = "wfd_trigger_method: ";
- if (requestShutdown) {
- ALOGI("Sending TEARDOWN trigger.");
- body.append("TEARDOWN");
- } else {
- body.append("SETUP");
+ switch (triggerType) {
+ case TRIGGER_SETUP:
+ body.append("SETUP");
+ break;
+ case TRIGGER_TEARDOWN:
+ ALOGI("Sending TEARDOWN trigger.");
+ body.append("TEARDOWN");
+ break;
+ case TRIGGER_PAUSE:
+ body.append("PAUSE");
+ break;
+ case TRIGGER_PLAY:
+ body.append("PLAY");
+ break;
+ default:
+ TRESPASS();
}
body.append("\r\n");
@@ -807,7 +882,7 @@ status_t WifiDisplaySource::onReceiveM4Response(
return OK;
}
- return sendM5(sessionID, false /* requestShutdown */);
+ return sendTrigger(sessionID, TRIGGER_SETUP);
}
status_t WifiDisplaySource::onReceiveM5Response(
@@ -1184,6 +1259,11 @@ status_t WifiDisplaySource::onPlayRequest(
return err;
}
+ if (mState == PAUSED_TO_PLAYING) {
+ mState = PLAYING;
+ return OK;
+ }
+
playbackSession->finishPlay();
CHECK_EQ(mState, AWAITING_CLIENT_PLAY);
@@ -1205,6 +1285,12 @@ status_t WifiDisplaySource::onPauseRequest(
return ERROR_MALFORMED;
}
+ ALOGI("Received PAUSE request.");
+
+ if (mState != PLAYING_TO_PAUSED) {
+ return INVALID_OPERATION;
+ }
+
status_t err = playbackSession->pause();
CHECK_EQ(err, (status_t)OK);
@@ -1214,6 +1300,12 @@ status_t WifiDisplaySource::onPauseRequest(
err = mNetSession->sendRequest(sessionID, response.c_str());
+ if (err != OK) {
+ return err;
+ }
+
+ mState = PAUSED;
+
return err;
}
diff --git a/media/libstagefright/wifi-display/source/WifiDisplaySource.h b/media/libstagefright/wifi-display/source/WifiDisplaySource.h
index 1e855e7..974e070 100644
--- a/media/libstagefright/wifi-display/source/WifiDisplaySource.h
+++ b/media/libstagefright/wifi-display/source/WifiDisplaySource.h
@@ -44,6 +44,9 @@ struct WifiDisplaySource : public AHandler {
status_t start(const char *iface);
status_t stop();
+ status_t pause();
+ status_t resume();
+
protected:
virtual ~WifiDisplaySource();
virtual void onMessageReceived(const sp<AMessage> &msg);
@@ -59,6 +62,9 @@ private:
AWAITING_CLIENT_PLAY,
ABOUT_TO_PLAY,
PLAYING,
+ PLAYING_TO_PAUSED,
+ PAUSED,
+ PAUSED_TO_PLAYING,
AWAITING_CLIENT_TEARDOWN,
STOPPING,
STOPPED,
@@ -68,6 +74,8 @@ private:
kWhatStart,
kWhatRTSPNotify,
kWhatStop,
+ kWhatPause,
+ kWhatResume,
kWhatReapDeadClients,
kWhatPlaybackSessionNotify,
kWhatKeepAlive,
@@ -147,7 +155,17 @@ private:
status_t sendM1(int32_t sessionID);
status_t sendM3(int32_t sessionID);
status_t sendM4(int32_t sessionID);
- status_t sendM5(int32_t sessionID, bool requestShutdown);
+
+ enum TriggerType {
+ TRIGGER_SETUP,
+ TRIGGER_TEARDOWN,
+ TRIGGER_PAUSE,
+ TRIGGER_PLAY,
+ };
+
+ // M5
+ status_t sendTrigger(int32_t sessionID, TriggerType triggerType);
+
status_t sendM16(int32_t sessionID);
status_t onReceiveM1Response(