Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7cc0c29d authored by Andreas Huber's avatar Andreas Huber
Browse files

Revive the code to support TCP interleaved transport

Also support non-interleaved transport now, but the sink gets to decide
what mode it wants to run in, _not_ the source.

Change-Id: I3b6057f86871084e4decf930bb4a7a2d7517b0f2
parent 08aa0bc9
Loading
Loading
Loading
Loading
+0 −1
Original line number Diff line number Diff line
@@ -1091,7 +1091,6 @@ void ANetworkSession::threadLoop() {
                                  clientSocket);

                            sp<Session> clientSession =
                                // using socket sd as sessionID
                                new Session(
                                        mNextSessionID++,
                                        Session::CONNECTED,
+13 −5
Original line number Diff line number Diff line
@@ -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
    if (kPacketLateDelayUs > 0ll) {
        msg = new AMessage(kWhatPacketLate, id());
        msg->setInt32("generation", mPacketLostGeneration);
        msg->post(kPacketLateDelayUs);
#endif
    }

    msg = new AMessage(kWhatPacketLost, id());
    msg->setInt32("generation", mPacketLostGeneration);
+47 −6
Original line number Diff line number Diff line
@@ -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(
        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;
        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();
            }
+7 −3
Original line number Diff line number Diff line
@@ -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;
+54 −70
Original line number Diff line number Diff line
@@ -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));
            }

            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: ";
    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/UDP;unicast 19000 0 mode=play\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");
Loading