From 48296b792a8d68358de74141fa80bd5bd84d0307 Mon Sep 17 00:00:00 2001 From: Chong Zhang Date: Sun, 14 Sep 2014 14:28:45 -0700 Subject: Disconnect HTTP-based data source upon reset Bug: 17425250 Change-Id: Ieb4c93fd9848489f9dbf35a36474376924fd8eb9 --- .../nuplayer/GenericSource.cpp | 9 ++++++ .../libmediaplayerservice/nuplayer/GenericSource.h | 2 ++ media/libmediaplayerservice/nuplayer/NuPlayer.cpp | 10 +++++++ .../nuplayer/NuPlayerSource.h | 3 ++ media/libstagefright/NuCachedSource2.cpp | 34 +++++++++++++++++----- media/libstagefright/include/NuCachedSource2.h | 3 ++ 6 files changed, 53 insertions(+), 8 deletions(-) diff --git a/media/libmediaplayerservice/nuplayer/GenericSource.cpp b/media/libmediaplayerservice/nuplayer/GenericSource.cpp index d8ed836..0b85b23 100644 --- a/media/libmediaplayerservice/nuplayer/GenericSource.cpp +++ b/media/libmediaplayerservice/nuplayer/GenericSource.cpp @@ -464,6 +464,15 @@ void NuPlayer::GenericSource::resume() { mStarted = true; } +void NuPlayer::GenericSource::disconnect() { + if (mDataSource != NULL) { + // disconnect data source + if (mDataSource->flags() & DataSource::kIsCachingDataSource) { + static_cast(mDataSource.get())->disconnect(); + } + } +} + void NuPlayer::GenericSource::setDrmPlaybackStatusIfNeeded(int playbackStatus, int64_t position) { if (mDecryptHandle != NULL) { mDrmManagerClient->setPlaybackStatus(mDecryptHandle, playbackStatus, position); diff --git a/media/libmediaplayerservice/nuplayer/GenericSource.h b/media/libmediaplayerservice/nuplayer/GenericSource.h index c70c48e..454edeb 100644 --- a/media/libmediaplayerservice/nuplayer/GenericSource.h +++ b/media/libmediaplayerservice/nuplayer/GenericSource.h @@ -55,6 +55,8 @@ struct NuPlayer::GenericSource : public NuPlayer::Source { virtual void pause(); virtual void resume(); + virtual void disconnect(); + virtual status_t feedMoreTSData(); virtual status_t dequeueAccessUnit(bool audio, sp *accessUnit); diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp index df3e992..078e78b 100644 --- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp +++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp @@ -306,6 +306,16 @@ void NuPlayer::resume() { } void NuPlayer::resetAsync() { + if (mSource != NULL) { + // During a reset, the data source might be unresponsive already, we need to + // disconnect explicitly so that reads exit promptly. + // We can't queue the disconnect request to the looper, as it might be + // queued behind a stuck read and never gets processed. + // Doing a disconnect outside the looper to allows the pending reads to exit + // (either successfully or with error). + mSource->disconnect(); + } + (new AMessage(kWhatReset, id()))->post(); } diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerSource.h b/media/libmediaplayerservice/nuplayer/NuPlayerSource.h index 7ccf3b1..7d994fa 100644 --- a/media/libmediaplayerservice/nuplayer/NuPlayerSource.h +++ b/media/libmediaplayerservice/nuplayer/NuPlayerSource.h @@ -67,6 +67,9 @@ struct NuPlayer::Source : public AHandler { virtual void pause() {} virtual void resume() {} + // Explicitly disconnect the underling data source + virtual void disconnect() {} + // Returns OK iff more data was available, // an error or ERROR_END_OF_STREAM if not. virtual status_t feedMoreTSData() = 0; diff --git a/media/libstagefright/NuCachedSource2.cpp b/media/libstagefright/NuCachedSource2.cpp index c1feff8..be2a873 100644 --- a/media/libstagefright/NuCachedSource2.cpp +++ b/media/libstagefright/NuCachedSource2.cpp @@ -191,6 +191,7 @@ NuCachedSource2::NuCachedSource2( mFinalStatus(OK), mLastAccessPos(0), mFetching(true), + mDisconnecting(false), mLastFetchTimeUs(-1), mNumRetriesLeft(kMaxNumRetries), mHighwaterThresholdBytes(kDefaultHighWaterThreshold), @@ -244,6 +245,23 @@ status_t NuCachedSource2::getEstimatedBandwidthKbps(int32_t *kbps) { return ERROR_UNSUPPORTED; } +void NuCachedSource2::disconnect() { + if (mSource->flags() & kIsHTTPBasedSource) { + ALOGV("disconnecting HTTPBasedSource"); + + { + Mutex::Autolock autoLock(mLock); + // set mDisconnecting to true, if a fetch returns after + // this, the source will be marked as EOS. + mDisconnecting = true; + } + + // explicitly disconnect from the source, to allow any + // pending reads to return more promptly + static_cast(mSource.get())->disconnect(); + } +} + status_t NuCachedSource2::setCacheStatCollectFreq(int32_t freqMs) { if (mSource->flags() & kIsHTTPBasedSource) { HTTPBase *source = static_cast(mSource.get()); @@ -327,7 +345,14 @@ void NuCachedSource2::fetchInternal() { Mutex::Autolock autoLock(mLock); - if (n < 0) { + if (n == 0 || mDisconnecting) { + ALOGI("ERROR_END_OF_STREAM"); + + mNumRetriesLeft = 0; + mFinalStatus = ERROR_END_OF_STREAM; + + mCache->releasePage(page); + } else if (n < 0) { mFinalStatus = n; if (n == ERROR_UNSUPPORTED || n == -EPIPE) { // These are errors that are not likely to go away even if we @@ -337,13 +362,6 @@ void NuCachedSource2::fetchInternal() { ALOGE("source returned error %zd, %d retries left", n, mNumRetriesLeft); mCache->releasePage(page); - } else if (n == 0) { - ALOGI("ERROR_END_OF_STREAM"); - - mNumRetriesLeft = 0; - mFinalStatus = ERROR_END_OF_STREAM; - - mCache->releasePage(page); } else { if (mFinalStatus != OK) { ALOGI("retrying a previously failed read succeeded."); diff --git a/media/libstagefright/include/NuCachedSource2.h b/media/libstagefright/include/NuCachedSource2.h index 5db4b4b..4252706 100644 --- a/media/libstagefright/include/NuCachedSource2.h +++ b/media/libstagefright/include/NuCachedSource2.h @@ -37,6 +37,8 @@ struct NuCachedSource2 : public DataSource { virtual ssize_t readAt(off64_t offset, void *data, size_t size); + virtual void disconnect(); + virtual status_t getSize(off64_t *size); virtual uint32_t flags(); @@ -103,6 +105,7 @@ private: off64_t mLastAccessPos; sp mAsyncResult; bool mFetching; + bool mDisconnecting; int64_t mLastFetchTimeUs; int32_t mNumRetriesLeft; -- cgit v1.1