拓十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Linux Gstreamer深度解析之gst_audio_decoder_set_use_default_pad_acceptcaps调用流程与实战(四十七)

Linux Gstreamer深度解析之gst_audio_decoder_set_use_default_pad_acceptcaps调用流程与实战(四十七)

简介:CSDN博客专家、《Android系统多媒体进阶实战》作者

博主新书推荐:《Android系统多媒体进阶实战》🚀
Android Audio工程师专栏地址:Audio工程师进阶系列【原创干货持续更新中……】🚀
Android多媒体专栏地址:多媒体系统工程师系列【原创干货持续更新中……】🚀
专题一 二:AAOS车载系统+AOSP14系统攻城狮入门视频实战课🚀
专题三:Android14 Binder之HIDL与AIDL通信实战课🚀
专题四:Android15快速自定义与集成音效实战课🚀
专题五:Android15音频策略实战课🚀
专题六:Android15音频性能实战课(无声/杂音/断音/爆音实战案例)🚀

人生格言:人生从来没有捷径,只有行动才是治疗恐惧和懒惰的唯一良药.

更多原创,欢迎关注:Android系统攻城狮


🍉🍉🍉文章目录🍉🍉🍉

      • 🌻1.前言
      • 🌻2.应用场景和用法
        • 2.1切换AcceptCaps处理路径
        • 2.2函数原型与返回语义
      • 🌻3.调用流程剖析
        • 3.1输入Pad查询与处理分派
        • 3.2默认处理与自定义处理的差异
      • 🌻4.实战案例
        • 4.1准备Opus解码器和宽泛Caps查询
        • 4.2切换处理路径并观察查询结果
        • 4.3完整代码与关键输出
      • 🌻5.总结

🌻1.前言

本篇目的:理解gst_audio_decoder_set_use_default_pad_acceptcaps()如何改变GstAudioDecoder输入Pad对ACCEPT_CAPS查询的处理路径,并通过实际查询验证默认Pad处理和自定义处理的差异。

GstAudioDecoder创建时会拥有输入Pad、输出Pad以及对应的Pad模板。上游在协商前可能通过GST_QUERY_ACCEPT_CAPS询问输入Pad是否能够接受某组Caps。

gst_audio_decoder_set_use_default_pad_acceptcaps()不直接执行查询,也不修改Caps。它只修改一个内部开关,决定后续ACCEPT_CAPS查询使用GStreamer默认Pad处理逻辑,还是使用GstAudioDecoder自己的兼容处理逻辑。

Pad上的GST_PAD_SET_ACCEPT_TEMPLATE和GST_PAD_SET_ACCEPT_INTERSECT标志,决定默认处理逻辑使用Pad模板还是动态查询结果,以及采用子集判断还是交集判断。

AudioDecoder子类和输入Pad

设置acceptcaps处理开关

收到ACCEPT CAPS查询

选择默认Pad处理或自定义处理

返回Caps接受结果

🌻2.应用场景和用法

2.1切换AcceptCaps处理路径

gst_audio_decoder_set_use_default_pad_acceptcaps()主要用于需要调整输入PadCaps接受策略的音频解码器子类。

场景使用方式解决的问题
解码器希望使用Pad默认查询逻辑传入TRUE由Pad默认处理器决定Caps是否可接受
解码器需要接受不完整Caps配合GST_PAD_SET_ACCEPT_INTERSECT使用交集判断,而不是要求查询Caps完全属于允许Caps
解码器希望避免递归查询配合GST_PAD_SET_ACCEPT_TEMPLATE直接使用Pad模板Caps,避免再次触发动态Caps查询
解码器需要自定义模板和动态Caps判断传入FALSE继续使用GstAudioDecoder内置的兼容处理逻辑

Vorbis和Opus解码器都在实例初始化时调用该函数,并把输入Pad设置为使用模板Caps。说明这个接口通常用于解码器子类初始化阶段,而不是每次收到查询时重复调用。

函数调用时机错误也会产生明显差异:

  • 只设置Pad标志而不调用该函数,GstAudioDecoder仍可能走自定义AcceptCaps路径。
  • 只传入TRUE而不设置交集标志,默认处理仍然可能使用子集判断。
  • 把ACCEPT_CAPS查询当成真正的Caps设置,不会改变当前PadCaps,也不会触发解码器的set_format()。
2.2函数原型与返回语义

函数原型如下:

voidgst_audio_decoder_set_use_default_pad_acceptcaps(GstAudioDecoder*decoder,gboolean use);
参数含义
decoder有效的GstAudioDecoder对象,通常是具体解码器子类实例
use传入TRUE使用默认PadAcceptCaps处理,传入FALSE使用GstAudioDecoder自定义处理

函数返回值为void。它只写入内部字段:

decoder->priv->use_default_pad_acceptcaps=use;

最小调用方式如下:

gst_audio_decoder_set_use_default_pad_acceptcaps(decoder,TRUE);GST_PAD_SET_ACCEPT_TEMPLATE(GST_AUDIO_DECODER_SINK_PAD(decoder));GST_PAD_SET_ACCEPT_INTERSECT(GST_AUDIO_DECODER_SINK_PAD(decoder));

调用前,解码器实例和输入Pad已经由GstAudioDecoder基类创建。调用后,后续输入Pad收到GST_QUERY_ACCEPT_CAPS时会根据内部开关选择处理路径。

这个函数不会:

  • 创建或释放Pad。
  • 修改Pad模板Caps。
  • 发送Caps事件。
  • 触发解码器回调。
  • 直接返回Caps查询结果。
  • 自动设置GST_PAD_SET_ACCEPT_TEMPLATE或GST_PAD_SET_ACCEPT_INTERSECT。

几个相邻接口的职责不同:

接口作用
gst_audio_decoder_set_use_default_pad_acceptcaps()切换GstAudioDecoder的AcceptCaps处理路径
gst_audio_decoder_sink_query_default()处理基类输入Pad收到的查询
gst_pad_query_default()执行Pad默认查询逻辑
gst_pad_query_accept_caps()由调用者发起AcceptCaps查询并取得布尔结果
GST_PAD_SET_ACCEPT_TEMPLATE()让默认处理使用Pad模板Caps
GST_PAD_SET_ACCEPT_INTERSECT()让默认处理使用交集判断
gst_audio_decoder_proxy_getcaps()处理CAPS查询,不等同于ACCEPT_CAPS查询

🌻3.调用流程剖析

3.1输入Pad查询与处理分派

GstAudioDecoder初始化时,会为输入Pad注册查询函数。输入Pad收到查询后,首先进入gst_audio_decoder_sink_query(),再调用GstAudioDecoderClass中的sink_query虚函数。

基类默认使用gst_audio_decoder_sink_query_default()。当查询类型为GST_QUERY_ACCEPT_CAPS时,函数读取use_default_pad_acceptcaps字段。

字段为TRUE时,调用gst_pad_query_default()。字段为FALSE时,进入音频解码器自己的模板Caps和允许Caps判断逻辑。

是

否

上游发起ACCEPT CAPS查询

输入Pad查询处理

使用默认Pad处理

默认Pad处理器按Pad标志判断

AudioDecoder自定义Caps判断

返回accept结果

这个函数只影响查询分派。真正发起查询的是上游或应用,真正设置查询结果的是Pad查询处理器。

3.2默认处理与自定义处理的差异

当use为FALSE时,gst_audio_decoder_sink_query_default()会执行自定义逻辑:

gst_query_parse_accept_caps(query,&caps);template_caps=gst_pad_get_pad_template_caps(pad);accept=gst_caps_is_subset(caps,template_caps);gst_caps_unref(template_caps);if(accept){allowed_caps=gst_pad_query_caps(pad,caps);accept=gst_caps_can_intersect(caps,allowed_caps);gst_caps_unref(allowed_caps);}gst_query_set_accept_caps_result(query,accept);

这条路径先要求查询Caps属于Pad模板Caps,再查询当前允许Caps并执行交集判断。

当use为TRUE时,函数调用gst_pad_query_default()。默认Pad处理器会先得到一组允许Caps:

  • 设置GST_PAD_SET_ACCEPT_TEMPLATE时,允许Caps来自Pad模板。
  • 未设置该标志时,允许Caps来自Pad的动态Caps查询。

得到允许Caps后,比较方式由另一个Pad标志决定:

  • 设置GST_PAD_SET_ACCEPT_INTERSECT时,调用gst_caps_can_intersect()。
  • 未设置该标志时,调用gst_caps_is_subset()。

是

否

默认Pad处理

得到允许Caps

使用交集判断

执行can_intersect

执行is_subset

设置accept查询结果

所以,gst_audio_decoder_set_use_default_pad_acceptcaps()只是处理路径开关。默认路径的最终行为,还要结合两个Pad标志共同决定。

🌻4.实战案例

4.1准备Opus解码器和宽泛Caps查询

本案例使用opusdec作为具体的GstAudioDecoder子类。Opus解码器的输入Pad模板包含多种audio/x-opus格式约束,宽泛的audio/x-opusCaps可以与模板产生交集,但不一定属于模板Caps的子集。

程序创建解码器后,获取输入Pad,并准备一组宽泛Caps:

GstElement*decoder;GstPad*sink_pad;GstCaps*query_caps;decoder=gst_element_factory_make("opusdec",NULL);sink_pad=gst_element_get_static_pad(decoder,"sink");query_caps=gst_caps_from_string("audio/x-opus");

系统需要安装包含opusdec的GStreamer插件。插件不存在时,程序会直接提示,不能把缺少插件误判为AcceptCaps失败。

4.2切换处理路径并观察查询结果

程序执行三次查询:

  1. use设置为FALSE,使用GstAudioDecoder自定义逻辑。
  2. use设置为TRUE,使用默认Pad逻辑,但关闭交集判断。
  3. use设置为TRUE,同时开启模板Caps和交集判断。

第三种配置允许宽泛的audio/x-opus与Pad模板产生交集,能够验证目标函数和Pad标志之间的关系。

4.3完整代码与关键输出
#include<gst/gst.h>#include<gst/audio/audio.h>intmain(intargc,char*argv[]){GstElement*decoder;GstPad*sink_pad;GstCaps*query_caps;gboolean custom_result;gboolean default_subset_result;gboolean default_intersect_result;gst_init(&argc,&argv);decoder=gst_element_factory_make("opusdec",NULL);if(decoder==NULL){g_printerr("opusdec plugin is unavailable\n");return1;}sink_pad=gst_element_get_static_pad(decoder,"sink");if(sink_pad==NULL){g_printerr("Failed to get decoder sink pad\n");gst_object_unref(decoder);return1;}query_caps=gst_caps_from_string("audio/x-opus");if(query_caps==NULL){g_printerr("Failed to create query caps\n");gst_object_unref(sink_pad);gst_object_unref(decoder);return1;}gst_audio_decoder_set_use_default_pad_acceptcaps(GST_AUDIO_DECODER(decoder),FALSE);custom_result=gst_pad_query_accept_caps(sink_pad,query_caps);gst_audio_decoder_set_use_default_pad_acceptcaps(GST_AUDIO_DECODER(decoder),TRUE);GST_PAD_SET_ACCEPT_TEMPLATE(sink_pad);GST_PAD_UNSET_ACCEPT_INTERSECT(sink_pad);default_subset_result=gst_pad_query_accept_caps(sink_pad,query_caps);GST_PAD_SET_ACCEPT_INTERSECT(sink_pad);default_intersect_result=gst_pad_query_accept_caps(sink_pad,query_caps);g_print("Custom handler: %s\n",custom_result?"TRUE":"FALSE");g_print("Default subset handler: %s\n",default_subset_result?"TRUE":"FALSE");g_print("Default intersect handler: %s\n",default_intersect_result?"TRUE":"FALSE");gst_caps_unref(query_caps);gst_object_unref(sink_pad);gst_object_unref(decoder);return0;}

编译运行:

gcc test_audio_decoder_acceptcaps.c-otest_audio_decoder_acceptcaps\$(pkg-config--cflags--libsgstreamer-1.0 gstreamer-audio-1.0)./test_audio_decoder_acceptcaps

在opusdec插件可用且Pad模板保持当前实现时,关键输出应体现三种处理差异:

Custom handler: FALSE Default subset handler: FALSE Default intersect handler: TRUE

这个结果说明,gst_audio_decoder_set_use_default_pad_acceptcaps()本身不决定Caps一定接受或拒绝。它只把查询交给默认Pad处理器,最终结果还取决于Pad模板、允许Caps以及GST_PAD_SET_ACCEPT_INTERSECT等标志。

🌻5.总结

gst_audio_decoder_set_use_default_pad_acceptcaps()就是为GstAudioDecoder输入Pad选择默认或自定义的AcceptCaps查询处理路径,但它不负责设置Caps,最终接受结果仍由Pad模板、动态Caps和Pad标志共同决定。

返回列表