Skip to content

Commit f2e1249

Browse files
theandi666Android (Google) Code Review
authored andcommitted
Merge "Properly identify how much metadata we need to cache in order to instantiate" into ics-mr1
2 parents 003c15d + b8e651a commit f2e1249

File tree

3 files changed

+136
-41
lines changed

3 files changed

+136
-41
lines changed

media/libstagefright/AwesomePlayer.cpp

Lines changed: 40 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1949,6 +1949,8 @@ status_t AwesomePlayer::finishSetDataSource_l() {
19491949
mUri = newURI;
19501950
}
19511951

1952+
AString sniffedMIME;
1953+
19521954
if (!strncasecmp("http://", mUri.string(), 7)
19531955
|| !strncasecmp("https://", mUri.string(), 8)
19541956
|| isWidevineStreaming) {
@@ -1998,7 +2000,6 @@ status_t AwesomePlayer::finishSetDataSource_l() {
19982000

19992001
mConnectingDataSource.clear();
20002002

2001-
20022003
String8 contentType = dataSource->getMIMEType();
20032004

20042005
if (strncasecmp(contentType.string(), "audio/", 6)) {
@@ -2020,16 +2021,51 @@ status_t AwesomePlayer::finishSetDataSource_l() {
20202021

20212022
mLock.unlock();
20222023

2024+
// Initially make sure we have at least 128 bytes for the sniff
2025+
// to complete without blocking.
2026+
static const size_t kMinBytesForSniffing = 128;
2027+
2028+
off64_t metaDataSize = -1ll;
20232029
for (;;) {
20242030
status_t finalStatus;
20252031
size_t cachedDataRemaining =
20262032
mCachedSource->approxDataRemaining(&finalStatus);
20272033

2028-
if (finalStatus != OK || cachedDataRemaining >= kHighWaterMarkBytes
2034+
if (finalStatus != OK
2035+
|| (metaDataSize >= 0
2036+
&& cachedDataRemaining >= metaDataSize)
20292037
|| (mFlags & PREPARE_CANCELLED)) {
20302038
break;
20312039
}
20322040

2041+
LOGV("now cached %d bytes of data", cachedDataRemaining);
2042+
2043+
if (metaDataSize < 0
2044+
&& cachedDataRemaining >= kMinBytesForSniffing) {
2045+
String8 tmp;
2046+
float confidence;
2047+
sp<AMessage> meta;
2048+
if (!dataSource->sniff(&tmp, &confidence, &meta)) {
2049+
mLock.lock();
2050+
return UNKNOWN_ERROR;
2051+
}
2052+
2053+
// We successfully identified the file's extractor to
2054+
// be, remember this mime type so we don't have to
2055+
// sniff it again when we call MediaExtractor::Create()
2056+
// below.
2057+
sniffedMIME = tmp.string();
2058+
2059+
if (meta == NULL
2060+
|| !meta->findInt64(
2061+
"meta-data-size", &metaDataSize)) {
2062+
metaDataSize = kHighWaterMarkBytes;
2063+
}
2064+
2065+
CHECK_GE(metaDataSize, 0ll);
2066+
LOGV("metaDataSize = %lld bytes", metaDataSize);
2067+
}
2068+
20332069
usleep(200000);
20342070
}
20352071

@@ -2067,7 +2103,8 @@ status_t AwesomePlayer::finishSetDataSource_l() {
20672103
mWVMExtractor->setAdaptiveStreamingMode(true);
20682104
extractor = mWVMExtractor;
20692105
} else {
2070-
extractor = MediaExtractor::Create(dataSource);
2106+
extractor = MediaExtractor::Create(
2107+
dataSource, sniffedMIME.empty() ? NULL : sniffedMIME.c_str());
20712108

20722109
if (extractor == NULL) {
20732110
return UNKNOWN_ERROR;

media/libstagefright/MPEG4Extractor.cpp

Lines changed: 94 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
#include <string.h>
3131

3232
#include <media/stagefright/foundation/ADebug.h>
33+
#include <media/stagefright/foundation/AMessage.h>
3334
#include <media/stagefright/DataSource.h>
3435
#include <media/stagefright/MediaBuffer.h>
3536
#include <media/stagefright/MediaBufferGroup.h>
@@ -2301,51 +2302,121 @@ static bool isCompatibleBrand(uint32_t fourcc) {
23012302

23022303
// Attempt to actually parse the 'ftyp' atom and determine if a suitable
23032304
// compatible brand is present.
2305+
// Also try to identify where this file's metadata ends
2306+
// (end of the 'moov' atom) and report it to the caller as part of
2307+
// the metadata.
23042308
static bool BetterSniffMPEG4(
2305-
const sp<DataSource> &source, String8 *mimeType, float *confidence) {
2306-
uint8_t header[12];
2307-
if (source->readAt(0, header, 12) != 12
2308-
|| memcmp("ftyp", &header[4], 4)) {
2309-
return false;
2310-
}
2309+
const sp<DataSource> &source, String8 *mimeType, float *confidence,
2310+
sp<AMessage> *meta) {
2311+
// We scan up to 128 bytes to identify this file as an MP4.
2312+
static const off64_t kMaxScanOffset = 128ll;
23112313

2312-
size_t atomSize = U32_AT(&header[0]);
2313-
if (atomSize < 16 || (atomSize % 4) != 0) {
2314-
return false;
2315-
}
2314+
off64_t offset = 0ll;
2315+
bool foundGoodFileType = false;
2316+
off64_t moovAtomEndOffset = -1ll;
2317+
bool done = false;
23162318

2317-
bool success = false;
2318-
if (isCompatibleBrand(U32_AT(&header[8]))) {
2319-
success = true;
2320-
} else {
2321-
size_t numCompatibleBrands = (atomSize - 16) / 4;
2322-
for (size_t i = 0; i < numCompatibleBrands; ++i) {
2323-
uint8_t tmp[4];
2324-
if (source->readAt(16 + i * 4, tmp, 4) != 4) {
2319+
while (!done && offset < kMaxScanOffset) {
2320+
uint32_t hdr[2];
2321+
if (source->readAt(offset, hdr, 8) < 8) {
2322+
return false;
2323+
}
2324+
2325+
uint64_t chunkSize = ntohl(hdr[0]);
2326+
uint32_t chunkType = ntohl(hdr[1]);
2327+
off64_t chunkDataOffset = offset + 8;
2328+
2329+
if (chunkSize == 1) {
2330+
if (source->readAt(offset + 8, &chunkSize, 8) < 8) {
23252331
return false;
23262332
}
23272333

2328-
if (isCompatibleBrand(U32_AT(&tmp[0]))) {
2329-
success = true;
2334+
chunkSize = ntoh64(chunkSize);
2335+
chunkDataOffset += 8;
2336+
2337+
if (chunkSize < 16) {
2338+
// The smallest valid chunk is 16 bytes long in this case.
2339+
return false;
2340+
}
2341+
} else if (chunkSize < 8) {
2342+
// The smallest valid chunk is 8 bytes long.
2343+
return false;
2344+
}
2345+
2346+
off64_t chunkDataSize = offset + chunkSize - chunkDataOffset;
2347+
2348+
switch (chunkType) {
2349+
case FOURCC('f', 't', 'y', 'p'):
2350+
{
2351+
if (chunkDataSize < 8) {
2352+
return false;
2353+
}
2354+
2355+
uint32_t numCompatibleBrands = (chunkDataSize - 8) / 4;
2356+
for (size_t i = 0; i < numCompatibleBrands + 2; ++i) {
2357+
if (i == 1) {
2358+
// Skip this index, it refers to the minorVersion,
2359+
// not a brand.
2360+
continue;
2361+
}
2362+
2363+
uint32_t brand;
2364+
if (source->readAt(
2365+
chunkDataOffset + 4 * i, &brand, 4) < 4) {
2366+
return false;
2367+
}
2368+
2369+
brand = ntohl(brand);
2370+
2371+
if (isCompatibleBrand(brand)) {
2372+
foundGoodFileType = true;
2373+
break;
2374+
}
2375+
}
2376+
2377+
if (!foundGoodFileType) {
2378+
return false;
2379+
}
2380+
23302381
break;
23312382
}
2383+
2384+
case FOURCC('m', 'o', 'o', 'v'):
2385+
{
2386+
moovAtomEndOffset = offset + chunkSize;
2387+
2388+
done = true;
2389+
break;
2390+
}
2391+
2392+
default:
2393+
break;
23322394
}
2395+
2396+
offset += chunkSize;
23332397
}
23342398

2335-
if (!success) {
2399+
if (!foundGoodFileType) {
23362400
return false;
23372401
}
23382402

23392403
*mimeType = MEDIA_MIMETYPE_CONTAINER_MPEG4;
23402404
*confidence = 0.4f;
23412405

2406+
if (moovAtomEndOffset >= 0) {
2407+
*meta = new AMessage;
2408+
(*meta)->setInt64("meta-data-size", moovAtomEndOffset);
2409+
2410+
LOGV("found metadata size: %lld", moovAtomEndOffset);
2411+
}
2412+
23422413
return true;
23432414
}
23442415

23452416
bool SniffMPEG4(
23462417
const sp<DataSource> &source, String8 *mimeType, float *confidence,
2347-
sp<AMessage> *) {
2348-
if (BetterSniffMPEG4(source, mimeType, confidence)) {
2418+
sp<AMessage> *meta) {
2419+
if (BetterSniffMPEG4(source, mimeType, confidence, meta)) {
23492420
return true;
23502421
}
23512422

media/libstagefright/SampleTable.cpp

Lines changed: 2 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -631,14 +631,7 @@ status_t SampleTable::findSyncSampleNear(
631631
--left;
632632
}
633633

634-
uint32_t x;
635-
if (mDataSource->readAt(
636-
mSyncSampleOffset + 8 + left * 4, &x, 4) != 4) {
637-
return ERROR_IO;
638-
}
639-
640-
x = ntohl(x);
641-
--x;
634+
uint32_t x = mSyncSamples[left];
642635

643636
if (left + 1 < mNumSyncSamples) {
644637
uint32_t y = mSyncSamples[left + 1];
@@ -679,13 +672,7 @@ status_t SampleTable::findSyncSampleNear(
679672
if (x > start_sample_index) {
680673
CHECK(left > 0);
681674

682-
if (mDataSource->readAt(
683-
mSyncSampleOffset + 8 + (left - 1) * 4, &x, 4) != 4) {
684-
return ERROR_IO;
685-
}
686-
687-
x = ntohl(x);
688-
--x;
675+
x = mSyncSamples[left - 1];
689676

690677
CHECK(x <= start_sample_index);
691678
}

0 commit comments

Comments
 (0)