简介: CSDN博客专家、《Android系统多媒体进阶实战》作者
博主新书推荐:《Android系统多媒体进阶实战》🚀 Android Audio工程师专栏地址: Audio工程师进阶系列【原创干货持续更新中……】🚀 Android多媒体专栏地址: 多媒体系统工程师系列【原创干货持续更新中……】🚀 专题一 二:AAOS车载系统+AOSP14系统攻城狮入门视频实战课 🚀 专题三:Android14 Binder之HIDL与AIDL通信实战课 🚀 专题四:Android15快速自定义与集成音效实战课 🚀 专题五:Android15音频策略实战课 🚀 专题六:Android15音频性能实战课(无声/杂音/断音/爆音实战案例) 🚀
人生格言: 人生从来没有捷径,只有行动才是治疗恐惧和懒惰的唯一良药.
更多原创,欢迎关注:Android系统攻城狮
🍉🍉🍉文章目录🍉🍉🍉
-
-
- 🌻1.前言
- 🌻2.应用场景和用法
-
- 🌻2.1 应用场景
- 🌻2.2 函数用法
- 🌻3.调用流程剖析
-
- 🌻3.1 读取Converter内部状态
- 🌻3.2 配置对象的创建和失效边界
- 🌻4.实战案例
-
- 🌻4.1 创建带有重采样选项的Converter
- 🌻4.2 读取当前采样率和配置字段
- 🌻4.3 验证读取结果
- 🌻5.总结
-
🌻1.前言
本篇目的:理解gst_audio_converter_get_config()如何读取GstAudioConverter当前保存的配置和采样率,以及为什么它返回的是借用的配置对象,而不是新的配置副本。
GStreamer使用GstAudioConverter完成采样格式、采样率、声道布局和量化方式等音频转换。创建Converter时,调用者需要提供输入音频信息、输出音频信息以及可选的额外配置。
Converter创建完成后,GstAudioConverter是一个不透明对象,应用不能直接访问它内部的配置字段。当采样率或转换选项发生变化时,应用需要一种正式接口确认Converter当前使用的配置。
const GstStructure *gst_audio_converter_get_config(
GstAudioConverter *convert,
gint *in_rate,
gint *out_rate);
该函数读取:
convert->config
convert->in.rate
convert->out.rate
但它不会执行音频转换,也不会创建新的Converter。
#mermaid-svg-fCxuBj6yXFCzKSws{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-fCxuBj6yXFCzKSws .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-fCxuBj6yXFCzKSws .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-fCxuBj6yXFCzKSws .error-icon{fill:#552222;}#mermaid-svg-fCxuBj6yXFCzKSws .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-fCxuBj6yXFCzKSws .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-fCxuBj6yXFCzKSws .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-fCxuBj6yXFCzKSws .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-fCxuBj6yXFCzKSws .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-fCxuBj6yXFCzKSws .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-fCxuBj6yXFCzKSws .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-fCxuBj6yXFCzKSws .marker{fill:#333333;stroke:#333333;}#mermaid-svg-fCxuBj6yXFCzKSws .marker.cross{stroke:#333333;}#mermaid-svg-fCxuBj6yXFCzKSws svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-fCxuBj6yXFCzKSws p{margin:0;}#mermaid-svg-fCxuBj6yXFCzKSws .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-fCxuBj6yXFCzKSws .cluster-label text{fill:#333;}#mermaid-svg-fCxuBj6yXFCzKSws .cluster-label span{color:#333;}#mermaid-svg-fCxuBj6yXFCzKSws .cluster-label span p{background-color:transparent;}#mermaid-svg-fCxuBj6yXFCzKSws .label text,#mermaid-svg-fCxuBj6yXFCzKSws span{fill:#333;color:#333;}#mermaid-svg-fCxuBj6yXFCzKSws .node rect,#mermaid-svg-fCxuBj6yXFCzKSws .node circle,#mermaid-svg-fCxuBj6yXFCzKSws .node ellipse,#mermaid-svg-fCxuBj6yXFCzKSws .node polygon,#mermaid-svg-fCxuBj6yXFCzKSws .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-fCxuBj6yXFCzKSws .rough-node .label text,#mermaid-svg-fCxuBj6yXFCzKSws .node .label text,#mermaid-svg-fCxuBj6yXFCzKSws .image-shape .label,#mermaid-svg-fCxuBj6yXFCzKSws .icon-shape .label{text-anchor:middle;}#mermaid-svg-fCxuBj6yXFCzKSws .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-fCxuBj6yXFCzKSws .rough-node .label,#mermaid-svg-fCxuBj6yXFCzKSws .node .label,#mermaid-svg-fCxuBj6yXFCzKSws .image-shape .label,#mermaid-svg-fCxuBj6yXFCzKSws .icon-shape .label{text-align:center;}#mermaid-svg-fCxuBj6yXFCzKSws .node.clickable{cursor:pointer;}#mermaid-svg-fCxuBj6yXFCzKSws .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-fCxuBj6yXFCzKSws .arrowheadPath{fill:#333333;}#mermaid-svg-fCxuBj6yXFCzKSws .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-fCxuBj6yXFCzKSws .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-fCxuBj6yXFCzKSws .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-fCxuBj6yXFCzKSws .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-fCxuBj6yXFCzKSws .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-fCxuBj6yXFCzKSws .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-fCxuBj6yXFCzKSws .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-fCxuBj6yXFCzKSws .cluster text{fill:#333;}#mermaid-svg-fCxuBj6yXFCzKSws .cluster span{color:#333;}#mermaid-svg-fCxuBj6yXFCzKSws div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-fCxuBj6yXFCzKSws .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-fCxuBj6yXFCzKSws rect.text{fill:none;stroke-width:0;}#mermaid-svg-fCxuBj6yXFCzKSws .icon-shape,#mermaid-svg-fCxuBj6yXFCzKSws .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-fCxuBj6yXFCzKSws .icon-shape p,#mermaid-svg-fCxuBj6yXFCzKSws .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-fCxuBj6yXFCzKSws .icon-shape .label rect,#mermaid-svg-fCxuBj6yXFCzKSws .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-fCxuBj6yXFCzKSws .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-fCxuBj6yXFCzKSws .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-fCxuBj6yXFCzKSws :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
输入/输出GstAudioInfo
创建GstAudioConverter
保存配置和采样率
gst_audio_converter_get_config
读取当前状态
需要注意:
gst_audio_converter_get_config()
≠
重新配置Converter
它只是读取Converter已经保存的配置。真正修改配置需要调用gst_audio_converter_update_config()。
🌻2.应用场景和用法
🌻2.1 应用场景
GstAudioConverter可以理解成一台已经建立好的音频转换设备:
GstAudioInfo
↓
描述输入和输出音频格式
GstStructure
↓
保存额外转换选项
GstAudioConverter
↓
根据这些信息建立转换链
gst_audio_converter_get_config()相当于读取这台设备当前的配置台账。
它主要适合以下场景:
第一类是确认Converter当前的输入和输出采样率。
当应用使用GST_AUDIO_CONVERTER_FLAG_VARIABLE_RATE允许动态修改采样率后,可以通过该函数读取Converter当前保存的输入采样率和输出采样率,确认更新是否已经写入对象。
第二类是检查额外转换选项。
Converter配置可以包含:
重采样算法
抖动方式
噪声整形方式
量化步长
声道混音矩阵
抖动阈值
应用可以读取这些字段,判断当前配置中是否显式设置了某个选项。
第三类是保存配置快照。
该函数返回的GstStructure不属于调用者。如果应用需要跨越后续的gst_audio_converter_update_config()调用,或者需要在Converter释放后继续比较配置,就必须调用gst_structure_copy()创建自己的副本。
有一个容易混淆的边界:
get_config()返回的是额外配置结构
+
通过输出参数返回当前输入、输出采样率
它不是完整的GstAudioInfo,不会返回格式、声道数、声道位置和内存布局等全部音频信息。
还需要区分显式配置和实际采用的默认值。
例如没有设置重采样算法时,配置结构中可能没有GST_AUDIO_CONVERTER_OPT_RESAMPLER_METHOD字段,但Converter内部仍会使用默认重采样方法。因此,get_config()返回的结构主要表示当前保存的配置字段,不等于已经展开所有默认选项的最终配置表。
🌻2.2 函数用法
函数原型:
const GstStructure *gst_audio_converter_get_config(
GstAudioConverter *convert,
gint *in_rate,
gint *out_rate);
参数:
| convert | 已经创建的GstAudioConverter对象 |
| in_rate | 可选输出参数,用于接收当前输入采样率 |
| out_rate | 可选输出参数,用于接收当前输出采样率 |
in_rate和out_rate可以传入NULL。如果不需要读取某个采样率,就不需要提供对应的输出地址。
返回值:
成功:返回当前内部配置的const GstStructure*
失败:convert为NULL时返回NULL
返回的配置对象具有以下生命周期:
从get_config()返回
↓
只读使用
↓
直到Converter更新配置或被释放
它的所有权标记为transfer none,调用者不能执行:
gst_structure_free(config);
如果需要长期保存,应当复制:
GstStructure *snapshot =
gst_structure_copy(config);
最小读取代码:
gint in_rate = 0;
gint out_rate = 0;
const GstStructure *config =
gst_audio_converter_get_config(
converter,
&in_rate,
&out_rate);
if (config == NULL) {
g_printerr("Failed to get converter config\\n");
}
调用前,Converter已经保存:
输入采样率
输出采样率
额外配置字段
调用后:
in_rate ← convert->in.rate
out_rate ← convert->out.rate
config ← convert->config
Converter本身没有因为读取操作发生状态变化。
🌻3.调用流程剖析
🌻3.1 读取Converter内部状态
gst_audio_converter_get_config()的实现非常短,但它连接了三个重要对象:
GstAudioConverter
├── in.rate
├── out.rate
└── config
核心逻辑可以概括为:
g_return_val_if_fail(convert != NULL, NULL);
if (in_rate)
*in_rate = convert->in.rate;
if (out_rate)
*out_rate = convert->out.rate;
return convert->config;
#mermaid-svg-8ZYddB2kzAIXrMb6{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-8ZYddB2kzAIXrMb6 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-8ZYddB2kzAIXrMb6 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-8ZYddB2kzAIXrMb6 .error-icon{fill:#552222;}#mermaid-svg-8ZYddB2kzAIXrMb6 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-8ZYddB2kzAIXrMb6 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-8ZYddB2kzAIXrMb6 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-8ZYddB2kzAIXrMb6 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-8ZYddB2kzAIXrMb6 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-8ZYddB2kzAIXrMb6 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-8ZYddB2kzAIXrMb6 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-8ZYddB2kzAIXrMb6 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-8ZYddB2kzAIXrMb6 .marker.cross{stroke:#333333;}#mermaid-svg-8ZYddB2kzAIXrMb6 svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-8ZYddB2kzAIXrMb6 p{margin:0;}#mermaid-svg-8ZYddB2kzAIXrMb6 .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-8ZYddB2kzAIXrMb6 .cluster-label text{fill:#333;}#mermaid-svg-8ZYddB2kzAIXrMb6 .cluster-label span{color:#333;}#mermaid-svg-8ZYddB2kzAIXrMb6 .cluster-label span p{background-color:transparent;}#mermaid-svg-8ZYddB2kzAIXrMb6 .label text,#mermaid-svg-8ZYddB2kzAIXrMb6 span{fill:#333;color:#333;}#mermaid-svg-8ZYddB2kzAIXrMb6 .node rect,#mermaid-svg-8ZYddB2kzAIXrMb6 .node circle,#mermaid-svg-8ZYddB2kzAIXrMb6 .node ellipse,#mermaid-svg-8ZYddB2kzAIXrMb6 .node polygon,#mermaid-svg-8ZYddB2kzAIXrMb6 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-8ZYddB2kzAIXrMb6 .rough-node .label text,#mermaid-svg-8ZYddB2kzAIXrMb6 .node .label text,#mermaid-svg-8ZYddB2kzAIXrMb6 .image-shape .label,#mermaid-svg-8ZYddB2kzAIXrMb6 .icon-shape .label{text-anchor:middle;}#mermaid-svg-8ZYddB2kzAIXrMb6 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-8ZYddB2kzAIXrMb6 .rough-node .label,#mermaid-svg-8ZYddB2kzAIXrMb6 .node .label,#mermaid-svg-8ZYddB2kzAIXrMb6 .image-shape .label,#mermaid-svg-8ZYddB2kzAIXrMb6 .icon-shape .label{text-align:center;}#mermaid-svg-8ZYddB2kzAIXrMb6 .node.clickable{cursor:pointer;}#mermaid-svg-8ZYddB2kzAIXrMb6 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-8ZYddB2kzAIXrMb6 .arrowheadPath{fill:#333333;}#mermaid-svg-8ZYddB2kzAIXrMb6 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-8ZYddB2kzAIXrMb6 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-8ZYddB2kzAIXrMb6 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-8ZYddB2kzAIXrMb6 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-8ZYddB2kzAIXrMb6 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-8ZYddB2kzAIXrMb6 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-8ZYddB2kzAIXrMb6 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-8ZYddB2kzAIXrMb6 .cluster text{fill:#333;}#mermaid-svg-8ZYddB2kzAIXrMb6 .cluster span{color:#333;}#mermaid-svg-8ZYddB2kzAIXrMb6 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-8ZYddB2kzAIXrMb6 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-8ZYddB2kzAIXrMb6 rect.text{fill:none;stroke-width:0;}#mermaid-svg-8ZYddB2kzAIXrMb6 .icon-shape,#mermaid-svg-8ZYddB2kzAIXrMb6 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-8ZYddB2kzAIXrMb6 .icon-shape p,#mermaid-svg-8ZYddB2kzAIXrMb6 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-8ZYddB2kzAIXrMb6 .icon-shape .label rect,#mermaid-svg-8ZYddB2kzAIXrMb6 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-8ZYddB2kzAIXrMb6 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-8ZYddB2kzAIXrMb6 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-8ZYddB2kzAIXrMb6 :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
GstAudioConverter*
检查convert
写入in_rate/out_rate
读取convert->config
返回借用指针
第一步,函数检查convert是否为空。
如果传入NULL,函数返回NULL,不会继续读取内部字段。
第二步,根据输出参数是否为空,分别写入:
convert->in.rate
convert->out.rate
这两个采样率不通过返回的GstStructure传递,而是通过调用者提供的指针返回。
第三步,直接返回:
convert->config
这里没有调用gst_structure_copy(),也没有重新创建配置对象。
因此它属于本地同步读取:
没有协议消息
没有异步请求
没有回调
没有音频Sample处理
没有Converter状态迁移
返回值是const GstStructure*,调用者只能读取其中的字段,不能通过这个指针修改Converter内部配置。
🌻3.2 配置对象的创建和失效边界
GstAudioConverter创建时,内部会先建立一个名为GstAudioConverter的空配置结构:
convert->config =
gst_structure_new_empty("GstAudioConverter");
如果gst_audio_converter_new()收到调用者提供的配置,内部会通过gst_audio_converter_update_config()把配置字段复制到convert->config中。
关系可以表示为:
#mermaid-svg-vszLwsn0G42Z8yDe{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-vszLwsn0G42Z8yDe .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-vszLwsn0G42Z8yDe .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-vszLwsn0G42Z8yDe .error-icon{fill:#552222;}#mermaid-svg-vszLwsn0G42Z8yDe .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-vszLwsn0G42Z8yDe .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-vszLwsn0G42Z8yDe .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-vszLwsn0G42Z8yDe .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-vszLwsn0G42Z8yDe .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-vszLwsn0G42Z8yDe .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-vszLwsn0G42Z8yDe .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-vszLwsn0G42Z8yDe .marker{fill:#333333;stroke:#333333;}#mermaid-svg-vszLwsn0G42Z8yDe .marker.cross{stroke:#333333;}#mermaid-svg-vszLwsn0G42Z8yDe svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-vszLwsn0G42Z8yDe p{margin:0;}#mermaid-svg-vszLwsn0G42Z8yDe .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-vszLwsn0G42Z8yDe .cluster-label text{fill:#333;}#mermaid-svg-vszLwsn0G42Z8yDe .cluster-label span{color:#333;}#mermaid-svg-vszLwsn0G42Z8yDe .cluster-label span p{background-color:transparent;}#mermaid-svg-vszLwsn0G42Z8yDe .label text,#mermaid-svg-vszLwsn0G42Z8yDe span{fill:#333;color:#333;}#mermaid-svg-vszLwsn0G42Z8yDe .node rect,#mermaid-svg-vszLwsn0G42Z8yDe .node circle,#mermaid-svg-vszLwsn0G42Z8yDe .node ellipse,#mermaid-svg-vszLwsn0G42Z8yDe .node polygon,#mermaid-svg-vszLwsn0G42Z8yDe .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-vszLwsn0G42Z8yDe .rough-node .label text,#mermaid-svg-vszLwsn0G42Z8yDe .node .label text,#mermaid-svg-vszLwsn0G42Z8yDe .image-shape .label,#mermaid-svg-vszLwsn0G42Z8yDe .icon-shape .label{text-anchor:middle;}#mermaid-svg-vszLwsn0G42Z8yDe .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-vszLwsn0G42Z8yDe .rough-node .label,#mermaid-svg-vszLwsn0G42Z8yDe .node .label,#mermaid-svg-vszLwsn0G42Z8yDe .image-shape .label,#mermaid-svg-vszLwsn0G42Z8yDe .icon-shape .label{text-align:center;}#mermaid-svg-vszLwsn0G42Z8yDe .node.clickable{cursor:pointer;}#mermaid-svg-vszLwsn0G42Z8yDe .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-vszLwsn0G42Z8yDe .arrowheadPath{fill:#333333;}#mermaid-svg-vszLwsn0G42Z8yDe .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-vszLwsn0G42Z8yDe .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-vszLwsn0G42Z8yDe .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-vszLwsn0G42Z8yDe .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-vszLwsn0G42Z8yDe .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-vszLwsn0G42Z8yDe .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-vszLwsn0G42Z8yDe .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-vszLwsn0G42Z8yDe .cluster text{fill:#333;}#mermaid-svg-vszLwsn0G42Z8yDe .cluster span{color:#333;}#mermaid-svg-vszLwsn0G42Z8yDe div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-vszLwsn0G42Z8yDe .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-vszLwsn0G42Z8yDe rect.text{fill:none;stroke-width:0;}#mermaid-svg-vszLwsn0G42Z8yDe .icon-shape,#mermaid-svg-vszLwsn0G42Z8yDe .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-vszLwsn0G42Z8yDe .icon-shape p,#mermaid-svg-vszLwsn0G42Z8yDe .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-vszLwsn0G42Z8yDe .icon-shape .label rect,#mermaid-svg-vszLwsn0G42Z8yDe .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-vszLwsn0G42Z8yDe .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-vszLwsn0G42Z8yDe .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-vszLwsn0G42Z8yDe :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
gst_audio_converter_new
创建内部GstStructure
update_config复制选项
get_config返回内部配置
free释放配置
gst_audio_converter_get_config()返回的是内部结构的借用指针。
因此下面两种操作都会结束该指针的可用生命周期:
gst_audio_converter_update_config(...);
gst_audio_converter_free(converter);
更新配置后,应当重新调用:
config = gst_audio_converter_get_config(
converter,
&in_rate,
&out_rate);
如果需要跨越更新操作保存旧配置,应当在更新前复制:
GstStructure *old_config =
gst_structure_copy(config);
复制后的old_config由调用者负责释放。
还需要区分两个方向相反的接口:
gst_audio_converter_update_config()
↓
写入采样率和额外配置
gst_audio_converter_get_config()
↓
读取采样率和额外配置
get_config()不会触发gst_audio_converter_samples()或gst_audio_converter_convert(),也不会启动重采样、格式转换、声道混音和量化处理。
🌻4.实战案例
🌻4.1 创建带有重采样选项的Converter
准备输入和输出音频信息:
gst_audio_info_set_format(
&in_info,
GST_AUDIO_FORMAT_S16,
48000,
2,
NULL);
gst_audio_info_set_format(
&out_info,
GST_AUDIO_FORMAT_F32,
44100,
2,
NULL);
再创建一个配置结构,显式指定线性重采样:
config = gst_structure_new_empty(
"GstAudioConverter");
gst_structure_set(
config,
GST_AUDIO_CONVERTER_OPT_RESAMPLER_METHOD,
GST_TYPE_AUDIO_RESAMPLER_METHOD,
GST_AUDIO_RESAMPLER_METHOD_LINEAR,
NULL);
将config传给gst_audio_converter_new()后,配置对象的所有权转移给Converter创建流程,调用者不能再次释放原始config。
🌻4.2 读取当前采样率和配置字段
Converter创建成功后调用:
current = gst_audio_converter_get_config(
converter,
&in_rate,
&out_rate);
随后读取重采样算法:
gst_structure_get_enum(
current,
GST_AUDIO_CONVERTER_OPT_RESAMPLER_METHOD,
GST_TYPE_AUDIO_RESAMPLER_METHOD,
&method);
如果需要长期保存当前配置:
snapshot = gst_structure_copy(current);
这里的current是Converter内部对象,snapshot才是由应用独立管理的配置副本。
🌻4.3 验证读取结果
完整测试代码:
#include <gst/gst.h>
#include <gst/audio/audio.h>
int
main(int argc, char *argv[])
{
GstAudioInfo in_info;
GstAudioInfo out_info;
GstStructure *config = NULL;
GstStructure *snapshot = NULL;
GstAudioConverter *converter = NULL;
const GstStructure *current = NULL;
gint in_rate = 0;
gint out_rate = 0;
gint method = –1;
gint status = 1;
gst_init(&argc, &argv);
gst_audio_info_init(&in_info);
gst_audio_info_init(&out_info);
gst_audio_info_set_format(
&in_info,
GST_AUDIO_FORMAT_S16,
48000,
2,
NULL);
gst_audio_info_set_format(
&out_info,
GST_AUDIO_FORMAT_F32,
44100,
2,
NULL);
config = gst_structure_new_empty(
"GstAudioConverter");
if (config == NULL)
goto cleanup;
gst_structure_set(
config,
GST_AUDIO_CONVERTER_OPT_RESAMPLER_METHOD,
GST_TYPE_AUDIO_RESAMPLER_METHOD,
GST_AUDIO_RESAMPLER_METHOD_LINEAR,
NULL);
converter = gst_audio_converter_new(
GST_AUDIO_CONVERTER_FLAG_NONE,
&in_info,
&out_info,
config);
/*
* config的所有权已经交给gst_audio_converter_new()
*/
config = NULL;
if (converter == NULL)
goto cleanup;
current = gst_audio_converter_get_config(
converter,
&in_rate,
&out_rate);
if (current == NULL)
goto cleanup;
if (!gst_structure_get_enum(
current,
GST_AUDIO_CONVERTER_OPT_RESAMPLER_METHOD,
GST_TYPE_AUDIO_RESAMPLER_METHOD,
&method))
goto cleanup;
snapshot = gst_structure_copy(current);
if (snapshot == NULL)
goto cleanup;
g_print(
"input rate : %d\\n",
in_rate);
g_print(
"output rate: %d\\n",
out_rate);
g_print(
"resampler method: %s\\n",
method == GST_AUDIO_RESAMPLER_METHOD_LINEAR
? "linear"
: "other");
g_print(
"snapshot has explicit option: %s\\n",
gst_structure_has_field(
snapshot,
GST_AUDIO_CONVERTER_OPT_RESAMPLER_METHOD)
? "yes"
: "no");
status = 0;
cleanup:
if (snapshot)
gst_structure_free(snapshot);
if (converter)
gst_audio_converter_free(converter);
if (config)
gst_structure_free(config);
return status;
}
编译:
gcc test_audio_converter_get_config.c \\
-o test_audio_converter_get_config \\
$(pkg-config –cflags –libs \\
gstreamer-audio-1.0)
运行:
./test_audio_converter_get_config
重点观察:
input rate : 48000
output rate: 44100
resampler method: linear
snapshot has explicit option: yes
这组结果说明:
in_rate ← Converter当前输入采样率
out_rate ← Converter当前输出采样率
method ← 内部配置结构中的重采样选项
snapshot ← 应用自己拥有的配置副本
测试程序没有调用音频Sample转换接口,但已经验证了gst_audio_converter_get_config()的三个核心行为:
读取当前采样率
返回当前配置结构
不转移内部配置对象的所有权
🌻5.总结
gst_audio_converter_get_config()就是从GstAudioConverter中同步读取当前输入、输出采样率和借用的额外配置结构,供应用检查状态或复制配置快照。






