Gstreamer 通过GstBufferPool提供了通用内存池的管理。
GstBufferPool统一管理的buffer,需要所有的属性参数都一致,比如大小、填充、元数据metadata和对齐方式alignment。
GstBufferPool分为非激活状态和激活状态。非激活状态下才能配置属性,配置内容包括参数、分配器allocator。激活状态下才可以申请和归还buffer。
struct _GstBufferPool {
GstObject object;
/*< protected >*/
gint flushing;
/*< private >*/
GstBufferPoolPrivate *priv;
gpointer _gst_reserved[GST_PADDING];
};
初始化
使用 gst_buffer_pool_new来新建一个bufferpool。示例;
GstStructure *config;
GstBufferPool *pool;
[...]
/* get config structure */
pool = gst_buffer_pool_new ();
config = gst_buffer_pool_get_config (pool);
/* set caps, size, minimum and maximum buffers in the pool */
gst_buffer_pool_config_set_params (config, caps, size, min, max);
/* configure allocator and parameters */
gst_buffer_pool_config_set_allocator (config, allocator, ¶ms);
/* store the updated configuration again */
gst_buffer_pool_set_config (pool, config);
gst_buffer_pool_set_active (pool, TRUE);
[...]
配置的内容包括:
- buffer的capability
- buffer的size
- buffer数目的最大值和最小值
- buffer的分配器allocator
- 其它选项,可以通过gst_buffer_pool_config_add_option 来添加。
之后可以激活buffer pool,并从pool中获取buffer来使用。注意要检查gst_buffer_pool_acquire_buffer 的返回值。
获取和归还Buffer
通过 gst_buffer_pool_acquire_buffer从内存池中获取一个buffer使用,通过 gst_buffer_pool_release_buffer来将不再使用的buffer归还到内存池。
示例:
[...]
ret = gst_buffer_pool_acquire_buffer (pool, &buffer, NULL);
if (G_UNLIKELY (ret != GST_FLOW_OK))
goto pool_failed;
// Do sth
[...]
gst_buffer_pool_release_buffer(pool, buffer);
[...]
option
GstBufferPool 可以通过option接口进行来进行metadata的操作,包括添加,查询,获取和删除。
[...]
GstBufferPool *pool;
GstStructure *config;
pool = gst_video_buffer_pool_new ();
config = gst_buffer_pool_get_config (pool);
gst_buffer_pool_config_add_option (config, GST_BUFFER_POOL_OPTION_VIDEO_META);
gst_buffer_pool_set_config (pool, config);
/* and activate */
gst_buffer_pool_set_active (pool, TRUE);
[...]
释放规则
当buffer的引用计数为零时,Gstreamer 会判断该buffer是否来自pool,如果是,会自动调用gst_buffer_pool_release_buffer来归还buffer,否则才按照通常情况来释放。用户不需要知道当前使用的buffer是来自某个buffer池。
当所有buffer被归还到pool之后,它们会被释放(文档上是这样讲,但是代码上面没有确认到)。
新建一个BufferPool
实现一个新的BufferPool需要自定义相关的实现函数。
以下通过v4l2的bufferpool(gst-plugins-good-1.18.4\sys\v4l2\gstv4l2bufferpool.c)示例:
static void
gst_v4l2_buffer_pool_class_init (GstV4l2BufferPoolClass * klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GstBufferPoolClass *bufferpool_class = GST_BUFFER_POOL_CLASS (klass);
object_class->dispose = gst_v4l2_buffer_pool_dispose;
object_class->finalize = gst_v4l2_buffer_pool_finalize;
bufferpool_class->start = gst_v4l2_buffer_pool_start;
bufferpool_class->stop = gst_v4l2_buffer_pool_stop;
bufferpool_class->set_config = gst_v4l2_buffer_pool_set_config;
bufferpool_class->alloc_buffer = gst_v4l2_buffer_pool_alloc_buffer;
bufferpool_class->acquire_buffer = gst_v4l2_buffer_pool_acquire_buffer;
bufferpool_class->release_buffer = gst_v4l2_buffer_pool_release_buffer;
bufferpool_class->flush_start = gst_v4l2_buffer_pool_flush_start;
bufferpool_class->flush_stop = gst_v4l2_buffer_pool_flush_stop;
GST_DEBUG_CATEGORY_INIT (v4l2bufferpool_debug, "v4l2bufferpool", 0,
"V4L2 Buffer Pool");
GST_DEBUG_CATEGORY_GET (CAT_PERFORMANCE, "GST_PERFORMANCE");
}
首先我们看以下两个不太相关的函数,有点麻人:
object_class->dispose = gst_v4l2_buffer_pool_dispose;
object_class->finalize = gst_v4l2_buffer_pool_finalize;
这是GObjectClass的两个方法,dispose是丢弃的意思,finalize是结束,都涉及到资源释放。
我们看官方注释:
@dispose: the @dispose function is supposed to drop all references to other objects, but keep the instance otherwise intact, so that client method invocations still work.
It may be run multiple times (due to reference loops). Before returning, @dispose should chain up to the @dispose method of the parent class.
@finalize: instance finalization function, should finish the finalization of the instance begun in @dispose ,
and chain up to the @finalize method of the parent class.
意思是dispose会接触其他对象的所有引用,但是实例还存在,可以使用它们的函数。finalize是结束,释放所有资源。在上面的代码中,我们可以看到dispose是简单的接触引用,而finalize是free和清除资源。
接下来看看属于GstBufferPoolClass的函数:
- set_config: 设置buffer的配置
- start: 启动bufferpool. 默认实现是预分配最小的buffer并加到队列上。
- stop: 停止bufferpool. 默认实现是释放预分配的内存,需要在当所有buffer被归还时调用该函数.
- acquire_buffer: 从pool中获取一个buffer. 默认从队列获取一个buff,当没有可用的buffer时,会等待buffer归还.
- alloc_buffer: 分配buffer。默认实现是根据配置的参数,从配置的allocator分配内存。在buffer中的metadata会被标记为 #GST_META_FLAG_POOLED 和#GST_META_FLAG_LOCKED ,在reset_buffer时不会被移除。
- reset_buffer: 重置buffer到刚被分配时的状态,会清除flags、时隙、和没有被标记为GST_META_FLAG_POOLED的metadata。如果标记了GST_BUFFER_FLAG_TAG_MEMORY,会清除并恢复memory。
- release_buffer: 将buffer归还到pool池。
如果该buffer没有被标记为GST_BUFFER_FLAG_TAG_MEMORY,会通知阻塞的acquire_buffer调用。
如果有GST_BUFFER_FLAG_TAG_MEMORY标记,buffer会被free_buffer接口释放。
* @free_buffer: 释放buffer,默认实现是取消引用。
* @flush_start: 进入flush模式,buffer不能再被获取,并等待正在仍在使用中的buffer被归还.
* @flush_stop: 退出flush模式.