diff options
author | Andreas Huber <andih@google.com> | 2011-12-05 12:01:26 -0800 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2011-12-05 12:01:26 -0800 |
commit | f2e1249846a17c69d728189a8dc67f37261f0a59 (patch) | |
tree | ffc0cb47562e1293fe946a8335cb91574e12a5d0 /media | |
parent | 003c15d72ccd3856d5abfe6d66a2a40d0eca85bc (diff) | |
parent | b8e651a6757c8e55fc3d9e5e86a13ead7326e91d (diff) | |
download | frameworks_base-f2e1249846a17c69d728189a8dc67f37261f0a59.zip frameworks_base-f2e1249846a17c69d728189a8dc67f37261f0a59.tar.gz frameworks_base-f2e1249846a17c69d728189a8dc67f37261f0a59.tar.bz2 |
Merge "Properly identify how much metadata we need to cache in order to instantiate" into ics-mr1
Diffstat (limited to 'media')
-rw-r--r-- | media/libstagefright/AwesomePlayer.cpp | 43 | ||||
-rw-r--r-- | media/libstagefright/MPEG4Extractor.cpp | 117 | ||||
-rw-r--r-- | media/libstagefright/SampleTable.cpp | 17 |
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); } |