在这一篇文章中,我们将了解C2GraphicBlock、C2BufferQueueBlockPoolData与C2GraphicView的实现。
1、fetchGraphicBlock
首先提出一个疑问:C2PooledBlockPool(没有surface)和C2BufferQueueBlockPool(有surface)分配的2D buffer有什么异同呢?想要回答这个问题还要再看一下fetchGraphicBlock方法。
1.1、C2PooledBlockPool
前面的文章提到C2PooledBlockPool可以分配2D buffer,将这句话补充完整:在没有surface的video decoder流程中,2D buffer由C2PooledBlockPool使用C2AllocatorGralloc来分配。需要注意的是,整个分配过程是在组件进程(HAL)中完成的,分配的buffer由bufferpool管理。
简单看下C2PooledBlockPool的fetchGraphicBlock实现:
class C2PooledBlockPool::Impl {
public:
c2_status_t fetchGraphicBlock(
uint32_t width, uint32_t height, uint32_t format,
C2MemoryUsage usage,
std::shared_ptr<C2GraphicBlock> *block) {
std::shared_ptr<bufferpool::BufferPoolData> bufferPoolData;
native_handle_t *cHandle = nullptr;
// 1. 通过bufferpool获取一个native_handle_t,以及bufferPoolData
ResultStatus status = mBufferPoolManager->allocate(
mConnectionId, params, &cHandle, &bufferPoolData);
if (status == ResultStatus::OK) {
std::shared_ptr<C2GraphicAllocation> alloc;
// 2. 创建C2PooledBlockPoolData
std::shared_ptr<C2PooledBlockPoolData> poolData =
std::make_shared<C2PooledBlockPoolData>(bufferPoolData);
// 3. 使用handle创建C2GraphicAllocation
c2_status_t err = mAllocator->priorGraphicAllocation(
cHandle, &alloc);
if (err == C2_OK && poolData && alloc) {
// 4. 创建C2GraphicBlock
*block = _C2BlockFactory::CreateGraphicBlock(
alloc, poolData, C2Rect(width, height));
if (*block) {
return C2_OK;
}
}
return C2_NO_MEMORY;
}
return C2_CORRUPTED;
}
}
- C2PooledBlockPool通过HAL层的ClientManager拿到native_handle_t(clone)和BufferPoolData;
- 将BufferPoolData封装为C2PooledBlockPoolData,BufferPoolData存储有ConnectionId和buffer在bufferpool中的id;
- 使用handle创建C2GraphicAllocation;
- 调用CreateGraphicBlock创建出C2GraphicBlock。
1.2、C2BufferQueueBlockPool
接着再看C2BufferQueueBlockPool::fetchGraphicBlock实现:
class C2BufferQueueBlockPool
public:
c2_status_t fetchGraphicBlock(
uint32_t width,
uint32_t height,
uint32_t format,
C2MemoryUsage usage,
std::shared_ptr<C2GraphicBlock> *block /* nonnull */,
C2Fence *fence) {
// ...
c2_status_t status = fetchFromIgbp_l(width, height, format, usage, block,
}
}
class C2BufferQueueBlockPool::Impl
private:
c2_status_t fetchFromIgbp_l(
uint32_t width,
uint32_t height,
uint32_t format,
C2MemoryUsage usage,
std::shared_ptr<C2GraphicBlock> *block /* nonnull */,
C2Fence *c2Fence) {
C2Handle *c2Handle = android::WrapNativeCodec2GrallocHandle(
slotBuffer->handle,
slotBuffer->width,
slotBuffer->height,
slotBuffer->format,
slotBuffer->usage,
slotBuffer->stride,
slotBuffer->getGenerationNumber(),
mProducerId, slot);
if (c2Handle) {
std::shared_ptr<C2GraphicAllocation> alloc;
// 1. 创建C2GraphicAllocation
c2_status_t err = mAllocator->priorGraphicAllocation(c2Handle, &alloc);
// 2. 创建C2BufferQueueBlockPoolData
std::shared_ptr<C2BufferQueueBlockPoolData> poolData =
std::make_shared<C2BufferQueueBlockPoolData>(
slotBuffer->getGenerationNumber(),
mProducerId, slot,
mIgbpValidityToken, mProducer, mSyncMem);
mPoolDatas[slot] = poolData;
// 3. 创建C2GraphicBlock
*block = _C2BlockFactory::CreateGraphicBlock(alloc, poolData);
return C2_OK;
}
}
}
详细流程在前面两篇文章中已经讲过了,这里只做简单概括:
- 从producer的dequeueBuffer方法拿到slotId;
- 调用producer的requestBuffer拿到native_handle_t,封装到GraphicBuffer中;
- 从GraphicBuffer中拿到相关信息,封装成C2Handle;
- 使用C2Handle创建C2GraphicAllocation;
- 使用generation、producerId,slotId、producer实例、C2SurfaceSyncMemory实例创建C2BufferQueueBlockPoolData;
- 使用C2GraphicAllocation和C2BufferQueueBlockPoolData创建出C2GraphicBlock;
1.3、对比与小结
2、C2BufferQueueBlockPoolData
3、_C2BlockFactory
4、C2Block2D::Impl
5、_C2MappingBlock2DImpl::Mapped
6、C2GraphicBlock
7、C2GraphicView
8、小结
原文阅读:
Android Codec2(二四)C2GraphicBlock
扫描下方二维码,关注公众号《青山渺渺》阅读音视频开发内容。