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

Commit 8a6f0b1f authored by Andreas Huber's avatar Andreas Huber Committed by Android (Google) Code Review
Browse files

Merge "Code to support RTP retransmission according to rfc4585, rfc4588" into jb-mr1-dev

parents 75041228 efd9c63d
Loading
Loading
Loading
Loading
+152 −34
Original line number Diff line number Diff line
@@ -209,11 +209,18 @@ WifiDisplaySource::PlaybackSession::PlaybackSession(
      mRTPPort(0),
      mRTPSessionID(0),
      mRTCPSessionID(0),
#if ENABLE_RETRANSMISSION
      mRTPRetransmissionSessionID(0),
      mRTCPRetransmissionSessionID(0),
#endif
      mClientRTPPort(0),
      mClientRTCPPort(0),
      mRTPConnected(false),
      mRTCPConnected(false),
      mRTPSeqNo(0),
#if ENABLE_RETRANSMISSION
      mRTPRetransmissionSeqNo(0),
#endif
      mLastNTPTime(0),
      mLastRTPTime(0),
      mNumRTPSent(0),
@@ -279,6 +286,15 @@ status_t WifiDisplaySource::PlaybackSession::init(

    sp<AMessage> rtpNotify = new AMessage(kWhatRTPNotify, id());
    sp<AMessage> rtcpNotify = new AMessage(kWhatRTCPNotify, id());

#if ENABLE_RETRANSMISSION
    sp<AMessage> rtpRetransmissionNotify =
        new AMessage(kWhatRTPRetransmissionNotify, id());

    sp<AMessage> rtcpRetransmissionNotify =
        new AMessage(kWhatRTCPRetransmissionNotify, id());
#endif

    for (serverRtp = 15550;; serverRtp += 2) {
        int32_t rtpSession;
        if (mTransportMode == TRANSPORT_UDP) {
@@ -296,18 +312,9 @@ status_t WifiDisplaySource::PlaybackSession::init(
            continue;
        }

        if (clientRtcp < 0) {
            // No RTCP.

            mRTPPort = serverRtp;
            mRTPSessionID = rtpSession;
            mRTCPSessionID = 0;

            ALOGI("rtpSessionId = %d", rtpSession);
            break;
        }
        int32_t rtcpSession = 0;

        int32_t rtcpSession;
        if (clientRtcp >= 0) {
            if (mTransportMode == TRANSPORT_UDP) {
                err = mNetSession->createUDPSession(
                        serverRtp + 1, clientIP, clientRtcp,
@@ -318,7 +325,57 @@ status_t WifiDisplaySource::PlaybackSession::init(
                        rtcpNotify, &rtcpSession);
            }

        if (err == OK) {
            if (err != OK) {
                ALOGI("failed to create RTCP socket on port %d", serverRtp + 1);

                mNetSession->destroySession(rtpSession);
                continue;
            }
        }

#if ENABLE_RETRANSMISSION
        if (mTransportMode == TRANSPORT_UDP) {
            int32_t rtpRetransmissionSession;

            err = mNetSession->createUDPSession(
                        serverRtp + kRetransmissionPortOffset,
                        clientIP,
                        clientRtp + kRetransmissionPortOffset,
                        rtpRetransmissionNotify,
                        &rtpRetransmissionSession);

            if (err != OK) {
                mNetSession->destroySession(rtcpSession);
                mNetSession->destroySession(rtpSession);
                continue;
            }

            CHECK_GE(clientRtcp, 0);

            int32_t rtcpRetransmissionSession;
            err = mNetSession->createUDPSession(
                        serverRtp + 1 + kRetransmissionPortOffset,
                        clientIP,
                        clientRtp + 1 + kRetransmissionPortOffset,
                        rtcpRetransmissionNotify,
                        &rtcpRetransmissionSession);

            if (err != OK) {
                mNetSession->destroySession(rtpRetransmissionSession);
                mNetSession->destroySession(rtcpSession);
                mNetSession->destroySession(rtpSession);
                continue;
            }

            mRTPRetransmissionSessionID = rtpRetransmissionSession;
            mRTCPRetransmissionSessionID = rtcpRetransmissionSession;

            ALOGI("rtpRetransmissionSessionID = %d, "
                  "rtcpRetransmissionSessionID = %d",
                  rtpRetransmissionSession, rtcpRetransmissionSession);
        }
#endif

        mRTPPort = serverRtp;
        mRTPSessionID = rtpSession;
        mRTCPSessionID = rtcpSession;
@@ -327,10 +384,6 @@ status_t WifiDisplaySource::PlaybackSession::init(
        break;
    }

        ALOGI("failed to create RTCP socket on port %d", serverRtp + 1);
        mNetSession->destroySession(rtpSession);
    }

    if (mRTPPort == 0) {
        return UNKNOWN_ERROR;
    }
@@ -461,6 +514,16 @@ status_t WifiDisplaySource::PlaybackSession::destroy() {
        service->connectDisplay(NULL);
    }

#if ENABLE_RETRANSMISSION
    if (mRTCPRetransmissionSessionID != 0) {
        mNetSession->destroySession(mRTCPRetransmissionSessionID);
    }

    if (mRTPRetransmissionSessionID != 0) {
        mNetSession->destroySession(mRTPRetransmissionSessionID);
    }
#endif

    if (mRTCPSessionID != 0) {
        mNetSession->destroySession(mRTCPSessionID);
    }
@@ -477,6 +540,10 @@ void WifiDisplaySource::PlaybackSession::onMessageReceived(
    switch (msg->what()) {
        case kWhatRTPNotify:
        case kWhatRTCPNotify:
#if ENABLE_RETRANSMISSION
        case kWhatRTPRetransmissionNotify:
        case kWhatRTCPRetransmissionNotify:
#endif
        {
            int32_t reason;
            CHECK(msg->findInt32("reason", &reason));
@@ -496,8 +563,11 @@ void WifiDisplaySource::PlaybackSession::onMessageReceived(
                    AString detail;
                    CHECK(msg->findString("detail", &detail));

                    if (msg->what() == kWhatRTPNotify
                            && !errorOccuredDuringSend) {
                    if ((msg->what() == kWhatRTPNotify
#if ENABLE_RETRANSMISSION
                            || msg->what() == kWhatRTPRetransmissionNotify
#endif
                        ) && !errorOccuredDuringSend) {
                        // This is ok, we don't expect to receive anything on
                        // the RTP socket.
                        break;
@@ -518,6 +588,13 @@ void WifiDisplaySource::PlaybackSession::onMessageReceived(
                    } else if (sessionID == mRTCPSessionID) {
                        mRTCPSessionID = 0;
                    }
#if ENABLE_RETRANSMISSION
                    else if (sessionID == mRTPRetransmissionSessionID) {
                        mRTPRetransmissionSessionID = 0;
                    } else if (sessionID == mRTCPRetransmissionSessionID) {
                        mRTCPRetransmissionSessionID = 0;
                    }
#endif

                    // Inform WifiDisplaySource of our premature death (wish).
                    sp<AMessage> notify = mNotify->dup();
@@ -535,7 +612,12 @@ void WifiDisplaySource::PlaybackSession::onMessageReceived(
                    CHECK(msg->findBuffer("data", &data));

                    status_t err;
                    if (msg->what() == kWhatRTCPNotify) {
                    if (msg->what() == kWhatRTCPNotify
#if ENABLE_RETRANSMISSION
                            || msg->what() == kWhatRTCPRetransmissionNotify
#endif
                       )
                    {
                        err = parseRTCP(data);
                    }
                    break;
@@ -1293,9 +1375,11 @@ status_t WifiDisplaySource::PlaybackSession::parseRTCP(
            case 204:  // APP
                break;

#if ENABLE_RETRANSMISSION
            case 205:  // TSFB (transport layer specific feedback)
                parseTSFB(data, headerLength);
                break;
#endif

            case 206:  // PSFB (payload specific feedback)
                hexdump(data, headerLength);
@@ -1316,6 +1400,7 @@ status_t WifiDisplaySource::PlaybackSession::parseRTCP(
    return OK;
}

#if ENABLE_RETRANSMISSION
status_t WifiDisplaySource::PlaybackSession::parseTSFB(
        const uint8_t *data, size_t size) {
    if ((data[0] & 0x1f) != 1) {
@@ -1332,31 +1417,64 @@ status_t WifiDisplaySource::PlaybackSession::parseTSFB(
        uint16_t blp = U16_AT(&data[i + 2]);

        List<sp<ABuffer> >::iterator it = mHistory.begin();
        bool found = false;
        bool foundSeqNo = false;
        while (it != mHistory.end()) {
            const sp<ABuffer> &buffer = *it;

            uint16_t bufferSeqNo = buffer->int32Data() & 0xffff;

            bool retransmit = false;
            if (bufferSeqNo == seqNo) {
                retransmit = true;
            } else if (blp != 0) {
                for (size_t i = 0; i < 16; ++i) {
                    if ((blp & (1 << i))
                        && (bufferSeqNo == ((seqNo + i + 1) & 0xffff))) {
                        blp &= ~(1 << i);
                        retransmit = true;
                    }
                }
            }

            if (retransmit) {
                ALOGI("retransmitting seqNo %d", bufferSeqNo);

                sp<ABuffer> retransRTP = new ABuffer(2 + buffer->size());
                uint8_t *rtp = retransRTP->data();
                memcpy(rtp, buffer->data(), 12);
                rtp[2] = (mRTPRetransmissionSeqNo >> 8) & 0xff;
                rtp[3] = mRTPRetransmissionSeqNo & 0xff;
                rtp[12] = (bufferSeqNo >> 8) & 0xff;
                rtp[13] = bufferSeqNo & 0xff;
                memcpy(&rtp[14], buffer->data() + 12, buffer->size() - 12);

                ++mRTPRetransmissionSeqNo;

                sendPacket(
                        mRTPRetransmissionSessionID,
                        retransRTP->data(), retransRTP->size());

                if (bufferSeqNo == seqNo) {
                sendPacket(mRTPSessionID, buffer->data(), buffer->size());
                    foundSeqNo = true;
                }

                found = true;
                if (foundSeqNo && blp == 0) {
                    break;
                }
            }

            ++it;
        }

        if (found) {
            ALOGI("retransmitting seqNo %d", seqNo);
        } else {
            ALOGI("seqNo %d no longer available", seqNo);
        if (!foundSeqNo || blp != 0) {
            ALOGI("Some sequence numbers were no longer available for "
                  "retransmission");
        }
    }

    return OK;
}
#endif

void WifiDisplaySource::PlaybackSession::requestIDRFrame() {
    for (size_t i = 0; i < mTracks.size(); ++i) {
+21 −1
Original line number Diff line number Diff line
@@ -32,6 +32,7 @@ struct Serializer;
struct TSPacketizer;

#define LOG_TRANSPORT_STREAM            0
#define ENABLE_RETRANSMISSION           0

// Encapsulates the state of an RTP/RTCP session in the context of wifi
// display.
@@ -86,6 +87,10 @@ private:
        kWhatSendSR,
        kWhatRTPNotify,
        kWhatRTCPNotify,
#if ENABLE_RETRANSMISSION
        kWhatRTPRetransmissionNotify,
        kWhatRTCPRetransmissionNotify,
#endif
        kWhatSerializerNotify,
        kWhatConverterNotify,
        kWhatUpdateSurface,
@@ -96,6 +101,10 @@ private:
    static const uint32_t kSourceID = 0xdeadbeef;
    static const size_t kMaxHistoryLength = 128;

#if ENABLE_RETRANSMISSION
    static const size_t kRetransmissionPortOffset = 120;
#endif

    sp<ANetworkSession> mNetSession;
    sp<AMessage> mNotify;
    in_addr mInterfaceAddr;
@@ -128,12 +137,20 @@ private:
    int32_t mRTPSessionID;
    int32_t mRTCPSessionID;

#if ENABLE_RETRANSMISSION
    int32_t mRTPRetransmissionSessionID;
    int32_t mRTCPRetransmissionSessionID;
#endif

    int32_t mClientRTPPort;
    int32_t mClientRTCPPort;
    bool mRTPConnected;
    bool mRTCPConnected;

    uint32_t mRTPSeqNo;
#if ENABLE_RETRANSMISSION
    uint32_t mRTPRetransmissionSeqNo;
#endif

    uint64_t mLastNTPTime;
    uint32_t mLastRTPTime;
@@ -177,7 +194,10 @@ private:
    void scheduleSendSR();

    status_t parseRTCP(const sp<ABuffer> &buffer);

#if ENABLE_RETRANSMISSION
    status_t parseTSFB(const uint8_t *data, size_t size);
#endif

    status_t sendPacket(int32_t sessionID, const void *data, size_t size);
    status_t onFinishPlay();
+1 −0
Original line number Diff line number Diff line
@@ -869,6 +869,7 @@ status_t WifiDisplaySource::onSetupRequest(
        } else if (sscanf(clientPort.c_str(), "%d", &clientRtp) == 1) {
            // No RTCP.
            clientRtcp = -1;
            clientRtcp = clientRtp + 1;  // XXX
        } else {
            badRequest = true;
        }