欢迎光临
我们一直在努力

Linux Gstreamer深度解析之gst_audio_converter_get_config调用流程与实战(二十三)

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

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

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

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

欢迎关注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中同步读取当前输入、输出采样率和借用的额外配置结构,供应用检查状态或复制配置快照。

赞(0)
未经允许不得转载:171主机测评 » Linux Gstreamer深度解析之gst_audio_converter_get_config调用流程与实战(二十三)
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址