VT: Enhancements on RTP depacketizer
1) Do not merge FU pkts if rtptimes are different.
[Problem] There was a case that Fragmented Units of RTP be merged as
an one frame even Fragmented Units are has different timestamp.
[Solution] Added a condition to check rtptime between Fragmented Units.
2) Implementation of a new frame drop rule for p-frame.
[Problem] P-frame should be dropped only if FU packets damaged
more than half of amount of frame.
[Solution] Implemented a rule for p-frame drop.
3) Discards a rtp buffer that has unexpected ssrc.
[Problem] so many packet loss observed and video loss because about
4 different video stream coming at the same time.
[Solution] Allow only one stream that matched SSRC of first stream.
Bug: 165061754
Change-Id: If840df274a6fc4b04910f9201359b7c09fd2bc85
Signed-off-by: Byeongjo Park <bjo.park@samsung.com>
diff --git a/media/libmediaplayerservice/nuplayer/RTPSource.cpp b/media/libmediaplayerservice/nuplayer/RTPSource.cpp
index 3c3ad86..8072863 100644
--- a/media/libmediaplayerservice/nuplayer/RTPSource.cpp
+++ b/media/libmediaplayerservice/nuplayer/RTPSource.cpp
@@ -281,20 +281,19 @@
}
int32_t cvo;
- if ((*accessUnit) != NULL && (*accessUnit)->meta()->findInt32("cvo", &cvo)) {
- if (cvo != mLastCVOUpdated) {
- sp<AMessage> msg = new AMessage();
- msg->setInt32("payload-type", NuPlayer::RTPSource::RTP_CVO);
- msg->setInt32("cvo", cvo);
+ if ((*accessUnit) != NULL && (*accessUnit)->meta()->findInt32("cvo", &cvo) &&
+ cvo != mLastCVOUpdated) {
+ sp<AMessage> msg = new AMessage();
+ msg->setInt32("payload-type", NuPlayer::RTPSource::RTP_CVO);
+ msg->setInt32("cvo", cvo);
- sp<AMessage> notify = dupNotify();
- notify->setInt32("what", kWhatIMSRxNotice);
- notify->setMessage("message", msg);
- notify->post();
+ sp<AMessage> notify = dupNotify();
+ notify->setInt32("what", kWhatIMSRxNotice);
+ notify->setMessage("message", msg);
+ notify->post();
- ALOGV("notify cvo updated (%d)->(%d) to upper layer", mLastCVOUpdated, cvo);
- mLastCVOUpdated = cvo;
- }
+ ALOGV("notify cvo updated (%d)->(%d) to upper layer", mLastCVOUpdated, cvo);
+ mLastCVOUpdated = cvo;
}
return finalResult;
diff --git a/media/libstagefright/rtsp/AAVCAssembler.cpp b/media/libstagefright/rtsp/AAVCAssembler.cpp
index af82533..f0ee9b7 100644
--- a/media/libstagefright/rtsp/AAVCAssembler.cpp
+++ b/media/libstagefright/rtsp/AAVCAssembler.cpp
@@ -280,6 +280,11 @@
size_t totalCount = 1;
bool complete = false;
+ int32_t rtpTimeStartAt;
+ CHECK(buffer->meta()->findInt32("rtp-time", &rtpTimeStartAt));
+ uint32_t startSeqNo = buffer->int32Data();
+ bool pFrame = nalType == 0x1;
+
if (data[1] & 0x40) {
// Huh? End bit also set on the first buffer.
@@ -297,16 +302,20 @@
size_t size = buffer->size();
if ((uint32_t)buffer->int32Data() != expectedSeqNo) {
- ALOGV("sequence not complete, expected seqNo %d, got %d",
- expectedSeqNo, (uint32_t)buffer->int32Data());
+ ALOGV("sequence not complete, expected seqNo %d, got %d, pFrame %d",
+ expectedSeqNo, (uint32_t)buffer->int32Data(), pFrame);
- return WRONG_SEQUENCE_NUMBER;
+ if (!pFrame)
+ return WRONG_SEQUENCE_NUMBER;
}
+ int32_t rtpTime;
+ CHECK(buffer->meta()->findInt32("rtp-time", &rtpTime));
if (size < 2
|| data[0] != indicator
|| (data[1] & 0x1f) != nalType
- || (data[1] & 0x80)) {
+ || (data[1] & 0x80)
+ || rtpTime != rtpTimeStartAt) {
ALOGV("Ignoring malformed FU buffer.");
// Delete the whole start of the FU.
@@ -324,9 +333,26 @@
totalSize += size - 2;
++totalCount;
- expectedSeqNo = expectedSeqNo + 1;
+ expectedSeqNo = buffer->int32Data() + 1;
if (data[1] & 0x40) {
+ if (pFrame) {
+ ALOGV("checking p-frame losses.. recvBufs %d diff %d drop? %d",
+ (uint32_t)totalCount, expectedSeqNo - startSeqNo,
+ totalCount < ((expectedSeqNo - startSeqNo) / 2));
+ if (totalCount < ((expectedSeqNo - startSeqNo) / 2)) {
+ ALOGI("drop p-frame. recvBufs %d lastSeq %d startSeq %d",
+ (uint32_t)totalCount, expectedSeqNo - 1, startSeqNo);
+
+ it = queue->begin();
+ for (size_t i = 0; i <= totalCount; ++i) {
+ it = queue->erase(it);
+ }
+ mNextExpectedSeqNo = expectedSeqNo;
+
+ return MALFORMED_PACKET;
+ }
+ }
// This is the last fragment.
complete = true;
break;
diff --git a/media/libstagefright/rtsp/ARTPSource.cpp b/media/libstagefright/rtsp/ARTPSource.cpp
index 202e5d6..db5b9a8 100644
--- a/media/libstagefright/rtsp/ARTPSource.cpp
+++ b/media/libstagefright/rtsp/ARTPSource.cpp
@@ -47,6 +47,7 @@
mFirstSysTime(0),
mClockRate(0),
mJbTime(300), // default jitter buffer time is 300ms.
+ mFirstSsrc(0),
mID(id),
mHighestSeqNumber(0),
mPrevExpected(0),
@@ -121,6 +122,9 @@
bool ARTPSource::queuePacket(const sp<ABuffer> &buffer) {
uint32_t seqNum = (uint32_t)buffer->int32Data();
+ int32_t ssrc = 0;
+ buffer->meta()->findInt32("ssrc", &ssrc);
+
if (mNumBuffersReceived++ == 0 && mFirstSysTime == 0) {
int32_t firstRtpTime;
CHECK(buffer->meta()->findInt32("rtp-time", &firstRtpTime));
@@ -128,13 +132,19 @@
mHighestSeqNumber = seqNum;
mBaseSeqNumber = seqNum;
mFirstRtpTime = firstRtpTime;
- ALOGV("first-rtp arrived: first-rtp-time=%d, sys-time=%lld, seq-num=%u",
- mFirstRtpTime, (long long)mFirstSysTime, mHighestSeqNumber);
+ mFirstSsrc = ssrc;
+ ALOGD("first-rtp arrived: first-rtp-time=%d, sys-time=%lld, seq-num=%u, ssrc=%d",
+ mFirstRtpTime, (long long)mFirstSysTime, mHighestSeqNumber, mFirstSsrc);
mClockRate = 90000;
mQueue.push_back(buffer);
return true;
}
+ if (mFirstSsrc != ssrc) {
+ ALOGW("Discarding a buffer due to unexpected ssrc");
+ return false;
+ }
+
// Only the lower 16-bit of the sequence numbers are transmitted,
// derive the high-order bits by choosing the candidate closest
// to the highest sequence number (extended to 32 bits) received so far.
diff --git a/media/libstagefright/rtsp/ARTPSource.h b/media/libstagefright/rtsp/ARTPSource.h
index 0d92720..8bbab7f 100644
--- a/media/libstagefright/rtsp/ARTPSource.h
+++ b/media/libstagefright/rtsp/ARTPSource.h
@@ -65,6 +65,7 @@
int32_t mClockRate;
uint32_t mJbTime;
+ int32_t mFirstSsrc;
private: