Merge "Properly identify how much metadata we need to cache in order to instantiate" into ics-mr1

This commit is contained in:
Andreas Huber
2011-12-05 12:01:26 -08:00
committed by Android (Google) Code Review
3 changed files with 136 additions and 41 deletions

View File

@ -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;

View File

@ -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;
}

View File

@ -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);
}