Fix Bitreader "putBits" implementation, make sure we emulate timestamps

if we don't receive npt time mapping from the rtsp server (i.e. live stream)

Change-Id: I5147d665bd90c9a303ad6ffdafbf770f930f917c
related-to-bug: 5660357
diff --git a/media/libmediaplayerservice/nuplayer/RTSPSource.cpp b/media/libmediaplayerservice/nuplayer/RTSPSource.cpp
index e72adc4..6e6d4be 100644
--- a/media/libmediaplayerservice/nuplayer/RTSPSource.cpp
+++ b/media/libmediaplayerservice/nuplayer/RTSPSource.cpp
@@ -208,21 +208,32 @@
                 break;
             }
 
-            const TrackInfo &info = mTracks.editItemAt(trackIndex);
-            sp<AnotherPacketSource> source = info.mSource;
+            TrackInfo *info = &mTracks.editItemAt(trackIndex);
+
+            sp<AnotherPacketSource> source = info->mSource;
             if (source != NULL) {
-#if 1
                 uint32_t rtpTime;
                 CHECK(accessUnit->meta()->findInt32("rtp-time", (int32_t *)&rtpTime));
 
+                if (!info->mNPTMappingValid) {
+                    // This is a live stream, we didn't receive any normal
+                    // playtime mapping. Assume the first packets correspond
+                    // to time 0.
+
+                    LOGV("This is a live stream, assuming time = 0");
+
+                    info->mRTPTime = rtpTime;
+                    info->mNormalPlaytimeUs = 0ll;
+                    info->mNPTMappingValid = true;
+                }
+
                 int64_t nptUs =
-                    ((double)rtpTime - (double)info.mRTPTime)
-                        / info.mTimeScale
+                    ((double)rtpTime - (double)info->mRTPTime)
+                        / info->mTimeScale
                         * 1000000ll
-                        + info.mNormalPlaytimeUs;
+                        + info->mNormalPlaytimeUs;
 
                 accessUnit->meta()->setInt64("timeUs", nptUs);
-#endif
 
                 source->queueAccessUnit(accessUnit);
             }
@@ -278,6 +289,7 @@
             TrackInfo *info = &mTracks.editItemAt(trackIndex);
             info->mRTPTime = rtpTime;
             info->mNormalPlaytimeUs = nptUs;
+            info->mNPTMappingValid = true;
             break;
         }
 
@@ -305,6 +317,7 @@
         info.mTimeScale = timeScale;
         info.mRTPTime = 0;
         info.mNormalPlaytimeUs = 0ll;
+        info.mNPTMappingValid = false;
 
         if ((isAudio && mAudioTrack == NULL)
                 || (isVideo && mVideoTrack == NULL)) {
diff --git a/media/libmediaplayerservice/nuplayer/RTSPSource.h b/media/libmediaplayerservice/nuplayer/RTSPSource.h
index 66eab72..a401caa 100644
--- a/media/libmediaplayerservice/nuplayer/RTSPSource.h
+++ b/media/libmediaplayerservice/nuplayer/RTSPSource.h
@@ -76,6 +76,7 @@
         int32_t mTimeScale;
         uint32_t mRTPTime;
         int64_t mNormalPlaytimeUs;
+        bool mNPTMappingValid;
     };
 
     AString mURL;
diff --git a/media/libstagefright/foundation/ABitReader.cpp b/media/libstagefright/foundation/ABitReader.cpp
index f07dd4f..5499c32 100644
--- a/media/libstagefright/foundation/ABitReader.cpp
+++ b/media/libstagefright/foundation/ABitReader.cpp
@@ -79,7 +79,13 @@
 }
 
 void ABitReader::putBits(uint32_t x, size_t n) {
-    CHECK_LE(mNumBitsLeft + n, 32u);
+    CHECK_LE(n, 32u);
+
+    while (mNumBitsLeft + n > 32) {
+        mNumBitsLeft -= 8;
+        --mData;
+        ++mSize;
+    }
 
     mReservoir = (mReservoir >> n) | (x << (32 - n));
     mNumBitsLeft += n;
diff --git a/media/libstagefright/rtsp/MyHandler.h b/media/libstagefright/rtsp/MyHandler.h
index 794c60b..5a95f9c 100644
--- a/media/libstagefright/rtsp/MyHandler.h
+++ b/media/libstagefright/rtsp/MyHandler.h
@@ -1100,6 +1100,8 @@
         float npt1, npt2;
         if (!ASessionDescription::parseNTPRange(val.c_str(), &npt1, &npt2)) {
             // This is a live stream and therefore not seekable.
+
+            LOGI("This is a live stream");
             return;
         }
 
@@ -1386,12 +1388,14 @@
             msg->setInt32("what", kWhatConnected);
             msg->post();
 
-            for (size_t i = 0; i < mTracks.size(); ++i) {
-                TrackInfo *info = &mTracks.editItemAt(i);
+            if (mSeekable) {
+                for (size_t i = 0; i < mTracks.size(); ++i) {
+                    TrackInfo *info = &mTracks.editItemAt(i);
 
-                postNormalPlayTimeMapping(
-                        i,
-                        info->mNormalPlayTimeRTP, info->mNormalPlayTimeUs);
+                    postNormalPlayTimeMapping(
+                            i,
+                            info->mNormalPlayTimeRTP, info->mNormalPlayTimeUs);
+                }
             }
 
             mFirstAccessUnit = false;