From bff07d0b22a5ee2d9f044f6cb5e4be1532017ab0 Mon Sep 17 00:00:00 2001 From: Andreas Huber Date: Tue, 12 Oct 2010 11:34:37 -0700 Subject: HTTP Live content that are tagged as complete are now seekable. Change-Id: I9d0d2f009f883e5baf3e9de8c5c0aa05760e4bde related-to-bug: 2368598 --- media/libstagefright/httplive/LiveSource.cpp | 70 +++++++++++++++++++++++++++- media/libstagefright/httplive/M3UParser.cpp | 9 +++- 2 files changed, 77 insertions(+), 2 deletions(-) (limited to 'media/libstagefright/httplive') diff --git a/media/libstagefright/httplive/LiveSource.cpp b/media/libstagefright/httplive/LiveSource.cpp index 943a0fc..4124571 100644 --- a/media/libstagefright/httplive/LiveSource.cpp +++ b/media/libstagefright/httplive/LiveSource.cpp @@ -31,6 +31,7 @@ namespace android { LiveSource::LiveSource(const char *url) : mMasterURL(url), mInitCheck(NO_INIT), + mDurationUs(-1), mPlaylistIndex(0), mLastFetchTimeUs(-1), mSource(new NuHTTPDataSource), @@ -40,6 +41,8 @@ LiveSource::LiveSource(const char *url) mPrevBandwidthIndex(-1) { if (switchToNext()) { mInitCheck = OK; + + determineSeekability(); } } @@ -139,7 +142,7 @@ bool LiveSource::loadPlaylist(bool fetchMaster) { } #else // Stay on the lowest bandwidth available. - size_t index = 0; // Lowest bandwidth stream + size_t index = mBandwidthItems.size() - 1; // Highest bandwidth stream #endif mURL = mBandwidthItems.editItemAt(index).mURI; @@ -336,4 +339,69 @@ status_t LiveSource::fetchM3U(const char *url, sp *out) { return OK; } +bool LiveSource::seekTo(int64_t seekTimeUs) { + LOGV("seek to %lld us", seekTimeUs); + + if (!mPlaylist->isComplete()) { + return false; + } + + int32_t targetDuration; + if (!mPlaylist->meta()->findInt32("target-duration", &targetDuration)) { + return false; + } + + int64_t seekTimeSecs = (seekTimeUs + 500000ll) / 1000000ll; + + int64_t index = seekTimeSecs / targetDuration; + + if (index < 0 || index >= mPlaylist->size()) { + return false; + } + + size_t newPlaylistIndex = mFirstItemSequenceNumber + index; + + if (newPlaylistIndex == mPlaylistIndex) { + return false; + } + + mPlaylistIndex = newPlaylistIndex; + + switchToNext(); + mOffsetBias = 0; + + LOGV("seeking to index %lld", index); + + return true; +} + +bool LiveSource::getDuration(int64_t *durationUs) const { + if (mDurationUs >= 0) { + *durationUs = mDurationUs; + return true; + } + + *durationUs = 0; + return false; +} + +bool LiveSource::isSeekable() const { + return mDurationUs >= 0; +} + +void LiveSource::determineSeekability() { + mDurationUs = -1; + + if (!mPlaylist->isComplete()) { + return; + } + + int32_t targetDuration; + if (!mPlaylist->meta()->findInt32("target-duration", &targetDuration)) { + return; + } + + mDurationUs = targetDuration * 1000000ll * mPlaylist->size(); +} + } // namespace android diff --git a/media/libstagefright/httplive/M3UParser.cpp b/media/libstagefright/httplive/M3UParser.cpp index 0d7daa9..a68c641 100644 --- a/media/libstagefright/httplive/M3UParser.cpp +++ b/media/libstagefright/httplive/M3UParser.cpp @@ -27,7 +27,8 @@ M3UParser::M3UParser( : mInitCheck(NO_INIT), mBaseURI(baseURI), mIsExtM3U(false), - mIsVariantPlaylist(false) { + mIsVariantPlaylist(false), + mIsComplete(false) { mInitCheck = parse(data, size); } @@ -46,6 +47,10 @@ bool M3UParser::isVariantPlaylist() const { return mIsVariantPlaylist; } +bool M3UParser::isComplete() const { + return mIsComplete; +} + sp M3UParser::meta() { return mMeta; } @@ -153,6 +158,8 @@ status_t M3UParser::parse(const void *_data, size_t size) { return ERROR_MALFORMED; } err = parseMetaData(line, &mMeta, "media-sequence"); + } else if (line.startsWith("#EXT-X-ENDLIST")) { + mIsComplete = true; } else if (line.startsWith("#EXTINF")) { if (mIsVariantPlaylist) { return ERROR_MALFORMED; -- cgit v1.1