diff options
author | Robert Shih <robertshih@google.com> | 2014-08-29 19:01:29 -0700 |
---|---|---|
committer | Robert Shih <robertshih@google.com> | 2014-09-15 15:49:30 -0700 |
commit | f78f62bd6b0a99747db53828d281a50b9270a646 (patch) | |
tree | e106a91ffab628cf27a8965ecf31b3dd74e959d1 /media | |
parent | cb16968f593e4d58857c693c8ec6f2d2337f5512 (diff) | |
download | frameworks_av-f78f62bd6b0a99747db53828d281a50b9270a646.zip frameworks_av-f78f62bd6b0a99747db53828d281a50b9270a646.tar.gz frameworks_av-f78f62bd6b0a99747db53828d281a50b9270a646.tar.bz2 |
PlaylistFetcher: find the correct sequence number to start fetching
- skip over bad segemnts
- if we skipped too far into the future when adapting in live streams,
adjust back
Bug: 17141635
Bug: 17416657
Change-Id: I0877ceaf6e69cab751bf9e92579071f9e61643eb
Diffstat (limited to 'media')
-rw-r--r-- | media/libstagefright/httplive/PlaylistFetcher.cpp | 153 | ||||
-rw-r--r-- | media/libstagefright/httplive/PlaylistFetcher.h | 5 |
2 files changed, 107 insertions, 51 deletions
diff --git a/media/libstagefright/httplive/PlaylistFetcher.cpp b/media/libstagefright/httplive/PlaylistFetcher.cpp index 82a4c39..8ffe79e 100644 --- a/media/libstagefright/httplive/PlaylistFetcher.cpp +++ b/media/libstagefright/httplive/PlaylistFetcher.cpp @@ -951,7 +951,7 @@ void PlaylistFetcher::onDownloadNext() { } if (err == -EAGAIN) { - // starting sequence number too low + // starting sequence number too low/high mTSParser.clear(); postMonitorQueue(); return; @@ -1023,12 +1023,39 @@ void PlaylistFetcher::onDownloadNext() { return; } - mStartup = false; ++mSeqNumber; postMonitorQueue(); } +int32_t PlaylistFetcher::getSeqNumberWithAnchorTime(int64_t anchorTimeUs) const { + int32_t firstSeqNumberInPlaylist, lastSeqNumberInPlaylist; + if (mPlaylist->meta() == NULL + || !mPlaylist->meta()->findInt32("media-sequence", &firstSeqNumberInPlaylist)) { + firstSeqNumberInPlaylist = 0; + } + lastSeqNumberInPlaylist = firstSeqNumberInPlaylist + mPlaylist->size() - 1; + + int32_t index = mSeqNumber - firstSeqNumberInPlaylist - 1; + while (index >= 0 && anchorTimeUs > mStartTimeUs) { + sp<AMessage> itemMeta; + CHECK(mPlaylist->itemAt(index, NULL /* uri */, &itemMeta)); + + int64_t itemDurationUs; + CHECK(itemMeta->findInt64("durationUs", &itemDurationUs)); + + anchorTimeUs -= itemDurationUs; + --index; + } + + int32_t newSeqNumber = firstSeqNumberInPlaylist + index + 1; + if (newSeqNumber <= lastSeqNumberInPlaylist) { + return newSeqNumber; + } else { + return lastSeqNumberInPlaylist; + } +} + int32_t PlaylistFetcher::getSeqNumberForDiscontinuity(size_t discontinuitySeq) const { int32_t firstSeqNumberInPlaylist; if (mPlaylist->meta() == NULL @@ -1198,60 +1225,84 @@ status_t PlaylistFetcher::extractAndQueueAccessUnitsFromTs(const sp<ABuffer> &bu if (timeUs < 0) { timeUs = 0; } - } else if (mAdaptive && timeUs > mStartTimeUs) { - int32_t seq; - if (mStartTimeUsNotify != NULL - && !mStartTimeUsNotify->findInt32("discontinuitySeq", &seq)) { - mStartTimeUsNotify->setInt32("discontinuitySeq", mDiscontinuitySeq); + } + + if (timeUs < mStartTimeUs) { + // buffer up to the closest preceding IDR frame + ALOGV("timeUs %" PRId64 " us < mStartTimeUs %" PRId64 " us", + timeUs, mStartTimeUs); + const char *mime; + sp<MetaData> format = source->getFormat(); + bool isAvc = false; + if (format != NULL && format->findCString(kKeyMIMEType, &mime) + && !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) { + isAvc = true; + } + if (isAvc && IsIDR(accessUnit)) { + mVideoBuffer->clear(); } - int64_t startTimeUs; - if (mStartTimeUsNotify != NULL - && !mStartTimeUsNotify->findInt64(key, &startTimeUs)) { - mStartTimeUsNotify->setInt64(key, timeUs); - - uint32_t streamMask = 0; - mStartTimeUsNotify->findInt32("streamMask", (int32_t *) &streamMask); - streamMask |= mPacketSources.keyAt(i); - mStartTimeUsNotify->setInt32("streamMask", streamMask); - - if (streamMask == mStreamTypeMask) { - mStartTimeUsNotify->post(); - mStartTimeUsNotify.clear(); - } + if (isAvc) { + mVideoBuffer->queueAccessUnit(accessUnit); } + + continue; } + } - if (timeUs < mStartTimeUs) { - if (mAdaptive) { - int32_t targetDuration; - mPlaylist->meta()->findInt32("target-duration", &targetDuration); - int32_t incr = (mStartTimeUs - timeUs) / 1000000 / targetDuration; - if (incr == 0) { - // increment mSeqNumber by at least one - incr = 1; - } - mSeqNumber += incr; - err = -EAGAIN; - break; + CHECK(accessUnit->meta()->findInt64("timeUs", &timeUs)); + if (mStartTimeUsNotify != NULL && timeUs > mStartTimeUs) { + + int32_t targetDurationSecs; + CHECK(mPlaylist->meta()->findInt32("target-duration", &targetDurationSecs)); + int64_t targetDurationUs = targetDurationSecs * 1000000ll; + // mStartup + // mStartup is true until we have queued a packet for all the streams + // we are fetching. We queue packets whose timestamps are greater than + // mStartTimeUs. + // mSegmentStartTimeUs >= 0 + // mSegmentStartTimeUs is non-negative when adapting or switching tracks + // timeUs - mStartTimeUs > targetDurationUs: + // This and the 2 above conditions should only happen when adapting in a live + // stream; the old fetcher has already fetched to mStartTimeUs; the new fetcher + // would start fetching after timeUs, which should be greater than mStartTimeUs; + // the old fetcher would then continue fetching data until timeUs. We don't want + // timeUs to be too far ahead of mStartTimeUs because we want the old fetcher to + // stop as early as possible. The definition of being "too far ahead" is + // arbitrary; here we use targetDurationUs as threshold. + if (mStartup && mSegmentStartTimeUs >= 0 + && timeUs - mStartTimeUs > targetDurationUs) { + // we just guessed a starting timestamp that is too high when adapting in a + // live stream; re-adjust based on the actual timestamp extracted from the + // media segment; if we didn't move backward after the re-adjustment + // (newSeqNumber), start at least 1 segment prior. + int32_t newSeqNumber = getSeqNumberWithAnchorTime(timeUs); + if (newSeqNumber >= mSeqNumber) { + --mSeqNumber; } else { - // buffer up to the closest preceding IDR frame - ALOGV("timeUs %" PRId64 " us < mStartTimeUs %" PRId64 " us", - timeUs, mStartTimeUs); - const char *mime; - sp<MetaData> format = source->getFormat(); - bool isAvc = false; - if (format != NULL && format->findCString(kKeyMIMEType, &mime) - && !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) { - isAvc = true; - } - if (isAvc && IsIDR(accessUnit)) { - mVideoBuffer->clear(); - } - if (isAvc) { - mVideoBuffer->queueAccessUnit(accessUnit); - } - - continue; + mSeqNumber = newSeqNumber; + } + mStartTimeUsNotify = mNotify->dup(); + mStartTimeUsNotify->setInt32("what", kWhatStartedAt); + return -EAGAIN; + } + + int32_t seq; + if (!mStartTimeUsNotify->findInt32("discontinuitySeq", &seq)) { + mStartTimeUsNotify->setInt32("discontinuitySeq", mDiscontinuitySeq); + } + int64_t startTimeUs; + if (!mStartTimeUsNotify->findInt64(key, &startTimeUs)) { + mStartTimeUsNotify->setInt64(key, timeUs); + + uint32_t streamMask = 0; + mStartTimeUsNotify->findInt32("streamMask", (int32_t *) &streamMask); + streamMask |= mPacketSources.keyAt(i); + mStartTimeUsNotify->setInt32("streamMask", streamMask); + + if (streamMask == mStreamTypeMask) { + mStartup = false; + mStartTimeUsNotify->post(); + mStartTimeUsNotify.clear(); } } } diff --git a/media/libstagefright/httplive/PlaylistFetcher.h b/media/libstagefright/httplive/PlaylistFetcher.h index daefb26..4ba37fa 100644 --- a/media/libstagefright/httplive/PlaylistFetcher.h +++ b/media/libstagefright/httplive/PlaylistFetcher.h @@ -104,7 +104,12 @@ private: uint32_t mStreamTypeMask; int64_t mStartTimeUs; + + // Start time relative to the beginning of the first segment in the initial + // playlist. It's value is initialized to a non-negative value only when we are + // adapting or switching tracks. int64_t mSegmentStartTimeUs; + ssize_t mDiscontinuitySeq; bool mStartTimeUsRelative; sp<AMessage> mStopParams; // message containing the latest timestamps we should fetch. |