summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJames Dong <jdong@google.com>2011-05-25 19:37:03 -0700
committerJames Dong <jdong@google.com>2011-05-31 15:23:25 -0700
commit5b1b8a93a07326f1cbc627f09e02988375189e0a (patch)
tree1da7ba8c401fb96b4de5fab790fba8e51eea78f6
parent65580f9adf6c4d98449ad0716488f9fe3869aa5a (diff)
downloadframeworks_av-5b1b8a93a07326f1cbc627f09e02988375189e0a.zip
frameworks_av-5b1b8a93a07326f1cbc627f09e02988375189e0a.tar.gz
frameworks_av-5b1b8a93a07326f1cbc627f09e02988375189e0a.tar.bz2
Send estimated bandwidth value as informational event when cache fetcher pauses
o Application can make informed decision about the available network bandwidth when cache fetcher pauses. o Application can also adjust how frequently the bandwidth is estimated within a range from one second to one minute. Change-Id: I90068001343e79da1886de03c565537787e1580b
-rw-r--r--include/media/mediaplayer.h6
-rw-r--r--media/libstagefright/AwesomePlayer.cpp28
-rw-r--r--media/libstagefright/HTTPBase.cpp79
-rw-r--r--media/libstagefright/NuCachedSource2.cpp11
-rw-r--r--media/libstagefright/NuHTTPDataSource.cpp35
-rw-r--r--media/libstagefright/chromium_http/ChromiumHTTPDataSource.cpp35
-rw-r--r--media/libstagefright/include/AwesomePlayer.h2
-rw-r--r--media/libstagefright/include/ChromiumHTTPDataSource.h14
-rw-r--r--media/libstagefright/include/HTTPBase.h34
-rw-r--r--media/libstagefright/include/NuCachedSource2.h2
-rw-r--r--media/libstagefright/include/NuHTTPDataSource.h15
11 files changed, 162 insertions, 99 deletions
diff --git a/include/media/mediaplayer.h b/include/media/mediaplayer.h
index 50a378f..ea5a9d3 100644
--- a/include/media/mediaplayer.h
+++ b/include/media/mediaplayer.h
@@ -100,6 +100,9 @@ enum media_info_type {
MEDIA_INFO_BUFFERING_START = 701,
// MediaPlayer is resuming playback after filling buffers.
MEDIA_INFO_BUFFERING_END = 702,
+ // Bandwidth in recent past
+ MEDIA_INFO_NETWORK_BANDWIDTH = 703,
+
// 8xx
// Bad interleaving means that a media has been improperly interleaved or not
// interleaved at all, e.g has all the video samples first then all the audio
@@ -128,6 +131,9 @@ enum media_player_states {
enum media_set_parameter_keys {
KEY_PARAMETER_TIMED_TEXT_TRACK_INDEX = 1000,
KEY_PARAMETER_TIMED_TEXT_ADD_OUT_OF_BAND_SOURCE = 1001,
+
+ // Streaming/buffering parameters
+ KEY_PARAMETER_CACHE_STAT_COLLECT_FREQ_MS = 1100,
};
// ----------------------------------------------------------------------------
// ref-counted object for callbacks
diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp
index 3d270f8..07a47e5 100644
--- a/media/libstagefright/AwesomePlayer.cpp
+++ b/media/libstagefright/AwesomePlayer.cpp
@@ -634,6 +634,7 @@ void AwesomePlayer::onBufferingUpdate() {
mFlags |= CACHE_UNDERRUN;
pause_l();
ensureCacheIsFetching_l();
+ sendCacheStats();
notifyListener_l(MEDIA_INFO, MEDIA_INFO_BUFFERING_START);
} else if (eos || cachedDataRemaining > kHighWaterMarkBytes) {
if (mFlags & CACHE_UNDERRUN) {
@@ -692,6 +693,7 @@ void AwesomePlayer::onBufferingUpdate() {
mFlags |= CACHE_UNDERRUN;
pause_l();
ensureCacheIsFetching_l();
+ sendCacheStats();
notifyListener_l(MEDIA_INFO, MEDIA_INFO_BUFFERING_START);
} else if (eos || cachedDurationUs > highWaterMarkUs) {
if (mFlags & CACHE_UNDERRUN) {
@@ -711,6 +713,18 @@ void AwesomePlayer::onBufferingUpdate() {
postBufferingEvent_l();
}
+void AwesomePlayer::sendCacheStats() {
+ sp<MediaPlayerBase> listener = mListener.promote();
+ if (listener != NULL) {
+ int32_t kbps = 0;
+ status_t err = mCachedSource->getEstimatedBandwidthKbps(&kbps);
+ if (err == OK) {
+ listener->sendEvent(
+ MEDIA_INFO, MEDIA_INFO_NETWORK_BANDWIDTH, kbps);
+ }
+ }
+}
+
void AwesomePlayer::onStreamDone() {
// Posted whenever any stream finishes playing.
@@ -2083,6 +2097,10 @@ status_t AwesomePlayer::setParameter(int key, const Parcel &request) {
return mTextPlayer->setParameter(key, request);
}
+ case KEY_PARAMETER_CACHE_STAT_COLLECT_FREQ_MS:
+ {
+ return setCacheStatCollectFreq(request);
+ }
default:
{
return ERROR_UNSUPPORTED;
@@ -2090,6 +2108,16 @@ status_t AwesomePlayer::setParameter(int key, const Parcel &request) {
}
}
+status_t AwesomePlayer::setCacheStatCollectFreq(const Parcel &request) {
+ if (mCachedSource != NULL) {
+ int32_t freqMs = request.readInt32();
+ LOGD("Request to keep cache stats in the past %d ms",
+ freqMs);
+ return mCachedSource->setCacheStatCollectFreq(freqMs);
+ }
+ return ERROR_UNSUPPORTED;
+}
+
status_t AwesomePlayer::getParameter(int key, Parcel *reply) {
return OK;
}
diff --git a/media/libstagefright/HTTPBase.cpp b/media/libstagefright/HTTPBase.cpp
index 58b17a7..c0ae29d 100644
--- a/media/libstagefright/HTTPBase.cpp
+++ b/media/libstagefright/HTTPBase.cpp
@@ -14,6 +14,10 @@
* limitations under the License.
*/
+//#define LOG_NDEBUG 0
+#define LOG_TAG "HTTPBase"
+#include <utils/Log.h>
+
#include "include/HTTPBase.h"
#if CHROMIUM_AVAILABLE
@@ -22,11 +26,19 @@
#include "include/NuHTTPDataSource.h"
+#include <media/stagefright/foundation/ALooper.h>
#include <cutils/properties.h>
namespace android {
-HTTPBase::HTTPBase() {}
+HTTPBase::HTTPBase()
+ : mNumBandwidthHistoryItems(0),
+ mTotalTransferTimeUs(0),
+ mTotalTransferBytes(0),
+ mPrevBandwidthMeasureTimeUs(0),
+ mPrevEstimatedBandWidthKbps(0),
+ mBandWidthCollectFreqMs(5000) {
+}
// static
sp<HTTPBase> HTTPBase::Create(uint32_t flags) {
@@ -42,4 +54,69 @@ sp<HTTPBase> HTTPBase::Create(uint32_t flags) {
}
}
+void HTTPBase::addBandwidthMeasurement(
+ size_t numBytes, int64_t delayUs) {
+ Mutex::Autolock autoLock(mLock);
+
+ BandwidthEntry entry;
+ entry.mDelayUs = delayUs;
+ entry.mNumBytes = numBytes;
+ mTotalTransferTimeUs += delayUs;
+ mTotalTransferBytes += numBytes;
+
+ mBandwidthHistory.push_back(entry);
+ if (++mNumBandwidthHistoryItems > 100) {
+ BandwidthEntry *entry = &*mBandwidthHistory.begin();
+ mTotalTransferTimeUs -= entry->mDelayUs;
+ mTotalTransferBytes -= entry->mNumBytes;
+ mBandwidthHistory.erase(mBandwidthHistory.begin());
+ --mNumBandwidthHistoryItems;
+
+ int64_t timeNowUs = ALooper::GetNowUs();
+ if (timeNowUs - mPrevBandwidthMeasureTimeUs >=
+ mBandWidthCollectFreqMs * 1000LL) {
+
+ if (mPrevBandwidthMeasureTimeUs != 0) {
+ mPrevEstimatedBandWidthKbps =
+ (mTotalTransferBytes * 8E3 / mTotalTransferTimeUs);
+ }
+ mPrevBandwidthMeasureTimeUs = timeNowUs;
+ }
+ }
+
+}
+
+bool HTTPBase::estimateBandwidth(int32_t *bandwidth_bps) {
+ Mutex::Autolock autoLock(mLock);
+
+ if (mNumBandwidthHistoryItems < 2) {
+ return false;
+ }
+
+ *bandwidth_bps = ((double)mTotalTransferBytes * 8E6 / mTotalTransferTimeUs);
+
+ return true;
+}
+
+status_t HTTPBase::getEstimatedBandwidthKbps(int32_t *kbps) {
+ Mutex::Autolock autoLock(mLock);
+ *kbps = mPrevEstimatedBandWidthKbps;
+ return OK;
+}
+
+status_t HTTPBase::setBandwidthStatCollectFreq(int32_t freqMs) {
+ Mutex::Autolock autoLock(mLock);
+
+ if (freqMs < kMinBandwidthCollectFreqMs
+ || freqMs > kMaxBandwidthCollectFreqMs) {
+
+ LOGE("frequency (%d ms) is out of range [1000, 60000]", freqMs);
+ return BAD_VALUE;
+ }
+
+ LOGI("frequency set to %d ms", freqMs);
+ mBandWidthCollectFreqMs = freqMs;
+ return OK;
+}
+
} // namespace android
diff --git a/media/libstagefright/NuCachedSource2.cpp b/media/libstagefright/NuCachedSource2.cpp
index 81f2e47..b2ed427 100644
--- a/media/libstagefright/NuCachedSource2.cpp
+++ b/media/libstagefright/NuCachedSource2.cpp
@@ -19,6 +19,7 @@
#include <utils/Log.h>
#include "include/NuCachedSource2.h"
+#include "include/HTTPBase.h"
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/foundation/AMessage.h>
@@ -201,6 +202,16 @@ NuCachedSource2::~NuCachedSource2() {
mCache = NULL;
}
+status_t NuCachedSource2::getEstimatedBandwidthKbps(int32_t *kbps) {
+ HTTPBase* source = static_cast<HTTPBase *>(mSource.get());
+ return source->getEstimatedBandwidthKbps(kbps);
+}
+
+status_t NuCachedSource2::setCacheStatCollectFreq(int32_t freqMs) {
+ HTTPBase *source = static_cast<HTTPBase *>(mSource.get());
+ return source->setBandwidthStatCollectFreq(freqMs);
+}
+
status_t NuCachedSource2::initCheck() const {
return mSource->initCheck();
}
diff --git a/media/libstagefright/NuHTTPDataSource.cpp b/media/libstagefright/NuHTTPDataSource.cpp
index 821ba9b..c3b5e8f 100644
--- a/media/libstagefright/NuHTTPDataSource.cpp
+++ b/media/libstagefright/NuHTTPDataSource.cpp
@@ -97,9 +97,6 @@ NuHTTPDataSource::NuHTTPDataSource(uint32_t flags)
mContentLengthValid(false),
mHasChunkedTransferEncoding(false),
mChunkDataBytesLeft(0),
- mNumBandwidthHistoryItems(0),
- mTotalTransferTimeUs(0),
- mTotalTransferBytes(0),
mDecryptHandle(NULL),
mDrmManagerClient(NULL) {
}
@@ -431,7 +428,7 @@ ssize_t NuHTTPDataSource::readAt(off64_t offset, void *data, size_t size) {
}
int64_t delayUs = ALooper::GetNowUs() - startTimeUs;
- addBandwidthMeasurement_l(n, delayUs);
+ addBandwidthMeasurement(n, delayUs);
numBytesRead += (size_t)n;
@@ -517,36 +514,6 @@ void NuHTTPDataSource::applyTimeoutResponse() {
}
}
-bool NuHTTPDataSource::estimateBandwidth(int32_t *bandwidth_bps) {
- Mutex::Autolock autoLock(mLock);
-
- if (mNumBandwidthHistoryItems < 2) {
- return false;
- }
-
- *bandwidth_bps = ((double)mTotalTransferBytes * 8E6 / mTotalTransferTimeUs);
-
- return true;
-}
-
-void NuHTTPDataSource::addBandwidthMeasurement_l(
- size_t numBytes, int64_t delayUs) {
- BandwidthEntry entry;
- entry.mDelayUs = delayUs;
- entry.mNumBytes = numBytes;
- mTotalTransferTimeUs += delayUs;
- mTotalTransferBytes += numBytes;
-
- mBandwidthHistory.push_back(entry);
- if (++mNumBandwidthHistoryItems > 100) {
- BandwidthEntry *entry = &*mBandwidthHistory.begin();
- mTotalTransferTimeUs -= entry->mDelayUs;
- mTotalTransferBytes -= entry->mNumBytes;
- mBandwidthHistory.erase(mBandwidthHistory.begin());
- --mNumBandwidthHistoryItems;
- }
-}
-
sp<DecryptHandle> NuHTTPDataSource::DrmInitialization() {
if (mDrmManagerClient == NULL) {
mDrmManagerClient = new DrmManagerClient();
diff --git a/media/libstagefright/chromium_http/ChromiumHTTPDataSource.cpp b/media/libstagefright/chromium_http/ChromiumHTTPDataSource.cpp
index 1096717..ad1f342 100644
--- a/media/libstagefright/chromium_http/ChromiumHTTPDataSource.cpp
+++ b/media/libstagefright/chromium_http/ChromiumHTTPDataSource.cpp
@@ -34,9 +34,6 @@ ChromiumHTTPDataSource::ChromiumHTTPDataSource(uint32_t flags)
mCurrentOffset(0),
mIOResult(OK),
mContentSize(-1),
- mNumBandwidthHistoryItems(0),
- mTotalTransferTimeUs(0),
- mTotalTransferBytes(0),
mDecryptHandle(NULL),
mDrmManagerClient(NULL) {
mDelegate->setOwner(this);
@@ -188,7 +185,7 @@ ssize_t ChromiumHTTPDataSource::readAt(off64_t offset, void *data, size_t size)
// The read operation was successful, mIOResult contains
// the number of bytes read.
- addBandwidthMeasurement_l(mIOResult, delayUs);
+ addBandwidthMeasurement(mIOResult, delayUs);
mCurrentOffset += mIOResult;
return mIOResult;
@@ -246,36 +243,6 @@ void ChromiumHTTPDataSource::onDisconnectComplete() {
clearDRMState_l();
}
-void ChromiumHTTPDataSource::addBandwidthMeasurement_l(
- size_t numBytes, int64_t delayUs) {
- BandwidthEntry entry;
- entry.mDelayUs = delayUs;
- entry.mNumBytes = numBytes;
- mTotalTransferTimeUs += delayUs;
- mTotalTransferBytes += numBytes;
-
- mBandwidthHistory.push_back(entry);
- if (++mNumBandwidthHistoryItems > 100) {
- BandwidthEntry *entry = &*mBandwidthHistory.begin();
- mTotalTransferTimeUs -= entry->mDelayUs;
- mTotalTransferBytes -= entry->mNumBytes;
- mBandwidthHistory.erase(mBandwidthHistory.begin());
- --mNumBandwidthHistoryItems;
- }
-}
-
-bool ChromiumHTTPDataSource::estimateBandwidth(int32_t *bandwidth_bps) {
- Mutex::Autolock autoLock(mLock);
-
- if (mNumBandwidthHistoryItems < 2) {
- return false;
- }
-
- *bandwidth_bps = ((double)mTotalTransferBytes * 8E6 / mTotalTransferTimeUs);
-
- return true;
-}
-
sp<DecryptHandle> ChromiumHTTPDataSource::DrmInitialization() {
Mutex::Autolock autoLock(mLock);
diff --git a/media/libstagefright/include/AwesomePlayer.h b/media/libstagefright/include/AwesomePlayer.h
index a9e8e95..aebcdd1 100644
--- a/media/libstagefright/include/AwesomePlayer.h
+++ b/media/libstagefright/include/AwesomePlayer.h
@@ -93,6 +93,7 @@ struct AwesomePlayer {
status_t setParameter(int key, const Parcel &request);
status_t getParameter(int key, Parcel *reply);
+ status_t setCacheStatCollectFreq(const Parcel &request);
status_t seekTo(int64_t timeUs);
@@ -291,6 +292,7 @@ private:
void setNativeWindow_l(const sp<ANativeWindow> &native);
bool isStreamingHTTP() const;
+ void sendCacheStats();
AwesomePlayer(const AwesomePlayer &);
AwesomePlayer &operator=(const AwesomePlayer &);
diff --git a/media/libstagefright/include/ChromiumHTTPDataSource.h b/media/libstagefright/include/ChromiumHTTPDataSource.h
index 0e2927d..d833e2e 100644
--- a/media/libstagefright/include/ChromiumHTTPDataSource.h
+++ b/media/libstagefright/include/ChromiumHTTPDataSource.h
@@ -43,8 +43,6 @@ struct ChromiumHTTPDataSource : public HTTPBase {
virtual status_t getSize(off64_t *size);
virtual uint32_t flags();
- virtual bool estimateBandwidth(int32_t *bandwidth_bps);
-
virtual sp<DecryptHandle> DrmInitialization();
virtual void getDrmInfo(sp<DecryptHandle> &handle, DrmManagerClient **client);
@@ -67,11 +65,6 @@ private:
DISCONNECTING
};
- struct BandwidthEntry {
- int64_t mDelayUs;
- size_t mNumBytes;
- };
-
const uint32_t mFlags;
mutable Mutex mLock;
@@ -94,11 +87,6 @@ private:
String8 mContentType;
- List<BandwidthEntry> mBandwidthHistory;
- size_t mNumBandwidthHistoryItems;
- int64_t mTotalTransferTimeUs;
- size_t mTotalTransferBytes;
-
sp<DecryptHandle> mDecryptHandle;
DrmManagerClient *mDrmManagerClient;
@@ -121,8 +109,6 @@ private:
void onReadCompleted(ssize_t size);
void onDisconnectComplete();
- void addBandwidthMeasurement_l(size_t numBytes, int64_t delayUs);
-
void clearDRMState_l();
DISALLOW_EVIL_CONSTRUCTORS(ChromiumHTTPDataSource);
diff --git a/media/libstagefright/include/HTTPBase.h b/media/libstagefright/include/HTTPBase.h
index 6cec390..3a7fbb6 100644
--- a/media/libstagefright/include/HTTPBase.h
+++ b/media/libstagefright/include/HTTPBase.h
@@ -20,6 +20,8 @@
#include <media/stagefright/foundation/ABase.h>
#include <media/stagefright/DataSource.h>
+#include <media/stagefright/MediaErrors.h>
+#include <utils/threads.h>
namespace android {
@@ -40,11 +42,41 @@ struct HTTPBase : public DataSource {
// Returns true if bandwidth could successfully be estimated,
// false otherwise.
- virtual bool estimateBandwidth(int32_t *bandwidth_bps) = 0;
+ virtual bool estimateBandwidth(int32_t *bandwidth_bps);
+
+ virtual status_t getEstimatedBandwidthKbps(int32_t *kbps);
+
+ virtual status_t setBandwidthStatCollectFreq(int32_t freqMs);
static sp<HTTPBase> Create(uint32_t flags = 0);
+protected:
+ void addBandwidthMeasurement(size_t numBytes, int64_t delayUs);
+
private:
+
+ struct BandwidthEntry {
+ int64_t mDelayUs;
+ size_t mNumBytes;
+ };
+
+ Mutex mLock;
+
+ List<BandwidthEntry> mBandwidthHistory;
+ size_t mNumBandwidthHistoryItems;
+ int64_t mTotalTransferTimeUs;
+ size_t mTotalTransferBytes;
+
+ enum {
+ kMinBandwidthCollectFreqMs = 1000, // 1 second
+ kMaxBandwidthCollectFreqMs = 60000, // one minute
+ };
+
+ int64_t mPrevBandwidthMeasureTimeUs;
+ int32_t mPrevEstimatedBandWidthKbps;
+ int32_t mBandWidthCollectFreqMs;
+
+
DISALLOW_EVIL_CONSTRUCTORS(HTTPBase);
};
diff --git a/media/libstagefright/include/NuCachedSource2.h b/media/libstagefright/include/NuCachedSource2.h
index ed3e265..31fc0e5 100644
--- a/media/libstagefright/include/NuCachedSource2.h
+++ b/media/libstagefright/include/NuCachedSource2.h
@@ -47,8 +47,10 @@ struct NuCachedSource2 : public DataSource {
size_t cachedSize();
size_t approxDataRemaining(status_t *finalStatus);
+ status_t setCacheStatCollectFreq(int32_t freqMs);
void resumeFetchingIfNecessary();
+ status_t getEstimatedBandwidthKbps(int32_t *kbps);
protected:
virtual ~NuCachedSource2();
diff --git a/media/libstagefright/include/NuHTTPDataSource.h b/media/libstagefright/include/NuHTTPDataSource.h
index 2ab1f19..c265b3a 100644
--- a/media/libstagefright/include/NuHTTPDataSource.h
+++ b/media/libstagefright/include/NuHTTPDataSource.h
@@ -43,10 +43,6 @@ struct NuHTTPDataSource : public HTTPBase {
virtual status_t getSize(off64_t *size);
virtual uint32_t flags();
- // Returns true if bandwidth could successfully be estimated,
- // false otherwise.
- virtual bool estimateBandwidth(int32_t *bandwidth_bps);
-
virtual sp<DecryptHandle> DrmInitialization();
virtual void getDrmInfo(sp<DecryptHandle> &handle, DrmManagerClient **client);
virtual String8 getUri();
@@ -63,11 +59,6 @@ private:
CONNECTED
};
- struct BandwidthEntry {
- int64_t mDelayUs;
- size_t mNumBytes;
- };
-
Mutex mLock;
uint32_t mFlags;
@@ -93,11 +84,6 @@ private:
// chunk header (or -1 if no more chunks).
ssize_t mChunkDataBytesLeft;
- List<BandwidthEntry> mBandwidthHistory;
- size_t mNumBandwidthHistoryItems;
- int64_t mTotalTransferTimeUs;
- size_t mTotalTransferBytes;
-
sp<DecryptHandle> mDecryptHandle;
DrmManagerClient *mDrmManagerClient;
@@ -114,7 +100,6 @@ private:
ssize_t internalRead(void *data, size_t size);
void applyTimeoutResponse();
- void addBandwidthMeasurement_l(size_t numBytes, int64_t delayUs);
static void MakeFullHeaders(
const KeyedVector<String8, String8> *overrides,