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

Commit e6198959 authored by Chong Zhang's avatar Chong Zhang Committed by Android Git Automerger
Browse files

am b534f461: Merge "move cache prefill to GenericSource\'s message handler" into lmp-dev

* commit 'b534f461':
  move cache prefill to GenericSource's message handler
parents 687ee2d4 b534f461
Loading
Loading
Loading
Loading
+1 −5
Original line number Original line Diff line number Diff line
@@ -48,7 +48,7 @@ public:
            const sp<IMediaHTTPService> &httpService,
            const sp<IMediaHTTPService> &httpService,
            const char *uri,
            const char *uri,
            const KeyedVector<String8, String8> *headers = NULL,
            const KeyedVector<String8, String8> *headers = NULL,
            AString *sniffedMIME = NULL);
            String8 *contentType = NULL);


    DataSource() {}
    DataSource() {}


@@ -102,10 +102,6 @@ protected:
    virtual ~DataSource() {}
    virtual ~DataSource() {}


private:
private:
    enum {
        kDefaultMetaSize = 200000,
    };

    static Mutex gSnifferMutex;
    static Mutex gSnifferMutex;
    static List<SnifferFunc> gSniffers;
    static List<SnifferFunc> gSniffers;
    static bool gSniffersRegistered;
    static bool gSniffersRegistered;
+123 −24
Original line number Original line Diff line number Diff line
@@ -32,6 +32,7 @@
#include <media/stagefright/MediaExtractor.h>
#include <media/stagefright/MediaExtractor.h>
#include <media/stagefright/MediaSource.h>
#include <media/stagefright/MediaSource.h>
#include <media/stagefright/MetaData.h>
#include <media/stagefright/MetaData.h>
#include "../../libstagefright/include/NuCachedSource2.h"
#include "../../libstagefright/include/WVMExtractor.h"
#include "../../libstagefright/include/WVMExtractor.h"


namespace android {
namespace android {
@@ -47,7 +48,8 @@ NuPlayer::GenericSource::GenericSource(
      mAudioIsVorbis(false),
      mAudioIsVorbis(false),
      mIsWidevine(false),
      mIsWidevine(false),
      mUIDValid(uidValid),
      mUIDValid(uidValid),
      mUID(uid) {
      mUID(uid),
      mMetaDataSize(-1ll) {
    resetDataSource();
    resetDataSource();
    DataSource::RegisterDefaultSniffers();
    DataSource::RegisterDefaultSniffers();
}
}
@@ -92,18 +94,18 @@ status_t NuPlayer::GenericSource::setDataSource(
    return OK;
    return OK;
}
}


status_t NuPlayer::GenericSource::initFromDataSource(
status_t NuPlayer::GenericSource::initFromDataSource() {
        const sp<DataSource> &dataSource,
        const char* mime) {
    sp<MediaExtractor> extractor;
    sp<MediaExtractor> extractor;


    CHECK(mDataSource != NULL);

    if (mIsWidevine) {
    if (mIsWidevine) {
        String8 mimeType;
        String8 mimeType;
        float confidence;
        float confidence;
        sp<AMessage> dummy;
        sp<AMessage> dummy;
        bool success;
        bool success;


        success = SniffWVM(dataSource, &mimeType, &confidence, &dummy);
        success = SniffWVM(mDataSource, &mimeType, &confidence, &dummy);
        if (!success
        if (!success
                || strcasecmp(
                || strcasecmp(
                    mimeType.string(), MEDIA_MIMETYPE_CONTAINER_WVM)) {
                    mimeType.string(), MEDIA_MIMETYPE_CONTAINER_WVM)) {
@@ -111,14 +113,15 @@ status_t NuPlayer::GenericSource::initFromDataSource(
            return UNKNOWN_ERROR;
            return UNKNOWN_ERROR;
        }
        }


        sp<WVMExtractor> wvmExtractor = new WVMExtractor(dataSource);
        sp<WVMExtractor> wvmExtractor = new WVMExtractor(mDataSource);
        wvmExtractor->setAdaptiveStreamingMode(true);
        wvmExtractor->setAdaptiveStreamingMode(true);
        if (mUIDValid) {
        if (mUIDValid) {
            wvmExtractor->setUID(mUID);
            wvmExtractor->setUID(mUID);
        }
        }
        extractor = wvmExtractor;
        extractor = wvmExtractor;
    } else {
    } else {
        extractor = MediaExtractor::Create(dataSource, mime);
        extractor = MediaExtractor::Create(mDataSource,
                mSniffedMIME.empty() ? NULL: mSniffedMIME.c_str());
    }
    }


    if (extractor == NULL) {
    if (extractor == NULL) {
@@ -213,34 +216,49 @@ void NuPlayer::GenericSource::prepareAsync() {


void NuPlayer::GenericSource::onPrepareAsync() {
void NuPlayer::GenericSource::onPrepareAsync() {
    // delayed data source creation
    // delayed data source creation
    AString sniffedMIME;
    if (mDataSource == NULL) {
    sp<DataSource> dataSource;

        if (!mUri.empty()) {
        if (!mUri.empty()) {
            mIsWidevine = !strncasecmp(mUri.c_str(), "widevine://", 11);
            mIsWidevine = !strncasecmp(mUri.c_str(), "widevine://", 11);


        dataSource = DataSource::CreateFromURI(
            mDataSource = DataSource::CreateFromURI(
               mHTTPService, mUri.c_str(), &mUriHeaders, &sniffedMIME);
                   mHTTPService, mUri.c_str(), &mUriHeaders, &mContentType);
        } else {
        } else {
            // set to false first, if the extractor
            // set to false first, if the extractor
            // comes back as secure, set it to true then.
            // comes back as secure, set it to true then.
            mIsWidevine = false;
            mIsWidevine = false;


        dataSource = new FileSource(mFd, mOffset, mLength);
            mDataSource = new FileSource(mFd, mOffset, mLength);
        }
        }


    if (dataSource == NULL) {
        if (mDataSource == NULL) {
            ALOGE("Failed to create data source!");
            ALOGE("Failed to create data source!");
        notifyPrepared(UNKNOWN_ERROR);
            notifyPreparedAndCleanup(UNKNOWN_ERROR);
            return;
        }

        if (mDataSource->flags() & DataSource::kIsCachingDataSource) {
            mCachedSource = static_cast<NuCachedSource2 *>(mDataSource.get());
        }
    }

    // check initial caching status
    status_t err = prefillCacheIfNecessary();
    if (err != OK) {
        if (err == -EAGAIN) {
            (new AMessage(kWhatPrepareAsync, id()))->post(200000);
        } else {
            ALOGE("Failed to prefill data cache!");
            notifyPreparedAndCleanup(UNKNOWN_ERROR);
        }
        return;
        return;
    }
    }


    status_t err = initFromDataSource(
    // init extrator from data source
            dataSource, sniffedMIME.empty() ? NULL : sniffedMIME.c_str());
    err = initFromDataSource();


    if (err != OK) {
    if (err != OK) {
        ALOGE("Failed to init from data source!");
        ALOGE("Failed to init from data source!");
        notifyPrepared(err);
        notifyPreparedAndCleanup(err);
        return;
        return;
    }
    }


@@ -258,6 +276,87 @@ void NuPlayer::GenericSource::onPrepareAsync() {
    notifyPrepared();
    notifyPrepared();
}
}


void NuPlayer::GenericSource::notifyPreparedAndCleanup(status_t err) {
    if (err != OK) {
        mMetaDataSize = -1ll;
        mContentType = "";
        mSniffedMIME = "";
        mDataSource.clear();
        mCachedSource.clear();
    }
    notifyPrepared(err);
}

status_t NuPlayer::GenericSource::prefillCacheIfNecessary() {
    CHECK(mDataSource != NULL);

    if (mCachedSource == NULL) {
        // no prefill if the data source is not cached
        return OK;
    }

    // We're not doing this for streams that appear to be audio-only
    // streams to ensure that even low bandwidth streams start
    // playing back fairly instantly.
    if (!strncasecmp(mContentType.string(), "audio/", 6)) {
        return OK;
    }

    // We're going to prefill the cache before trying to instantiate
    // the extractor below, as the latter is an operation that otherwise
    // could block on the datasource for a significant amount of time.
    // During that time we'd be unable to abort the preparation phase
    // without this prefill.

    // Initially make sure we have at least 192 KB for the sniff
    // to complete without blocking.
    static const size_t kMinBytesForSniffing = 192 * 1024;
    static const size_t kDefaultMetaSize = 200000;

    status_t finalStatus;

    size_t cachedDataRemaining =
            mCachedSource->approxDataRemaining(&finalStatus);

    if (finalStatus != OK || (mMetaDataSize >= 0
            && (off64_t)cachedDataRemaining >= mMetaDataSize)) {
        ALOGV("stop caching, status %d, "
                "metaDataSize %lld, cachedDataRemaining %zu",
                finalStatus, mMetaDataSize, cachedDataRemaining);
        return OK;
    }

    ALOGV("now cached %zu bytes of data", cachedDataRemaining);

    if (mMetaDataSize < 0
            && cachedDataRemaining >= kMinBytesForSniffing) {
        String8 tmp;
        float confidence;
        sp<AMessage> meta;
        if (!mCachedSource->sniff(&tmp, &confidence, &meta)) {
            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()
        mSniffedMIME = tmp.string();

        if (meta == NULL
                || !meta->findInt64("meta-data-size",
                        reinterpret_cast<int64_t*>(&mMetaDataSize))) {
            mMetaDataSize = kDefaultMetaSize;
        }

        if (mMetaDataSize < 0ll) {
            ALOGE("invalid metaDataSize = %lld bytes", mMetaDataSize);
            return UNKNOWN_ERROR;
        }
    }

    return -EAGAIN;
}

void NuPlayer::GenericSource::start() {
void NuPlayer::GenericSource::start() {
    ALOGI("start");
    ALOGI("start");


+12 −4
Original line number Original line Diff line number Diff line
@@ -33,6 +33,7 @@ struct DataSource;
struct IMediaHTTPService;
struct IMediaHTTPService;
struct MediaSource;
struct MediaSource;
class MediaBuffer;
class MediaBuffer;
struct NuCachedSource2;


struct NuPlayer::GenericSource : public NuPlayer::Source {
struct NuPlayer::GenericSource : public NuPlayer::Source {
    GenericSource(const sp<AMessage> &notify, bool uidValid, uid_t uid);
    GenericSource(const sp<AMessage> &notify, bool uidValid, uid_t uid);
@@ -105,14 +106,21 @@ private:
    int64_t mOffset;
    int64_t mOffset;
    int64_t mLength;
    int64_t mLength;


    sp<ALooper> mLooper;
    sp<DataSource> mDataSource;
    sp<NuCachedSource2> mCachedSource;
    String8 mContentType;
    AString mSniffedMIME;
    off64_t mMetaDataSize;


    sp<ALooper> mLooper;


    void resetDataSource();
    void resetDataSource();


    status_t initFromDataSource(
    status_t initFromDataSource();
            const sp<DataSource> &dataSource,

            const char *mime);
    status_t prefillCacheIfNecessary();

    void notifyPreparedAndCleanup(status_t err);


    void onPrepareAsync();
    void onPrepareAsync();


+7 −70
Original line number Original line Diff line number Diff line
@@ -186,9 +186,9 @@ sp<DataSource> DataSource::CreateFromURI(
        const sp<IMediaHTTPService> &httpService,
        const sp<IMediaHTTPService> &httpService,
        const char *uri,
        const char *uri,
        const KeyedVector<String8, String8> *headers,
        const KeyedVector<String8, String8> *headers,
        AString *sniffedMIME) {
        String8 *contentType) {
    if (sniffedMIME != NULL) {
    if (contentType != NULL) {
        *sniffedMIME = "";
        *contentType = "";
    }
    }


    bool isWidevine = !strncasecmp("widevine://", uri, 11);
    bool isWidevine = !strncasecmp("widevine://", uri, 11);
@@ -226,77 +226,14 @@ sp<DataSource> DataSource::CreateFromURI(
        }
        }


        if (!isWidevine) {
        if (!isWidevine) {
            String8 contentType = httpSource->getMIMEType();
            if (contentType != NULL) {
                *contentType = httpSource->getMIMEType();
            }


            sp<NuCachedSource2> cachedSource = new NuCachedSource2(
            source = new NuCachedSource2(
                    httpSource,
                    httpSource,
                    cacheConfig.isEmpty() ? NULL : cacheConfig.string(),
                    cacheConfig.isEmpty() ? NULL : cacheConfig.string(),
                    disconnectAtHighwatermark);
                    disconnectAtHighwatermark);

            if (strncasecmp(contentType.string(), "audio/", 6)) {
                // We're not doing this for streams that appear to be audio-only
                // streams to ensure that even low bandwidth streams start
                // playing back fairly instantly.

                // We're going to prefill the cache before trying to instantiate
                // the extractor below, as the latter is an operation that otherwise
                // could block on the datasource for a significant amount of time.
                // During that time we'd be unable to abort the preparation phase
                // without this prefill.

                // Initially make sure we have at least 192 KB for the sniff
                // to complete without blocking.
                static const size_t kMinBytesForSniffing = 192 * 1024;

                off64_t metaDataSize = -1ll;
                for (;;) {
                    status_t finalStatus;
                    size_t cachedDataRemaining =
                            cachedSource->approxDataRemaining(&finalStatus);

                    if (finalStatus != OK || (metaDataSize >= 0
                            && (off64_t)cachedDataRemaining >= metaDataSize)) {
                        ALOGV("stop caching, status %d, "
                                "metaDataSize %lld, cachedDataRemaining %zu",
                                finalStatus, metaDataSize, cachedDataRemaining);
                        break;
                    }

                    ALOGV("now cached %zu bytes of data", cachedDataRemaining);

                    if (metaDataSize < 0
                            && cachedDataRemaining >= kMinBytesForSniffing) {
                        String8 tmp;
                        float confidence;
                        sp<AMessage> meta;
                        if (!cachedSource->sniff(&tmp, &confidence, &meta)) {
                            return NULL;
                        }

                        // 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()
                        if (sniffedMIME != NULL) {
                            *sniffedMIME = tmp.string();
                        }

                        if (meta == NULL
                                || !meta->findInt64("meta-data-size",
                                     reinterpret_cast<int64_t*>(&metaDataSize))) {
                            metaDataSize = kDefaultMetaSize;
                        }

                        if (metaDataSize < 0ll) {
                            ALOGE("invalid metaDataSize = %lld bytes", metaDataSize);
                            return NULL;
                        }
                    }

                    usleep(200000);
                }
            }

            source = cachedSource;
        } else {
        } else {
            // We do not want that prefetching, caching, datasource wrapper
            // We do not want that prefetching, caching, datasource wrapper
            // in the widevine:// case.
            // in the widevine:// case.