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

Commit e98f14ff authored by Andy Hung's avatar Andy Hung Committed by Android (Google) Code Review
Browse files

Merge "GenericSource: Allow multiple buffer reads for video" into nyc-mr1-dev

parents 9bbbdd3c cdeb6603
Loading
Loading
Loading
Loading
+13 −0
Original line number Diff line number Diff line
@@ -131,6 +131,10 @@ public:
    // Returns true if |readMultiple| is supported, otherwise false.
    virtual bool supportReadMultiple() = 0;

    // Returns true if |read| supports nonblocking option, otherwise false.
    // |readMultiple| if supported, always allows the nonblocking option.
    virtual bool supportNonblockingRead() = 0;

    // Causes this source to suspend pulling data from its upstream source
    // until a subsequent read-with-seek. Currently only supported by
    // OMXCodec.
@@ -161,6 +165,7 @@ public:
        return ERROR_UNSUPPORTED;
    }

    // TODO: Implement this for local media sources.
    virtual status_t readMultiple(
            Vector<MediaBuffer *> * /* buffers */, uint32_t /* maxNumBuffers = 1 */,
            const ReadOptions * /* options = nullptr */) {
@@ -171,7 +176,15 @@ public:
        return false;
    }

    // Override in source if nonblocking reads are supported.
    virtual bool supportNonblockingRead() {
        return false;
    }

    static const size_t kBinderMediaBuffers = 4; // buffers managed by BnMediaSource
    static const size_t kTransferSharedAsSharedThreshold = 4 * 1024;  // if >= shared, else inline
    static const size_t kTransferInlineAsSharedThreshold = 64 * 1024; // if >= shared, else inline
    static const size_t kInlineMaxTransfer = 256 * 1024; // Binder size limited to BINDER_VM_SIZE.

protected:
    virtual ~BnMediaSource();
+6 −0
Original line number Diff line number Diff line
@@ -30,10 +30,16 @@ class MetaData;
class MediaBufferGroup : public MediaBufferObserver {
public:
    MediaBufferGroup(size_t growthLimit = 0);

    // create a media buffer group with preallocated buffers
    MediaBufferGroup(size_t buffers, size_t buffer_size, size_t growthLimit = 0);

    ~MediaBufferGroup();

    void add_buffer(MediaBuffer *buffer);

    bool has_buffers();

    // If nonBlocking is false, it blocks until a buffer is available and
    // passes it to the caller in *buffer, while returning OK.
    // The returned buffer will have a reference count of 1.
+33 −3
Original line number Diff line number Diff line
@@ -38,7 +38,8 @@ enum {
    GETFORMAT,
    // READ, deprecated
    READMULTIPLE,
    RELEASE_BUFFER
    RELEASE_BUFFER,
    SUPPORT_NONBLOCKING_READ,
};

enum {
@@ -186,10 +187,22 @@ public:
        return ret;
    }

    bool supportReadMultiple() {
    // Binder proxy adds readMultiple support.
    virtual bool supportReadMultiple() {
        return true;
    }

    virtual bool supportNonblockingRead() {
        ALOGV("supportNonblockingRead");
        Parcel data, reply;
        data.writeInterfaceToken(BpMediaSource::getInterfaceDescriptor());
        status_t ret = remote()->transact(SUPPORT_NONBLOCKING_READ, data, &reply);
        if (ret == NO_ERROR) {
            return reply.readInt32() != 0;
        }
        return false;
    }

    virtual status_t pause() {
        ALOGV("pause");
        Parcel data, reply;
@@ -325,6 +338,7 @@ status_t BnMediaSource::onTransact(

            mGroup->gc(kBinderMediaBuffers /* freeBuffers */);
            mIndexCache.gc();
            size_t inlineTransferSize = 0;
            status_t ret = NO_ERROR;
            uint32_t bufferCount = 0;
            for (; bufferCount < maxNumBuffers; ++bufferCount, ++mBuffersSinceStop) {
@@ -344,7 +358,8 @@ status_t BnMediaSource::onTransact(
                MediaBuffer *transferBuf = nullptr;
                const size_t length = buf->range_length();
                size_t offset = buf->range_offset();
                if (length >= MediaBuffer::kSharedMemThreshold) {
                if (length >= (supportNonblockingRead() && buf->mMemory != nullptr ?
                        kTransferSharedAsSharedThreshold : kTransferInlineAsSharedThreshold)) {
                    if (buf->mMemory != nullptr) {
                        ALOGV("Use shared memory: %zu", length);
                        transferBuf = buf;
@@ -366,6 +381,9 @@ status_t BnMediaSource::onTransact(
                        } else {
                            memcpy(transferBuf->data(), (uint8_t*)buf->data() + offset, length);
                            offset = 0;
                            if (!mGroup->has_buffers()) {
                                maxNumBuffers = 0; // No more MediaBuffers, stop readMultiple.
                            }
                        }
                    }
                }
@@ -395,6 +413,8 @@ status_t BnMediaSource::onTransact(
                    buf->meta_data()->writeToParcel(*reply);
                    if (transferBuf != buf) {
                        buf->release();
                    } else if (!supportNonblockingRead()) {
                        maxNumBuffers = 0; // stop readMultiple with one shared buffer.
                    }
                } else {
                    ALOGV_IF(buf->mMemory != nullptr,
@@ -404,6 +424,10 @@ status_t BnMediaSource::onTransact(
                    reply->writeByteArray(length, (uint8_t*)buf->data() + offset);
                    buf->meta_data()->writeToParcel(*reply);
                    buf->release();
                    inlineTransferSize += length;
                    if (inlineTransferSize > kInlineMaxTransfer) {
                        maxNumBuffers = 0; // stop readMultiple if inline transfer is too large.
                    }
                }
            }
            reply->writeInt32(NULL_BUFFER); // Indicate no more MediaBuffers.
@@ -412,6 +436,12 @@ status_t BnMediaSource::onTransact(
                    ret, bufferCount, mBuffersSinceStop);
            return NO_ERROR;
        }
        case SUPPORT_NONBLOCKING_READ: {
            ALOGV("supportNonblockingRead");
            CHECK_INTERFACE(IMediaSource, data, reply);
            reply->writeInt32((int32_t)supportNonblockingRead());
            return NO_ERROR;
        }
        default:
            return BBinder::onTransact(code, data, reply, flags);
    }
+7 −8
Original line number Diff line number Diff line
@@ -1385,7 +1385,7 @@ void NuPlayer::GenericSource::readBuffer(
            if (mIsWidevine) {
                maxBuffers = 2;
            } else {
                maxBuffers = 4;
                maxBuffers = 8;  // too large of a number may influence seeks
            }
            break;
        case MEDIA_TRACK_TYPE_AUDIO:
@@ -1417,25 +1417,24 @@ void NuPlayer::GenericSource::readBuffer(
    MediaSource::ReadOptions options;

    bool seeking = false;

    if (seekTimeUs >= 0) {
        options.setSeekTo(seekTimeUs, MediaSource::ReadOptions::SEEK_PREVIOUS_SYNC);
        seeking = true;
    }

    if (mIsWidevine) {
    const bool couldReadMultiple = (!mIsWidevine && track->mSource->supportReadMultiple());

    if (mIsWidevine || couldReadMultiple) {
        options.setNonBlocking();
    }

    bool couldReadMultiple =
        (!mIsWidevine && trackType == MEDIA_TRACK_TYPE_AUDIO
                && track->mSource->supportReadMultiple());
    for (size_t numBuffers = 0; numBuffers < maxBuffers; ) {
        Vector<MediaBuffer *> mediaBuffers;
        status_t err = NO_ERROR;

        if (!seeking && couldReadMultiple) {
            err = track->mSource->readMultiple(&mediaBuffers, (maxBuffers - numBuffers));
        if (couldReadMultiple) {
            err = track->mSource->readMultiple(
                    &mediaBuffers, maxBuffers - numBuffers, &options);
        } else {
            MediaBuffer *mbuf = NULL;
            err = track->mSource->read(&mbuf, &options);
+17 −4
Original line number Diff line number Diff line
@@ -75,6 +75,7 @@ public:
    virtual sp<MetaData> getFormat();

    virtual status_t read(MediaBuffer **buffer, const ReadOptions *options = NULL);
    virtual bool supportNonblockingRead() { return true; }
    virtual status_t fragmentedRead(MediaBuffer **buffer, const ReadOptions *options = NULL);

protected:
@@ -3563,13 +3564,20 @@ status_t MPEG4Source::start(MetaData *params) {

    // A somewhat arbitrary limit that should be sufficient for 8k video frames
    // If you see the message below for a valid input stream: increase the limit
    if (max_size > 64 * 1024 * 1024) {
        ALOGE("bogus max input size: %zu", max_size);
    const size_t kMaxBufferSize = 64 * 1024 * 1024;
    if (max_size > kMaxBufferSize) {
        ALOGE("bogus max input size: %zu > %zu", max_size, kMaxBufferSize);
        return ERROR_MALFORMED;
    }
    if (max_size == 0) {
        ALOGE("zero max input size");
        return ERROR_MALFORMED;
    }
    mGroup = new MediaBufferGroup;
    mGroup->add_buffer(new MediaBuffer(max_size));

    // Allow up to kMaxBuffers, but not if the total exceeds kMaxBufferSize.
    const size_t kMaxBuffers = 8;
    const size_t buffers = min(kMaxBufferSize / max_size, kMaxBuffers);
    mGroup = new MediaBufferGroup(buffers, max_size);
    mSrcBuffer = new (std::nothrow) uint8_t[max_size];
    if (mSrcBuffer == NULL) {
        // file probably specified a bad max size
@@ -4196,6 +4204,11 @@ status_t MPEG4Source::read(

    CHECK(mStarted);

    if (options != nullptr && options->getNonBlocking() && !mGroup->has_buffers()) {
        *out = nullptr;
        return WOULD_BLOCK;
    }

    if (mFirstMoofOffset > 0) {
        return fragmentedRead(out, options);
    }
Loading