VT: Add TMMBR function on Rx
Now Player(Rx) can measure and check Rx status(bitrate & loss)
And send TMMBR base on the status
Merged-in: I203ff5022ca95859c8acc662ba6cedff256a6995
Change-Id: I203ff5022ca95859c8acc662ba6cedff256a6995
Signed-off-by: Kim Sungyeon <sy85.kim@samsung.com>
diff --git a/media/libmediaplayerservice/nuplayer/RTPSource.cpp b/media/libmediaplayerservice/nuplayer/RTPSource.cpp
index 4b1b164..6f4933c 100644
--- a/media/libmediaplayerservice/nuplayer/RTPSource.cpp
+++ b/media/libmediaplayerservice/nuplayer/RTPSource.cpp
@@ -110,6 +110,7 @@
// 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);
info->mRTPSocket = sockRtp;
info->mRTCPSocket = sockRtcp;
diff --git a/media/libmediaplayerservice/nuplayer/RTPSource.h b/media/libmediaplayerservice/nuplayer/RTPSource.h
index e3df2a4..faed1e1 100644
--- a/media/libmediaplayerservice/nuplayer/RTPSource.h
+++ b/media/libmediaplayerservice/nuplayer/RTPSource.h
@@ -46,6 +46,8 @@
struct ALooper;
struct AnotherPacketSource;
+const int32_t videoMinBitrate = 192000;
+
struct NuPlayer::RTPSource : public NuPlayer::Source {
RTPSource(
const sp<AMessage> ¬ify,
diff --git a/media/libstagefright/rtsp/ARTPConnection.cpp b/media/libstagefright/rtsp/ARTPConnection.cpp
index 2bedc9a..01ce43b 100644
--- a/media/libstagefright/rtsp/ARTPConnection.cpp
+++ b/media/libstagefright/rtsp/ARTPConnection.cpp
@@ -72,7 +72,8 @@
ARTPConnection::ARTPConnection(uint32_t flags)
: mFlags(flags),
mPollEventPending(false),
- mLastReceiverReportTimeUs(-1) {
+ mLastReceiverReportTimeUs(-1),
+ mLastBitrateReportTimeUs(-1) {
}
ARTPConnection::~ARTPConnection() {
@@ -411,6 +412,7 @@
}
int64_t nowUs = ALooper::GetNowUs();
+ showRxBitrate(nowUs);
if (mLastReceiverReportTimeUs <= 0
|| mLastReceiverReportTimeUs + 5000000LL <= nowUs) {
sp<ABuffer> buffer = new ABuffer(kMaxUDPSize);
@@ -435,7 +437,10 @@
for (size_t i = 0; i < s->mSources.size(); ++i) {
sp<ARTPSource> source = s->mSources.valueAt(i);
- source->addReceiverReport(buffer);
+ if (source->isNeedToReport()) {
+ source->addReceiverReport(buffer);
+ source->addTMMBR(buffer);
+ }
if (mFlags & kRegularlyRequestFIR) {
source->addFIR(buffer);
@@ -513,6 +518,7 @@
0,
remoteAddrLen > 0 ? pRemoteRTCPAddr : NULL,
remoteAddrLen > 0 ? &remoteAddrLen : NULL);
+ mCumulativeBytes += nbytes;
} while (nbytes < 0 && errno == EINTR);
if (nbytes <= 0) {
@@ -875,6 +881,7 @@
srcId, info->mSessionDesc, info->mIndex, info->mNotifyMsg);
source->setSelfID(mSelfID);
+ source->setMinMaxBitrate(mMinBitrate, mMaxBitrate);
info->mSources.add(srcId, source);
} else {
source = info->mSources.valueAt(index);
@@ -894,6 +901,23 @@
mSelfID = selfID;
}
+void ARTPConnection::setMinMaxBitrate(int32_t min, int32_t max) {
+ mMinBitrate = min;
+ mMaxBitrate = max;
+}
+
+void ARTPConnection::showRxBitrate(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);
+ mCumulativeBytes = 0;
+ mLastBitrateReportTimeUs = nowUs;
+ }
+}
void ARTPConnection::onInjectPacket(const sp<AMessage> &msg) {
int32_t index;
CHECK(msg->findInt32("index", &index));
diff --git a/media/libstagefright/rtsp/ARTPConnection.h b/media/libstagefright/rtsp/ARTPConnection.h
index 287430e..ae638e4 100644
--- a/media/libstagefright/rtsp/ARTPConnection.h
+++ b/media/libstagefright/rtsp/ARTPConnection.h
@@ -45,6 +45,7 @@
void injectPacket(int index, const sp<ABuffer> &buffer);
void setSelfID(const uint32_t selfID);
+ void setMinMaxBitrate(int32_t min, int32_t max);
// Creates a pair of UDP datagram sockets bound to adjacent ports
// (the rtpSocket is bound to an even port, the rtcpSocket to the
@@ -80,14 +81,20 @@
bool mPollEventPending;
int64_t mLastReceiverReportTimeUs;
+ int64_t mLastBitrateReportTimeUs;
int32_t mSelfID;
+ int32_t mMinBitrate;
+ int32_t mMaxBitrate;
+ int32_t mCumulativeBytes;
+
void onAddStream(const sp<AMessage> &msg);
void onRemoveStream(const sp<AMessage> &msg);
void onPollStreams();
void onInjectPacket(const sp<AMessage> &msg);
void onSendReceiverReports();
+ void showRxBitrate(int64_t nowUs);
status_t receive(StreamInfo *info, bool receiveRTP);
diff --git a/media/libstagefright/rtsp/ARTPSource.cpp b/media/libstagefright/rtsp/ARTPSource.cpp
index c39b4c2..5c3f2d8 100644
--- a/media/libstagefright/rtsp/ARTPSource.cpp
+++ b/media/libstagefright/rtsp/ARTPSource.cpp
@@ -263,10 +263,14 @@
fraction = (intervalPacketLost << 8) / intervalExpected;
}
+ mQualManager.setTargetBitrate(fraction);
+
mPrevExpected = expected;
mPrevNumBuffersReceived = mNumBuffersReceived;
int32_t cumulativePacketLost = (int32_t)expected - mNumBuffersReceived;
+ ALOGI("UID %p expectedPkts %lld lostPkts %lld", this, (long long)intervalExpected, (long long)intervalPacketLost);
+
uint8_t *data = buffer->data() + buffer->size();
data[0] = 0x80 | 1;
@@ -321,10 +325,63 @@
buffer->setRange(buffer->offset(), buffer->size() + 32);
}
+void ARTPSource::addTMMBR(const sp<ABuffer> &buffer) {
+ if (buffer->size() + 32 > buffer->capacity()) {
+ ALOGW("RTCP buffer too small to accomodate RR.");
+ return;
+ }
+ if (mQualManager.mTargetBitrate <= 0)
+ return;
+
+ uint8_t *data = buffer->data() + buffer->size();
+
+ data[0] = 0x80 | 3; // TMMBR
+ data[1] = 205; // TSFB
+ data[2] = 0;
+ data[3] = 4; // total (4+1) * sizeof(int32_t) = 20 bytes
+ data[4] = kSourceID >> 24;
+ data[5] = (kSourceID >> 16) & 0xff;
+ data[6] = (kSourceID >> 8) & 0xff;
+ data[7] = kSourceID & 0xff;
+
+ *(int32_t*)(&data[8]) = 0; // 4 bytes blank
+
+ data[12] = mID >> 24;
+ data[13] = (mID >> 16) & 0xff;
+ 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
+ ALOGI("UE -> Op Req Rx bitrate : %d ", targetBitrate & 0xfffffff0);
+ for (exp=4 ; exp < 32 ; exp++)
+ if (((targetBitrate >> exp) & 0x01) != 0)
+ break;
+ mantissa = targetBitrate >> 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);
+}
+
void ARTPSource::setSelfID(const uint32_t selfID) {
kSourceID = selfID;
}
+void ARTPSource::setMinMaxBitrate(int32_t min, int32_t max) {
+ mQualManager.setMinMaxBitrate(min, max);
+}
+
+bool ARTPSource::isNeedToReport() {
+ int64_t intervalReceived = mNumBuffersReceived - mPrevNumBuffersReceived;
+ return (intervalReceived > 0) ? true : false;
+}
+
void ARTPSource::noticeAbandonBuffer(int cnt) {
mNumBuffersReceived -= cnt;
}
diff --git a/media/libstagefright/rtsp/ARTPSource.h b/media/libstagefright/rtsp/ARTPSource.h
index 40f08f4..e4aa4c1 100644
--- a/media/libstagefright/rtsp/ARTPSource.h
+++ b/media/libstagefright/rtsp/ARTPSource.h
@@ -45,7 +45,11 @@
void addReceiverReport(const sp<ABuffer> &buffer);
void addFIR(const sp<ABuffer> &buffer);
+ void addTMMBR(const sp<ABuffer> &buffer);
void setSelfID(const uint32_t selfID);
+ void setMinMaxBitrate(int32_t min, int32_t max);
+
+ bool isNeedToReport();
void noticeAbandonBuffer(int cnt=1);
@@ -55,6 +59,36 @@
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;
uint32_t mPrevExpected;