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

Commit d030447b authored by Lajos Molnar's avatar Lajos Molnar Committed by Android (Google) Code Review
Browse files

stagefright: BufferProducer updates



Update BufferQueue and ConsumerBase users to new BufferQueue
API, to allow BufferQueue slots to be reused.  Buffer consumers
generally now need to track the unique frameNumber belonging to
each frame acquired if they are using BufferQueue directly.
Otherwise, they can simply track the graphicBuffer.

Change-Id: I30ee3158cf40fb10bbd085241646d5f1128ee480
Signed-off-by: default avatarLajos Molnar <lajos@google.com>
Related-to-bug: 7093648
parent 599d83e4
Loading
Loading
Loading
Loading
+6 −2
Original line number Diff line number Diff line
@@ -146,9 +146,13 @@ private:
    // this consumer
    sp<BufferQueue> mBufferQueue;

    // mBufferSlot caches GraphicBuffers from the buffer queue
    sp<GraphicBuffer> mBufferSlot[BufferQueue::NUM_BUFFER_SLOTS];
    struct SlotData {
        sp<GraphicBuffer> mGraphicBuffer;
        uint64_t mFrameNumber;
    };

    // mSlots caches GraphicBuffers and frameNumbers from the buffer queue
    SlotData mSlots[BufferQueue::NUM_BUFFER_SLOTS];

    // The permenent width and height of SMS buffers
    int mWidth;
+14 −10
Original line number Diff line number Diff line
@@ -305,8 +305,9 @@ status_t SurfaceMediaSource::read( MediaBuffer **buffer,

            // First time seeing the buffer?  Added it to the SMS slot
            if (item.mGraphicBuffer != NULL) {
                mBufferSlot[item.mBuf] = item.mGraphicBuffer;
                mSlots[item.mBuf].mGraphicBuffer = item.mGraphicBuffer;
            }
            mSlots[item.mBuf].mFrameNumber = item.mFrameNumber;

            // check for the timing of this buffer
            if (mNumFramesReceived == 0 && !mUseAbsoluteTimestamps) {
@@ -315,7 +316,8 @@ status_t SurfaceMediaSource::read( MediaBuffer **buffer,
                if (mStartTimeNs > 0) {
                    if (item.mTimestamp < mStartTimeNs) {
                        // This frame predates start of record, discard
                        mBufferQueue->releaseBuffer(item.mBuf, EGL_NO_DISPLAY,
                        mBufferQueue->releaseBuffer(
                                item.mBuf, item.mFrameNumber, EGL_NO_DISPLAY,
                                EGL_NO_SYNC_KHR, Fence::NO_FENCE);
                        continue;
                    }
@@ -345,17 +347,18 @@ status_t SurfaceMediaSource::read( MediaBuffer **buffer,

    // First time seeing the buffer?  Added it to the SMS slot
    if (item.mGraphicBuffer != NULL) {
        mBufferSlot[mCurrentSlot] = item.mGraphicBuffer;
        mSlots[item.mBuf].mGraphicBuffer = item.mGraphicBuffer;
    }
    mSlots[item.mBuf].mFrameNumber = item.mFrameNumber;

    mCurrentBuffers.push_back(mBufferSlot[mCurrentSlot]);
    mCurrentBuffers.push_back(mSlots[mCurrentSlot].mGraphicBuffer);
    int64_t prevTimeStamp = mCurrentTimestamp;
    mCurrentTimestamp = item.mTimestamp;

    mNumFramesEncoded++;
    // Pass the data to the MediaBuffer. Pass in only the metadata

    passMetadataBuffer(buffer, mBufferSlot[mCurrentSlot]->handle);
    passMetadataBuffer(buffer, mSlots[mCurrentSlot].mGraphicBuffer->handle);

    (*buffer)->setObserver(this);
    (*buffer)->add_ref();
@@ -405,15 +408,16 @@ void SurfaceMediaSource::signalBufferReturned(MediaBuffer *buffer) {
    }

    for (int id = 0; id < BufferQueue::NUM_BUFFER_SLOTS; id++) {
        if (mBufferSlot[id] == NULL) {
        if (mSlots[id].mGraphicBuffer == NULL) {
            continue;
        }

        if (bufferHandle == mBufferSlot[id]->handle) {
        if (bufferHandle == mSlots[id].mGraphicBuffer->handle) {
            ALOGV("Slot %d returned, matches handle = %p", id,
                    mBufferSlot[id]->handle);
                    mSlots[id].mGraphicBuffer->handle);

            mBufferQueue->releaseBuffer(id, EGL_NO_DISPLAY, EGL_NO_SYNC_KHR,
            mBufferQueue->releaseBuffer(id, mSlots[id].mFrameNumber,
                                        EGL_NO_DISPLAY, EGL_NO_SYNC_KHR,
                    Fence::NO_FENCE);

            buffer->setObserver(0);
@@ -469,7 +473,7 @@ void SurfaceMediaSource::onBuffersReleased() {
    mFrameAvailableCondition.signal();

    for (int i = 0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) {
       mBufferSlot[i] = 0;
       mSlots[i].mGraphicBuffer = 0;
    }
}

+20 −27
Original line number Diff line number Diff line
@@ -206,24 +206,15 @@ void GraphicBufferSource::codecBufferEmptied(OMX_BUFFERHEADERTYPE* header) {
    // Find matching entry in our cached copy of the BufferQueue slots.
    // If we find a match, release that slot.  If we don't, the BufferQueue
    // has dropped that GraphicBuffer, and there's nothing for us to release.
    //
    // (We could store "id" in CodecBuffer and avoid the slot search.)
    int id;
    for (id = 0; id < BufferQueue::NUM_BUFFER_SLOTS; id++) {
        if (mBufferSlot[id] == NULL) {
            continue;
        }

        if (mBufferSlot[id]->handle == codecBuffer.mGraphicBuffer->handle) {
    int id = codecBuffer.mBuf;
    if (mBufferSlot[id] != NULL &&
        mBufferSlot[id]->handle == codecBuffer.mGraphicBuffer->handle) {
        ALOGV("cbi %d matches bq slot %d, handle=%p",
                cbi, id, mBufferSlot[id]->handle);

            mBufferQueue->releaseBuffer(id, EGL_NO_DISPLAY, EGL_NO_SYNC_KHR,
                    Fence::NO_FENCE);
            break;
        }
    }
    if (id == BufferQueue::NUM_BUFFER_SLOTS) {
        mBufferQueue->releaseBuffer(id, codecBuffer.mFrameNumber,
                EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE);
    } else {
        ALOGV("codecBufferEmptied: no match for emptied buffer in cbi %d",
                cbi);
    }
@@ -287,11 +278,11 @@ bool GraphicBufferSource::fillCodecBuffer_l() {
        mBufferSlot[item.mBuf] = item.mGraphicBuffer;
    }

    err = submitBuffer_l(mBufferSlot[item.mBuf], item.mTimestamp / 1000, cbi);
    err = submitBuffer_l(item, cbi);
    if (err != OK) {
        ALOGV("submitBuffer_l failed, releasing bq buf %d", item.mBuf);
        mBufferQueue->releaseBuffer(item.mBuf, EGL_NO_DISPLAY,
                EGL_NO_SYNC_KHR, Fence::NO_FENCE);
        mBufferQueue->releaseBuffer(item.mBuf, item.mFrameNumber,
                EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE);
    } else {
        ALOGV("buffer submitted (bq %d, cbi %d)", item.mBuf, cbi);
    }
@@ -326,11 +317,13 @@ status_t GraphicBufferSource::signalEndOfInputStream() {
    return OK;
}

status_t GraphicBufferSource::submitBuffer_l(sp<GraphicBuffer>& graphicBuffer,
        int64_t timestampUsec, int cbi) {
status_t GraphicBufferSource::submitBuffer_l(
        const BufferQueue::BufferItem &item, int cbi) {
    ALOGV("submitBuffer_l cbi=%d", cbi);
    CodecBuffer& codecBuffer(mCodecBuffers.editItemAt(cbi));
    codecBuffer.mGraphicBuffer = graphicBuffer;
    codecBuffer.mGraphicBuffer = mBufferSlot[item.mBuf];
    codecBuffer.mBuf = item.mBuf;
    codecBuffer.mFrameNumber = item.mFrameNumber;

    OMX_BUFFERHEADERTYPE* header = codecBuffer.mHeader;
    CHECK(header->nAllocLen >= 4 + sizeof(buffer_handle_t));
@@ -342,7 +335,7 @@ status_t GraphicBufferSource::submitBuffer_l(sp<GraphicBuffer>& graphicBuffer,

    status_t err = mNodeInstance->emptyDirectBuffer(header, 0,
            4 + sizeof(buffer_handle_t), OMX_BUFFERFLAG_ENDOFFRAME,
            timestampUsec);
            item.mTimestamp / 1000);
    if (err != OK) {
        ALOGW("WARNING: emptyDirectBuffer failed: 0x%x", err);
        codecBuffer.mGraphicBuffer = NULL;
@@ -431,8 +424,8 @@ void GraphicBufferSource::onFrameAvailable() {
        BufferQueue::BufferItem item;
        status_t err = mBufferQueue->acquireBuffer(&item);
        if (err == OK) {
            mBufferQueue->releaseBuffer(item.mBuf, EGL_NO_DISPLAY,
                EGL_NO_SYNC_KHR, item.mFence);
            mBufferQueue->releaseBuffer(item.mBuf, item.mFrameNumber,
                    EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, item.mFence);
        }
        return;
    }
+8 −2
Original line number Diff line number Diff line
@@ -104,6 +104,13 @@ private:
    // (mGraphicBuffer == NULL) or in use by the codec.
    struct CodecBuffer {
        OMX_BUFFERHEADERTYPE* mHeader;

        // buffer producer's frame-number for buffer
        uint64_t mFrameNumber;

        // buffer producer's buffer slot for buffer
        int mBuf;

        sp<GraphicBuffer> mGraphicBuffer;
    };

@@ -130,8 +137,7 @@ private:

    // Marks the mCodecBuffers entry as in-use, copies the GraphicBuffer
    // reference into the codec buffer, and submits the data to the codec.
    status_t submitBuffer_l(sp<GraphicBuffer>& graphicBuffer,
            int64_t timestampUsec, int cbi);
    status_t submitBuffer_l(const BufferQueue::BufferItem &item, int cbi);

    // Submits an empty buffer, with the EOS flag set.   Returns without
    // doing anything if we don't have a codec buffer available.
+10 −3
Original line number Diff line number Diff line
@@ -214,7 +214,11 @@ status_t RingBufferConsumer::releaseOldestBufferLocked(size_t* pinnedFrames) {
        // In case the object was never pinned, pass the acquire fence
        // back to the release fence. If the fence was already waited on,
        // it'll just be a no-op to wait on it again.
        err = addReleaseFenceLocked(item.mBuf, item.mFence);

        // item.mGraphicBuffer was populated with the proper graphic-buffer
        // at acquire even if it was previously acquired
        err = addReleaseFenceLocked(item.mBuf,
                item.mGraphicBuffer, item.mFence);

        if (err != OK) {
            BI_LOGE("Failed to add release fence to buffer "
@@ -226,7 +230,9 @@ status_t RingBufferConsumer::releaseOldestBufferLocked(size_t* pinnedFrames) {
        BI_LOGV("Attempting to release buffer timestamp %lld, frame %lld",
                item.mTimestamp, item.mFrameNumber);

        err = releaseBufferLocked(item.mBuf,
        // item.mGraphicBuffer was populated with the proper graphic-buffer
        // at acquire even if it was previously acquired
        err = releaseBufferLocked(item.mBuf, item.mGraphicBuffer,
                                  EGL_NO_DISPLAY,
                                  EGL_NO_SYNC_KHR);
        if (err != OK) {
@@ -310,7 +316,8 @@ void RingBufferConsumer::unpinBuffer(const BufferItem& item) {

        RingBufferItem& find = *it;
        if (item.mGraphicBuffer == find.mGraphicBuffer) {
            status_t res = addReleaseFenceLocked(item.mBuf, item.mFence);
            status_t res = addReleaseFenceLocked(item.mBuf,
                    item.mGraphicBuffer, item.mFence);

            if (res != OK) {
                BI_LOGE("Failed to add release fence to buffer "