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

Commit fa9b2d8b authored by Lajos Molnar's avatar Lajos Molnar Committed by Gerrit Code Review
Browse files

Merge "VT: Add TMMBR feature for RTP Rx side"

parents 5e94515e a2c250d2
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -42,7 +42,7 @@ NuPlayer::RTPSource::RTPSource(
      mFinalResult(OK),
      mBuffering(false),
      mInPreparationPhase(true),
      mRTPConn(new ARTPConnection),
      mRTPConn(new ARTPConnection(ARTPConnection::kViLTEConnection)),
      mEOSTimeoutAudio(0),
      mEOSTimeoutVideo(0),
      mLastCVOUpdated(-1) {
@@ -111,7 +111,7 @@ void NuPlayer::RTPSource::prepareAsync() {
        // index(i) should be started from 1. 0 is reserved for [root]
        mRTPConn->addStream(sockRtp, sockRtcp, desc, i + 1, notify, false);
        mRTPConn->setSelfID(info->mSelfID);
        mRTPConn->setMinMaxBitrate(videoMinBitrate, 512000);
        mRTPConn->setMinMaxBitrate(videoMinBitrate, info->mAS * 1000);

        info->mRTPSocket = sockRtp;
        info->mRTCPSocket = sockRtcp;
+81 −23
Original line number Diff line number Diff line
@@ -427,7 +427,8 @@ void ARTPConnection::onPollStreams() {
    }

    int64_t nowUs = ALooper::GetNowUs();
    showRxBitrate(nowUs);
    checkRxBitrate(nowUs);

    if (mLastReceiverReportTimeUs <= 0
            || mLastReceiverReportTimeUs + 5000000LL <= nowUs) {
        sp<ABuffer> buffer = new ABuffer(kMaxUDPSize);
@@ -452,10 +453,7 @@ void ARTPConnection::onPollStreams() {
            for (size_t i = 0; i < s->mSources.size(); ++i) {
                sp<ARTPSource> source = s->mSources.valueAt(i);

                if (source->isNeedToReport()) {
                source->addReceiverReport(buffer);
                    source->addTMMBR(buffer);
                }

                if (mFlags & kRegularlyRequestFIR) {
                    source->addFIR(buffer);
@@ -465,22 +463,7 @@ void ARTPConnection::onPollStreams() {
            if (buffer->size() > 0) {
                ALOGV("Sending RR...");

                struct sockaddr* pRemoteRTCPAddr;
                int sizeSockSt;
                if (s->isIPv6) {
                    pRemoteRTCPAddr = (struct sockaddr *)&s->mRemoteRTCPAddr6;
                    sizeSockSt = sizeof(struct sockaddr_in6);
                } else {
                    pRemoteRTCPAddr = (struct sockaddr *)&s->mRemoteRTCPAddr;
                    sizeSockSt = sizeof(struct sockaddr_in);
                }

                ssize_t n;
                do {
                    n = sendto(
                            s->mRTCPSocket, buffer->data(), buffer->size(), 0,
                            pRemoteRTCPAddr, sizeSockSt);
                } while (n < 0 && errno == EINTR);
                ssize_t n = send(s, buffer);

                if (n <= 0) {
                    ALOGW("failed to send RTCP receiver report (%s).",
@@ -524,6 +507,9 @@ status_t ARTPConnection::receive(StreamInfo *s, bool receiveRTP) {
        (!receiveRTP && s->mNumRTCPPacketsReceived == 0)
            ? sizeSockSt : 0;

    if (mFlags & kViLTEConnection)
        remoteAddrLen = 0;

    ssize_t nbytes;
    do {
        nbytes = recvfrom(
@@ -554,6 +540,36 @@ status_t ARTPConnection::receive(StreamInfo *s, bool receiveRTP) {
    return err;
}

ssize_t ARTPConnection::send(const StreamInfo *info, const sp<ABuffer> buffer) {
        struct sockaddr* pRemoteRTCPAddr;
        int sizeSockSt;

        /* It seems this isIPv6 variable is useless.
         * We should remove it to prevent confusion */
        if (info->isIPv6) {
            pRemoteRTCPAddr = (struct sockaddr *)&info->mRemoteRTCPAddr6;
            sizeSockSt = sizeof(struct sockaddr_in6);
        } else {
            pRemoteRTCPAddr = (struct sockaddr *)&info->mRemoteRTCPAddr;
            sizeSockSt = sizeof(struct sockaddr_in);
        }

        if (mFlags & kViLTEConnection) {
            ALOGV("ViLTE RTCP");
            pRemoteRTCPAddr = NULL;
            sizeSockSt = 0;
        }

        ssize_t n;
        do {
            n = sendto(
                    info->mRTCPSocket, buffer->data(), buffer->size(), 0,
                    pRemoteRTCPAddr, sizeSockSt);
        } while (n < 0 && errno == EINTR);

        return n;
}

status_t ARTPConnection::parseRTP(StreamInfo *s, const sp<ABuffer> &buffer) {
    if (s->mNumRTPPacketsReceived++ == 0) {
        sp<AMessage> notify = s->mNotifyMsg->dup();
@@ -970,14 +986,56 @@ void ARTPConnection::setMinMaxBitrate(int32_t min, int32_t max) {
    mMaxBitrate = max;
}

void ARTPConnection::showRxBitrate(int64_t nowUs) {
void ARTPConnection::checkRxBitrate(int64_t nowUs) {
    if (mLastBitrateReportTimeUs <= 0) {
        mCumulativeBytes = 0;
        mLastBitrateReportTimeUs = nowUs;
    }
    else if (mLastBitrateReportTimeUs + 1000000ll <= nowUs) {
        int32_t timeDiff = (nowUs - mLastBitrateReportTimeUs) / 1000000ll;
        ALOGI("Actual Rx bitrate : %d bits/sec", mCumulativeBytes * 8 / timeDiff);
        int32_t bitrate = mCumulativeBytes * 8 / timeDiff;
        ALOGI("Actual Rx bitrate : %d bits/sec", bitrate);

        sp<ABuffer> buffer = new ABuffer(kMaxUDPSize);
        List<StreamInfo>::iterator it = mStreams.begin();
        while (it != mStreams.end()) {
            StreamInfo *s = &*it;
            if (s->mIsInjected) {
                ++it;
                continue;
            }

            if (s->mNumRTCPPacketsReceived == 0) {
                // We have never received any RTCP packets on this stream,
                // we don't even know where to send a report.
                ++it;
                continue;
            }

            buffer->setRange(0, 0);

            for (size_t i = 0; i < s->mSources.size(); ++i) {
                sp<ARTPSource> source = s->mSources.valueAt(i);
                source->setTargetBitrate();
                source->addTMMBR(buffer);
            }
            if (buffer->size() > 0) {
                ALOGV("Sending TMMBR...");

                ssize_t n = send(s, buffer);

                if (n <= 0) {
                    ALOGW("failed to send RTCP TMMBR (%s).",
                         n == 0 ? "connection gone" : strerror(errno));

                    it = mStreams.erase(it);
                    continue;
                }

                CHECK_EQ(n, (ssize_t)buffer->size());
            }
            ++it;
        }
        mCumulativeBytes = 0;
        mLastBitrateReportTimeUs = nowUs;
    }
+3 −1
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@ struct ASessionDescription;
struct ARTPConnection : public AHandler {
    enum Flags {
        kRegularlyRequestFIR = 2,
        kViLTEConnection = 4,
    };

    explicit ARTPConnection(uint32_t flags = 0);
@@ -94,9 +95,10 @@ private:
    void onPollStreams();
    void onInjectPacket(const sp<AMessage> &msg);
    void onSendReceiverReports();
    void showRxBitrate(int64_t nowUs);
    void checkRxBitrate(int64_t nowUs);

    status_t receive(StreamInfo *info, bool receiveRTP);
    ssize_t send(const StreamInfo *info, const sp<ABuffer> buffer);

    status_t parseRTP(StreamInfo *info, const sp<ABuffer> &buffer);
    status_t parseRTPExt(StreamInfo *s, const uint8_t *extData, size_t extLen, int32_t *cvoDegrees);
+25 −4
Original line number Diff line number Diff line
@@ -263,8 +263,6 @@ void ARTPSource::addReceiverReport(const sp<ABuffer> &buffer) {
        fraction = (intervalPacketLost << 8) / intervalExpected;
    }

    mQualManager.setTargetBitrate(fraction);

    mPrevExpected = expected;
    mPrevNumBuffersReceived = mNumBuffersReceived;
    int32_t cumulativePacketLost = (int32_t)expected - mNumBuffersReceived;
@@ -330,7 +328,9 @@ void ARTPSource::addTMMBR(const sp<ABuffer> &buffer) {
        ALOGW("RTCP buffer too small to accomodate RR.");
        return;
    }
    if (mQualManager.mTargetBitrate <= 0)

    int32_t targetBitrate = mQualManager.getTargetBitrate();
    if (targetBitrate <= 0)
        return;

    uint8_t *data = buffer->data() + buffer->size();
@@ -351,7 +351,6 @@ void ARTPSource::addTMMBR(const sp<ABuffer> &buffer) {
    data[14] = (mID >> 8) & 0xff;
    data[15] = mID & 0xff;

    int32_t targetBitrate = mQualManager.mTargetBitrate;
    int32_t exp, mantissa;

    // Round off to the nearest 2^4th
@@ -369,6 +368,9 @@ void ARTPSource::addTMMBR(const sp<ABuffer> &buffer) {
    buffer->setRange(buffer->offset(), buffer->size() + 20);
}

uint32_t ARTPSource::getSelfID() {
    return kSourceID;
}
void ARTPSource::setSelfID(const uint32_t selfID) {
    kSourceID = selfID;
}
@@ -377,6 +379,25 @@ void ARTPSource::setMinMaxBitrate(int32_t min, int32_t max) {
    mQualManager.setMinMaxBitrate(min, max);
}

void ARTPSource::setTargetBitrate() {
    uint8_t fraction = 0;

    // According to appendix A.3 in RFC 3550
    uint32_t expected = mHighestSeqNumber - mBaseSeqNumber + 1;
    int64_t intervalExpected = expected - mPrevExpected;
    int64_t intervalReceived = mNumBuffersReceived - mPrevNumBuffersReceived;
    int64_t intervalPacketLost = intervalExpected - intervalReceived;

    if (intervalPacketLost < 0)
        fraction = 0;
    else if (intervalExpected <= intervalPacketLost || intervalExpected == 0)
        fraction = 255;
    else
        fraction = (intervalPacketLost << 8) / intervalExpected;

    mQualManager.setTargetBitrate(fraction, ALooper::GetNowUs());
}

bool ARTPSource::isNeedToReport() {
    int64_t intervalReceived = mNumBuffersReceived - mPrevNumBuffersReceived;
    return (intervalReceived > 0) ? true : false;
+5 −29
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@
#include <media/stagefright/foundation/ABase.h>
#include <utils/List.h>
#include <utils/RefBase.h>
#include <QualManager.h>

namespace android {

@@ -46,8 +47,10 @@ struct ARTPSource : public RefBase {
    void addReceiverReport(const sp<ABuffer> &buffer);
    void addFIR(const sp<ABuffer> &buffer);
    void addTMMBR(const sp<ABuffer> &buffer);
    uint32_t getSelfID();
    void setSelfID(const uint32_t selfID);
    void setMinMaxBitrate(int32_t min, int32_t max);
    void setTargetBitrate();

    bool isNeedToReport();

@@ -59,35 +62,6 @@ struct ARTPSource : public RefBase {
    int32_t mClockRate;

private:
    struct QualManager {
        QualManager() : mMinBitrate(-1), mMaxBitrate(-1), mTargetBitrate(-1) {};

        int32_t mMinBitrate;
        int32_t mMaxBitrate;
        int32_t mBitrateStep;

        int32_t mTargetBitrate;

        void setTargetBitrate(uint8_t fraction) {
            if (fraction <= (256 * 2 /100)) {           // loss less than 2%
                mTargetBitrate += mBitrateStep;
            } else if (fraction > (256 * 5 / 100)) {    // loss more than 5%
                mTargetBitrate -= mBitrateStep;
            }

            if (mTargetBitrate > mMaxBitrate)
                mTargetBitrate = mMaxBitrate;
            else if (mTargetBitrate < mMinBitrate)
                mTargetBitrate = mMinBitrate;
        };

        void setMinMaxBitrate(int32_t min, int32_t max) {
            mMinBitrate = min;
            mMaxBitrate = max;
            mBitrateStep = (max - min) / 8;
            mTargetBitrate = min;
        };
    } mQualManager;

    uint32_t mID;
    uint32_t mHighestSeqNumber;
@@ -108,6 +82,8 @@ private:

    sp<AMessage> mNotify;

    QualManager mQualManager;

    bool queuePacket(const sp<ABuffer> &buffer);

    DISALLOW_EVIL_CONSTRUCTORS(ARTPSource);
Loading