Loading media/libstagefright/AwesomePlayer.cpp +40 −3 Original line number Diff line number Diff line Loading @@ -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) { Loading Loading @@ -1998,7 +2000,6 @@ status_t AwesomePlayer::finishSetDataSource_l() { mConnectingDataSource.clear(); String8 contentType = dataSource->getMIMEType(); if (strncasecmp(contentType.string(), "audio/", 6)) { Loading @@ -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); } Loading Loading @@ -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; Loading media/libstagefright/MPEG4Extractor.cpp +94 −23 Original line number Diff line number Diff line Loading @@ -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> Loading Loading @@ -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)) { 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; off64_t offset = 0ll; bool foundGoodFileType = false; off64_t moovAtomEndOffset = -1ll; bool done = false; while (!done && offset < kMaxScanOffset) { uint32_t hdr[2]; if (source->readAt(offset, hdr, 8) < 8) { return false; } size_t atomSize = U32_AT(&header[0]); if (atomSize < 16 || (atomSize % 4) != 0) { 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; } 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) { 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; } if (isCompatibleBrand(U32_AT(&tmp[0]))) { success = true; 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; } Loading media/libstagefright/SampleTable.cpp +2 −15 Original line number Diff line number Diff line Loading @@ -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]; Loading Loading @@ -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); } Loading Loading
media/libstagefright/AwesomePlayer.cpp +40 −3 Original line number Diff line number Diff line Loading @@ -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) { Loading Loading @@ -1998,7 +2000,6 @@ status_t AwesomePlayer::finishSetDataSource_l() { mConnectingDataSource.clear(); String8 contentType = dataSource->getMIMEType(); if (strncasecmp(contentType.string(), "audio/", 6)) { Loading @@ -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); } Loading Loading @@ -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; Loading
media/libstagefright/MPEG4Extractor.cpp +94 −23 Original line number Diff line number Diff line Loading @@ -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> Loading Loading @@ -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)) { 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; off64_t offset = 0ll; bool foundGoodFileType = false; off64_t moovAtomEndOffset = -1ll; bool done = false; while (!done && offset < kMaxScanOffset) { uint32_t hdr[2]; if (source->readAt(offset, hdr, 8) < 8) { return false; } size_t atomSize = U32_AT(&header[0]); if (atomSize < 16 || (atomSize % 4) != 0) { 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; } 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) { 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; } if (isCompatibleBrand(U32_AT(&tmp[0]))) { success = true; 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; } Loading
media/libstagefright/SampleTable.cpp +2 −15 Original line number Diff line number Diff line Loading @@ -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]; Loading Loading @@ -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); } Loading