diff options
author | Robert Shih <robertshih@google.com> | 2014-09-15 23:56:04 +0000 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2014-09-15 23:56:05 +0000 |
commit | 60a89850fdbb71fd48bdef3712b340cc2fa5a722 (patch) | |
tree | 8fb5057cda5a78d35b156fd6db71d187a94e1773 /media/libstagefright/httplive | |
parent | 73721170e1a3c9751ef00fd53b6b5eec5f2c5c81 (diff) | |
parent | f78f62bd6b0a99747db53828d281a50b9270a646 (diff) | |
download | frameworks_av-60a89850fdbb71fd48bdef3712b340cc2fa5a722.zip frameworks_av-60a89850fdbb71fd48bdef3712b340cc2fa5a722.tar.gz frameworks_av-60a89850fdbb71fd48bdef3712b340cc2fa5a722.tar.bz2 |
Merge "PlaylistFetcher: find the correct sequence number to start fetching" into lmp-dev
Diffstat (limited to 'media/libstagefright/httplive')
-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 3ef0f06..1166762 100644 --- a/media/libstagefright/httplive/PlaylistFetcher.cpp +++ b/media/libstagefright/httplive/PlaylistFetcher.cpp @@ -945,7 +945,7 @@ void PlaylistFetcher::onDownloadNext() { } if (err == -EAGAIN) { - // starting sequence number too low + // starting sequence number too low/high mTSParser.clear(); postMonitorQueue(); return; @@ -1017,12 +1017,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 @@ -1192,60 +1219,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. |