在两个衬垫的caps协商完成之后,元件之间需要确认如何分配buffer。本文梳理Gstreamer 内存协商机制,比如当某元件不能自己分配内存时,如何使用其他元件的分配器。

场景和目的

一般而言,内存分配的协商是在caps协商之后。根据需求匹配到对应的参数,获取到分配器和内存池,然后才能开始数据传输。
在sink_event函数的GST_EVENT_CAPS分支,通过解析到上游的caps信息,来设置自己的caps。紧接着就会发起内存分配的协商。
因此我们在Gstreamer 源码中,很多协商都是在元件的gst_xxx_set_caps函数中进行的。

对于很多基础类,我们会看到两个相关的虚函数:

  • propose_allocation
    在收到GST_QUERY_ALLOCATION问询时,一般时候直接调用该函数来处理,为上游元件提供建议值。
  • decide_allocation
    根据下游的建议参数,来决定最终的参数值。一般会判断当前query是否具有有效值,补齐query中的参数。该函数可能在默认的negotiate函数中调用,也可能在set caps之后调用(通常的element)。

发起问询

协商总是由源衬垫src pad来发起,srcpad给出想要的参数,最终由下游节点判断是否能满足要求。
下游的sinkpad可以返回以下三类信息:

  • GstAllocator
  • GstBufferPool
  • GstMeta

请求端——创建问询

首先创建一个问询:GST_QUERY_ALLOCATION,携带需要存放的caps格式 。如果需要使用内存池,可以把need-pool的标志位置一。
和其他问询一样,在实际代码中,并不直接调用GST_QUERY_ALLOCATION ,而是通过封装的接口gst_query_new_allocation来进行的:

  GstQuery *query;query = gst_query_new_allocation (outcaps, TRUE);

gst_query_new_allocation 其实现如下:

GstQuery *
gst_query_new_allocation (GstCaps * caps, gboolean need_pool)
{GstQuery *query;GstStructure *structure;structure = gst_structure_new_id (GST_QUARK (QUERY_ALLOCATION),GST_QUARK (CAPS), GST_TYPE_CAPS, caps,GST_QUARK (NEED_POOL), G_TYPE_BOOLEAN, need_pool, NULL);query = gst_query_new_custom (GST_QUERY_ALLOCATION, structure);return query;
}

请求端——发送问询

之后我们往对等节点发送这个问询:

  if (!gst_pad_peer_query (scope->priv->srcpad, query)) {/* not a problem, we use the query defaults */GST_DEBUG_OBJECT (scope, "allocation query failed");}

请求端——检查问询结果

接下来解析结果,获取分配器、参数、pool信息:

  GstAllocator *allocator;GstAllocationParams params;GstBufferPool *pool = NULL;//获取params和allocatorif (gst_query_get_n_allocation_params (query) > 0) {gst_query_parse_nth_allocation_param (query, 0, &allocator, &params);}//获取poolif (gst_query_get_n_allocation_pools (query) > 0)gst_query_parse_nth_allocation_pool (query, 0, &pool, &size, &min, &max);//接下来可以按正常流程使用pool和allocatorconfig = gst_buffer_pool_get_config (pool);//查询meta,并在buffer中添加video meta选项if (gst_query_find_allocation_meta (query, GST_VIDEO_META_API_TYPE, NULL))gst_buffer_pool_config_add_option (config, GST_BUFFER_POOL_OPTION_VIDEO_META);//设置并激活poolgst_buffer_pool_config_set_params (config, caps, size, min, max);gst_buffer_pool_config_set_allocator (config, allocator, &params);gst_buffer_pool_set_config (pool, config);/* and activate */gst_buffer_pool_set_active (pool, TRUE);

响应问询

和其他问询一样,问询的响应都是在sink_query函数中完成的。一般是调用propose_allocation函数来直接处理。

响应端——解析问询

我们可以通过gst_query_parse_allocation来解析问询结果,拿到caps和pool的需求信息。

    GstCaps *outcaps;gboolean need_pool;gst_query_parse_allocation (query, &caps, &need_pool);

响应端——配置问询

根据解析到信息,创建对应资源,并添加到query:

//1. 添加allocator和params:
gst_query_add_allocation_param(query, priv->propose_allocator, &priv->propose_allocation_params);
//2. 创建poolif (need_pool) {pool = gst_video_buffer_pool_new ();config = gst_buffer_pool_get_config (pool);gst_buffer_pool_config_set_params (config, caps, size, 0, 0);if (!gst_buffer_pool_set_config (pool, config))goto config_failed;
//添加poolgst_query_add_allocation_pool (query, pool, size, 2, 0);}
//3. 添加meta,可以添加多个meta */gst_query_add_allocation_meta (query, GST_VIDEO_META_API_TYPE, 0);

之后,src端就可以在自己的decide_allocation函数来解析这些设定值了。

重协商

当配置发生变化的时候,可能会执行再协商一个新的pool,比如视频分辨率发生变化。

上游变化

上游发生变化时,这时候我们不能马上把当前的pool重新配置,因为pipeline中可能还在使用其中的buffer,所以需要创建新的pool。当然也可以等待当前pool耗尽之后,重新配置当前的pool。
重新协商的过程和之前一样,在协商caps之后发起同样的流程。

下游变化

当下游想要修改配置时,需要发送一个GST_EVENT_RECONFIGURE的事件,命令上游重新协商格式和pool。
当pipeline出现元件的增删,或者拓扑结构变化时,会触发RECONFIGURE事件。pipeline的重新配置也会触发caps和pool的重新协商。
GST_EVENT_RECONFIGURE事件标记每一个需要重新配置的pad。然后,下一次缓冲区分配将需要重新协商或重新配置pool。
对于GST_EVENT_RECONFIGURE的caps相关流程可以参考《capabilities negociation 规格协商》。

参考

插件开发教程之内存分配
Gstreamer 设计文档之bufferpool
Gstreamer API之bufferpool

Gstreamer 内存分配协商机制相关推荐

  1. Yarn 内存分配管理机制及相关参数配置

    理解Yarn的内存管理与分配机制,对于我们搭建.部署集群,开发维护应用都是尤为重要的,对于这方面我做了一些调研供大家参考. 一.相关配置情况 关于Yarn内存分配与管理,主要涉及到了ResourceM ...

  2. JVM源码简析(楔子)-对象内存分配过程和PS回收器中YGC触发FGC的现象

    前言 想要搞明白Java对象内存申请过程的原因,是因为第一次接触线上GC日志的时候,发现了一些很奇怪的现象,就是young gc触发了full gc.为了搞清楚这个现象,得先要来个测试去复现. 复现现 ...

  3. 深入理解JVM内存分配策略

    点击上方 "程序员小乐"关注公众号, 星标或置顶一起成长 每天早上8点20分, 第一时间与你相约 每日英文 Don't blame people for disappointing ...

  4. 内存分配算法java_被说烂了的Java垃圾回收算法,我带来了最“清新脱俗”的详细图解...

    一.概况 理解Java虚拟机垃圾回收机制的底层原理,是系统调优与线上问题排查的基础,也是一个高级Java程序员的基本功,本文就针对Java垃圾回收这一主题做一些整理与记录.Java垃圾回收器的种类繁多 ...

  5. JVM-09自动内存管理机制【内存分配和回收策略】

    文章目录 思维导图 对象优先在eden区域分配 理论 案例 虚拟机参数设置及参数说明 代码 GC结果分析 大对象直接进入老年代 理论 案例 虚拟机参数设置及参数说明 代码 GC日志 长期存活的对象将进 ...

  6. MySQL • 源码分析 • 内存分配机制

    摘要: 前言 内存资源由操作系统管理,分配与回收操作可能会执行系统调用(以 malloc 算法为例,较大的内存空间分配接口是 mmap, 而较小的空间 free 之后并不归还给操作系统 ),频繁的系统 ...

  7. Linux内存分配机制之伙伴系统和SLAB

    转载请注明原文地址:http://www.cnblogs.com/ygj0930/p/6539590.html  内核内存管理的一项重要工作就是如何在频繁申请释放内存的情况下,避免碎片的产生.这就要求 ...

  8. Java基础-Java中的内存分配与回收机制

    Java基础-Java中的内存分配与回收机制 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一. 二. 转载于:https://www.cnblogs.com/yinzhengji ...

  9. 阿里P8架构师谈:JVM的内存分配、运行原理、回收算法机制

    不管是BAT面试,还是工作实践中的JVM调优以及参数设置,或者内存溢出检测等,都需要涉及到Java虚拟机的内存模型.内存分配,以及回收算法机制等,这些都是必考.必会技能. JVM内存模型 JVM内存模 ...

最新文章

  1. 如何规划创建一个家庭实验室
  2. https、SSL与数字证书介绍
  3. python可以制作网站吗_小白如何入门Python? 制作一个网站为例
  4. Lunar New Year and a Wander
  5. linux下scp命令详解
  6. First Impression on BBED: recover deleted rows
  7. Oracle学习笔记:数据字典
  8. 数据结构实验 寻找数组主元素(2013考研题)
  9. 后端CORS解决跨域问题
  10. Spring3.0核心组件的源码简单分析
  11. 数组模拟栈解决括号匹配
  12. Ubuntu-AMD显卡驱动更新
  13. 单相Boost功率因数校正电路(PFC)设计与仿真(Simulink Saber):第二章 仿真模型搭建与控制参数整定
  14. 优化机场值机体验之护照阅读器
  15. Android 11 AppOps setOnOpNotedCallback实现分析
  16. leetcode记录-340-至多包含 K 个不同字符的最长子串-双指针
  17. mix2s适配鸿蒙,小米MIX2S|MIUI10|9.05.12|GPU调节|CPU调节_最新最全的小米MIX 2SROM刷机包下载、刷机...
  18. web中的清除浮动方法
  19. 自动批量翻译文件夹名称为中文
  20. 常用的几款Vue移动端UI推荐

热门文章

  1. 第一个合作开发的游戏项目--飞机大战(cocos creater)
  2. Linux防火墙(二)
  3. 树莓派ubuntu换源方法
  4. vrrp广播风暴_VRRP常见故障解决方法
  5. 星辰和大海都需要门票,诗和远方也很贵
  6. 大数据小说 | 如何用一小时看透一个初识的姑娘
  7. kaggle实战:基于超市消费数据的用户个性化分析案例
  8. python time.strftime_Python time.strftime()用法及代码示例
  9. 清洗一下自身的系统——五脏排毒DIY(转载)
  10. css 绝对定位fixed,按钮居中