summaryrefslogtreecommitdiffstats
path: root/media
diff options
context:
space:
mode:
authorAndreas Huber <andih@google.com>2011-12-05 11:34:43 -0800
committerAndreas Huber <andih@google.com>2011-12-05 11:34:43 -0800
commita0f2bf56e30f580535229fa6a58e7d48b762727c (patch)
treef375e7f5e9f183289bbd5c907f90b89924f11aa8 /media
parentfed8bb604c31bf6a60ca84aafed016d21d3e0f90 (diff)
downloadframeworks_av-a0f2bf56e30f580535229fa6a58e7d48b762727c.zip
frameworks_av-a0f2bf56e30f580535229fa6a58e7d48b762727c.tar.gz
frameworks_av-a0f2bf56e30f580535229fa6a58e7d48b762727c.tar.bz2
Properly identify how much metadata we need to cache in order to instantiate
the extractor without blocking (and therefore be able to abort). Change-Id: Id2acdde897e02baaeabadae70b7c95b66c9041b3 related-to-bug: 5666532
Diffstat (limited to 'media')
-rw-r--r--media/libstagefright/AwesomePlayer.cpp43
-rw-r--r--media/libstagefright/MPEG4Extractor.cpp117
-rw-r--r--media/libstagefright/SampleTable.cpp17
3 files changed, 136 insertions, 41 deletions
diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp
index f6d054d..18dd8ef 100644
--- a/media/libstagefright/AwesomePlayer.cpp
+++ b/media/libstagefright/AwesomePlayer.cpp
@@ -1949,6 +1949,8 @@ status_t AwesomePlayer::finishSetDataSource_l() {
mUri = newURI;
}
+ AString sniffedMIME;
+
if (!strncasecmp("http://", mUri.string(), 7)
|| !strncasecmp("https://", mUri.string(), 8)
|| isWidevineStreaming) {
@@ -1998,7 +2000,6 @@ status_t AwesomePlayer::finishSetDataSource_l() {
mConnectingDataSource.clear();
-
String8 contentType = dataSource->getMIMEType();
if (strncasecmp(contentType.string(), "audio/", 6)) {
@@ -2020,16 +2021,51 @@ status_t AwesomePlayer::finishSetDataSource_l() {
mLock.unlock();
+ // Initially make sure we have at least 128 bytes for the sniff
+ // to complete without blocking.
+ static const size_t kMinBytesForSniffing = 128;
+
+ off64_t metaDataSize = -1ll;
for (;;) {
status_t finalStatus;
size_t cachedDataRemaining =
mCachedSource->approxDataRemaining(&finalStatus);
- if (finalStatus != OK || cachedDataRemaining >= kHighWaterMarkBytes
+ if (finalStatus != OK
+ || (metaDataSize >= 0
+ && cachedDataRemaining >= metaDataSize)
|| (mFlags & PREPARE_CANCELLED)) {
break;
}
+ LOGV("now cached %d bytes of data", cachedDataRemaining);
+
+ if (metaDataSize < 0
+ && cachedDataRemaining >= kMinBytesForSniffing) {
+ String8 tmp;
+ float confidence;
+ sp<AMessage> meta;
+ if (!dataSource->sniff(&tmp, &confidence, &meta)) {
+ mLock.lock();
+ 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()
+ // below.
+ sniffedMIME = tmp.string();
+
+ if (meta == NULL
+ || !meta->findInt64(
+ "meta-data-size", &metaDataSize)) {
+ metaDataSize = kHighWaterMarkBytes;
+ }
+
+ CHECK_GE(metaDataSize, 0ll);
+ LOGV("metaDataSize = %lld bytes", metaDataSize);
+ }
+
usleep(200000);
}
@@ -2067,7 +2103,8 @@ status_t AwesomePlayer::finishSetDataSource_l() {
mWVMExtractor->setAdaptiveStreamingMode(true);
extractor = mWVMExtractor;
} else {
- extractor = MediaExtractor::Create(dataSource);
+ extractor = MediaExtractor::Create(
+ dataSource, sniffedMIME.empty() ? NULL : sniffedMIME.c_str());
if (extractor == NULL) {
return UNKNOWN_ERROR;
diff --git a/media/libstagefright/MPEG4Extractor.cpp b/media/libstagefright/MPEG4Extractor.cpp
index 1ebf0a8..f6b06c7 100644
--- a/media/libstagefright/MPEG4Extractor.cpp
+++ b/media/libstagefright/MPEG4Extractor.cpp
@@ -30,6 +30,7 @@
#include <string.h>
#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/AMessage.h>
#include <media/stagefright/DataSource.h>
#include <media/stagefright/MediaBuffer.h>
#include <media/stagefright/MediaBufferGroup.h>
@@ -2301,51 +2302,121 @@ static bool isCompatibleBrand(uint32_t fourcc) {
// Attempt to actually parse the 'ftyp' atom and determine if a suitable
// compatible brand is present.
+// Also try to identify where this file's metadata ends
+// (end of the 'moov' atom) and report it to the caller as part of
+// the metadata.
static bool BetterSniffMPEG4(
- const sp<DataSource> &source, String8 *mimeType, float *confidence) {
- uint8_t header[12];
- if (source->readAt(0, header, 12) != 12
- || memcmp("ftyp", &header[4], 4)) {
- return false;
- }
+ const sp<DataSource> &source, String8 *mimeType, float *confidence,
+ sp<AMessage> *meta) {
+ // We scan up to 128 bytes to identify this file as an MP4.
+ static const off64_t kMaxScanOffset = 128ll;
- size_t atomSize = U32_AT(&header[0]);
- if (atomSize < 16 || (atomSize % 4) != 0) {
- return false;
- }
+ off64_t offset = 0ll;
+ bool foundGoodFileType = false;
+ off64_t moovAtomEndOffset = -1ll;
+ bool done = false;
- bool success = false;
- if (isCompatibleBrand(U32_AT(&header[8]))) {
- success = true;
- } else {
- size_t numCompatibleBrands = (atomSize - 16) / 4;
- for (size_t i = 0; i < numCompatibleBrands; ++i) {
- uint8_t tmp[4];
- if (source->readAt(16 + i * 4, tmp, 4) != 4) {
+ while (!done && offset < kMaxScanOffset) {
+ uint32_t hdr[2];
+ if (source->readAt(offset, hdr, 8) < 8) {
+ return false;
+ }
+
+ uint64_t chunkSize = ntohl(hdr[0]);
+ uint32_t chunkType = ntohl(hdr[1]);
+ off64_t chunkDataOffset = offset + 8;
+
+ if (chunkSize == 1) {
+ if (source->readAt(offset + 8, &chunkSize, 8) < 8) {
return false;
}
- if (isCompatibleBrand(U32_AT(&tmp[0]))) {
- success = true;
+ chunkSize = ntoh64(chunkSize);
+ chunkDataOffset += 8;
+
+ if (chunkSize < 16) {
+ // The smallest valid chunk is 16 bytes long in this case.
+ return false;
+ }
+ } else if (chunkSize < 8) {
+ // The smallest valid chunk is 8 bytes long.
+ return false;
+ }
+
+ off64_t chunkDataSize = offset + chunkSize - chunkDataOffset;
+
+ switch (chunkType) {
+ case FOURCC('f', 't', 'y', 'p'):
+ {
+ if (chunkDataSize < 8) {
+ return false;
+ }
+
+ uint32_t numCompatibleBrands = (chunkDataSize - 8) / 4;
+ for (size_t i = 0; i < numCompatibleBrands + 2; ++i) {
+ if (i == 1) {
+ // Skip this index, it refers to the minorVersion,
+ // not a brand.
+ continue;
+ }
+
+ uint32_t brand;
+ if (source->readAt(
+ chunkDataOffset + 4 * i, &brand, 4) < 4) {
+ return false;
+ }
+
+ brand = ntohl(brand);
+
+ if (isCompatibleBrand(brand)) {
+ foundGoodFileType = true;
+ break;
+ }
+ }
+
+ if (!foundGoodFileType) {
+ return false;
+ }
+
break;
}
+
+ case FOURCC('m', 'o', 'o', 'v'):
+ {
+ moovAtomEndOffset = offset + chunkSize;
+
+ done = true;
+ break;
+ }
+
+ default:
+ break;
}
+
+ offset += chunkSize;
}
- if (!success) {
+ if (!foundGoodFileType) {
return false;
}
*mimeType = MEDIA_MIMETYPE_CONTAINER_MPEG4;
*confidence = 0.4f;
+ if (moovAtomEndOffset >= 0) {
+ *meta = new AMessage;
+ (*meta)->setInt64("meta-data-size", moovAtomEndOffset);
+
+ LOGV("found metadata size: %lld", moovAtomEndOffset);
+ }
+
return true;
}
bool SniffMPEG4(
const sp<DataSource> &source, String8 *mimeType, float *confidence,
- sp<AMessage> *) {
- if (BetterSniffMPEG4(source, mimeType, confidence)) {
+ sp<AMessage> *meta) {
+ if (BetterSniffMPEG4(source, mimeType, confidence, meta)) {
return true;
}
diff --git a/media/libstagefright/SampleTable.cpp b/media/libstagefright/SampleTable.cpp
index ebad321..69d1785 100644
--- a/media/libstagefright/SampleTable.cpp
+++ b/media/libstagefright/SampleTable.cpp
@@ -631,14 +631,7 @@ status_t SampleTable::findSyncSampleNear(
--left;
}
- uint32_t x;
- if (mDataSource->readAt(
- mSyncSampleOffset + 8 + left * 4, &x, 4) != 4) {
- return ERROR_IO;
- }
-
- x = ntohl(x);
- --x;
+ uint32_t x = mSyncSamples[left];
if (left + 1 < mNumSyncSamples) {
uint32_t y = mSyncSamples[left + 1];
@@ -679,13 +672,7 @@ status_t SampleTable::findSyncSampleNear(
if (x > start_sample_index) {
CHECK(left > 0);
- if (mDataSource->readAt(
- mSyncSampleOffset + 8 + (left - 1) * 4, &x, 4) != 4) {
- return ERROR_IO;
- }
-
- x = ntohl(x);
- --x;
+ x = mSyncSamples[left - 1];
CHECK(x <= start_sample_index);
}