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

Commit 66cf4592 authored by Chih-Yu Huang's avatar Chih-Yu Huang
Browse files

Expose C2BufferQueueBlockPoolData definition at header file

C2BufferQueueBlockPoolData class is used to track the ownership of
C2GraphicBlock and migrate the buffer when surface switching. It's
originally only accessed by C2BufferQueueBlockPool and
_C2BlockFactory, so we hide the definition at cpp file.

However, this class is highly coupled with the CCodec buffer
transition logic. Without exposing the definition, the child class of
C2BufferQueueBlockPool (i.e. C2VdaBqBlockPool) has to add hacky
workaround for the same logic. Furthermore, C2VdaBqBlockPool cannot
migrate all the buffers when surface switching.

This CL exposes the definition of C2BufferQueueBlockPoolData to the
header file, and let C2VdaBqBlockPool could access the class.

Bug: 174188958
Test: android.media.cts.AdaptivePlaybackTest

Change-Id: Ic0d76e3bd4d3e14ea6023b0c1b0fac662028dbe7
parent 713bd44e
Loading
Loading
Loading
Loading
+59 −0
Original line number Diff line number Diff line
@@ -20,9 +20,14 @@
#include <android/hardware/graphics/bufferqueue/2.0/IGraphicBufferProducer.h>

#include <C2Buffer.h>
#include <C2BlockInternal.h>

#include <functional>

namespace android {
class GraphicBuffer;
}  // namespace android

class C2BufferQueueBlockPool : public C2BlockPool {
public:
    C2BufferQueueBlockPool(const std::shared_ptr<C2Allocator> &allocator, const local_id_t localId);
@@ -77,4 +82,58 @@ private:
    friend struct C2BufferQueueBlockPoolData;
};


struct C2BufferQueueBlockPoolData : public _C2BlockPoolData {
public:
    typedef ::android::hardware::graphics::bufferqueue::V2_0::
            IGraphicBufferProducer HGraphicBufferProducer;

    // Create a remote BlockPoolData.
    C2BufferQueueBlockPoolData(
            uint32_t generation, uint64_t bqId, int32_t bqSlot,
            const std::shared_ptr<int> &owner,
            const android::sp<HGraphicBufferProducer>& producer);

    // Create a local BlockPoolData.
    C2BufferQueueBlockPoolData(
            uint32_t generation, uint64_t bqId, int32_t bqSlot,
            const std::shared_ptr<C2BufferQueueBlockPool::Impl>& pool);

    virtual ~C2BufferQueueBlockPoolData() override;

    virtual type_t getType() const override;

    int migrate(const android::sp<HGraphicBufferProducer>& producer,
                uint32_t toGeneration, uint64_t toBqId,
                android::sp<android::GraphicBuffer> *buffers, uint32_t oldGeneration);

private:
    friend struct _C2BlockFactory;

    // Methods delegated from _C2BlockFactory.
    void getBufferQueueData(uint32_t* generation, uint64_t* bqId, int32_t* bqSlot) const;
    bool holdBlockFromBufferQueue(const std::shared_ptr<int>& owner,
                                  const android::sp<HGraphicBufferProducer>& igbp);
    bool beginTransferBlockToClient();
    bool endTransferBlockToClient(bool transfer);
    bool beginAttachBlockToBufferQueue();
    bool endAttachBlockToBufferQueue(const std::shared_ptr<int>& owner,
                                     const android::sp<HGraphicBufferProducer>& igbp,
                                     uint32_t generation, uint64_t bqId, int32_t bqSlot);
    bool displayBlockToBufferQueue();

    const bool mLocal;
    bool mHeld;
    uint32_t mGeneration;
    uint64_t mBqId;
    int32_t mBqSlot;
    bool mTransfer; // local transfer to remote
    bool mAttach; // attach on remote
    bool mDisplay; // display on remote;
    std::weak_ptr<int> mOwner;
    android::sp<HGraphicBufferProducer> mIgbp;
    std::shared_ptr<C2BufferQueueBlockPool::Impl> mLocalPool;
    mutable std::mutex mLock;
};

#endif // STAGEFRIGHT_CODEC2_BUFFER_PRIV_H_
+140 −137
Original line number Diff line number Diff line
@@ -54,59 +54,13 @@ using ::android::hardware::graphics::bufferqueue::V2_0::utils::HFenceWrapper;
using HGraphicBufferProducer = ::android::hardware::graphics::bufferqueue::V2_0
        ::IGraphicBufferProducer;

struct C2BufferQueueBlockPoolData : public _C2BlockPoolData {

    bool held;
    bool local;
    uint32_t generation;
    uint64_t bqId;
    int32_t bqSlot;
    bool transfer; // local transfer to remote
    bool attach; // attach on remote
    bool display; // display on remote;
    std::weak_ptr<int> owner;
    sp<HGraphicBufferProducer> igbp;
    std::shared_ptr<C2BufferQueueBlockPool::Impl> localPool;
    mutable std::mutex lock;

    virtual type_t getType() const override {
        return TYPE_BUFFERQUEUE;
    }

    // Create a remote BlockPoolData.
    C2BufferQueueBlockPoolData(
            uint32_t generation, uint64_t bqId, int32_t bqSlot,
            const std::shared_ptr<int> &owner,
            const sp<HGraphicBufferProducer>& producer);

    // Create a local BlockPoolData.
    C2BufferQueueBlockPoolData(
            uint32_t generation, uint64_t bqId, int32_t bqSlot,
            const std::shared_ptr<C2BufferQueueBlockPool::Impl>& pool);

    virtual ~C2BufferQueueBlockPoolData() override;

    int migrate(const sp<HGraphicBufferProducer>& producer,
                uint32_t toGeneration, uint64_t toBqId,
                sp<GraphicBuffer> *buffers, uint32_t oldGeneration);
};

bool _C2BlockFactory::GetBufferQueueData(
        const std::shared_ptr<const _C2BlockPoolData>& data,
        uint32_t* generation, uint64_t* bqId, int32_t* bqSlot) {
    if (data && data->getType() == _C2BlockPoolData::TYPE_BUFFERQUEUE) {
        if (generation) {
        const std::shared_ptr<const C2BufferQueueBlockPoolData> poolData =
                std::static_pointer_cast<const C2BufferQueueBlockPoolData>(data);
            std::scoped_lock<std::mutex> lock(poolData->lock);
            *generation = poolData->generation;
            if (bqId) {
                *bqId = poolData->bqId;
            }
            if (bqSlot) {
                *bqSlot = poolData->bqSlot;
            }
        }
        poolData->getBufferQueueData(generation, bqId, bqSlot);
        return true;
    }
    return false;
@@ -118,26 +72,14 @@ bool _C2BlockFactory::HoldBlockFromBufferQueue(
        const sp<HGraphicBufferProducer>& igbp) {
    const std::shared_ptr<C2BufferQueueBlockPoolData> poolData =
            std::static_pointer_cast<C2BufferQueueBlockPoolData>(data);
    std::scoped_lock<std::mutex> lock(poolData->lock);
    if (!poolData->local) {
        poolData->owner = owner;
        poolData->igbp = igbp;
    }
    if (poolData->held) {
        poolData->held = true;
        return false;
    }
    poolData->held = true;
    return true;
    return poolData->holdBlockFromBufferQueue(owner, igbp);
}

bool _C2BlockFactory::BeginTransferBlockToClient(
        const std::shared_ptr<_C2BlockPoolData>& data) {
    const std::shared_ptr<C2BufferQueueBlockPoolData> poolData =
            std::static_pointer_cast<C2BufferQueueBlockPoolData>(data);
    std::scoped_lock<std::mutex> lock(poolData->lock);
    poolData->transfer = true;
    return true;
    return poolData->beginTransferBlockToClient();
}

bool _C2BlockFactory::EndTransferBlockToClient(
@@ -145,28 +87,14 @@ bool _C2BlockFactory::EndTransferBlockToClient(
        bool transfer) {
    const std::shared_ptr<C2BufferQueueBlockPoolData> poolData =
            std::static_pointer_cast<C2BufferQueueBlockPoolData>(data);
    std::scoped_lock<std::mutex> lock(poolData->lock);
    poolData->transfer = false;
    if (transfer) {
        poolData->held = false;
    }
    return true;
    return poolData->endTransferBlockToClient(transfer);
}

bool _C2BlockFactory::BeginAttachBlockToBufferQueue(
        const std::shared_ptr<_C2BlockPoolData>& data) {
    const std::shared_ptr<C2BufferQueueBlockPoolData> poolData =
            std::static_pointer_cast<C2BufferQueueBlockPoolData>(data);
    std::scoped_lock<std::mutex> lock(poolData->lock);
    if (poolData->local || poolData->display ||
        poolData->attach || !poolData->held) {
        return false;
    }
    if (poolData->bqId == 0) {
        return false;
    }
    poolData->attach = true;
    return true;
    return poolData->beginAttachBlockToBufferQueue();
}

// if display was tried during attach, buffer should be retired ASAP.
@@ -179,42 +107,14 @@ bool _C2BlockFactory::EndAttachBlockToBufferQueue(
        int32_t bqSlot) {
    const std::shared_ptr<C2BufferQueueBlockPoolData> poolData =
            std::static_pointer_cast<C2BufferQueueBlockPoolData>(data);
    std::scoped_lock<std::mutex> lock(poolData->lock);
    if (poolData->local || !poolData->attach ) {
        return false;
    }
    if (poolData->display) {
        poolData->attach = false;
        poolData->held = false;
        return false;
    }
    poolData->attach = false;
    poolData->held = true;
    poolData->owner = owner;
    poolData->igbp = igbp;
    poolData->generation = generation;
    poolData->bqId = bqId;
    poolData->bqSlot = bqSlot;
    return true;
    return poolData->endAttachBlockToBufferQueue(owner, igbp, generation, bqId, bqSlot);
}

bool _C2BlockFactory::DisplayBlockToBufferQueue(
        const std::shared_ptr<_C2BlockPoolData>& data) {
    const std::shared_ptr<C2BufferQueueBlockPoolData> poolData =
            std::static_pointer_cast<C2BufferQueueBlockPoolData>(data);
    std::scoped_lock<std::mutex> lock(poolData->lock);
    if (poolData->local || poolData->display || !poolData->held) {
        return false;
    }
    if (poolData->bqId == 0) {
        return false;
    }
    poolData->display = true;
    if (poolData->attach) {
        return false;
    }
    poolData->held = false;
    return true;
    return poolData->displayBlockToBufferQueue();
}

std::shared_ptr<C2GraphicBlock> _C2BlockFactory::CreateGraphicBlock(
@@ -668,65 +568,70 @@ C2BufferQueueBlockPoolData::C2BufferQueueBlockPoolData(
        uint32_t generation, uint64_t bqId, int32_t bqSlot,
        const std::shared_ptr<int>& owner,
        const sp<HGraphicBufferProducer>& producer) :
        held(producer && bqId != 0), local(false),
        generation(generation), bqId(bqId), bqSlot(bqSlot),
        transfer(false), attach(false), display(false),
        owner(owner), igbp(producer),
        localPool() {
        mLocal(false), mHeld(producer && bqId != 0),
        mGeneration(generation), mBqId(bqId), mBqSlot(bqSlot),
        mTransfer(false), mAttach(false), mDisplay(false),
        mOwner(owner), mIgbp(producer),
        mLocalPool() {
}

C2BufferQueueBlockPoolData::C2BufferQueueBlockPoolData(
        uint32_t generation, uint64_t bqId, int32_t bqSlot,
        const std::shared_ptr<C2BufferQueueBlockPool::Impl>& pool) :
        held(true), local(true),
        generation(generation), bqId(bqId), bqSlot(bqSlot),
        transfer(false), attach(false), display(false),
        igbp(pool ? pool->mProducer : nullptr),
        localPool(pool) {
        mLocal(true), mHeld(true),
        mGeneration(generation), mBqId(bqId), mBqSlot(bqSlot),
        mTransfer(false), mAttach(false), mDisplay(false),
        mIgbp(pool ? pool->mProducer : nullptr),
        mLocalPool(pool) {
}

C2BufferQueueBlockPoolData::~C2BufferQueueBlockPoolData() {
    if (!held || bqId == 0) {
    if (!mHeld || mBqId == 0) {
        return;
    }
    if (local) {
        if (localPool) {
            localPool->cancel(generation, bqId, bqSlot);
    if (mLocal) {
        if (mLocalPool) {
            mLocalPool->cancel(mGeneration, mBqId, mBqSlot);
        }
    } else if (igbp && !owner.expired()) {
        igbp->cancelBuffer(bqSlot, hidl_handle{}).isOk();
    } else if (mIgbp && !mOwner.expired()) {
        mIgbp->cancelBuffer(mBqSlot, hidl_handle{}).isOk();
    }
}

C2BufferQueueBlockPoolData::type_t C2BufferQueueBlockPoolData::getType() const {
    return TYPE_BUFFERQUEUE;
}

int C2BufferQueueBlockPoolData::migrate(
        const sp<HGraphicBufferProducer>& producer,
        uint32_t toGeneration, uint64_t toBqId,
        sp<GraphicBuffer> *buffers, uint32_t oldGeneration) {
    std::scoped_lock<std::mutex> l(lock);
    if (!held || bqId == 0) {
    std::scoped_lock<std::mutex> l(mLock);
    if (!mHeld || mBqId == 0) {
        ALOGV("buffer is not owned");
        return -1;
    }
    if (!local || !localPool) {
    if (!mLocal || !mLocalPool) {
        ALOGV("pool is not local");
        return -1;
    }
    if (bqSlot < 0 || bqSlot >= NUM_BUFFER_SLOTS || !buffers[bqSlot]) {
    if (mBqSlot < 0 || mBqSlot >= NUM_BUFFER_SLOTS || !buffers[mBqSlot]) {
        ALOGV("slot is not in effect");
        return -1;
    }
    if (toGeneration == generation && bqId == toBqId) {
    if (toGeneration == mGeneration && mBqId == toBqId) {
        ALOGV("cannot migrate to same bufferqueue");
        return -1;
    }
    if (oldGeneration != generation) {
    if (oldGeneration != mGeneration) {
        ALOGV("cannot migrate stale buffer");
    }
    if (transfer) {
    if (mTransfer) {
        // either transferred or detached.
        ALOGV("buffer is in transfer");
        return -1;
    }
    sp<GraphicBuffer> const& graphicBuffer = buffers[bqSlot];
    sp<GraphicBuffer> const& graphicBuffer = buffers[mBqSlot];
    graphicBuffer->setGenerationNumber(toGeneration);

    HBuffer hBuffer{};
@@ -755,13 +660,111 @@ int C2BufferQueueBlockPoolData::migrate(
        return -1;
    }
    ALOGV("local migration from gen %u : %u slot %d : %d",
          generation, toGeneration, bqSlot, slot);
    generation = toGeneration;
    bqId = toBqId;
    bqSlot = slot;
          mGeneration, toGeneration, mBqSlot, slot);
    mGeneration = toGeneration;
    mBqId = toBqId;
    mBqSlot = slot;
    return slot;
}

void C2BufferQueueBlockPoolData::getBufferQueueData(
        uint32_t* generation, uint64_t* bqId, int32_t* bqSlot) const {
    if (generation) {
        std::scoped_lock<std::mutex> lock(mLock);
        *generation = mGeneration;
        if (bqId) {
            *bqId = mBqId;
        }
        if (bqSlot) {
            *bqSlot = mBqSlot;
        }
    }
}

bool C2BufferQueueBlockPoolData::holdBlockFromBufferQueue(
        const std::shared_ptr<int>& owner,
        const sp<HGraphicBufferProducer>& igbp) {
    std::scoped_lock<std::mutex> lock(mLock);
    if (!mLocal) {
        mOwner = owner;
        mIgbp = igbp;
    }
    if (mHeld) {
        return false;
    }
    mHeld = true;
    return true;
}

bool C2BufferQueueBlockPoolData::beginTransferBlockToClient() {
    std::scoped_lock<std::mutex> lock(mLock);
    mTransfer = true;
    return true;
}

bool C2BufferQueueBlockPoolData::endTransferBlockToClient(bool transfer) {
    std::scoped_lock<std::mutex> lock(mLock);
    mTransfer = false;
    if (transfer) {
        mHeld = false;
    }
    return true;
}

bool C2BufferQueueBlockPoolData::beginAttachBlockToBufferQueue() {
    std::scoped_lock<std::mutex> lock(mLock);
    if (mLocal || mDisplay ||
        mAttach || !mHeld) {
        return false;
    }
    if (mBqId == 0) {
        return false;
    }
    mAttach = true;
    return true;
}

bool C2BufferQueueBlockPoolData::endAttachBlockToBufferQueue(
        const std::shared_ptr<int>& owner,
        const sp<HGraphicBufferProducer>& igbp,
        uint32_t generation,
        uint64_t bqId,
        int32_t bqSlot) {
    std::scoped_lock<std::mutex> lock(mLock);
    if (mLocal || !mAttach) {
        return false;
    }
    if (mDisplay) {
        mAttach = false;
        mHeld = false;
        return false;
    }
    mAttach = false;
    mHeld = true;
    mOwner = owner;
    mIgbp = igbp;
    mGeneration = generation;
    mBqId = bqId;
    mBqSlot = bqSlot;
    return true;
}

bool C2BufferQueueBlockPoolData::displayBlockToBufferQueue() {
    std::scoped_lock<std::mutex> lock(mLock);
    if (mLocal || mDisplay || !mHeld) {
        return false;
    }
    if (mBqId == 0) {
        return false;
    }
    mDisplay = true;
    if (mAttach) {
        return false;
    }
    mHeld = false;
    return true;
}

C2BufferQueueBlockPool::C2BufferQueueBlockPool(
        const std::shared_ptr<C2Allocator> &allocator, const local_id_t localId)
        : mAllocator(allocator), mLocalId(localId), mImpl(new Impl(allocator)) {}