diff options
author | Andreas Huber <andih@google.com> | 2012-11-27 15:02:53 -0800 |
---|---|---|
committer | Andreas Huber <andih@google.com> | 2012-11-27 15:50:08 -0800 |
commit | b7c8e91880463ff4981e3e53e98e45d68e2fe374 (patch) | |
tree | 3de921dd21aa2f4899487d3c56e4bfd28f4c004f /media/libstagefright/httplive | |
parent | 41829f30e60cdb7ae8eb1f0266834d245164f70e (diff) | |
download | frameworks_av-b7c8e91880463ff4981e3e53e98e45d68e2fe374.zip frameworks_av-b7c8e91880463ff4981e3e53e98e45d68e2fe374.tar.gz frameworks_av-b7c8e91880463ff4981e3e53e98e45d68e2fe374.tar.bz2 |
Add support for HLS playlists of type 'event'.
related-to-bug: 6870049
Squashed commit of the following:
commit eee2f3ba6bb7335f4e285632726db85645669929
Author: Andreas Huber <andih@google.com>
Date: Tue Nov 27 15:02:01 2012 -0800
Make everything a lot less verbose by default.
Change-Id: I884d7a7901aa1e7d4ff590f065ca57a79d2af8b3
commit 6bbdb837ed5bd88008e45efb8faf595e4051ba26
Author: Andreas Huber <andih@google.com>
Date: Tue Nov 27 14:34:46 2012 -0800
HLS now properly signals media time changes at discontinuities including
the start of playback (which may not necessarily be at time 0 if the playlist
is of type 'event' and hasn't completed yet).
Change-Id: I5ab747d024f9b8d0df72a4e06a12ebb29f62802e
commit 1555589832b1878a144a976a643e1af4d61f877c
Author: Andreas Huber <andih@google.com>
Date: Tue Nov 27 14:32:28 2012 -0800
As part of a time discontinuity, clients of IStreamListener can now
signal the corresponding media time after the discontinuity, i.e. the first PTS
timestamp following the discontinuity will be considered equivalent to the
specified media time and media buffers timestamped accordingly.
Change-Id: Id7db7679b7faa6efd6270620ff52e34e884f3e92
commit 5c24c605c073a11c426d025b1e7478fc1ad8365a
Author: Andreas Huber <andih@google.com>
Date: Tue Nov 27 13:00:56 2012 -0800
NuPlayer sources now expose flags() and can announce
that duration may change (increase) dynamically, in which case duration
will be polled at 1 second intervals and communicated to the upper layers.
Change-Id: I45102909b7a19eed0dda576747e3814d742a0eea
commit ecb71de8e281e61971a2cd73e7161a97540bc357
Author: Andreas Huber <andih@google.com>
Date: Tue Nov 27 12:57:47 2012 -0800
Stop caching duration in MediaPlayer, duration could increase dynamically.
Change-Id: I7bb2f16c0abe49debdf45c776d2266aa069d7791
commit 544aec5823e6d7a3e97e15b6b23546616bcd343e
Author: Andreas Huber <andih@google.com>
Date: Tue Nov 27 08:46:28 2012 -0800
An attempt to add support for "event" style HLS playlists.
Change-Id: I3dfb2e801ecaff8f5d8bdb3a4fca1b18aeeb2c60
Change-Id: I48cf7f65a654d33f2f49ded74f8be22aed9e3b98
Diffstat (limited to 'media/libstagefright/httplive')
-rw-r--r-- | media/libstagefright/httplive/LiveSession.cpp | 92 | ||||
-rw-r--r-- | media/libstagefright/httplive/M3UParser.cpp | 9 |
2 files changed, 88 insertions, 13 deletions
diff --git a/media/libstagefright/httplive/LiveSession.cpp b/media/libstagefright/httplive/LiveSession.cpp index 93d6429..733753b 100644 --- a/media/libstagefright/httplive/LiveSession.cpp +++ b/media/libstagefright/httplive/LiveSession.cpp @@ -55,7 +55,9 @@ LiveSession::LiveSession(uint32_t flags, bool uidValid, uid_t uid) mSeqNumber(-1), mSeekTimeUs(-1), mNumRetries(0), + mStartOfPlayback(true), mDurationUs(-1), + mDurationFixed(false), mSeekDone(false), mDisconnectPending(false), mMonitorQueueGeneration(0), @@ -311,6 +313,8 @@ status_t LiveSession::fetchFile( } sp<M3UParser> LiveSession::fetchPlaylist(const char *url, bool *unchanged) { + ALOGV("fetchPlaylist '%s'", url); + *unchanged = false; sp<ABuffer> buffer; @@ -364,6 +368,37 @@ sp<M3UParser> LiveSession::fetchPlaylist(const char *url, bool *unchanged) { return playlist; } +int64_t LiveSession::getSegmentStartTimeUs(int32_t seqNumber) const { + CHECK(mPlaylist != NULL); + + int32_t firstSeqNumberInPlaylist; + if (mPlaylist->meta() == NULL || !mPlaylist->meta()->findInt32( + "media-sequence", &firstSeqNumberInPlaylist)) { + firstSeqNumberInPlaylist = 0; + } + + int32_t lastSeqNumberInPlaylist = + firstSeqNumberInPlaylist + (int32_t)mPlaylist->size() - 1; + + CHECK_GE(seqNumber, firstSeqNumberInPlaylist); + CHECK_LE(seqNumber, lastSeqNumberInPlaylist); + + int64_t segmentStartUs = 0ll; + for (int32_t index = 0; + index < seqNumber - firstSeqNumberInPlaylist; ++index) { + sp<AMessage> itemMeta; + CHECK(mPlaylist->itemAt( + index, NULL /* uri */, &itemMeta)); + + int64_t itemDurationUs; + CHECK(itemMeta->findInt64("durationUs", &itemDurationUs)); + + segmentStartUs += itemDurationUs; + } + + return segmentStartUs; +} + static double uniformRand() { return (double)rand() / RAND_MAX; } @@ -512,8 +547,6 @@ rinse_repeat: url = mMasterURL; } - bool firstTime = (mPlaylist == NULL); - if ((ssize_t)bandwidthIndex != mPrevBandwidthIndex) { // If we switch bandwidths, do not pay any heed to whether // playlists changed since the last time... @@ -535,11 +568,12 @@ rinse_repeat: mPlaylist = playlist; } - if (firstTime) { + if (!mDurationFixed) { Mutex::Autolock autoLock(mLock); - if (!mPlaylist->isComplete()) { + if (!mPlaylist->isComplete() && !mPlaylist->isEvent()) { mDurationUs = -1; + mDurationFixed = true; } else { mDurationUs = 0; for (size_t i = 0; i < mPlaylist->size(); ++i) { @@ -552,6 +586,8 @@ rinse_repeat: mDurationUs += itemDurationUs; } + + mDurationFixed = mPlaylist->isComplete(); } } @@ -569,7 +605,7 @@ rinse_repeat: bool bandwidthChanged = false; if (mSeekTimeUs >= 0) { - if (mPlaylist->isComplete()) { + if (mPlaylist->isComplete() || mPlaylist->isEvent()) { size_t index = 0; int64_t segmentStartUs = 0; while (index < mPlaylist->size()) { @@ -617,13 +653,21 @@ rinse_repeat: mCondition.broadcast(); } + const int32_t lastSeqNumberInPlaylist = + firstSeqNumberInPlaylist + (int32_t)mPlaylist->size() - 1; + if (mSeqNumber < 0) { - mSeqNumber = firstSeqNumberInPlaylist; + if (mPlaylist->isComplete()) { + mSeqNumber = firstSeqNumberInPlaylist; + } else { + // If this is a live session, start 3 segments from the end. + mSeqNumber = lastSeqNumberInPlaylist - 3; + if (mSeqNumber < firstSeqNumberInPlaylist) { + mSeqNumber = firstSeqNumberInPlaylist; + } + } } - int32_t lastSeqNumberInPlaylist = - firstSeqNumberInPlaylist + (int32_t)mPlaylist->size() - 1; - if (mSeqNumber < firstSeqNumberInPlaylist || mSeqNumber > lastSeqNumberInPlaylist) { if (mPrevBandwidthIndex != (ssize_t)bandwidthIndex) { @@ -686,6 +730,9 @@ rinse_repeat: range_length = -1; } + ALOGV("fetching segment %d from (%d .. %d)", + mSeqNumber, firstSeqNumberInPlaylist, lastSeqNumberInPlaylist); + sp<ABuffer> buffer; status_t err = fetchFile(uri.c_str(), &buffer, range_offset, range_length); if (err != OK) { @@ -737,6 +784,11 @@ rinse_repeat: bandwidthChanged = false; } + if (mStartOfPlayback) { + seekDiscontinuity = true; + mStartOfPlayback = false; + } + if (seekDiscontinuity || explicitDiscontinuity || bandwidthChanged) { // Signal discontinuity. @@ -747,7 +799,19 @@ rinse_repeat: memset(tmp->data(), 0, tmp->size()); // signal a 'hard' discontinuity for explicit or bandwidthChanged. - tmp->data()[1] = (explicitDiscontinuity || bandwidthChanged) ? 1 : 0; + uint8_t type = (explicitDiscontinuity || bandwidthChanged) ? 1 : 0; + + if (mPlaylist->isComplete() || mPlaylist->isEvent()) { + // If this was a live event this made no sense since + // we don't have access to all the segment before the current + // one. + int64_t segmentStartTimeUs = getSegmentStartTimeUs(mSeqNumber); + memcpy(tmp->data() + 2, &segmentStartTimeUs, sizeof(segmentStartTimeUs)); + + type |= 2; + } + + tmp->data()[1] = type; mDataSource->queueBuffer(tmp); } @@ -923,17 +987,21 @@ void LiveSession::onSeek(const sp<AMessage> &msg) { postMonitorQueue(); } -status_t LiveSession::getDuration(int64_t *durationUs) { +status_t LiveSession::getDuration(int64_t *durationUs) const { Mutex::Autolock autoLock(mLock); *durationUs = mDurationUs; return OK; } -bool LiveSession::isSeekable() { +bool LiveSession::isSeekable() const { int64_t durationUs; return getDuration(&durationUs) == OK && durationUs >= 0; } +bool LiveSession::hasDynamicDuration() const { + return !mDurationFixed; +} + } // namespace android diff --git a/media/libstagefright/httplive/M3UParser.cpp b/media/libstagefright/httplive/M3UParser.cpp index 7d3cf05..44e03dc 100644 --- a/media/libstagefright/httplive/M3UParser.cpp +++ b/media/libstagefright/httplive/M3UParser.cpp @@ -32,7 +32,8 @@ M3UParser::M3UParser( mBaseURI(baseURI), mIsExtM3U(false), mIsVariantPlaylist(false), - mIsComplete(false) { + mIsComplete(false), + mIsEvent(false) { mInitCheck = parse(data, size); } @@ -55,6 +56,10 @@ bool M3UParser::isComplete() const { return mIsComplete; } +bool M3UParser::isEvent() const { + return mIsEvent; +} + sp<AMessage> M3UParser::meta() { return mMeta; } @@ -200,6 +205,8 @@ status_t M3UParser::parse(const void *_data, size_t size) { err = parseCipherInfo(line, &itemMeta, mBaseURI); } else if (line.startsWith("#EXT-X-ENDLIST")) { mIsComplete = true; + } else if (line.startsWith("#EXT-X-PLAYLIST-TYPE:EVENT")) { + mIsEvent = true; } else if (line.startsWith("#EXTINF")) { if (mIsVariantPlaylist) { return ERROR_MALFORMED; |