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

Commit a7346034 authored by Chris Watkins's avatar Chris Watkins Committed by Android (Google) Code Review
Browse files

Merge "stagefright: add a 2kb cache for CallbackDataSource."

parents 7184bab9 da7e453e
Loading
Loading
Loading
Loading
+49 −3
Original line number Diff line number Diff line
@@ -70,9 +70,10 @@ ssize_t CallbackDataSource::readAt(off64_t offset, void* data, size_t size) {
        if (numRead == 0) {
            return totalNumRead;
        }
        // Sanity check.
        CHECK((size_t)numRead <= numToRead && numRead >= 0 &&
                (size_t)numRead <= bufferSize);
        if ((size_t)numRead > numToRead) {
            return ERROR_OUT_OF_RANGE;
        }
        CHECK(numRead >= 0 && (size_t)numRead <= bufferSize);
        memcpy(((uint8_t*)data) + totalNumRead, mMemory->pointer(), numRead);
        numLeft -= numRead;
        totalNumRead += numRead;
@@ -94,4 +95,49 @@ status_t CallbackDataSource::getSize(off64_t *size) {
    return OK;
}

TinyCacheSource::TinyCacheSource(const sp<DataSource>& source)
    : mSource(source), mCachedOffset(0), mCachedSize(0) {
}

status_t TinyCacheSource::initCheck() const {
    return mSource->initCheck();
}

ssize_t TinyCacheSource::readAt(off64_t offset, void* data, size_t size) {
    if (size >= kCacheSize) {
        return mSource->readAt(offset, data, size);
    }

    // Check if the cache satisfies the read.
    if (offset >= mCachedOffset && offset + size <= mCachedOffset + mCachedSize) {
        memcpy(data, &mCache[offset - mCachedOffset], size);
        return size;
    }

    // Fill the cache and copy to the caller.
    const ssize_t numRead = mSource->readAt(offset, mCache, kCacheSize);
    if (numRead <= 0) {
        return numRead;
    }
    if ((size_t)numRead > kCacheSize) {
        return ERROR_OUT_OF_RANGE;
    }

    mCachedSize = numRead;
    mCachedOffset = offset;
    CHECK(mCachedSize <= kCacheSize && mCachedOffset >= 0);
    const size_t numToReturn = std::min(size, (size_t)numRead);
    memcpy(data, mCache, numToReturn);

    return numToReturn;
}

status_t TinyCacheSource::getSize(off64_t *size) {
    return mSource->getSize(size);
}

uint32_t TinyCacheSource::flags() {
    return mSource->flags();
}

} // namespace android
+1 −1
Original line number Diff line number Diff line
@@ -283,7 +283,7 @@ sp<DataSource> DataSource::CreateMediaHTTP(const sp<IMediaHTTPService> &httpServ
}

sp<DataSource> DataSource::CreateFromIDataSource(const sp<IDataSource> &source) {
    return new CallbackDataSource(source);
    return new TinyCacheSource(new CallbackDataSource(source));
}

String8 DataSource::getMIMEType() const {
+30 −0
Original line number Diff line number Diff line
@@ -44,6 +44,36 @@ private:
    DISALLOW_EVIL_CONSTRUCTORS(CallbackDataSource);
};


// A caching DataSource that wraps a CallbackDataSource. For reads smaller
// than kCacheSize it will read up to kCacheSize ahead and cache it.
// This reduces the number of binder round trips to the IDataSource and has a significant
// impact on time taken for filetype sniffing and metadata extraction.
class TinyCacheSource : public DataSource {
public:
    TinyCacheSource(const sp<DataSource>& source);

    virtual status_t initCheck() const;
    virtual ssize_t readAt(off64_t offset, void* data, size_t size);
    virtual status_t getSize(off64_t* size);
    virtual uint32_t flags();

private:
    // 2kb comes from experimenting with the time-to-first-frame from a MediaPlayer
    // with an in-memory MediaDataSource source on a Nexus 5. Beyond 2kb there was
    // no improvement.
    enum {
        kCacheSize = 2048,
    };

    sp<DataSource> mSource;
    uint8_t mCache[kCacheSize];
    off64_t mCachedOffset;
    size_t mCachedSize;

    DISALLOW_EVIL_CONSTRUCTORS(TinyCacheSource);
};

}; // namespace android

#endif // ANDROID_CALLBACKDATASOURCE_H