Buffer at least 2 secs worth of data at startup of after a seek before

resuming starting RTSP playback.

Change-Id: I060c6c7fd627ab7ebd5c095ddcfdb4cc0f637aad
related-to-bug: 6364126
diff --git a/media/libmediaplayerservice/nuplayer/RTSPSource.cpp b/media/libmediaplayerservice/nuplayer/RTSPSource.cpp
index 4c65b65..a138be8 100644
--- a/media/libmediaplayerservice/nuplayer/RTSPSource.cpp
+++ b/media/libmediaplayerservice/nuplayer/RTSPSource.cpp
@@ -39,6 +39,7 @@
       mState(DISCONNECTED),
       mFinalResult(OK),
       mDisconnectReplyID(0),
+      mStartingUp(true),
       mSeekGeneration(0) {
     if (headers) {
         mExtraHeaders = *headers;
@@ -104,8 +105,45 @@
     return source->getFormat();
 }
 
+bool NuPlayer::RTSPSource::haveSufficientDataOnAllTracks() {
+    // We're going to buffer at least 2 secs worth data on all tracks before
+    // starting playback (both at startup and after a seek).
+
+    static const int64_t kMinDurationUs = 2000000ll;
+
+    status_t err;
+    int64_t durationUs;
+    if (mAudioTrack != NULL
+            && (durationUs = mAudioTrack->getBufferedDurationUs(&err))
+                    < kMinDurationUs
+            && err == OK) {
+        ALOGV("audio track doesn't have enough data yet. (%.2f secs buffered)",
+              durationUs / 1E6);
+        return false;
+    }
+
+    if (mVideoTrack != NULL
+            && (durationUs = mVideoTrack->getBufferedDurationUs(&err))
+                    < kMinDurationUs
+            && err == OK) {
+        ALOGV("video track doesn't have enough data yet. (%.2f secs buffered)",
+              durationUs / 1E6);
+        return false;
+    }
+
+    return true;
+}
+
 status_t NuPlayer::RTSPSource::dequeueAccessUnit(
         bool audio, sp<ABuffer> *accessUnit) {
+    if (mStartingUp) {
+        if (!haveSufficientDataOnAllTracks()) {
+            return -EWOULDBLOCK;
+        }
+
+        mStartingUp = false;
+    }
+
     sp<AnotherPacketSource> source = getSource(audio);
 
     if (source == NULL) {
@@ -209,6 +247,7 @@
         case MyHandler::kWhatSeekDone:
         {
             mState = CONNECTED;
+            mStartingUp = true;
             break;
         }
 
diff --git a/media/libmediaplayerservice/nuplayer/RTSPSource.h b/media/libmediaplayerservice/nuplayer/RTSPSource.h
index 59d06ad..e11e304 100644
--- a/media/libmediaplayerservice/nuplayer/RTSPSource.h
+++ b/media/libmediaplayerservice/nuplayer/RTSPSource.h
@@ -88,6 +88,7 @@
     State mState;
     status_t mFinalResult;
     uint32_t mDisconnectReplyID;
+    bool mStartingUp;
 
     sp<ALooper> mLooper;
     sp<AHandlerReflector<RTSPSource> > mReflector;
@@ -107,6 +108,8 @@
 
     void performSeek(int64_t seekTimeUs);
 
+    bool haveSufficientDataOnAllTracks();
+
     DISALLOW_EVIL_CONSTRUCTORS(RTSPSource);
 };
 
diff --git a/media/libstagefright/mpeg2ts/AnotherPacketSource.cpp b/media/libstagefright/mpeg2ts/AnotherPacketSource.cpp
index d708ba6..a605a05 100644
--- a/media/libstagefright/mpeg2ts/AnotherPacketSource.cpp
+++ b/media/libstagefright/mpeg2ts/AnotherPacketSource.cpp
@@ -198,6 +198,40 @@
     return false;
 }
 
+int64_t AnotherPacketSource::getBufferedDurationUs(status_t *finalResult) {
+    Mutex::Autolock autoLock(mLock);
+
+    *finalResult = mEOSResult;
+
+    if (mBuffers.empty()) {
+        return 0;
+    }
+
+    int64_t time1 = -1;
+    int64_t time2 = -1;
+
+    List<sp<ABuffer> >::iterator it = mBuffers.begin();
+    while (it != mBuffers.end()) {
+        const sp<ABuffer> &buffer = *it;
+
+        int64_t timeUs;
+        if (buffer->meta()->findInt64("timeUs", &timeUs)) {
+            if (time1 < 0) {
+                time1 = timeUs;
+            }
+
+            time2 = timeUs;
+        } else {
+            // This is a discontinuity, reset everything.
+            time1 = time2 = -1;
+        }
+
+        ++it;
+    }
+
+    return time2 - time1;
+}
+
 status_t AnotherPacketSource::nextBufferTime(int64_t *timeUs) {
     *timeUs = 0;
 
diff --git a/media/libstagefright/mpeg2ts/AnotherPacketSource.h b/media/libstagefright/mpeg2ts/AnotherPacketSource.h
index c99f7f2..d685b98 100644
--- a/media/libstagefright/mpeg2ts/AnotherPacketSource.h
+++ b/media/libstagefright/mpeg2ts/AnotherPacketSource.h
@@ -43,6 +43,10 @@
 
     bool hasBufferAvailable(status_t *finalResult);
 
+    // Returns the difference between the last and the first queued
+    // presentation timestamps since the last discontinuity (if any).
+    int64_t getBufferedDurationUs(status_t *finalResult);
+
     status_t nextBufferTime(int64_t *timeUs);
 
     void queueAccessUnit(const sp<ABuffer> &buffer);