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

Commit bd887691 authored by Kim Sungyeon's avatar Kim Sungyeon Committed by Lajos Molnar
Browse files

VT: Add TMMBN feature on RTP Tx side



StagefrightRecorder adjusts encoding rate and sends TMMBN as requested bitrate.

1. Add TMMBN packetizing function on ARTPWriter.
2. StagefrightRecorder holds opponent's SSRC ID that is used for TMMBN.
3. MediaRecorder can set parameter on RECORDING state if format is for RTP.

Merged-in: I768649c02e50fd5fab2ecb53c3743915662c100a
Change-Id: I768649c02e50fd5fab2ecb53c3743915662c100a
Signed-off-by: default avatarKim Sungyeon <sy85.kim@samsung.com>
parent 8f935263
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -291,6 +291,8 @@ private:
    bool                        mIsOutputFileSet;
    Mutex                       mLock;
    Mutex                       mNotifyLock;

    int                         mOutputFormat;
};

};  // namespace android
+9 −0
Original line number Diff line number Diff line
@@ -244,6 +244,7 @@ status_t MediaRecorder::setOutputFormat(int of)
        mCurrentState = MEDIA_RECORDER_ERROR;
        return ret;
    }
    mOutputFormat = of;
    mCurrentState = MEDIA_RECORDER_DATASOURCE_CONFIGURED;
    return ret;
}
@@ -479,6 +480,13 @@ status_t MediaRecorder::setParameters(const String8& params) {
                           (MEDIA_RECORDER_PREPARED |
                            MEDIA_RECORDER_RECORDING |
                            MEDIA_RECORDER_ERROR));

    // For RTP video, parameter should be set dynamically.
    if (isInvalidState) {
        if (mCurrentState == MEDIA_RECORDER_RECORDING &&
            mOutputFormat == OUTPUT_FORMAT_RTP_AVP)
            isInvalidState = false;
    }
    if (isInvalidState) {
        ALOGE("setParameters is called in an invalid state: %d", mCurrentState);
        return INVALID_OPERATION;
@@ -737,6 +745,7 @@ void MediaRecorder::doCleanUp()
    mIsAudioEncoderSet = false;
    mIsVideoEncoderSet = false;
    mIsOutputFileSet   = false;
    mOutputFormat      = 0;
}

// Release should be OK in any state
+7 −0
Original line number Diff line number Diff line
@@ -581,6 +581,8 @@ status_t StagefrightRecorder::setParamVideoEncodingBitRate(int32_t bitRate) {
        const float coefficient = 0.8f;
        mVideoBitRate = (bitRate * coefficient) / 1000 * 1000;
        mVideoEncoderSource->setEncodingBitrate(mVideoBitRate);
        ARTPWriter* rtpWriter  = static_cast<ARTPWriter*>(mWriter.get());
        rtpWriter->setTMMBNInfo(mOpponentID, bitRate);
    }

    return OK;
@@ -827,6 +829,11 @@ status_t StagefrightRecorder::setParamSelfID(int32_t selfID) {
    return OK;
}

status_t StagefrightRecorder::setParamVideoOpponentID(int32_t opponentID) {
    mOpponentID = opponentID;
    return OK;
}

status_t StagefrightRecorder::setParamPayloadType(int32_t payloadType) {
    ALOGV("setParamPayloadType: %x", payloadType);

+2 −0
Original line number Diff line number Diff line
@@ -143,6 +143,7 @@ private:
    int32_t mLocalPort;
    int32_t mRemotePort;
    int32_t mSelfID;
    int32_t mOpponentID;
    int32_t mPayloadType;
    int32_t mRTPCVOExtMap;
    int32_t mRTPCVODegrees;
@@ -232,6 +233,7 @@ private:
    status_t setParamRtpRemoteIp(const String8 &remoteIp);
    status_t setParamRtpRemotePort(int32_t remotePort);
    status_t setParamSelfID(int32_t selfID);
    status_t setParamVideoOpponentID(int32_t opponentID);
    status_t setParamPayloadType(int32_t payloadType);
    status_t setRTPCVOExtMap(int32_t extmap);
    status_t setRTPCVODegrees(int32_t cvoDegrees);
+64 −2
Original line number Diff line number Diff line
@@ -57,6 +57,7 @@ namespace android {

// static const size_t kMaxPacketSize = 65507;  // maximum payload in UDP over IP
static const size_t kMaxPacketSize = 1500;
static char kCNAME[255] = "someone@somewhere";

static int UniformRand(int limit) {
    return ((double)rand() * limit) / RAND_MAX;
@@ -197,6 +198,8 @@ status_t ARTPWriter::start(MetaData * params) {
    mNumRTPOctetsSent = 0;
    mLastRTPTime = 0;
    mLastNTPTime = 0;
    mOpponentID = 0;
    mBitrate = 192000;
    mNumSRsSent = 0;
    mRTPCVOExtMap = -1;
    mRTPCVODegrees = 0;
@@ -406,6 +409,18 @@ void ARTPWriter::onMessageReceived(const sp<AMessage> &msg) {
    }
}

void ARTPWriter::setTMMBNInfo(uint32_t opponentID, uint32_t bitrate) {
    mOpponentID = opponentID;
    mBitrate = bitrate;

    sp<ABuffer> buffer = new ABuffer(65536);
    buffer->setRange(0, 0);

    addTMMBN(buffer);

    send(buffer, true /* isRTCP */);
}

void ARTPWriter::onRead(const sp<AMessage> &msg) {
    MediaBufferBase *mediaBuf;
    status_t err = mSource->read(&mediaBuf);
@@ -543,7 +558,6 @@ void ARTPWriter::addSDES(const sp<ABuffer> &buffer) {

    data[offset++] = 1;  // CNAME

    static const char *kCNAME = "someone@somewhere";
    data[offset++] = strlen(kCNAME);

    memcpy(&data[offset], kCNAME, strlen(kCNAME));
@@ -580,9 +594,52 @@ void ARTPWriter::addSDES(const sp<ABuffer> &buffer) {
    buffer->setRange(buffer->offset(), buffer->size() + offset);
}

void ARTPWriter::addTMMBN(const sp<ABuffer> &buffer) {
    if (buffer->size() + 20 > buffer->capacity()) {
        ALOGW("RTCP buffer too small to accomodate SR.");
        return;
    }
    if (mOpponentID == 0)
        return;

    uint8_t *data = buffer->data() + buffer->size();

    data[0] = 0x80 | 4; // TMMBN
    data[1] = 205;      // TSFB
    data[2] = 0;
    data[3] = 4;        // total (4+1) * sizeof(int32_t) = 20 bytes
    data[4] = mSourceID >> 24;
    data[5] = (mSourceID >> 16) & 0xff;
    data[6] = (mSourceID >> 8) & 0xff;
    data[7] = mSourceID & 0xff;

    *(int32_t*)(&data[8]) = 0;  // 4 bytes blank

    data[12] = mOpponentID >> 24;
    data[13] = (mOpponentID >> 16) & 0xff;
    data[14] = (mOpponentID >> 8) & 0xff;
    data[15] = mOpponentID & 0xff;

    int32_t exp, mantissa;

    // Round off to the nearest 2^4th
    ALOGI("UE -> Op Noti Tx bitrate : %d ", mBitrate & 0xfffffff0);
    for (exp=4 ; exp < 32 ; exp++)
        if (((mBitrate >> exp) & 0x01) != 0)
            break;
    mantissa = mBitrate >> exp;

    data[16] = ((exp << 2) & 0xfc) | ((mantissa & 0x18000) >> 15);
    data[17] =                        (mantissa & 0x07f80) >> 7;
    data[18] =                        (mantissa & 0x0007f) << 1;
    data[19] = 40;              // 40 bytes overhead;

    buffer->setRange(buffer->offset(), buffer->size() + 20);
}

// static
uint64_t ARTPWriter::GetNowNTP() {
    uint64_t nowUs = ALooper::GetNowUs();
    uint64_t nowUs = systemTime(SYSTEM_TIME_REALTIME) / 1000ll;

    nowUs += ((70LL * 365 + 17) * 24) * 60 * 60 * 1000000LL;

@@ -1217,6 +1274,11 @@ void ARTPWriter::sendAMRData(MediaBufferBase *mediaBuf) {

void ARTPWriter::makeSocketPairAndBind(String8& localIp, int localPort,
        String8& remoteIp, int remotePort) {
    static char kSomeone[16] = "someone@";
    int nameLength = strlen(kSomeone);
    memcpy(kCNAME, kSomeone, nameLength);
    memcpy(kCNAME + nameLength, localIp.c_str(), localIp.length() + 1);

    if (localIp.contains(":"))
        mIsIPv6 = true;
    else
Loading