Loading include/media/stagefright/DataSource.h +1 −0 Original line number Diff line number Diff line Loading @@ -36,6 +36,7 @@ public: enum Flags { kWantsPrefetching = 1, kStreamedFromLocalHost = 2, kIsCachingDataSource = 4, }; static sp<DataSource> CreateFromURI( Loading media/libstagefright/AwesomePlayer.cpp +8 −4 Original line number Diff line number Diff line Loading @@ -26,6 +26,7 @@ #include "include/SoftwareRenderer.h" #include "include/NuCachedSource2.h" #include "include/ThrottledSource.h" #include "include/MPEG2TSExtractor.h" #include "ARTPSession.h" #include "APacketSource.h" Loading Loading @@ -506,8 +507,8 @@ void AwesomePlayer::onBufferingUpdate() { // We don't know the bitrate of the stream, use absolute size // limits to maintain the cache. const size_t kLowWaterMarkBytes = 400000; const size_t kHighWaterMarkBytes = 1000000; const size_t kLowWaterMarkBytes = 40000; const size_t kHighWaterMarkBytes = 200000; if ((mFlags & PLAYING) && !eos && (cachedDataRemaining < kLowWaterMarkBytes)) { Loading Loading @@ -1343,14 +1344,17 @@ status_t AwesomePlayer::finishSetDataSource_l() { String8 uri("http://"); uri.append(mUri.string() + 11); dataSource = new LiveSource(uri.string()); sp<LiveSource> liveSource = new LiveSource(uri.string()); mCachedSource = new NuCachedSource2(dataSource); mCachedSource = new NuCachedSource2(liveSource); dataSource = mCachedSource; sp<MediaExtractor> extractor = MediaExtractor::Create(dataSource, MEDIA_MIMETYPE_CONTAINER_MPEG2TS); static_cast<MPEG2TSExtractor *>(extractor.get()) ->setLiveSource(liveSource); return setDataSource_l(extractor); } else if (!strncmp("rtsp://gtalk/", mUri.string(), 13)) { if (mLooper == NULL) { Loading media/libstagefright/NuCachedSource2.cpp +45 −3 Original line number Diff line number Diff line Loading @@ -179,7 +179,8 @@ NuCachedSource2::NuCachedSource2(const sp<DataSource> &source) mFinalStatus(OK), mLastAccessPos(0), mFetching(true), mLastFetchTimeUs(-1) { mLastFetchTimeUs(-1), mSuspended(false) { mLooper->setName("NuCachedSource2"); mLooper->registerHandler(mReflector); mLooper->start(); Loading @@ -205,7 +206,7 @@ status_t NuCachedSource2::getSize(off_t *size) { } uint32_t NuCachedSource2::flags() { return mSource->flags(); return (mSource->flags() & ~kWantsPrefetching) | kIsCachingDataSource; } void NuCachedSource2::onMessageReceived(const sp<AMessage> &msg) { Loading @@ -222,6 +223,12 @@ void NuCachedSource2::onMessageReceived(const sp<AMessage> &msg) { break; } case kWhatSuspend: { onSuspend(); break; } default: TRESPASS(); } Loading Loading @@ -263,6 +270,7 @@ void NuCachedSource2::onFetch() { bool keepAlive = !mFetching && !mSuspended && mFinalStatus == OK && ALooper::GetNowUs() >= mLastFetchTimeUs + kKeepAliveIntervalUs; Loading @@ -279,7 +287,7 @@ void NuCachedSource2::onFetch() { LOGI("Cache full, done prefetching for now"); mFetching = false; } } else { } else if (!mSuspended) { Mutex::Autolock autoLock(mLock); restartPrefetcherIfNecessary_l(); } Loading Loading @@ -468,5 +476,39 @@ status_t NuCachedSource2::seekInternal_l(off_t offset) { return OK; } void NuCachedSource2::clearCacheAndResume() { LOGV("clearCacheAndResume"); Mutex::Autolock autoLock(mLock); CHECK(mSuspended); mCacheOffset = 0; mFinalStatus = OK; mLastAccessPos = 0; mLastFetchTimeUs = -1; size_t totalSize = mCache->totalSize(); CHECK_EQ(mCache->releaseFromStart(totalSize), totalSize); mFetching = true; mSuspended = false; } void NuCachedSource2::suspend() { (new AMessage(kWhatSuspend, mReflector->id()))->post(); while (!mSuspended) { usleep(10000); } } void NuCachedSource2::onSuspend() { Mutex::Autolock autoLock(mLock); mFetching = false; mSuspended = true; } } // namespace android media/libstagefright/httplive/LiveSource.cpp +69 −1 Original line number Diff line number Diff line Loading @@ -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), Loading @@ -40,6 +41,8 @@ LiveSource::LiveSource(const char *url) mPrevBandwidthIndex(-1) { if (switchToNext()) { mInitCheck = OK; determineSeekability(); } } Loading Loading @@ -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; Loading Loading @@ -336,4 +339,69 @@ status_t LiveSource::fetchM3U(const char *url, sp<ABuffer> *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 media/libstagefright/httplive/M3UParser.cpp +8 −1 Original line number Diff line number Diff line Loading @@ -27,7 +27,8 @@ M3UParser::M3UParser( : mInitCheck(NO_INIT), mBaseURI(baseURI), mIsExtM3U(false), mIsVariantPlaylist(false) { mIsVariantPlaylist(false), mIsComplete(false) { mInitCheck = parse(data, size); } Loading @@ -46,6 +47,10 @@ bool M3UParser::isVariantPlaylist() const { return mIsVariantPlaylist; } bool M3UParser::isComplete() const { return mIsComplete; } sp<AMessage> M3UParser::meta() { return mMeta; } Loading Loading @@ -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; Loading Loading
include/media/stagefright/DataSource.h +1 −0 Original line number Diff line number Diff line Loading @@ -36,6 +36,7 @@ public: enum Flags { kWantsPrefetching = 1, kStreamedFromLocalHost = 2, kIsCachingDataSource = 4, }; static sp<DataSource> CreateFromURI( Loading
media/libstagefright/AwesomePlayer.cpp +8 −4 Original line number Diff line number Diff line Loading @@ -26,6 +26,7 @@ #include "include/SoftwareRenderer.h" #include "include/NuCachedSource2.h" #include "include/ThrottledSource.h" #include "include/MPEG2TSExtractor.h" #include "ARTPSession.h" #include "APacketSource.h" Loading Loading @@ -506,8 +507,8 @@ void AwesomePlayer::onBufferingUpdate() { // We don't know the bitrate of the stream, use absolute size // limits to maintain the cache. const size_t kLowWaterMarkBytes = 400000; const size_t kHighWaterMarkBytes = 1000000; const size_t kLowWaterMarkBytes = 40000; const size_t kHighWaterMarkBytes = 200000; if ((mFlags & PLAYING) && !eos && (cachedDataRemaining < kLowWaterMarkBytes)) { Loading Loading @@ -1343,14 +1344,17 @@ status_t AwesomePlayer::finishSetDataSource_l() { String8 uri("http://"); uri.append(mUri.string() + 11); dataSource = new LiveSource(uri.string()); sp<LiveSource> liveSource = new LiveSource(uri.string()); mCachedSource = new NuCachedSource2(dataSource); mCachedSource = new NuCachedSource2(liveSource); dataSource = mCachedSource; sp<MediaExtractor> extractor = MediaExtractor::Create(dataSource, MEDIA_MIMETYPE_CONTAINER_MPEG2TS); static_cast<MPEG2TSExtractor *>(extractor.get()) ->setLiveSource(liveSource); return setDataSource_l(extractor); } else if (!strncmp("rtsp://gtalk/", mUri.string(), 13)) { if (mLooper == NULL) { Loading
media/libstagefright/NuCachedSource2.cpp +45 −3 Original line number Diff line number Diff line Loading @@ -179,7 +179,8 @@ NuCachedSource2::NuCachedSource2(const sp<DataSource> &source) mFinalStatus(OK), mLastAccessPos(0), mFetching(true), mLastFetchTimeUs(-1) { mLastFetchTimeUs(-1), mSuspended(false) { mLooper->setName("NuCachedSource2"); mLooper->registerHandler(mReflector); mLooper->start(); Loading @@ -205,7 +206,7 @@ status_t NuCachedSource2::getSize(off_t *size) { } uint32_t NuCachedSource2::flags() { return mSource->flags(); return (mSource->flags() & ~kWantsPrefetching) | kIsCachingDataSource; } void NuCachedSource2::onMessageReceived(const sp<AMessage> &msg) { Loading @@ -222,6 +223,12 @@ void NuCachedSource2::onMessageReceived(const sp<AMessage> &msg) { break; } case kWhatSuspend: { onSuspend(); break; } default: TRESPASS(); } Loading Loading @@ -263,6 +270,7 @@ void NuCachedSource2::onFetch() { bool keepAlive = !mFetching && !mSuspended && mFinalStatus == OK && ALooper::GetNowUs() >= mLastFetchTimeUs + kKeepAliveIntervalUs; Loading @@ -279,7 +287,7 @@ void NuCachedSource2::onFetch() { LOGI("Cache full, done prefetching for now"); mFetching = false; } } else { } else if (!mSuspended) { Mutex::Autolock autoLock(mLock); restartPrefetcherIfNecessary_l(); } Loading Loading @@ -468,5 +476,39 @@ status_t NuCachedSource2::seekInternal_l(off_t offset) { return OK; } void NuCachedSource2::clearCacheAndResume() { LOGV("clearCacheAndResume"); Mutex::Autolock autoLock(mLock); CHECK(mSuspended); mCacheOffset = 0; mFinalStatus = OK; mLastAccessPos = 0; mLastFetchTimeUs = -1; size_t totalSize = mCache->totalSize(); CHECK_EQ(mCache->releaseFromStart(totalSize), totalSize); mFetching = true; mSuspended = false; } void NuCachedSource2::suspend() { (new AMessage(kWhatSuspend, mReflector->id()))->post(); while (!mSuspended) { usleep(10000); } } void NuCachedSource2::onSuspend() { Mutex::Autolock autoLock(mLock); mFetching = false; mSuspended = true; } } // namespace android
media/libstagefright/httplive/LiveSource.cpp +69 −1 Original line number Diff line number Diff line Loading @@ -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), Loading @@ -40,6 +41,8 @@ LiveSource::LiveSource(const char *url) mPrevBandwidthIndex(-1) { if (switchToNext()) { mInitCheck = OK; determineSeekability(); } } Loading Loading @@ -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; Loading Loading @@ -336,4 +339,69 @@ status_t LiveSource::fetchM3U(const char *url, sp<ABuffer> *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
media/libstagefright/httplive/M3UParser.cpp +8 −1 Original line number Diff line number Diff line Loading @@ -27,7 +27,8 @@ M3UParser::M3UParser( : mInitCheck(NO_INIT), mBaseURI(baseURI), mIsExtM3U(false), mIsVariantPlaylist(false) { mIsVariantPlaylist(false), mIsComplete(false) { mInitCheck = parse(data, size); } Loading @@ -46,6 +47,10 @@ bool M3UParser::isVariantPlaylist() const { return mIsVariantPlaylist; } bool M3UParser::isComplete() const { return mIsComplete; } sp<AMessage> M3UParser::meta() { return mMeta; } Loading Loading @@ -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; Loading