summaryrefslogtreecommitdiffstats
path: root/media
diff options
context:
space:
mode:
authorChong Zhang <chz@google.com>2014-08-05 20:54:44 -0700
committerChong Zhang <chz@google.com>2014-08-06 15:23:54 -0700
commit3de157dd8f9cd45bf9b0406268f5830887105ae1 (patch)
tree4c3423bb8c2005aac32ab3519ad73978d144b8ad /media
parent92ce4715315bddd158c7d4028556632f0547e3b9 (diff)
downloadframeworks_av-3de157dd8f9cd45bf9b0406268f5830887105ae1.zip
frameworks_av-3de157dd8f9cd45bf9b0406268f5830887105ae1.tar.gz
frameworks_av-3de157dd8f9cd45bf9b0406268f5830887105ae1.tar.bz2
some fixes for crash when extractor creation fails
- prefetch data for sniffing - notify error instead of crashing if extractor is NULL Bug: 16818302 Change-Id: I56ff4996d99ac2811d19d141f7ff7acdd7c1da17
Diffstat (limited to 'media')
-rw-r--r--media/libmediaplayerservice/nuplayer/GenericSource.cpp60
-rw-r--r--media/libmediaplayerservice/nuplayer/GenericSource.h18
-rw-r--r--media/libmediaplayerservice/nuplayer/NuPlayer.cpp46
-rw-r--r--media/libstagefright/DataSource.cpp80
-rw-r--r--media/libstagefright/include/WVMExtractor.h3
5 files changed, 152 insertions, 55 deletions
diff --git a/media/libmediaplayerservice/nuplayer/GenericSource.cpp b/media/libmediaplayerservice/nuplayer/GenericSource.cpp
index 32842bb..a18407f 100644
--- a/media/libmediaplayerservice/nuplayer/GenericSource.cpp
+++ b/media/libmediaplayerservice/nuplayer/GenericSource.cpp
@@ -37,10 +37,6 @@ namespace android {
NuPlayer::GenericSource::GenericSource(
const sp<AMessage> &notify,
- const sp<IMediaHTTPService> &httpService,
- const char *url,
- const KeyedVector<String8, String8> *headers,
- bool isWidevine,
bool uidValid,
uid_t uid)
: Source(notify),
@@ -48,38 +44,41 @@ NuPlayer::GenericSource::GenericSource(
mFetchTimedTextDataGeneration(0),
mDurationUs(0ll),
mAudioIsVorbis(false),
- mIsWidevine(isWidevine),
+ mIsWidevine(false),
mUIDValid(uidValid),
mUID(uid) {
DataSource::RegisterDefaultSniffers();
+}
+
+status_t NuPlayer::GenericSource::init(
+ const sp<IMediaHTTPService> &httpService,
+ const char *url,
+ const KeyedVector<String8, String8> *headers) {
+ mIsWidevine = !strncasecmp(url, "widevine://", 11);
+
+ AString sniffedMIME;
sp<DataSource> dataSource =
- DataSource::CreateFromURI(httpService, url, headers);
- CHECK(dataSource != NULL);
+ DataSource::CreateFromURI(httpService, url, headers, &sniffedMIME);
- initFromDataSource(dataSource);
-}
+ if (dataSource == NULL) {
+ return UNKNOWN_ERROR;
+ }
-NuPlayer::GenericSource::GenericSource(
- const sp<AMessage> &notify,
- int fd, int64_t offset, int64_t length)
- : Source(notify),
- mFetchSubtitleDataGeneration(0),
- mFetchTimedTextDataGeneration(0),
- mDurationUs(0ll),
- mAudioIsVorbis(false),
- mIsWidevine(false),
- mUIDValid(false),
- mUID(0) {
- DataSource::RegisterDefaultSniffers();
+ return initFromDataSource(
+ dataSource, sniffedMIME.empty() ? NULL : sniffedMIME.c_str());
+}
+status_t NuPlayer::GenericSource::init(
+ int fd, int64_t offset, int64_t length) {
sp<DataSource> dataSource = new FileSource(dup(fd), offset, length);
- initFromDataSource(dataSource);
+ return initFromDataSource(dataSource, NULL);
}
-void NuPlayer::GenericSource::initFromDataSource(
- const sp<DataSource> &dataSource) {
+status_t NuPlayer::GenericSource::initFromDataSource(
+ const sp<DataSource> &dataSource,
+ const char* mime) {
sp<MediaExtractor> extractor;
if (mIsWidevine) {
@@ -93,7 +92,7 @@ void NuPlayer::GenericSource::initFromDataSource(
|| strcasecmp(
mimeType.string(), MEDIA_MIMETYPE_CONTAINER_WVM)) {
ALOGE("unsupported widevine mime: %s", mimeType.string());
- return;
+ return UNKNOWN_ERROR;
}
sp<WVMExtractor> wvmExtractor = new WVMExtractor(dataSource);
@@ -103,10 +102,12 @@ void NuPlayer::GenericSource::initFromDataSource(
}
extractor = wvmExtractor;
} else {
- extractor = MediaExtractor::Create(dataSource);
+ extractor = MediaExtractor::Create(dataSource, mime);
}
- CHECK(extractor != NULL);
+ if (extractor == NULL) {
+ return UNKNOWN_ERROR;
+ }
sp<MetaData> fileMeta = extractor->getMetaData();
if (fileMeta != NULL) {
@@ -144,6 +145,9 @@ void NuPlayer::GenericSource::initFromDataSource(
int32_t secure;
if (meta->findInt32(kKeyRequiresSecureBuffers, &secure) && secure) {
mIsWidevine = true;
+ if (mUIDValid) {
+ extractor->setUID(mUID);
+ }
}
}
}
@@ -158,6 +162,8 @@ void NuPlayer::GenericSource::initFromDataSource(
}
}
}
+
+ return OK;
}
status_t NuPlayer::GenericSource::setBuffers(bool audio, Vector<MediaBuffer *> &buffers) {
diff --git a/media/libmediaplayerservice/nuplayer/GenericSource.h b/media/libmediaplayerservice/nuplayer/GenericSource.h
index 3c5f55c..76e628b 100644
--- a/media/libmediaplayerservice/nuplayer/GenericSource.h
+++ b/media/libmediaplayerservice/nuplayer/GenericSource.h
@@ -34,18 +34,14 @@ struct MediaSource;
class MediaBuffer;
struct NuPlayer::GenericSource : public NuPlayer::Source {
- GenericSource(
- const sp<AMessage> &notify,
+ GenericSource(const sp<AMessage> &notify, bool uidValid, uid_t uid);
+
+ status_t init(
const sp<IMediaHTTPService> &httpService,
const char *url,
- const KeyedVector<String8, String8> *headers,
- bool isWidevine = false,
- bool uidValid = false,
- uid_t uid = 0);
+ const KeyedVector<String8, String8> *headers);
- GenericSource(
- const sp<AMessage> &notify,
- int fd, int64_t offset, int64_t length);
+ status_t init(int fd, int64_t offset, int64_t length);
virtual void prepareAsync();
@@ -101,7 +97,9 @@ private:
bool mUIDValid;
uid_t mUID;
- void initFromDataSource(const sp<DataSource> &dataSource);
+ status_t initFromDataSource(
+ const sp<DataSource> &dataSource,
+ const char *mime);
void fetchTextData(
uint32_t what, media_track_type type,
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
index 17038a4..d56b1f0 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
@@ -207,6 +207,7 @@ void NuPlayer::setDataSourceAsync(
const sp<IMediaHTTPService> &httpService,
const char *url,
const KeyedVector<String8, String8> *headers) {
+
sp<AMessage> msg = new AMessage(kWhatSetDataSource, id());
size_t len = strlen(url);
@@ -224,16 +225,21 @@ void NuPlayer::setDataSourceAsync(
|| strstr(url, ".sdp?"))) {
source = new RTSPSource(
notify, httpService, url, headers, mUIDValid, mUID, true);
- } else if ((!strncasecmp(url, "widevine://", 11))) {
- source = new GenericSource(notify, httpService, url, headers,
- true /* isWidevine */, mUIDValid, mUID);
- // Don't set FLAG_SECURE on mSourceFlags here, the correct flags
- // will be updated in Source::kWhatFlagsChanged handler when
- // GenericSource is prepared.
} else {
- source = new GenericSource(notify, httpService, url, headers);
- }
+ sp<GenericSource> genericSource =
+ new GenericSource(notify, mUIDValid, mUID);
+ // Don't set FLAG_SECURE on mSourceFlags here for widevine.
+ // The correct flags will be updated in Source::kWhatFlagsChanged
+ // handler when GenericSource is prepared.
+ status_t err = genericSource->init(httpService, url, headers);
+
+ if (err == OK) {
+ source = genericSource;
+ } else {
+ ALOGE("Failed to initialize generic source!");
+ }
+ }
msg->setObject("source", source);
msg->post();
}
@@ -243,7 +249,16 @@ void NuPlayer::setDataSourceAsync(int fd, int64_t offset, int64_t length) {
sp<AMessage> notify = new AMessage(kWhatSourceNotify, id());
- sp<Source> source = new GenericSource(notify, fd, offset, length);
+ sp<GenericSource> source =
+ new GenericSource(notify, mUIDValid, mUID);
+
+ status_t err = source->init(fd, offset, length);
+
+ if (err != OK) {
+ ALOGE("Failed to initialize generic source!");
+ source = NULL;
+ }
+
msg->setObject("source", source);
msg->post();
}
@@ -352,17 +367,20 @@ void NuPlayer::onMessageReceived(const sp<AMessage> &msg) {
CHECK(mSource == NULL);
+ status_t err = OK;
sp<RefBase> obj;
CHECK(msg->findObject("source", &obj));
-
- mSource = static_cast<Source *>(obj.get());
-
- looper()->registerHandler(mSource);
+ if (obj != NULL) {
+ mSource = static_cast<Source *>(obj.get());
+ looper()->registerHandler(mSource);
+ } else {
+ err = UNKNOWN_ERROR;
+ }
CHECK(mDriver != NULL);
sp<NuPlayerDriver> driver = mDriver.promote();
if (driver != NULL) {
- driver->notifySetDataSourceCompleted(OK);
+ driver->notifySetDataSourceCompleted(err);
}
break;
}
diff --git a/media/libstagefright/DataSource.cpp b/media/libstagefright/DataSource.cpp
index 6e0f37a..908cdca 100644
--- a/media/libstagefright/DataSource.cpp
+++ b/media/libstagefright/DataSource.cpp
@@ -13,6 +13,8 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+//#define LOG_NDEBUG 0
+#define LOG_TAG "DataSource"
#include "include/AMRExtractor.h"
@@ -33,6 +35,7 @@
#include <media/IMediaHTTPConnection.h>
#include <media/IMediaHTTPService.h>
+#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/foundation/AMessage.h>
#include <media/stagefright/DataSource.h>
#include <media/stagefright/DataURISource.h>
@@ -182,7 +185,12 @@ void DataSource::RegisterDefaultSniffers() {
sp<DataSource> DataSource::CreateFromURI(
const sp<IMediaHTTPService> &httpService,
const char *uri,
- const KeyedVector<String8, String8> *headers) {
+ const KeyedVector<String8, String8> *headers,
+ AString *sniffedMIME) {
+ if (sniffedMIME != NULL) {
+ *sniffedMIME = "";
+ }
+
bool isWidevine = !strncasecmp("widevine://", uri, 11);
sp<DataSource> source;
@@ -202,6 +210,7 @@ sp<DataSource> DataSource::CreateFromURI(
}
if (httpSource->connect(uri, headers) != OK) {
+ ALOGE("Failed to connect http source!");
return NULL;
}
@@ -214,9 +223,76 @@ sp<DataSource> DataSource::CreateFromURI(
&copy, &cacheConfig, &disconnectAtHighwatermark);
}
- source = new NuCachedSource2(
+ sp<NuCachedSource2> cachedSource = new NuCachedSource2(
httpSource,
cacheConfig.isEmpty() ? NULL : cacheConfig.string());
+
+ String8 contentType = httpSource->getMIMEType();
+
+ if (strncasecmp(contentType.string(), "audio/", 6)) {
+ // 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.
+
+ // 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;
+
+ off64_t metaDataSize = -1ll;
+ for (;;) {
+ status_t finalStatus;
+ size_t cachedDataRemaining =
+ cachedSource->approxDataRemaining(&finalStatus);
+
+ if (finalStatus != OK || (metaDataSize >= 0
+ && (off64_t)cachedDataRemaining >= metaDataSize)) {
+ ALOGV("stop caching, status %d, "
+ "metaDataSize %lld, cachedDataRemaining %zu",
+ finalStatus, metaDataSize, cachedDataRemaining);
+ break;
+ }
+
+ ALOGV("now cached %zu bytes of data", cachedDataRemaining);
+
+ if (metaDataSize < 0
+ && cachedDataRemaining >= kMinBytesForSniffing) {
+ String8 tmp;
+ float confidence;
+ sp<AMessage> meta;
+ if (!cachedSource->sniff(&tmp, &confidence, &meta)) {
+ return NULL;
+ }
+
+ // 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()
+ if (sniffedMIME != NULL) {
+ *sniffedMIME = tmp.string();
+ }
+
+ if (meta == NULL
+ || !meta->findInt64("meta-data-size",
+ reinterpret_cast<int64_t*>(&metaDataSize))) {
+ metaDataSize = kDefaultMetaSize;
+ }
+
+ if (metaDataSize < 0ll) {
+ ALOGE("invalid metaDataSize = %lld bytes", metaDataSize);
+ return NULL;
+ }
+ }
+
+ usleep(200000);
+ }
+ }
+
+ source = cachedSource;
} else {
// We do not want that prefetching, caching, datasource wrapper
// in the widevine:// case.
diff --git a/media/libstagefright/include/WVMExtractor.h b/media/libstagefright/include/WVMExtractor.h
index 8e62946..ab7e8b8 100644
--- a/media/libstagefright/include/WVMExtractor.h
+++ b/media/libstagefright/include/WVMExtractor.h
@@ -49,6 +49,7 @@ public:
virtual sp<MediaSource> getTrack(size_t index);
virtual sp<MetaData> getTrackMetaData(size_t index, uint32_t flags);
virtual sp<MetaData> getMetaData();
+ virtual void setUID(uid_t uid);
// Return the amount of data cached from the current
// playback positiion (in us).
@@ -74,8 +75,6 @@ public:
// codec.
void setCryptoPluginMode(bool cryptoPluginMode);
- void setUID(uid_t uid);
-
static bool getVendorLibHandle();
status_t getError();