OSDN Git Service

HLS: fix freezes when toggling between a/v streams
authorRobert Shih <robertshih@google.com>
Sat, 30 Aug 2014 01:22:44 +0000 (18:22 -0700)
committerRobert Shih <robertshih@google.com>
Tue, 16 Sep 2014 01:41:36 +0000 (01:41 +0000)
Bug: 17412740
Change-Id: Iacaf2fa1d20584056375803e1782ad6761c56fc5

media/libstagefright/httplive/LiveSession.cpp
media/libstagefright/httplive/PlaylistFetcher.cpp
media/libstagefright/httplive/PlaylistFetcher.h

index 3720085..7786c27 100644 (file)
@@ -158,9 +158,16 @@ status_t LiveSession::dequeueAccessUnit(
 
     // wait for counterpart
     sp<AnotherPacketSource> otherSource;
-    if (stream == STREAMTYPE_AUDIO && (mStreamMask & STREAMTYPE_VIDEO)) {
+    uint32_t mask = mNewStreamMask & mStreamMask;
+    uint32_t fetchersMask  = 0;
+    for (size_t i = 0; i < mFetcherInfos.size(); ++i) {
+        uint32_t fetcherMask = mFetcherInfos.valueAt(i).mFetcher->getStreamTypeMask();
+        fetchersMask |= fetcherMask;
+    }
+    mask &= fetchersMask;
+    if (stream == STREAMTYPE_AUDIO && (mask & STREAMTYPE_VIDEO)) {
         otherSource = mPacketSources.valueFor(STREAMTYPE_VIDEO);
-    } else if (stream == STREAMTYPE_VIDEO && (mStreamMask & STREAMTYPE_AUDIO)) {
+    } else if (stream == STREAMTYPE_VIDEO && (mask & STREAMTYPE_AUDIO)) {
         otherSource = mPacketSources.valueFor(STREAMTYPE_AUDIO);
     }
     if (otherSource != NULL && !otherSource->hasBufferAvailable(&finalResult)) {
index 1166762..f78f8b4 100644 (file)
@@ -1009,7 +1009,16 @@ void PlaylistFetcher::onDownloadNext() {
 
     // bulk extract non-ts files
     if (tsBuffer == NULL) {
-      err = extractAndQueueAccessUnits(buffer, itemMeta);
+        err = extractAndQueueAccessUnits(buffer, itemMeta);
+        if (err == -EAGAIN) {
+            // starting sequence number too low/high
+            postMonitorQueue();
+            return;
+        } else if (err == ERROR_OUT_OF_RANGE) {
+            // reached stopping point
+            stopAsync(/* clear = */false);
+            return;
+        }
     }
 
     if (err != OK) {
@@ -1552,14 +1561,52 @@ status_t PlaylistFetcher::extractAndQueueAccessUnits(
             if (startTimeUs < mStartTimeUs) {
                 continue;
             }
+
+            if (mStartTimeUsNotify != NULL) {
+                int32_t targetDurationSecs;
+                CHECK(mPlaylist->meta()->findInt32("target-duration", &targetDurationSecs));
+                int64_t targetDurationUs = targetDurationSecs * 1000000ll;
+
+                // Duplicated logic from how we handle .ts playlists.
+                if (mStartup && mSegmentStartTimeUs >= 0
+                        && timeUs - mStartTimeUs > targetDurationUs) {
+                    int32_t newSeqNumber = getSeqNumberWithAnchorTime(timeUs);
+                    if (newSeqNumber >= mSeqNumber) {
+                        --mSeqNumber;
+                    } else {
+                        mSeqNumber = newSeqNumber;
+                    }
+                    return -EAGAIN;
+                }
+
+                mStartTimeUsNotify->setInt64("timeUsAudio", timeUs);
+                mStartTimeUsNotify->setInt32("discontinuitySeq", mDiscontinuitySeq);
+                mStartTimeUsNotify->setInt32("streamMask", LiveSession::STREAMTYPE_AUDIO);
+                mStartTimeUsNotify->post();
+                mStartTimeUsNotify.clear();
+            }
+        }
+
+        if (mStopParams != NULL) {
+            // Queue discontinuity in original stream.
+            int32_t discontinuitySeq;
+            int64_t stopTimeUs;
+            if (!mStopParams->findInt32("discontinuitySeq", &discontinuitySeq)
+                    || discontinuitySeq > mDiscontinuitySeq
+                    || !mStopParams->findInt64("timeUsAudio", &stopTimeUs)
+                    || (discontinuitySeq == mDiscontinuitySeq && unitTimeUs >= stopTimeUs)) {
+                packetSource->queueAccessUnit(mSession->createFormatChangeBuffer());
+                mStreamTypeMask = 0;
+                mPacketSources.clear();
+                return ERROR_OUT_OF_RANGE;
+            }
         }
 
         sp<ABuffer> unit = new ABuffer(aac_frame_length);
         memcpy(unit->data(), adtsHeader, aac_frame_length);
 
         unit->meta()->setInt64("timeUs", unitTimeUs);
-        unit->meta()->setInt64("segmentStartTimeUs", getSegmentStartTimeUs(mSeqNumber));
-        unit->meta()->setInt32("discontinuitySeq", mDiscontinuitySeq);
+        setAccessUnitProperties(unit, packetSource);
         packetSource->queueAccessUnit(unit);
     }
 
index 4ba37fa..4b09df1 100644 (file)
@@ -69,6 +69,10 @@ struct PlaylistFetcher : public AHandler {
 
     void resumeUntilAsync(const sp<AMessage> &params);
 
+    uint32_t getStreamTypeMask() const {
+        return mStreamTypeMask;
+    }
+
 protected:
     virtual ~PlaylistFetcher();
     virtual void onMessageReceived(const sp<AMessage> &msg);