VT: ARTPSource: Jitter buffer implementation.
* AAVCAssembler(H264) holds media buffers and
it will not be played out till jitter buffer time expired.
- Jitter buffer time : 200ms
- Applied module : AAVCAssmbler(H264).
* Too late packets will be treated as lost ones.
And be thrown away from buffers.
This makes Assembler more flexable for packet missing condition.
Bug: 121230209
Change-Id: I6da96e7af01c640e501035d2583d7d958f30539e
Signed-off-by: Byeongjo Park <bjo.park@samsung.com>
Signed-off-by: Kim Sungyeon <sy85.kim@samsung.com>
diff --git a/media/libstagefright/rtsp/AAVCAssembler.cpp b/media/libstagefright/rtsp/AAVCAssembler.cpp
index 4bc67e8..13d74e4 100644
--- a/media/libstagefright/rtsp/AAVCAssembler.cpp
+++ b/media/libstagefright/rtsp/AAVCAssembler.cpp
@@ -51,7 +51,52 @@
return NOT_ENOUGH_DATA;
}
+ sp<ABuffer> buffer = *queue->begin();
+ int32_t rtpTime;
+ CHECK(buffer->meta()->findInt32("rtp-time", &rtpTime));
+ int64_t startTime = source->mFirstSysTime / 1000;
+ int64_t nowTime = ALooper::GetNowUs() / 1000;
+ int64_t playedTime = nowTime - startTime;
+ int32_t playedTimeRtp = source->mFirstRtpTime +
+ (((uint32_t)playedTime) * (source->mClockRate / 1000));
+ const int32_t jitterTime = source->mClockRate / 5; // 200ms
+ int32_t expiredTimeInJb = rtpTime + jitterTime;
+ bool isExpired = expiredTimeInJb <= (playedTimeRtp);
+ bool isTooLate = expiredTimeInJb < (playedTimeRtp - jitterTime);
+ ALOGV("start=%lld, now=%lld, played=%lld", (long long)startTime,
+ (long long)nowTime, (long long)playedTime);
+ ALOGV("rtp-time(JB)=%d, played-rtp-time(JB)=%d, expired-rtp-time(JB)=%d isExpired=%d",
+ rtpTime, playedTimeRtp, expiredTimeInJb, isExpired);
+
+ if (!isExpired) {
+ ALOGV("buffering in jitter buffer.");
+ return NOT_ENOUGH_DATA;
+ }
+
+ if (isTooLate) {
+ ALOGV("buffer arrived too lately..");
+ ALOGW("start=%lld, now=%lld, played=%lld", (long long)startTime,
+ (long long)nowTime, (long long)playedTime);
+ ALOGW("rtp-time(JB)=%d, plyed-rtp-time(JB)=%d, exp-rtp-time(JB)=%d diff=%lld isExpired=%d",
+ rtpTime, playedTimeRtp, expiredTimeInJb,
+ ((long long)playedTimeRtp) - expiredTimeInJb, isExpired);
+ ALOGW("expected Seq. NO =%d", buffer->int32Data());
+
+ List<sp<ABuffer> >::iterator it = queue->begin();
+ while (it != queue->end()) {
+ CHECK((*it)->meta()->findInt32("rtp-time", &rtpTime));
+ if (rtpTime + jitterTime >= playedTimeRtp) {
+ mNextExpectedSeqNo = (*it)->int32Data();
+ break;
+ }
+ it++;
+ }
+ source->noticeAbandonBuffer();
+ }
+
if (mNextExpectedSeqNoValid) {
+ int32_t size = queue->size();
+ int32_t cnt = 0;
List<sp<ABuffer> >::iterator it = queue->begin();
while (it != queue->end()) {
if ((uint32_t)(*it)->int32Data() >= mNextExpectedSeqNo) {
@@ -59,15 +104,18 @@
}
it = queue->erase(it);
+ cnt++;
}
+ if (cnt > 0) {
+ source->noticeAbandonBuffer(cnt);
+ ALOGW("delete %d of %d buffers", cnt, size);
+ }
if (queue->empty()) {
return NOT_ENOUGH_DATA;
}
}
- sp<ABuffer> buffer = *queue->begin();
-
if (!mNextExpectedSeqNoValid) {
mNextExpectedSeqNoValid = true;
mNextExpectedSeqNo = (uint32_t)buffer->int32Data();
diff --git a/media/libstagefright/rtsp/ARTPSource.cpp b/media/libstagefright/rtsp/ARTPSource.cpp
index 4afa6f4..f17c9e7 100644
--- a/media/libstagefright/rtsp/ARTPSource.cpp
+++ b/media/libstagefright/rtsp/ARTPSource.cpp
@@ -41,7 +41,11 @@
uint32_t id,
const sp<ASessionDescription> &sessionDesc, size_t index,
const sp<AMessage> ¬ify)
- : mID(id),
+ : mFirstSeqNumber(0),
+ mFirstRtpTime(0),
+ mFirstSysTime(0),
+ mClockRate(0),
+ mID(id),
mHighestSeqNumber(0),
mPrevExpected(0),
mBaseSeqNumber(0),
@@ -108,9 +112,16 @@
bool ARTPSource::queuePacket(const sp<ABuffer> &buffer) {
uint32_t seqNum = (uint32_t)buffer->int32Data();
- if (mNumBuffersReceived++ == 0) {
+ if (mNumBuffersReceived++ == 0 && mFirstSysTime == 0) {
+ int32_t firstRtpTime;
+ CHECK(buffer->meta()->findInt32("rtp-time", &firstRtpTime));
+ mFirstSysTime = ALooper::GetNowUs();
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);
+ mClockRate = 90000;
mQueue.push_back(buffer);
return true;
}
@@ -300,6 +311,9 @@
buffer->setRange(buffer->offset(), buffer->size() + 32);
}
+void ARTPSource::noticeAbandonBuffer(int cnt) {
+ mNumBuffersReceived -= cnt;
+}
} // namespace android
diff --git a/media/libstagefright/rtsp/ARTPSource.h b/media/libstagefright/rtsp/ARTPSource.h
index f44e83f..12de18d 100644
--- a/media/libstagefright/rtsp/ARTPSource.h
+++ b/media/libstagefright/rtsp/ARTPSource.h
@@ -46,6 +46,13 @@
void addReceiverReport(const sp<ABuffer> &buffer);
void addFIR(const sp<ABuffer> &buffer);
+ void noticeAbandonBuffer(int cnt=1);
+
+ int32_t mFirstSeqNumber;
+ int32_t mFirstRtpTime;
+ int64_t mFirstSysTime;
+ int32_t mClockRate;
+
private:
uint32_t mID;
uint32_t mHighestSeqNumber;