summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--media/libstagefright/wifi-display/ANetworkSession.cpp1
-rw-r--r--media/libstagefright/wifi-display/sink/DirectRenderer.cpp18
-rw-r--r--media/libstagefright/wifi-display/sink/RTPSink.cpp53
-rw-r--r--media/libstagefright/wifi-display/sink/RTPSink.h10
-rw-r--r--media/libstagefright/wifi-display/sink/WifiDisplaySink.cpp124
-rw-r--r--media/libstagefright/wifi-display/sink/WifiDisplaySink.h9
-rw-r--r--media/libstagefright/wifi-display/source/PlaybackSession.cpp12
-rw-r--r--media/libstagefright/wifi-display/source/WifiDisplaySource.cpp40
-rw-r--r--media/libstagefright/wifi-display/source/WifiDisplaySource.h1
9 files changed, 157 insertions, 111 deletions
diff --git a/media/libstagefright/wifi-display/ANetworkSession.cpp b/media/libstagefright/wifi-display/ANetworkSession.cpp
index 62a6e7f..06f71f4 100644
--- a/media/libstagefright/wifi-display/ANetworkSession.cpp
+++ b/media/libstagefright/wifi-display/ANetworkSession.cpp
@@ -1091,7 +1091,6 @@ void ANetworkSession::threadLoop() {
clientSocket);
sp<Session> clientSession =
- // using socket sd as sessionID
new Session(
mNextSessionID++,
Session::CONNECTED,
diff --git a/media/libstagefright/wifi-display/sink/DirectRenderer.cpp b/media/libstagefright/wifi-display/sink/DirectRenderer.cpp
index 93430eb..23cf6fd 100644
--- a/media/libstagefright/wifi-display/sink/DirectRenderer.cpp
+++ b/media/libstagefright/wifi-display/sink/DirectRenderer.cpp
@@ -35,11 +35,19 @@
namespace android {
+#if 0
// static
const int64_t DirectRenderer::kPacketLostDelayUs = 80000ll;
// static
const int64_t DirectRenderer::kPacketLateDelayUs = 60000ll;
+#else
+// static
+const int64_t DirectRenderer::kPacketLostDelayUs = 1000000ll;
+
+// static
+const int64_t DirectRenderer::kPacketLateDelayUs = -1ll;
+#endif
DirectRenderer::DirectRenderer(
const sp<AMessage> &notifyLost,
@@ -309,11 +317,11 @@ void DirectRenderer::dequeueAccessUnits() {
void DirectRenderer::schedulePacketLost() {
sp<AMessage> msg;
-#if 1
- msg = new AMessage(kWhatPacketLate, id());
- msg->setInt32("generation", mPacketLostGeneration);
- msg->post(kPacketLateDelayUs);
-#endif
+ if (kPacketLateDelayUs > 0ll) {
+ msg = new AMessage(kWhatPacketLate, id());
+ msg->setInt32("generation", mPacketLostGeneration);
+ msg->post(kPacketLateDelayUs);
+ }
msg = new AMessage(kWhatPacketLost, id());
msg->setInt32("generation", mPacketLostGeneration);
diff --git a/media/libstagefright/wifi-display/sink/RTPSink.cpp b/media/libstagefright/wifi-display/sink/RTPSink.cpp
index 7f4b66f..be54595 100644
--- a/media/libstagefright/wifi-display/sink/RTPSink.cpp
+++ b/media/libstagefright/wifi-display/sink/RTPSink.cpp
@@ -253,6 +253,8 @@ RTPSink::RTPSink(
mRTPPort(0),
mRTPSessionID(0),
mRTCPSessionID(0),
+ mRTPClientSessionID(0),
+ mRTCPClientSessionID(0),
mFirstArrivalTimeUs(-1ll),
mNumPacketsReceived(0ll),
mRegression(1000),
@@ -260,6 +262,14 @@ RTPSink::RTPSink(
}
RTPSink::~RTPSink() {
+ if (mRTCPClientSessionID != 0) {
+ mNetSession->destroySession(mRTCPClientSessionID);
+ }
+
+ if (mRTPClientSessionID != 0) {
+ mNetSession->destroySession(mRTPClientSessionID);
+ }
+
if (mRTCPSessionID != 0) {
mNetSession->destroySession(mRTCPSessionID);
}
@@ -269,8 +279,8 @@ RTPSink::~RTPSink() {
}
}
-status_t RTPSink::init(bool useTCPInterleaving) {
- if (useTCPInterleaving) {
+status_t RTPSink::init(bool usingTCPTransport, bool usingTCPInterleaving) {
+ if (usingTCPInterleaving) {
return OK;
}
@@ -280,8 +290,16 @@ status_t RTPSink::init(bool useTCPInterleaving) {
sp<AMessage> rtcpNotify = new AMessage(kWhatRTCPNotify, id());
for (clientRtp = 15550;; clientRtp += 2) {
int32_t rtpSession;
- status_t err = mNetSession->createUDPSession(
- clientRtp, rtpNotify, &rtpSession);
+ status_t err;
+ struct in_addr ifaceAddr;
+ if (usingTCPTransport) {
+ ifaceAddr.s_addr = INADDR_ANY;
+ err = mNetSession->createTCPDatagramSession(
+ ifaceAddr, clientRtp, rtpNotify, &rtpSession);
+ } else {
+ err = mNetSession->createUDPSession(
+ clientRtp, rtpNotify, &rtpSession);
+ }
if (err != OK) {
ALOGI("failed to create RTP socket on port %d", clientRtp);
@@ -289,8 +307,13 @@ status_t RTPSink::init(bool useTCPInterleaving) {
}
int32_t rtcpSession;
- err = mNetSession->createUDPSession(
- clientRtp + 1, rtcpNotify, &rtcpSession);
+ if (usingTCPTransport) {
+ err = mNetSession->createTCPDatagramSession(
+ ifaceAddr, clientRtp + 1, rtcpNotify, &rtcpSession);
+ } else {
+ err = mNetSession->createUDPSession(
+ clientRtp + 1, rtcpNotify, &rtcpSession);
+ }
if (err == OK) {
mRTPPort = clientRtp;
@@ -367,6 +390,24 @@ void RTPSink::onMessageReceived(const sp<AMessage> &msg) {
break;
}
+ case ANetworkSession::kWhatClientConnected:
+ {
+ int32_t sessionID;
+ CHECK(msg->findInt32("sessionID", &sessionID));
+ ALOGI("TCP session %d now connected", sessionID);
+
+ int32_t serverPort;
+ CHECK(msg->findInt32("server-port", &serverPort));
+
+ if (serverPort == mRTPPort) {
+ mRTPClientSessionID = sessionID;
+ } else {
+ CHECK_EQ(serverPort, mRTPPort + 1);
+ mRTCPClientSessionID = sessionID;
+ }
+ break;
+ }
+
default:
TRESPASS();
}
diff --git a/media/libstagefright/wifi-display/sink/RTPSink.h b/media/libstagefright/wifi-display/sink/RTPSink.h
index 6e40185..f9cbce9 100644
--- a/media/libstagefright/wifi-display/sink/RTPSink.h
+++ b/media/libstagefright/wifi-display/sink/RTPSink.h
@@ -48,7 +48,7 @@ struct RTPSink : public AHandler {
// If TCP interleaving is used, no UDP sockets are created, instead
// incoming RTP/RTCP packets (arriving on the RTSP control connection)
// are manually injected by WifiDisplaySink.
- status_t init(bool useTCPInterleaving);
+ status_t init(bool usingTCPTransport, bool usingTCPInterleaving);
status_t connect(
const char *host, int32_t remoteRtpPort, int32_t remoteRtcpPort);
@@ -79,8 +79,12 @@ private:
KeyedVector<uint32_t, sp<Source> > mSources;
int32_t mRTPPort;
- int32_t mRTPSessionID;
- int32_t mRTCPSessionID;
+
+ int32_t mRTPSessionID; // in TCP unicast mode these are just server
+ int32_t mRTCPSessionID; // sockets. No data is transferred through them.
+
+ int32_t mRTPClientSessionID; // in TCP unicast mode
+ int32_t mRTCPClientSessionID;
int64_t mFirstArrivalTimeUs;
int64_t mNumPacketsReceived;
diff --git a/media/libstagefright/wifi-display/sink/WifiDisplaySink.cpp b/media/libstagefright/wifi-display/sink/WifiDisplaySink.cpp
index 46c40c7..55581a6 100644
--- a/media/libstagefright/wifi-display/sink/WifiDisplaySink.cpp
+++ b/media/libstagefright/wifi-display/sink/WifiDisplaySink.cpp
@@ -27,6 +27,8 @@
#include <media/stagefright/foundation/AMessage.h>
#include <media/stagefright/MediaErrors.h>
+#include <cutils/properties.h>
+
namespace android {
WifiDisplaySink::WifiDisplaySink(
@@ -37,6 +39,8 @@ WifiDisplaySink::WifiDisplaySink(
mNetSession(netSession),
mSurfaceTex(bufferProducer),
mNotify(notify),
+ mUsingTCPTransport(false),
+ mUsingTCPInterleaving(false),
mSessionID(0),
mNextCSeq(1) {
#if 1
@@ -141,17 +145,8 @@ void WifiDisplaySink::onMessageReceived(const sp<AMessage> &msg) {
sleep(2); // XXX
int32_t sourcePort;
-
- if (msg->findString("setupURI", &mSetupURI)) {
- AString path, user, pass;
- CHECK(ParseURL(
- mSetupURI.c_str(),
- &mRTSPHost, &sourcePort, &path, &user, &pass)
- && user.empty() && pass.empty());
- } else {
- CHECK(msg->findString("sourceHost", &mRTSPHost));
- CHECK(msg->findInt32("sourcePort", &sourcePort));
- }
+ CHECK(msg->findString("sourceHost", &mRTSPHost));
+ CHECK(msg->findInt32("sourcePort", &sourcePort));
sp<AMessage> notify = new AMessage(kWhatRTSPNotify, id());
@@ -208,13 +203,6 @@ void WifiDisplaySink::onMessageReceived(const sp<AMessage> &msg) {
{
ALOGI("We're now connected.");
mState = CONNECTED;
-
- if (!mSetupURI.empty()) {
- status_t err =
- sendDescribe(mSessionID, mSetupURI.c_str());
-
- CHECK_EQ(err, (status_t)OK);
- }
break;
}
@@ -226,7 +214,7 @@ void WifiDisplaySink::onMessageReceived(const sp<AMessage> &msg) {
case ANetworkSession::kWhatBinaryData:
{
- CHECK(sUseTCPInterleaving);
+ CHECK(mUsingTCPInterleaving);
int32_t channel;
CHECK(msg->findInt32("channel", &channel));
@@ -312,20 +300,6 @@ status_t WifiDisplaySink::onReceiveM2Response(
return OK;
}
-status_t WifiDisplaySink::onReceiveDescribeResponse(
- int32_t sessionID, const sp<ParsedMessage> &msg) {
- int32_t statusCode;
- if (!msg->getStatusCode(&statusCode)) {
- return ERROR_MALFORMED;
- }
-
- if (statusCode != 200) {
- return ERROR_UNSUPPORTED;
- }
-
- return sendSetup(sessionID, mSetupURI.c_str());
-}
-
status_t WifiDisplaySink::onReceiveSetupResponse(
int32_t sessionID, const sp<ParsedMessage> &msg) {
int32_t statusCode;
@@ -365,12 +339,11 @@ status_t WifiDisplaySink::onReceiveSetupResponse(
return sendPlay(
sessionID,
- !mSetupURI.empty()
- ? mSetupURI.c_str() : "rtsp://x.x.x.x:x/wfd1.0/streamid=0");
+ "rtsp://x.x.x.x:x/wfd1.0/streamid=0");
}
status_t WifiDisplaySink::configureTransport(const sp<ParsedMessage> &msg) {
- if (sUseTCPInterleaving) {
+ if (mUsingTCPTransport) {
return OK;
}
@@ -514,11 +487,45 @@ void WifiDisplaySink::onGetParameterRequest(
int32_t sessionID,
int32_t cseq,
const sp<ParsedMessage> &data) {
- AString body = "wfd_video_formats: ";
- body.append(mSinkSupportedVideoFormats.getFormatSpec());
- body.append(
- "\r\nwfd_audio_codecs: AAC 0000000F 00\r\n"
- "wfd_client_rtp_ports: RTP/AVP/UDP;unicast 19000 0 mode=play\r\n");
+ AString body;
+
+ if (mState == CONNECTED) {
+ mUsingTCPTransport = false;
+ mUsingTCPInterleaving = false;
+
+ char val[PROPERTY_VALUE_MAX];
+ if (property_get("media.wfd-sink.tcp-mode", val, NULL)) {
+ if (!strcasecmp("true", val) || !strcmp("1", val)) {
+ ALOGI("Using TCP unicast transport.");
+ mUsingTCPTransport = true;
+ mUsingTCPInterleaving = false;
+ } else if (!strcasecmp("interleaved", val)) {
+ ALOGI("Using TCP interleaved transport.");
+ mUsingTCPTransport = true;
+ mUsingTCPInterleaving = true;
+ }
+ }
+
+ body = "wfd_video_formats: ";
+ body.append(mSinkSupportedVideoFormats.getFormatSpec());
+
+ body.append(
+ "\r\nwfd_audio_codecs: AAC 0000000F 00\r\n"
+ "wfd_client_rtp_ports: RTP/AVP/");
+
+ if (mUsingTCPTransport) {
+ body.append("TCP;");
+ if (mUsingTCPInterleaving) {
+ body.append("interleaved");
+ } else {
+ body.append("unicast 19000 0");
+ }
+ } else {
+ body.append("UDP;unicast 19000 0");
+ }
+
+ body.append(" mode=play\r\n");
+ }
AString response = "RTSP/1.0 200 OK\r\n";
AppendCommonResponse(&response, cseq);
@@ -531,38 +538,13 @@ void WifiDisplaySink::onGetParameterRequest(
CHECK_EQ(err, (status_t)OK);
}
-status_t WifiDisplaySink::sendDescribe(int32_t sessionID, const char *uri) {
- uri = "rtsp://xwgntvx.is.livestream-api.com/livestreamiphone/wgntv";
- uri = "rtsp://v2.cache6.c.youtube.com/video.3gp?cid=e101d4bf280055f9&fmt=18";
-
- AString request = StringPrintf("DESCRIBE %s RTSP/1.0\r\n", uri);
- AppendCommonResponse(&request, mNextCSeq);
-
- request.append("Accept: application/sdp\r\n");
- request.append("\r\n");
-
- status_t err = mNetSession->sendRequest(
- sessionID, request.c_str(), request.size());
-
- if (err != OK) {
- return err;
- }
-
- registerResponseHandler(
- sessionID, mNextCSeq, &WifiDisplaySink::onReceiveDescribeResponse);
-
- ++mNextCSeq;
-
- return OK;
-}
-
status_t WifiDisplaySink::sendSetup(int32_t sessionID, const char *uri) {
sp<AMessage> notify = new AMessage(kWhatRTPSinkNotify, id());
mRTPSink = new RTPSink(mNetSession, mSurfaceTex, notify);
looper()->registerHandler(mRTPSink);
- status_t err = mRTPSink->init(sUseTCPInterleaving);
+ status_t err = mRTPSink->init(mUsingTCPTransport, mUsingTCPInterleaving);
if (err != OK) {
looper()->unregisterHandler(mRTPSink->id());
@@ -574,15 +556,17 @@ status_t WifiDisplaySink::sendSetup(int32_t sessionID, const char *uri) {
AppendCommonResponse(&request, mNextCSeq);
- if (sUseTCPInterleaving) {
+ if (mUsingTCPInterleaving) {
request.append("Transport: RTP/AVP/TCP;interleaved=0-1\r\n");
} else {
int32_t rtpPort = mRTPSink->getRTPPort();
request.append(
StringPrintf(
- "Transport: RTP/AVP/UDP;unicast;client_port=%d-%d\r\n",
- rtpPort, rtpPort + 1));
+ "Transport: RTP/AVP/%s;unicast;client_port=%d-%d\r\n",
+ mUsingTCPTransport ? "TCP" : "UDP",
+ rtpPort,
+ rtpPort + 1));
}
request.append("\r\n");
diff --git a/media/libstagefright/wifi-display/sink/WifiDisplaySink.h b/media/libstagefright/wifi-display/sink/WifiDisplaySink.h
index 5f86519..8b5ff6b 100644
--- a/media/libstagefright/wifi-display/sink/WifiDisplaySink.h
+++ b/media/libstagefright/wifi-display/sink/WifiDisplaySink.h
@@ -86,14 +86,13 @@ private:
typedef status_t (WifiDisplaySink::*HandleRTSPResponseFunc)(
int32_t sessionID, const sp<ParsedMessage> &msg);
- static const bool sUseTCPInterleaving = false;
-
State mState;
VideoFormats mSinkSupportedVideoFormats;
sp<ANetworkSession> mNetSession;
sp<IGraphicBufferProducer> mSurfaceTex;
sp<AMessage> mNotify;
- AString mSetupURI;
+ bool mUsingTCPTransport;
+ bool mUsingTCPInterleaving;
AString mRTSPHost;
int32_t mSessionID;
@@ -106,7 +105,6 @@ private:
int32_t mPlaybackSessionTimeoutSecs;
status_t sendM2(int32_t sessionID);
- status_t sendDescribe(int32_t sessionID, const char *uri);
status_t sendSetup(int32_t sessionID, const char *uri);
status_t sendPlay(int32_t sessionID, const char *uri);
status_t sendIDRFrameRequest(int32_t sessionID);
@@ -114,9 +112,6 @@ private:
status_t onReceiveM2Response(
int32_t sessionID, const sp<ParsedMessage> &msg);
- status_t onReceiveDescribeResponse(
- int32_t sessionID, const sp<ParsedMessage> &msg);
-
status_t onReceiveSetupResponse(
int32_t sessionID, const sp<ParsedMessage> &msg);
diff --git a/media/libstagefright/wifi-display/source/PlaybackSession.cpp b/media/libstagefright/wifi-display/source/PlaybackSession.cpp
index e542908..ede4e60 100644
--- a/media/libstagefright/wifi-display/source/PlaybackSession.cpp
+++ b/media/libstagefright/wifi-display/source/PlaybackSession.cpp
@@ -542,6 +542,18 @@ void WifiDisplaySource::PlaybackSession::onMessageReceived(
onFinishPlay2();
} else if (what == Sender::kWhatSessionDead) {
notifySessionDead();
+ } else if (what == Sender::kWhatBinaryData) {
+ sp<AMessage> notify = mNotify->dup();
+ notify->setInt32("what", kWhatBinaryData);
+
+ int32_t channel;
+ CHECK(msg->findInt32("channel", &channel));
+ notify->setInt32("channel", channel);
+
+ sp<ABuffer> data;
+ CHECK(msg->findBuffer("data", &data));
+ notify->setBuffer("data", data);
+ notify->post();
} else {
TRESPASS();
}
diff --git a/media/libstagefright/wifi-display/source/WifiDisplaySource.cpp b/media/libstagefright/wifi-display/source/WifiDisplaySource.cpp
index 981d5f9..825ebc6 100644
--- a/media/libstagefright/wifi-display/source/WifiDisplaySource.cpp
+++ b/media/libstagefright/wifi-display/source/WifiDisplaySource.cpp
@@ -597,15 +597,6 @@ status_t WifiDisplaySource::sendM3(int32_t sessionID) {
status_t WifiDisplaySource::sendM4(int32_t sessionID) {
CHECK_EQ(sessionID, mClientSessionID);
- AString transportString = "UDP";
-
- char val[PROPERTY_VALUE_MAX];
- if (property_get("media.wfd.enable-tcp", val, NULL)
- && (!strcasecmp("true", val) || !strcmp("1", val))) {
- ALOGI("Using TCP transport.");
- transportString = "TCP";
- }
-
AString body;
if (mSinkSupportsVideo) {
@@ -630,11 +621,11 @@ status_t WifiDisplaySource::sendM4(int32_t sessionID) {
body.append(
StringPrintf(
- "wfd_presentation_URL: rtsp://%s/wfd1.0/streamid=0 none\r\n"
- "wfd_client_rtp_ports: RTP/AVP/%s;unicast %d 0 mode=play\r\n",
- mClientInfo.mLocalIP.c_str(),
- transportString.c_str(),
- mChosenRTPPort));
+ "wfd_presentation_URL: rtsp://%s/wfd1.0/streamid=0 none\r\n",
+ mClientInfo.mLocalIP.c_str()));
+
+ body.append(mWfdClientRtpPorts);
+ body.append("\r\n");
AString request = "SET_PARAMETER rtsp://localhost/wfd1.0 RTSP/1.0\r\n";
AppendCommonResponse(&request, mNextCSeq);
@@ -797,18 +788,29 @@ status_t WifiDisplaySource::onReceiveM3Response(
return ERROR_MALFORMED;
}
- unsigned port0, port1;
+ unsigned port0 = 0, port1 = 0;
if (sscanf(value.c_str(),
"RTP/AVP/UDP;unicast %u %u mode=play",
&port0,
- &port1) != 2
- || port0 == 0 || port0 > 65535 || port1 != 0) {
- ALOGE("Sink chose its wfd_client_rtp_ports poorly (%s)",
+ &port1) == 2
+ || sscanf(value.c_str(),
+ "RTP/AVP/TCP;unicast %u %u mode=play",
+ &port0,
+ &port1) == 2) {
+ if (port0 == 0 || port0 > 65535 || port1 != 0) {
+ ALOGE("Sink chose its wfd_client_rtp_ports poorly (%s)",
+ value.c_str());
+
+ return ERROR_MALFORMED;
+ }
+ } else if (strcmp(value.c_str(), "RTP/AVP/TCP;interleaved mode=play")) {
+ ALOGE("Unsupported value for wfd_client_rtp_ports (%s)",
value.c_str());
- return ERROR_MALFORMED;
+ return ERROR_UNSUPPORTED;
}
+ mWfdClientRtpPorts = value;
mChosenRTPPort = port0;
if (!params->findParameter("wfd_video_formats", &value)) {
diff --git a/media/libstagefright/wifi-display/source/WifiDisplaySource.h b/media/libstagefright/wifi-display/source/WifiDisplaySource.h
index fec2c6d..724462c 100644
--- a/media/libstagefright/wifi-display/source/WifiDisplaySource.h
+++ b/media/libstagefright/wifi-display/source/WifiDisplaySource.h
@@ -119,6 +119,7 @@ private:
uint32_t mStopReplyID;
+ AString mWfdClientRtpPorts;
int32_t mChosenRTPPort; // extracted from "wfd_client_rtp_ports"
bool mSinkSupportsVideo;