vcu-sw-ctrl 2018.3 version
一. 官方解释
官方解释请参考手册pg252-vcu.pdf和代码中的注释。
Memory operations are indirected through function pointers. The AL_Allocator default implementation simply wraps malloc and free, etc.
Two higher level techniques are used for memory management: reference counted buffers, and buffer pools. A reference counted buffer is created with a zero reference count. The AL_Buffer_Ref and AL_Buffer_Unref functions increment and decrement the reference count, respectively. The AL_Buffer interface separates the management of buffer metadata from the management of the data memory associated with the buffer. Usage of the reference count is optional. The AL_TBufPool implementation manages a buffer pool with a ring buffer. Some ring buffers have sizes fixed at compile time. Exceeding the buffer pool size results in undefined behavior. See AL_Decoder_PutDisplayPicture.
The AL_TBuffer api doesn't allocate the memory itself and only provide an easy access to it via its api. It wraps a memory buffer allocated using the AL_TAllocator api. The AL_TBuffer takes ownership of the memory buffer and will free it at destruction.
二.结构体解析
AL_TBuffer的指针指向实际是AL_TBufferImpl的头指针,只在具体函数中操作值,外部不暴露。符合管理与内存分离的思想。
BufferAPI.c中的都是通过AL_TBuffer的handle,封装好的api,操作AL_TBufferImpl中的真实数据,用户只能通过这种方式操作,AL_Buffer_Create,AL_Buffer_InitData等,具体看api实现。
AL_TMetaData实际也是管理和内存分离的思路,解耦合做的很好。
-
AL_TBuffer
typedef struct
{
AL_TAllocator* pAllocator; /*!< Used to retrieve the memory hidden behind hBuf */
size_t zSize; /*!< Size of the allocated memory attached to the buffer */
AL_HANDLE hBuf; /*!< Handle to the allocated buffer */
}AL_TBuffer;
size和medata无关,表示的是AL_HANDLE hBuf的所指向内存的大小,在wrapper时,指的是AL_TWrapperHandle hBUF->pdata的大小。
AL_TAllocator* pAllocator为 s_WrapperAllocator 或s_DefaultAllocator 。
指针AL_HANDLE hBuf指向一段分配的内存,在wrapper时,指向AL_TWrapperHandle结构体,非wapper时,由LinuxDma_Alloc_256B_Aligned分配的DmaBuffer结构体。
2. AL_TWrapperHandle
typedef struct
{
uint8_t* pData;
void* pUserData;
void (* destructor)(void* pUserData, uint8_t* pData);
}AL_TWrapperHandle;
3. AL_TBufferImpl
typedef struct al_t_BufferImpl
{
AL_TBuffer buf;
AL_MUTEX pLock;
int32_t iRefCount;
AL_TMetaData** pMeta;
int iMetaCount;
void* ; /*!< user private data */
PFN_RefCount_CallBack pCallBack; /*!< user callback. called when the buffer refcount reaches 0 */
uint8_t* pData; /*!< Buffer data mapped in userspace */
}AL_TBufferImpl;
iRefCount通过AL_Buffer_Ref,AL_Buffer_Unref加减。ref实际上是在pool的Fifo Dequeue 出队后,不在fifo中了,用户获取到了;用户归还内存后,Unref后,继续在fifo中排队,等着用户。
pCallBack,为unref后调用的回调函数,实际上看起来是FreeBufInPool函数,继续回fifo中排队了。
pUserData和pData有关门的set,get函数,看客户使用。
AL_TBufferImpl中的AL_TMetaData** pMeta;,为真实数据。
4. AL_TMetaData** pMeta;
struct al_t_MetaData
{
AL_EMetaType eType; /*< tag of the metadata */
AL_FCN_MetaDestroy MetaDestroy; /*< custom deleter */
};
typedef enum
{
AL_META_TYPE_SOURCE, /*< useful information related to the reconstructed picture */
AL_META_TYPE_STREAM, /*< useful section of the buffer containing the bitstream */
AL_META_TYPE_CIRCULAR, /*< circular buffer implementation inside the buffer */
AL_META_TYPE_PICTURE, /*< useful information about the bitstream choices for the frame */
#if AL_ENABLE_TWOPASS
AL_META_TYPE_LOOKAHEAD, /*< useful information about the frame for the lookahead*/
#endif
AL_META_TYPE_MAX, /* sentinel */
AL_META_TYPE_EXTENDED = 0x7F000000 /*< user can define their own metadatas after this value. */
}AL_EMetaType;
5.AL_TStreamMetaData
AL_META_TYPE_STREAM时为如下结构体。有专门的封装后函数调用。
typedef struct AL_t_StreamMetaData
{
AL_TMetaData tMeta;
AL_TStreamSection* pSections; /*!< Array of sections */
uint16_t uNumSection; /*!< number of sections inside the buffer */
uint16_t uMaxNumSection /*!< maximum number of sections available */;
}AL_TStreamMetaData;
内存的初始化时主要调用的是AL_Buffer_WrapData, AL_Buffer_Create_And_AllocateNamed和AL_Buffer_Create_And_Allocate,具体看这两个api的调用逻辑,别的都是get,set之类。
参考资料:
pg252-vcu.pdf