summaryrefslogtreecommitdiffstats
path: root/media/libmediaplayerservice
diff options
context:
space:
mode:
authorChong Zhang <chz@google.com>2014-08-20 13:09:58 -0700
committerChong Zhang <chz@google.com>2014-08-21 18:38:09 -0700
commitd354d8d1b09503c0166c1f3e626cda72a3eeb83c (patch)
treebcb5370e8abc4611587dbef4066c0345a647c068 /media/libmediaplayerservice
parent111333eaab12448f45927464c8aeacbbf9a578a1 (diff)
downloadframeworks_av-d354d8d1b09503c0166c1f3e626cda72a3eeb83c.zip
frameworks_av-d354d8d1b09503c0166c1f3e626cda72a3eeb83c.tar.gz
frameworks_av-d354d8d1b09503c0166c1f3e626cda72a3eeb83c.tar.bz2
move cache prefill to GenericSource's message handler
This allows prepareAsync to be terminated by reset promptly. It also makes it easier to do buffer update as GenericSource can access the cache status now. Bug: 16892748 Bug: 17182378 Change-Id: Ia55c04a810fd805041cb2025f6739afa5120b5ed
Diffstat (limited to 'media/libmediaplayerservice')
-rw-r--r--media/libmediaplayerservice/nuplayer/GenericSource.cpp147
-rw-r--r--media/libmediaplayerservice/nuplayer/GenericSource.h16
2 files changed, 135 insertions, 28 deletions
diff --git a/media/libmediaplayerservice/nuplayer/GenericSource.cpp b/media/libmediaplayerservice/nuplayer/GenericSource.cpp
index 76e1d54..3706117 100644
--- a/media/libmediaplayerservice/nuplayer/GenericSource.cpp
+++ b/media/libmediaplayerservice/nuplayer/GenericSource.cpp
@@ -32,6 +32,7 @@
#include <media/stagefright/MediaExtractor.h>
#include <media/stagefright/MediaSource.h>
#include <media/stagefright/MetaData.h>
+#include "../../libstagefright/include/NuCachedSource2.h"
#include "../../libstagefright/include/WVMExtractor.h"
namespace android {
@@ -47,7 +48,8 @@ NuPlayer::GenericSource::GenericSource(
mAudioIsVorbis(false),
mIsWidevine(false),
mUIDValid(uidValid),
- mUID(uid) {
+ mUID(uid),
+ mMetaDataSize(-1ll) {
resetDataSource();
DataSource::RegisterDefaultSniffers();
}
@@ -92,18 +94,18 @@ status_t NuPlayer::GenericSource::setDataSource(
return OK;
}
-status_t NuPlayer::GenericSource::initFromDataSource(
- const sp<DataSource> &dataSource,
- const char* mime) {
+status_t NuPlayer::GenericSource::initFromDataSource() {
sp<MediaExtractor> extractor;
+ CHECK(mDataSource != NULL);
+
if (mIsWidevine) {
String8 mimeType;
float confidence;
sp<AMessage> dummy;
bool success;
- success = SniffWVM(dataSource, &mimeType, &confidence, &dummy);
+ success = SniffWVM(mDataSource, &mimeType, &confidence, &dummy);
if (!success
|| strcasecmp(
mimeType.string(), MEDIA_MIMETYPE_CONTAINER_WVM)) {
@@ -111,14 +113,15 @@ status_t NuPlayer::GenericSource::initFromDataSource(
return UNKNOWN_ERROR;
}
- sp<WVMExtractor> wvmExtractor = new WVMExtractor(dataSource);
+ sp<WVMExtractor> wvmExtractor = new WVMExtractor(mDataSource);
wvmExtractor->setAdaptiveStreamingMode(true);
if (mUIDValid) {
wvmExtractor->setUID(mUID);
}
extractor = wvmExtractor;
} else {
- extractor = MediaExtractor::Create(dataSource, mime);
+ extractor = MediaExtractor::Create(mDataSource,
+ mSniffedMIME.empty() ? NULL: mSniffedMIME.c_str());
}
if (extractor == NULL) {
@@ -213,34 +216,49 @@ void NuPlayer::GenericSource::prepareAsync() {
void NuPlayer::GenericSource::onPrepareAsync() {
// delayed data source creation
- AString sniffedMIME;
- sp<DataSource> dataSource;
+ if (mDataSource == NULL) {
+ if (!mUri.empty()) {
+ mIsWidevine = !strncasecmp(mUri.c_str(), "widevine://", 11);
- if (!mUri.empty()) {
- mIsWidevine = !strncasecmp(mUri.c_str(), "widevine://", 11);
+ mDataSource = DataSource::CreateFromURI(
+ mHTTPService, mUri.c_str(), &mUriHeaders, &mContentType);
+ } else {
+ // set to false first, if the extractor
+ // comes back as secure, set it to true then.
+ mIsWidevine = false;
- dataSource = DataSource::CreateFromURI(
- mHTTPService, mUri.c_str(), &mUriHeaders, &sniffedMIME);
- } else {
- // set to false first, if the extractor
- // comes back as secure, set it to true then.
- mIsWidevine = false;
+ mDataSource = new FileSource(mFd, mOffset, mLength);
+ }
+
+ if (mDataSource == NULL) {
+ ALOGE("Failed to create data source!");
+ notifyPreparedAndCleanup(UNKNOWN_ERROR);
+ return;
+ }
- dataSource = new FileSource(mFd, mOffset, mLength);
+ if (mDataSource->flags() & DataSource::kIsCachingDataSource) {
+ mCachedSource = static_cast<NuCachedSource2 *>(mDataSource.get());
+ }
}
- if (dataSource == NULL) {
- ALOGE("Failed to create data source!");
- notifyPrepared(UNKNOWN_ERROR);
+ // check initial caching status
+ status_t err = prefillCacheIfNecessary();
+ if (err != OK) {
+ if (err == -EAGAIN) {
+ (new AMessage(kWhatPrepareAsync, id()))->post(200000);
+ } else {
+ ALOGE("Failed to prefill data cache!");
+ notifyPreparedAndCleanup(UNKNOWN_ERROR);
+ }
return;
}
- status_t err = initFromDataSource(
- dataSource, sniffedMIME.empty() ? NULL : sniffedMIME.c_str());
+ // init extrator from data source
+ err = initFromDataSource();
if (err != OK) {
ALOGE("Failed to init from data source!");
- notifyPrepared(err);
+ notifyPreparedAndCleanup(err);
return;
}
@@ -258,6 +276,87 @@ void NuPlayer::GenericSource::onPrepareAsync() {
notifyPrepared();
}
+void NuPlayer::GenericSource::notifyPreparedAndCleanup(status_t err) {
+ if (err != OK) {
+ mMetaDataSize = -1ll;
+ mContentType = "";
+ mSniffedMIME = "";
+ mDataSource.clear();
+ mCachedSource.clear();
+ }
+ notifyPrepared(err);
+}
+
+status_t NuPlayer::GenericSource::prefillCacheIfNecessary() {
+ CHECK(mDataSource != NULL);
+
+ if (mCachedSource == NULL) {
+ // no prefill if the data source is not cached
+ return OK;
+ }
+
+ // We're not doing this for streams that appear to be audio-only
+ // streams to ensure that even low bandwidth streams start
+ // playing back fairly instantly.
+ if (!strncasecmp(mContentType.string(), "audio/", 6)) {
+ return OK;
+ }
+
+ // We're going to prefill the cache before trying to instantiate
+ // the extractor below, as the latter is an operation that otherwise
+ // could block on the datasource for a significant amount of time.
+ // During that time we'd be unable to abort the preparation phase
+ // without this prefill.
+
+ // Initially make sure we have at least 192 KB for the sniff
+ // to complete without blocking.
+ static const size_t kMinBytesForSniffing = 192 * 1024;
+ static const size_t kDefaultMetaSize = 200000;
+
+ status_t finalStatus;
+
+ size_t cachedDataRemaining =
+ mCachedSource->approxDataRemaining(&finalStatus);
+
+ if (finalStatus != OK || (mMetaDataSize >= 0
+ && (off64_t)cachedDataRemaining >= mMetaDataSize)) {
+ ALOGV("stop caching, status %d, "
+ "metaDataSize %lld, cachedDataRemaining %zu",
+ finalStatus, mMetaDataSize, cachedDataRemaining);
+ return OK;
+ }
+
+ ALOGV("now cached %zu bytes of data", cachedDataRemaining);
+
+ if (mMetaDataSize < 0
+ && cachedDataRemaining >= kMinBytesForSniffing) {
+ String8 tmp;
+ float confidence;
+ sp<AMessage> meta;
+ if (!mCachedSource->sniff(&tmp, &confidence, &meta)) {
+ return UNKNOWN_ERROR;
+ }
+
+ // We successfully identified the file's extractor to
+ // be, remember this mime type so we don't have to
+ // sniff it again when we call MediaExtractor::Create()
+ mSniffedMIME = tmp.string();
+
+ if (meta == NULL
+ || !meta->findInt64("meta-data-size",
+ reinterpret_cast<int64_t*>(&mMetaDataSize))) {
+ mMetaDataSize = kDefaultMetaSize;
+ }
+
+ if (mMetaDataSize < 0ll) {
+ ALOGE("invalid metaDataSize = %lld bytes", mMetaDataSize);
+ return UNKNOWN_ERROR;
+ }
+ }
+
+ return -EAGAIN;
+}
+
void NuPlayer::GenericSource::start() {
ALOGI("start");
diff --git a/media/libmediaplayerservice/nuplayer/GenericSource.h b/media/libmediaplayerservice/nuplayer/GenericSource.h
index d3081de..946307c 100644
--- a/media/libmediaplayerservice/nuplayer/GenericSource.h
+++ b/media/libmediaplayerservice/nuplayer/GenericSource.h
@@ -33,6 +33,7 @@ struct DataSource;
struct IMediaHTTPService;
struct MediaSource;
class MediaBuffer;
+struct NuCachedSource2;
struct NuPlayer::GenericSource : public NuPlayer::Source {
GenericSource(const sp<AMessage> &notify, bool uidValid, uid_t uid);
@@ -105,14 +106,21 @@ private:
int64_t mOffset;
int64_t mLength;
- sp<ALooper> mLooper;
+ sp<DataSource> mDataSource;
+ sp<NuCachedSource2> mCachedSource;
+ String8 mContentType;
+ AString mSniffedMIME;
+ off64_t mMetaDataSize;
+ sp<ALooper> mLooper;
void resetDataSource();
- status_t initFromDataSource(
- const sp<DataSource> &dataSource,
- const char *mime);
+ status_t initFromDataSource();
+
+ status_t prefillCacheIfNecessary();
+
+ void notifyPreparedAndCleanup(status_t err);
void onPrepareAsync();