简介:CSDN博客专家、《Android系统多媒体进阶实战》作者
博主新书推荐:《Android系统多媒体进阶实战》🚀
Android Audio工程师专栏地址:Audio工程师进阶系列【原创干货持续更新中……】🚀
Android多媒体专栏地址:多媒体系统工程师系列【原创干货持续更新中……】🚀
专题一 二:AAOS车载系统+AOSP14系统攻城狮入门视频实战课🚀
专题三:Android14 Binder之HIDL与AIDL通信实战课🚀
专题四:Android15快速自定义与集成音效实战课🚀
专题五:Android15音频策略实战课🚀
专题六:Android15音频性能实战课(无声/杂音/断音/爆音实战案例)🚀
人生格言:人生从来没有捷径,只有行动才是治疗恐惧和懒惰的唯一良药.
🍉🍉🍉文章目录🍉🍉🍉
- 🌻1.前言
- 🌻2.应用场景和用法
- 2.1保存每个输入Pad的音频格式
- 2.2函数原型与状态变化
- 🌻3.调用流程剖析
- 3.1从输入Caps处理函数进入Pad信息更新
- 3.2在Pad锁内更新GstAudioInfo
- 🌻4.实战案例
- 4.1准备interleave和请求Pad
- 4.2调用接口并检查Pad信息
- 4.3完整代码
- 🌻5.总结
🌻1.前言
本篇目的:理解
gst_audio_aggregator_set_sink_caps()如何把输入Caps解析成GstAudioAggregatorPad的音频信息,并梳理它在interleave接收端Caps处理中的位置。
聚合类音频元素需要知道每个Sink Pad收到的音频格式,后续才能按Pad的格式处理输入数据。gst_audio_aggregator_set_sink_caps()负责把Caps解析并写入指定Pad的info字段。它不负责Caps协商,也不负责检查不同输入Pad的格式是否兼容。
🌻2.应用场景和用法
2.1保存每个输入Pad的音频格式
GstAudioAggregatorPad包含一个GstAudioInfo成员,用于记录这个输入Pad当前对应的音频格式。gst_audio_aggregator_set_sink_caps()把Caps转换成该成员,供聚合器后续读取。
| 场景 | 调用前的处理 | 调用后的作用 |
|---|---|---|
interleave收到输入Caps | 检查音频格式是否有效 | 保存Pad的采样率、声道数和格式 |
| 聚合器准备处理输入Buffer | 已有Pad级音频信息 | 按Pad格式解释输入数据 |
| 输入格式变化 | 元素确认新Caps可以接受 | 更新Pad的音频信息 |
自定义GstAudioAggregator子类 | 确认Caps与自身策略兼容 | 将输入Caps写入聚合Pad状态 |
不能把这个接口当作Caps协商入口。它不会向上游查询Caps,也不会决定Src Pad输出Caps。调用者应先检查Caps,再调用此函数。
2.2函数原型与状态变化
函数原型如下:
voidgst_audio_aggregator_set_sink_caps(GstAudioAggregator*aagg,GstAudioAggregatorPad*pad,GstCaps*caps);| 参数 | 含义 |
|---|---|
aagg | 所属的GstAudioAggregator对象 |
pad | 需要更新音频信息的聚合器Sink Pad |
caps | 描述该Pad输入音频格式的Caps |
函数返回类型为void。它会锁定Pad对象,调用gst_audio_info_from_caps()解析Caps并写入pad->info,随后解锁。
在启用断言的构建中,解析结果会通过g_assert()检查。禁用断言时,函数仍然尝试解析,但不处理失败结果。因此调用者需要在调用前确保Caps有效。函数本身不返回成功或失败状态。
相邻接口的职责不同:
| 接口或操作 | 职责 |
|---|---|
gst_audio_info_from_caps() | 将Caps解析成GstAudioInfo |
gst_audio_aggregator_set_sink_caps() | 将解析结果写入聚合器Pad的info字段 |
| 聚合器的Caps处理函数 | 检查输入Caps是否符合元素策略 |
| 聚合器输出Caps协商 | 确定Src Pad对下游提供的格式 |
🌻3.调用流程剖析
3.1从输入Caps处理函数进入Pad信息更新
gst_audio_aggregator_set_sink_caps()在gstaudioaggregator.c中实现。一个实际调用者是GstAudioInterleave的Sink Pad Caps处理路径。
interleave先用gst_audio_info_from_caps()解析输入Caps,并检查输入格式以及它与已有Sink Pad格式的关系。通过这些检查后,才调用gst_audio_aggregator_set_sink_caps()更新对应Pad的信息。
调用者的预检查很重要:interleave可能需要确保多个Sink Pad的输入格式能用于同一个输出格式。这个策略由元素自身完成,不是gst_audio_aggregator_set_sink_caps()完成。
3.2在Pad锁内更新GstAudioInfo
函数的主体只做一件事:在Pad对象锁保护下解析Caps并更新pad->info。
核心逻辑如下:
GST_OBJECT_LOCK(pad);valid=gst_audio_info_from_caps(&pad->info,caps);g_assert(valid);GST_OBJECT_UNLOCK(pad);在禁用断言的编译分支中,源码仍会执行gst_audio_info_from_caps(),但会忽略布尔返回值。由于函数返回void,调用者无法从函数返回值判断Caps解析结果。
pad->info表示单个Sink Pad的输入格式。它不是聚合器的输出格式,也不代表Caps已经成功发送给下游。输出格式仍由聚合器自己的Caps协商流程确定。
🌻4.实战案例
4.1准备interleave和请求Pad
本例创建interleave元素,请求一个Sink Pad,再准备一组合法的单声道S16LE音频Caps。
这里直接调用gst_audio_aggregator_set_sink_caps(),观察它对Pad音频信息的更新。这个最小例子只检查Pad字段,不运行完整的音频聚合管线。
4.2调用接口并检查Pad信息
调用前,先确认interleave元素和请求到的Sink Pad都创建成功。调用接口后,在Pad对象锁内检查采样率、声道数和音频格式是否与Caps一致。
Caps由调用者持有,因此检查完成后由调用者释放。请求Pad也应通过元素释放,再解除调用者持有的Pad引用。
4.3完整代码
#include<gst/gst.h>#include<gst/audio/audio.h>intmain(intargc,char*argv[]){GstElement*interleave;GstPad*sink_pad;GstCaps*caps;GstAudioAggregatorPad*audio_pad;gboolean valid;gst_init(&argc,&argv);/* 创建实际使用GstAudioAggregatorPad的interleave元素 */interleave=gst_element_factory_make("interleave",NULL);if(interleave==NULL)return1;/* 请求一个聚合器Sink Pad */sink_pad=gst_element_request_pad_simple(interleave,"sink_%u");if(sink_pad==NULL){gst_object_unref(interleave);return1;}/* 准备有效的单声道S16LE输入Caps */caps=gst_caps_new_simple("audio/x-raw","format",G_TYPE_STRING,"S16LE","rate",G_TYPE_INT,48000,"channels",G_TYPE_INT,1,"layout",G_TYPE_STRING,"interleaved",NULL);audio_pad=GST_AUDIO_AGGREGATOR_PAD(sink_pad);/* 将Caps解析结果写入该Sink Pad的音频信息 */gst_audio_aggregator_set_sink_caps(GST_AUDIO_AGGREGATOR(interleave),audio_pad,caps);/* 按Pad对象锁要求读取公开的只读info字段 */GST_OBJECT_LOCK(audio_pad);valid=GST_AUDIO_INFO_FORMAT(&audio_pad->info)==GST_AUDIO_FORMAT_S16&&GST_AUDIO_INFO_RATE(&audio_pad->info)==48000&&GST_AUDIO_INFO_CHANNELS(&audio_pad->info)==1;GST_OBJECT_UNLOCK(audio_pad);/* 释放Caps、请求Pad和元素 */gst_caps_unref(caps);gst_element_release_request_pad(interleave,sink_pad);gst_object_unref(sink_pad);gst_object_unref(interleave);returnvalid?0:1;}🌻5.总结
gst_audio_aggregator_set_sink_caps()在Pad对象锁保护下把有效Caps解析为GstAudioInfo并保存到指定的GstAudioAggregatorPad中。