在这篇文章中,我们首先将了解C2BlockPool是什么,随后会探讨C2BlockPool与buffer pool以及C2Allocator之间的关系。最后,我们将深入了解C2BlockPool的一个子类—C2PooledBlockPool的具体实现方式,以及它是如何分配buffers的。
1、C2BlockPool
Codec2框架使用BlockPool封装C2Allocator和bufferpool,我们可以通过它来分配/管理buffer。我们可以用C2BlockPool分配linear(1D),circular(1D)以及graphic(2D) blocks,block翻译为内存块,可以理解为一块buffer。C2BlockPool声明于C2Buffer.h,它定义了两个纯虚函数:
- getLocalId:创建C2BlockPool子类实例时,需要传入一个独一无二的id,此方法返回该id;
- getAllocatorId:返回C2BlockPool依赖的C2Allocator id;
此外,C2BlockPool还定义了5个虚函数并提供了默认空实现,下面列出三个:
- fetchLinearBlock:获取一块1D buffer;
- fetchCircularBlock:获取一块环形buffer,暂不了解;
- fetchGraphicBlock:获取一块2D buffer;
在大多数情况下,C2BlockPool需要依赖于C2Allocator来分配buffer。我们之前了解到,C2Allocator的实现通常专注于1D或2D buffer的分配,因此,一个C2BlockPool实例通常只能专注于分配一种特定类型的buffer。
另外,C2Allocator和C2BlockPool还有一层对应关系,具体可以参考如下代码:
c2_status_t _createBlockPool(C2PlatformAllocatorStore::id_t allocatorId,std::vector<std::shared_ptr<const C2Component>> components,C2BlockPool::local_id_t poolId,std::shared_ptr<C2BlockPool> *pool) {// ......switch(allocatorId) {case C2PlatformAllocatorStore::ION: /* also ::DMABUFHEAP */res = allocatorStore->fetchAllocator(C2PlatformAllocatorStore::ION, &allocator);std::shared_ptr<C2BlockPool> ptr(new C2PooledBlockPool(allocator, poolId), deleter);break;case C2PlatformAllocatorStore::BLOB:res = allocatorStore->fetchAllocator(C2PlatformAllocatorStore::BLOB, &allocator);std::shared_ptr<C2BlockPool> ptr(new C2PooledBlockPool(allocator, poolId), deleter);break;case C2PlatformAllocatorStore::GRALLOC:case C2AllocatorStore::DEFAULT_GRAPHIC:res = allocatorStore->fetchAllocator(C2AllocatorStore::DEFAULT_GRAPHIC, &allocator);std::shared_ptr<C2BlockPool> ptr(new C2PooledBlockPool(allocator, poolId), deleter);break;case C2PlatformAllocatorStore::BUFFERQUEUE:res = allocatorStore->fetchAllocator(C2PlatformAllocatorStore::BUFFERQUEUE, &allocator);std::shared_ptr<C2BlockPool> ptr(new C2BufferQueueBlockPool(allocator, poolId), deleter);break;default:std::shared_ptr<C2BlockPool> ptr;res = C2PlatformStorePluginLoader::GetInstance()->createBlockPool(allocatorId, poolId, &ptr, deleter);break;}return res;
}
对于Codec2框架提供的C2Allocator和C2BlockPool:
- 如果Allocator id为BUFFERQUEUE,需要创建C2BufferQueueBlockPool;
- 如果Allocator id为ION或GRALLOC,则需要创建C2PooledBlockPool;
如果厂商需要自定义Allocator,那么也要实现一个对应的C2BlockPool,实例创建使用C2PlatformStorePluginLoader的createBlockPool来完成。
2、C2PooledBlockPool
C2PooledBlockPool用于管理一组预先分配的内存块,这些内存块可以被重复使用,以避免频繁的内存分配和释放操作。C2PooledBlockPool通常用于那些对内存块的大小和数量有一定需求,但这些需求相对固定的情况。
先来看一下C2PooledBlockPool的UML类图:
C2PooledBlockPool::C2PooledBlockPool(const std::shared_ptr<C2Allocator> &allocator,const local_id_t localId,BufferPoolVer ver): mAllocator(allocator), mLocalId(localId), mBufferPoolVer(ver) {if (mBufferPoolVer == VER_HIDL) {mImpl = std::make_unique<Impl>(allocator);}if (mBufferPoolVer == VER_AIDL2) {mImpl2 = std::make_unique<Impl2>(allocator);}
}
创建C2PooledBlockPool需要传入两个参数:
- allocator:C2BlockPool内部使用的C2Allocator;
- localId:当前进程独一无二的C2BlockPool id;
3、buffer获取过程分析(一)
4、buffer获取过程分析(二)
5、小结
原文阅读:
Android Codec2(十八)C2PooledBlockPool
扫描下方二维码,关注公众号《青山渺渺》阅读音视频开发内容。