diff options
author | Andreas Huber <andih@google.com> | 2013-02-05 17:55:48 +0000 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2013-02-05 17:55:48 +0000 |
commit | a0216af1a45b4c657a5801b766ec34a82fac1b3e (patch) | |
tree | a07cdb30af5365237b9744c41279309490d18514 /media/libstagefright/wifi-display | |
parent | 6bb6f2f9cba46aa2b853357a139ae5166c5b6713 (diff) | |
parent | 7cc0c29d6a7b76520ec588437ab51d5b8eac9ebc (diff) | |
download | frameworks_av-a0216af1a45b4c657a5801b766ec34a82fac1b3e.zip frameworks_av-a0216af1a45b4c657a5801b766ec34a82fac1b3e.tar.gz frameworks_av-a0216af1a45b4c657a5801b766ec34a82fac1b3e.tar.bz2 |
Merge "Revive the code to support TCP interleaved transport"
Diffstat (limited to 'media/libstagefright/wifi-display')
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> ¬ifyLost, @@ -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; |