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

Commit 7bad7223 authored by Lajos Molnar's avatar Lajos Molnar
Browse files

stagefright: add indexed buffer and format getters to MediaCodec

These are designed to be called from the same thread as the one
calling dequeue?Buffer, and use a mutex to avoid switching
context.  All other calls of MediaCodec are designed to be blocking
and synchronous.

Bug: 14297827
Change-Id: If341c6e4407ca6f10f5e0d47008dddc0e20b0a50
parent 94bda640
Loading
Loading
Loading
Loading
+15 −0
Original line number Diff line number Diff line
@@ -112,6 +112,10 @@ struct MediaCodec : public AHandler {
    status_t getInputBuffers(Vector<sp<ABuffer> > *buffers) const;
    status_t getOutputBuffers(Vector<sp<ABuffer> > *buffers) const;

    status_t getOutputBuffer(size_t index, sp<ABuffer> *buffer);
    status_t getOutputFormat(size_t index, sp<AMessage> *format);
    status_t getInputBuffer(size_t index, sp<ABuffer> *buffer);

    status_t requestIDRFrame();

    // Notification will be posted once there "is something to do", i.e.
@@ -189,6 +193,7 @@ private:
        sp<ABuffer> mData;
        sp<ABuffer> mEncryptedData;
        sp<AMessage> mNotify;
        sp<AMessage> mFormat;
        bool mOwnedByClient;
    };

@@ -204,6 +209,12 @@ private:
    sp<AMessage> mOutputFormat;
    sp<AMessage> mInputFormat;

    // Used only to synchronize asynchronous getBufferAndFormat
    // across all the other (synchronous) buffer state change
    // operations, such as de/queueIn/OutputBuffer, start and
    // stop/flush/reset/release.
    Mutex mBufferLock;

    List<size_t> mAvailPortBuffers[2];
    Vector<BufferInfo> mPortBuffers[2];

@@ -236,6 +247,10 @@ private:
    status_t onReleaseOutputBuffer(const sp<AMessage> &msg);
    ssize_t dequeuePortBuffer(int32_t portIndex);

    status_t getBufferAndFormat(
            size_t portIndex, size_t index,
            sp<ABuffer> *buffer, sp<AMessage> *format);

    bool handleDequeueInputBuffer(uint32_t replyID, bool newRequest = false);
    bool handleDequeueOutputBuffer(uint32_t replyID, bool newRequest = false);
    void cancelPendingDequeueOperations();
+60 −5
Original line number Diff line number Diff line
@@ -410,6 +410,46 @@ status_t MediaCodec::getOutputBuffers(Vector<sp<ABuffer> > *buffers) const {
    return PostAndAwaitResponse(msg, &response);
}

status_t MediaCodec::getOutputBuffer(size_t index, sp<ABuffer> *buffer) {
    sp<AMessage> format;
    return getBufferAndFormat(kPortIndexOutput, index, buffer, &format);
}

status_t MediaCodec::getOutputFormat(size_t index, sp<AMessage> *format) {
    sp<ABuffer> buffer;
    return getBufferAndFormat(kPortIndexOutput, index, &buffer, format);
}

status_t MediaCodec::getInputBuffer(size_t index, sp<ABuffer> *buffer) {
    sp<AMessage> format;
    return getBufferAndFormat(kPortIndexInput, index, buffer, &format);
}

status_t MediaCodec::getBufferAndFormat(
        size_t portIndex, size_t index,
        sp<ABuffer> *buffer, sp<AMessage> *format) {
    // use mutex instead of a context switch

    buffer->clear();
    format->clear();
    if (mState != STARTED) {
        return INVALID_OPERATION;
    }

    // we do not want mPortBuffers to change during this section
    // we also don't want mOwnedByClient to change during this
    Mutex::Autolock al(mBufferLock);
    Vector<BufferInfo> *buffers = &mPortBuffers[portIndex];
    if (index < buffers->size()) {
        const BufferInfo &info = buffers->itemAt(index);
        if (info.mOwnedByClient) {
            *buffer = info.mData;
            *format = info.mFormat;
        }
    }
    return OK;
}

status_t MediaCodec::flush() {
    sp<AMessage> msg = new AMessage(kWhatFlush, id());

@@ -710,6 +750,7 @@ void MediaCodec::onMessageReceived(const sp<AMessage> &msg) {

                case CodecBase::kWhatBuffersAllocated:
                {
                    Mutex::Autolock al(mBufferLock);
                    int32_t portIndex;
                    CHECK(msg->findInt32("portIndex", &portIndex));

@@ -1463,8 +1504,8 @@ void MediaCodec::extractCSD(const sp<AMessage> &format) {
status_t MediaCodec::queueCSDInputBuffer(size_t bufferIndex) {
    CHECK(!mCSD.empty());

    BufferInfo *info =
        &mPortBuffers[kPortIndexInput].editItemAt(bufferIndex);
    const BufferInfo *info =
        &mPortBuffers[kPortIndexInput].itemAt(bufferIndex);

    sp<ABuffer> csd = *mCSD.begin();
    mCSD.erase(mCSD.begin());
@@ -1530,6 +1571,7 @@ void MediaCodec::returnBuffersToCodec() {

void MediaCodec::returnBuffersToCodecOnPort(int32_t portIndex) {
    CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput);
    Mutex::Autolock al(mBufferLock);

    Vector<BufferInfo> *buffers = &mPortBuffers[portIndex];

@@ -1684,11 +1726,15 @@ status_t MediaCodec::onQueueInputBuffer(const sp<AMessage> &msg) {
        info->mData->setRange(0, result);
    }

    // synchronization boundary for getBufferAndFormat
    {
        Mutex::Autolock al(mBufferLock);
        info->mOwnedByClient = false;
    }
    reply->setBuffer("buffer", info->mData);
    reply->post();

    info->mNotify = NULL;
    info->mOwnedByClient = false;

    return OK;
}
@@ -1716,6 +1762,12 @@ status_t MediaCodec::onReleaseOutputBuffer(const sp<AMessage> &msg) {
        return -EACCES;
    }

    // synchronization boundary for getBufferAndFormat
    {
        Mutex::Autolock al(mBufferLock);
        info->mOwnedByClient = false;
    }

    if (render && info->mData != NULL && info->mData->size() != 0) {
        info->mNotify->setInt32("render", true);

@@ -1743,7 +1795,6 @@ status_t MediaCodec::onReleaseOutputBuffer(const sp<AMessage> &msg) {

    info->mNotify->post();
    info->mNotify = NULL;
    info->mOwnedByClient = false;

    return OK;
}
@@ -1762,7 +1813,11 @@ ssize_t MediaCodec::dequeuePortBuffer(int32_t portIndex) {

    BufferInfo *info = &mPortBuffers[portIndex].editItemAt(index);
    CHECK(!info->mOwnedByClient);
    {
        Mutex::Autolock al(mBufferLock);
        info->mFormat = portIndex == kPortIndexInput ? mInputFormat : mOutputFormat;
        info->mOwnedByClient = true;
    }

    return index;
}