Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f2e12498 authored by Andreas Huber's avatar Andreas Huber Committed by Android (Google) Code Review
Browse files

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

parents 003c15d7 b8e651a6
Loading
Loading
Loading
Loading
+40 −3
Original line number Diff line number Diff line
@@ -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;
+94 −23
Original line number Diff line number Diff line
@@ -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)) {
        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;
    }

+2 −15
Original line number Diff line number Diff line
@@ -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);
            }