diff options
author | Andreas Huber <andih@google.com> | 2011-12-05 13:30:52 -0800 |
---|---|---|
committer | Andreas Huber <andih@google.com> | 2011-12-05 13:31:17 -0800 |
commit | 456caf3f5f0af673dc120c17c23635f40d8f5ac2 (patch) | |
tree | 0c7007b18f37e2311147e34b44189ebf487c6991 | |
parent | 2158db000d227875b12c85c850ec6e3039553f9b (diff) | |
parent | 1a733a33e1428f577747fcd74dccd8853bd1b29f (diff) | |
download | frameworks_av-456caf3f5f0af673dc120c17c23635f40d8f5ac2.zip frameworks_av-456caf3f5f0af673dc120c17c23635f40d8f5ac2.tar.gz frameworks_av-456caf3f5f0af673dc120c17c23635f40d8f5ac2.tar.bz2 |
resolved conflicts for merge of 07bacabe to master
Change-Id: Idb56996f7c1b78d96e3d3d3f08419c4d122db0b1
-rw-r--r-- | media/libstagefright/AwesomePlayer.cpp | 43 | ||||
-rw-r--r-- | media/libstagefright/MPEG4Extractor.cpp | 117 |
2 files changed, 134 insertions, 26 deletions
diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp index 1f225a7..759d05a 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; } + ALOGV("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); + ALOGV("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 7b6fa38..0a69df4 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> @@ -2302,51 +2303,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); + + ALOGV("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; } |