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> &notify)
-    : 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;