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

Commit 1398b90b authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Camera: Detach shared buffers if they are still referenced"

parents cc530bdb 6f82372d
Loading
Loading
Loading
Loading
+45 −11
Original line number Original line Diff line number Diff line
@@ -275,9 +275,17 @@ status_t Camera3StreamSplitter::removeOutputLocked(size_t surfaceId) {
    //still attached to the removed surface.
    //still attached to the removed surface.
    std::vector<uint64_t> pendingBufferIds;
    std::vector<uint64_t> pendingBufferIds;
    auto& outputSlots = *mOutputSlots[gbp];
    auto& outputSlots = *mOutputSlots[gbp];
    for (const auto &it : outputSlots) {
    for (size_t i = 0; i < outputSlots.size(); i++) {
        if (it.get() != nullptr) {
        if (outputSlots[i] != nullptr) {
            pendingBufferIds.push_back(it->getId());
            pendingBufferIds.push_back(outputSlots[i]->getId());
            auto rc = gbp->detachBuffer(i);
            if (rc != NO_ERROR) {
                //Buffers that fail to detach here will be scheduled for detach in the
                //input buffer queue and the rest of the registered outputs instead.
                //This will help ensure that camera stops accessing buffers that still
                //can get referenced by the disconnected output.
                mDetachedBuffers.emplace(outputSlots[i]->getId());
            }
        }
        }
    }
    }
    mOutputs[surfaceId] = nullptr;
    mOutputs[surfaceId] = nullptr;
@@ -521,10 +529,11 @@ void Camera3StreamSplitter::decrementBufRefCountLocked(uint64_t id, size_t surfa
    uint64_t bufferId = tracker_ptr->getBuffer()->getId();
    uint64_t bufferId = tracker_ptr->getBuffer()->getId();
    int consumerSlot = -1;
    int consumerSlot = -1;
    uint64_t frameNumber;
    uint64_t frameNumber;
    for (const auto &it : mInputSlots) {
    auto inputSlot = mInputSlots.begin();
        if (it.second.mGraphicBuffer->getId() == bufferId) {
    for (; inputSlot != mInputSlots.end(); inputSlot++) {
            consumerSlot = it.second.mSlot;
        if (inputSlot->second.mGraphicBuffer->getId() == bufferId) {
            frameNumber = it.second.mFrameNumber;
            consumerSlot = inputSlot->second.mSlot;
            frameNumber = inputSlot->second.mFrameNumber;
            break;
            break;
        }
        }
    }
    }
@@ -533,6 +542,12 @@ void Camera3StreamSplitter::decrementBufRefCountLocked(uint64_t id, size_t surfa
        return;
        return;
    }
    }


    auto detachBuffer = mDetachedBuffers.find(bufferId);
    bool detach = (detachBuffer != mDetachedBuffers.end());
    if (detach) {
        mDetachedBuffers.erase(detachBuffer);
        mInputSlots.erase(inputSlot);
    }
    // Temporarily unlock mutex to avoid circular lock:
    // Temporarily unlock mutex to avoid circular lock:
    // 1. This function holds splitter lock, calls releaseBuffer which triggers
    // 1. This function holds splitter lock, calls releaseBuffer which triggers
    // onBufferReleased in Camera3OutputStream. onBufferReleased waits on the
    // onBufferReleased in Camera3OutputStream. onBufferReleased waits on the
@@ -544,17 +559,25 @@ void Camera3StreamSplitter::decrementBufRefCountLocked(uint64_t id, size_t surfa
    mMutex.unlock();
    mMutex.unlock();
    int res = NO_ERROR;
    int res = NO_ERROR;
    if (consumer != nullptr) {
    if (consumer != nullptr) {
        if (detach) {
            res = consumer->detachBuffer(consumerSlot);
        } else {
            res = consumer->releaseBuffer(consumerSlot, frameNumber,
            res = consumer->releaseBuffer(consumerSlot, frameNumber,
                    EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, tracker_ptr->getMergedFence());
                    EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, tracker_ptr->getMergedFence());
        }
    } else {
    } else {
        SP_LOGE("%s: consumer has become null!", __FUNCTION__);
        SP_LOGE("%s: consumer has become null!", __FUNCTION__);
    }
    }
    mMutex.lock();
    mMutex.lock();
    // If the producer of this queue is disconnected, -22 error will occur

    if (res != NO_ERROR) {
    if (res != NO_ERROR) {
        if (detach) {
            SP_LOGE("%s: detachBuffer returns %d", __FUNCTION__, res);
        } else {
            SP_LOGE("%s: releaseBuffer returns %d", __FUNCTION__, res);
            SP_LOGE("%s: releaseBuffer returns %d", __FUNCTION__, res);
        }
        }
    }
    }
}


void Camera3StreamSplitter::onBufferReleasedByOutput(
void Camera3StreamSplitter::onBufferReleasedByOutput(
        const sp<IGraphicBufferProducer>& from) {
        const sp<IGraphicBufferProducer>& from) {
@@ -626,6 +649,17 @@ void Camera3StreamSplitter::onBufferReleasedByOutputLocked(
    SP_LOGV("%s: dequeued buffer %" PRId64 " %p from output %p", __FUNCTION__,
    SP_LOGV("%s: dequeued buffer %" PRId64 " %p from output %p", __FUNCTION__,
            buffer->getId(), buffer.get(), from.get());
            buffer->getId(), buffer.get(), from.get());


    auto detachBuffer = mDetachedBuffers.find(buffer->getId());
    bool detach = (detachBuffer != mDetachedBuffers.end());
    if (detach) {
        res = from->detachBuffer(slot);
        if (res == NO_ERROR) {
            outputSlots[slot] = nullptr;
        } else {
            SP_LOGE("%s: detach buffer from output failed (%d)", __FUNCTION__, res);
        }
    }

    // Check to see if this is the last outstanding reference to this buffer
    // Check to see if this is the last outstanding reference to this buffer
    decrementBufRefCountLocked(buffer->getId(), surfaceId);
    decrementBufRefCountLocked(buffer->getId(), surfaceId);
}
}
+6 −0
Original line number Original line Diff line number Diff line
@@ -17,6 +17,8 @@
#ifndef ANDROID_SERVERS_STREAMSPLITTER_H
#ifndef ANDROID_SERVERS_STREAMSPLITTER_H
#define ANDROID_SERVERS_STREAMSPLITTER_H
#define ANDROID_SERVERS_STREAMSPLITTER_H


#include <unordered_set>

#include <gui/IConsumerListener.h>
#include <gui/IConsumerListener.h>
#include <gui/IProducerListener.h>
#include <gui/IProducerListener.h>
#include <gui/BufferItemConsumer.h>
#include <gui/BufferItemConsumer.h>
@@ -255,6 +257,10 @@ private:
    std::unordered_map<sp<IGraphicBufferProducer>, std::unique_ptr<OutputSlots>,
    std::unordered_map<sp<IGraphicBufferProducer>, std::unique_ptr<OutputSlots>,
            GBPHash> mOutputSlots;
            GBPHash> mOutputSlots;


    //A set of buffers that could potentially stay in some of the outputs after removal
    //and therefore should be detached from the input queue.
    std::unordered_set<uint64_t> mDetachedBuffers;

    // Latest onFrameAvailable return value
    // Latest onFrameAvailable return value
    std::atomic<status_t> mOnFrameAvailableRes{0};
    std::atomic<status_t> mOnFrameAvailableRes{0};