diff options
author | Chong Zhang <chz@google.com> | 2015-04-20 16:03:00 -0700 |
---|---|---|
committer | Chong Zhang <chz@google.com> | 2015-04-23 18:45:44 -0700 |
commit | 5abbd3dcbb0bb32a3d4b90dddbcf90458967eb6f (patch) | |
tree | a56ccf00558ad454c1e2da546c449e506cc3b9bc /media/libstagefright/httplive/PlaylistFetcher.cpp | |
parent | 04f07fd61022dac46ddda9c815d65bc3d3278b84 (diff) | |
download | frameworks_av-5abbd3dcbb0bb32a3d4b90dddbcf90458967eb6f.zip frameworks_av-5abbd3dcbb0bb32a3d4b90dddbcf90458967eb6f.tar.gz frameworks_av-5abbd3dcbb0bb32a3d4b90dddbcf90458967eb6f.tar.bz2 |
HLS: make disconnect faster to prevent ANR
disconnect HTTP connection when we absolutely won't resume
bug: 19890444
Change-Id: Idee36b48741f6f8eb1d65bca32156e9e18349c67
Diffstat (limited to 'media/libstagefright/httplive/PlaylistFetcher.cpp')
-rw-r--r-- | media/libstagefright/httplive/PlaylistFetcher.cpp | 129 |
1 files changed, 78 insertions, 51 deletions
diff --git a/media/libstagefright/httplive/PlaylistFetcher.cpp b/media/libstagefright/httplive/PlaylistFetcher.cpp index 8350c1b..53087b6 100644 --- a/media/libstagefright/httplive/PlaylistFetcher.cpp +++ b/media/libstagefright/httplive/PlaylistFetcher.cpp @@ -20,23 +20,16 @@ #include <utils/misc.h> #include "PlaylistFetcher.h" - -#include "LiveDataSource.h" +#include "HTTPDownloader.h" #include "LiveSession.h" #include "M3UParser.h" - #include "include/avc_utils.h" -#include "include/HTTPBase.h" #include "include/ID3.h" #include "mpeg2ts/AnotherPacketSource.h" -#include <media/IStreamSource.h> #include <media/stagefright/foundation/ABitReader.h> #include <media/stagefright/foundation/ABuffer.h> #include <media/stagefright/foundation/ADebug.h> -#include <media/stagefright/foundation/AUtils.h> -#include <media/stagefright/foundation/hexdump.h> -#include <media/stagefright/FileSource.h> #include <media/stagefright/MediaDefs.h> #include <media/stagefright/MetaData.h> #include <media/stagefright/Utils.h> @@ -44,7 +37,6 @@ #include <ctype.h> #include <inttypes.h> #include <openssl/aes.h> -#include <openssl/md5.h> #define FLOGV(fmt, ...) ALOGV("[fetcher-%d] " fmt, mFetcherID, ##__VA_ARGS__) #define FSLOGV(stream, fmt, ...) ALOGV("[fetcher-%d] [%s] " fmt, mFetcherID, \ @@ -179,7 +171,7 @@ PlaylistFetcher::PlaylistFetcher( mDownloadState(new DownloadState()), mHasMetadata(false) { memset(mPlaylistHash, 0, sizeof(mPlaylistHash)); - mHTTPDataSource = mSession->getHTTPDataSource(); + mHTTPDownloader = mSession->getHTTPDownloader(); } PlaylistFetcher::~PlaylistFetcher() { @@ -338,9 +330,11 @@ status_t PlaylistFetcher::decryptBuffer( if (index >= 0) { key = mAESKeyForURI.valueAt(index); } else { - ssize_t err = mSession->fetchFile(keyURI.c_str(), &key); + ssize_t err = mHTTPDownloader->fetchFile(keyURI.c_str(), &key); - if (err < 0) { + if (err == ERROR_NOT_CONNECTED) { + return ERROR_NOT_CONNECTED; + } else if (err < 0) { ALOGE("failed to fetch cipher key from '%s'.", keyURI.c_str()); return ERROR_IO; } else if (key->size() != 16) { @@ -448,12 +442,32 @@ void PlaylistFetcher::cancelMonitorQueue() { ++mMonitorQueueGeneration; } -void PlaylistFetcher::setStoppingThreshold(float thresholdRatio) { - AutoMutex _l(mThresholdLock); - if (mStreamTypeMask == LiveSession::STREAMTYPE_SUBTITLES) { - return; +void PlaylistFetcher::setStoppingThreshold(float thresholdRatio, bool disconnect) { + { + AutoMutex _l(mThresholdLock); + mThresholdRatio = thresholdRatio; + } + if (disconnect) { + mHTTPDownloader->disconnect(); + } +} + +void PlaylistFetcher::resetStoppingThreshold(bool disconnect) { + { + AutoMutex _l(mThresholdLock); + mThresholdRatio = -1.0f; + } + if (disconnect) { + mHTTPDownloader->disconnect(); + } else { + // allow reconnect + mHTTPDownloader->reconnect(); } - mThresholdRatio = thresholdRatio; +} + +float PlaylistFetcher::getStoppingThreshold() { + AutoMutex _l(mThresholdLock); + return mThresholdRatio; } void PlaylistFetcher::startAsync( @@ -497,15 +511,15 @@ void PlaylistFetcher::startAsync( msg->post(); } -void PlaylistFetcher::pauseAsync(float thresholdRatio) { - if (thresholdRatio >= 0.0f) { - setStoppingThreshold(thresholdRatio); - } +void PlaylistFetcher::pauseAsync( + float thresholdRatio, bool disconnect) { + setStoppingThreshold(thresholdRatio, disconnect); + (new AMessage(kWhatPause, this))->post(); } void PlaylistFetcher::stopAsync(bool clear) { - setStoppingThreshold(0.0f); + setStoppingThreshold(0.0f, true /* disconncect */); sp<AMessage> msg = new AMessage(kWhatStop, this); msg->setInt32("clear", clear); @@ -520,6 +534,10 @@ void PlaylistFetcher::resumeUntilAsync(const sp<AMessage> ¶ms) { msg->post(); } +void PlaylistFetcher::fetchPlaylistAsync() { + (new AMessage(kWhatFetchPlaylist, this))->post(); +} + void PlaylistFetcher::onMessageReceived(const sp<AMessage> &msg) { switch (msg->what()) { case kWhatStart: @@ -557,6 +575,19 @@ void PlaylistFetcher::onMessageReceived(const sp<AMessage> &msg) { break; } + case kWhatFetchPlaylist: + { + bool unchanged; + sp<M3UParser> playlist = mHTTPDownloader->fetchPlaylist( + mURI.c_str(), NULL /* curPlaylistHash */, &unchanged); + + sp<AMessage> notify = mNotify->dup(); + notify->setInt32("what", kWhatPlaylistFetched); + notify->setObject("playlist", playlist); + notify->post(); + break; + } + case kWhatMonitorQueue: case kWhatDownloadNext: { @@ -676,7 +707,7 @@ void PlaylistFetcher::onPause() { cancelMonitorQueue(); mLastDiscontinuitySeq = mDiscontinuitySeq; - setStoppingThreshold(-1.0f); + resetStoppingThreshold(false /* disconnect */); } void PlaylistFetcher::onStop(const sp<AMessage> &msg) { @@ -691,14 +722,11 @@ void PlaylistFetcher::onStop(const sp<AMessage> &msg) { } } - // close off the connection after use - mHTTPDataSource->disconnect(); - mDownloadState->resetState(); mPacketSources.clear(); mStreamTypeMask = 0; - setStoppingThreshold(-1.0f); + resetStoppingThreshold(true /* disconnect */); } // Resume until we have reached the boundary timestamps listed in `msg`; when @@ -815,7 +843,7 @@ void PlaylistFetcher::onMonitorQueue() { status_t PlaylistFetcher::refreshPlaylist() { if (delayUsToRefreshPlaylist() <= 0) { bool unchanged; - sp<M3UParser> playlist = mSession->fetchPlaylist( + sp<M3UParser> playlist = mHTTPDownloader->fetchPlaylist( mURI.c_str(), mPlaylistHash, &unchanged); if (playlist == NULL) { @@ -864,18 +892,12 @@ bool PlaylistFetcher::shouldPauseDownload() { } // Calculate threshold to abort current download - int64_t targetDurationUs = mPlaylist->getTargetDuration(); - int64_t thresholdUs = -1; - { - AutoMutex _l(mThresholdLock); - thresholdUs = (mThresholdRatio < 0.0f) ? - -1ll : mThresholdRatio * targetDurationUs; - } + float thresholdRatio = getStoppingThreshold(); - if (thresholdUs < 0) { + if (thresholdRatio < 0.0f) { // never abort return false; - } else if (thresholdUs == 0) { + } else if (thresholdRatio == 0.0f) { // immediately abort return true; } @@ -905,6 +927,9 @@ bool PlaylistFetcher::shouldPauseDownload() { } lastEnqueueUs -= mSegmentFirstPTS; + int64_t targetDurationUs = mPlaylist->getTargetDuration(); + int64_t thresholdUs = thresholdRatio * targetDurationUs; + FLOGV("%spausing now, thresholdUs %lld, remaining %lld", targetDurationUs - lastEnqueueUs > thresholdUs ? "" : "not ", (long long)thresholdUs, @@ -1101,7 +1126,9 @@ bool PlaylistFetcher::initDownloadState( junk->setRange(0, 16); status_t err = decryptBuffer(mSeqNumber - firstSeqNumberInPlaylist, junk, true /* first */); - if (err != OK) { + if (err == ERROR_NOT_CONNECTED) { + return false; + } else if (err != OK) { notifyError(err); return false; } @@ -1202,12 +1229,21 @@ void PlaylistFetcher::onDownloadNext() { bool shouldPause = false; ssize_t bytesRead; do { - sp<DataSource> source = mHTTPDataSource; - int64_t startUs = ALooper::GetNowUs(); - bytesRead = mSession->fetchFile( + bytesRead = mHTTPDownloader->fetchBlock( uri.c_str(), &buffer, range_offset, range_length, kDownloadBlockSize, - &source, NULL, connectHTTP); + NULL /* actualURL */, connectHTTP); + int64_t delayUs = ALooper::GetNowUs() - startUs; + + if (bytesRead == ERROR_NOT_CONNECTED) { + return; + } + if (bytesRead < 0) { + status_t err = bytesRead; + ALOGE("failed to fetch .ts segment at url '%s'", uri.c_str()); + notifyError(err); + return; + } // add sample for bandwidth estimation, excluding samples from subtitles (as // its too small), or during startup/resumeUntil (when we could have more than @@ -1216,9 +1252,7 @@ void PlaylistFetcher::onDownloadNext() { && (mStreamTypeMask & (LiveSession::STREAMTYPE_AUDIO | LiveSession::STREAMTYPE_VIDEO))) { - int64_t delayUs = ALooper::GetNowUs() - startUs; mSession->addBandwidthMeasurement(bytesRead, delayUs); - if (delayUs > 2000000ll) { FLOGV("bytesRead %zd took %.2f seconds - abnormal bandwidth dip", bytesRead, (double)delayUs / 1.0e6); @@ -1227,13 +1261,6 @@ void PlaylistFetcher::onDownloadNext() { connectHTTP = false; - if (bytesRead < 0) { - status_t err = bytesRead; - ALOGE("failed to fetch .ts segment at url '%s'", uri.c_str()); - notifyError(err); - return; - } - CHECK(buffer != NULL); size_t size = buffer->size(); |