Linux Gstreamer深度解析之gst_audio_ring_buffer_parse_caps调用流程与实战(八十)

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

博主新书推荐:《Android系统多媒体进阶实战》🚀

Android Audio工程师专栏地址:Audio工程师进阶系列【原创干货持续更新中...... 】🚀

Android多媒体专栏地址:多媒体系统工程师系列【原创干货持续更新中...... 】🚀

专题一 二:AAOS车载系统+AOSP14系统攻城狮入门视频实战课 🚀

专题三:Android14 Binder之HIDL与AIDL通信实战课 🚀

专题四:Android15快速自定义与集成音效实战课 🚀

专题五:Android15音频策略实战课 🚀

专题六:Android15音频性能实战课(无声/杂音/断音/爆音实战案例) 🚀

人生格言: 人生从来没有捷径,只有行动才是治疗恐惧和懒惰的唯一良药.
更多原创,欢迎关注:Android系统攻城狮

🍉🍉🍉文章目录🍉🍉🍉

🌻1.前言

本篇目的:理解gst_audio_ring_buffer_parse_caps()如何把协商后的音频Caps转换为GstAudioRingBufferSpec,分析格式识别和分段参数计算,并通过C程序检查解析结果。

音频设备需要的不只是audio/x-raw格式。RingBuffer还要知道音频类型、采样率、每帧字节数、缓冲区时长和单段大小。gst_audio_ring_buffer_parse_caps()负责把Caps中的格式信息写入规格对象,并根据预设的缓冲时长计算分段参数。

它只解析Caps并更新GstAudioRingBufferSpec,不申请设备资源、不分配音频缓冲区,也不启动读写。
#mermaid-svg-vPVC3F6W4tLA3s2P{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-vPVC3F6W4tLA3s2P .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-vPVC3F6W4tLA3s2P .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-vPVC3F6W4tLA3s2P .error-icon{fill:#552222;}#mermaid-svg-vPVC3F6W4tLA3s2P .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-vPVC3F6W4tLA3s2P .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-vPVC3F6W4tLA3s2P .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-vPVC3F6W4tLA3s2P .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-vPVC3F6W4tLA3s2P .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-vPVC3F6W4tLA3s2P .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-vPVC3F6W4tLA3s2P .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-vPVC3F6W4tLA3s2P .marker{fill:#333333;stroke:#333333;}#mermaid-svg-vPVC3F6W4tLA3s2P .marker.cross{stroke:#333333;}#mermaid-svg-vPVC3F6W4tLA3s2P svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-vPVC3F6W4tLA3s2P p{margin:0;}#mermaid-svg-vPVC3F6W4tLA3s2P .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-vPVC3F6W4tLA3s2P .cluster-label text{fill:#333;}#mermaid-svg-vPVC3F6W4tLA3s2P .cluster-label span{color:#333;}#mermaid-svg-vPVC3F6W4tLA3s2P .cluster-label span p{background-color:transparent;}#mermaid-svg-vPVC3F6W4tLA3s2P .label text,#mermaid-svg-vPVC3F6W4tLA3s2P span{fill:#333;color:#333;}#mermaid-svg-vPVC3F6W4tLA3s2P .node rect,#mermaid-svg-vPVC3F6W4tLA3s2P .node circle,#mermaid-svg-vPVC3F6W4tLA3s2P .node ellipse,#mermaid-svg-vPVC3F6W4tLA3s2P .node polygon,#mermaid-svg-vPVC3F6W4tLA3s2P .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-vPVC3F6W4tLA3s2P .rough-node .label text,#mermaid-svg-vPVC3F6W4tLA3s2P .node .label text,#mermaid-svg-vPVC3F6W4tLA3s2P .image-shape .label,#mermaid-svg-vPVC3F6W4tLA3s2P .icon-shape .label{text-anchor:middle;}#mermaid-svg-vPVC3F6W4tLA3s2P .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-vPVC3F6W4tLA3s2P .rough-node .label,#mermaid-svg-vPVC3F6W4tLA3s2P .node .label,#mermaid-svg-vPVC3F6W4tLA3s2P .image-shape .label,#mermaid-svg-vPVC3F6W4tLA3s2P .icon-shape .label{text-align:center;}#mermaid-svg-vPVC3F6W4tLA3s2P .node.clickable{cursor:pointer;}#mermaid-svg-vPVC3F6W4tLA3s2P .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-vPVC3F6W4tLA3s2P .arrowheadPath{fill:#333333;}#mermaid-svg-vPVC3F6W4tLA3s2P .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-vPVC3F6W4tLA3s2P .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-vPVC3F6W4tLA3s2P .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-vPVC3F6W4tLA3s2P .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-vPVC3F6W4tLA3s2P .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-vPVC3F6W4tLA3s2P .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-vPVC3F6W4tLA3s2P .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-vPVC3F6W4tLA3s2P .cluster text{fill:#333;}#mermaid-svg-vPVC3F6W4tLA3s2P .cluster span{color:#333;}#mermaid-svg-vPVC3F6W4tLA3s2P 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-vPVC3F6W4tLA3s2P .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-vPVC3F6W4tLA3s2P rect.text{fill:none;stroke-width:0;}#mermaid-svg-vPVC3F6W4tLA3s2P .icon-shape,#mermaid-svg-vPVC3F6W4tLA3s2P .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-vPVC3F6W4tLA3s2P .icon-shape p,#mermaid-svg-vPVC3F6W4tLA3s2P .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-vPVC3F6W4tLA3s2P .icon-shape .label rect,#mermaid-svg-vPVC3F6W4tLA3s2P .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-vPVC3F6W4tLA3s2P .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-vPVC3F6W4tLA3s2P .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-vPVC3F6W4tLA3s2P :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 协商后的音频Caps
gst_audio_ring_buffer_parse_caps
已设置的缓冲时长
识别音频类型并填写音频信息
计算分段大小和分段数量
更新GstAudioRingBufferSpec

🌻2.应用场景和用法

2.1从Caps准备RingBuffer规格

GstAudioBaseSink和GstAudioBaseSrc都需要在设置Caps时准备RingBuffer规格。Sink解析新Caps后调用该函数,再申请缓冲资源;Source解析Caps后还会根据采样率、BPF和延迟参数重新计算分段大小。

该函数支持多种音频媒体类型。audio/x-raw分支调用gst_audio_info_from_caps()解析原始音频信息;其他分支根据媒体类型提取所需字段,并设置对应的RingBuffer格式类型和BPF。源码包含A-Law、μ-Law、IEC 958、AC-3、E-AC-3、DTS、MPEG音频、AAC、FLAC和DSD等处理分支。

2.2函数原型与返回语义

函数原型如下:

c 复制代码
gboolean
gst_audio_ring_buffer_parse_caps (GstAudioRingBufferSpec *spec,
                                 GstCaps *caps);
参数或返回值 含义
spec 接收解析结果的RingBuffer规格对象
caps 描述已协商音频格式的Caps
TRUE 媒体类型及必需字段解析成功,分段参数已写入spec
FALSE Caps类型不支持、必需字段缺失或格式解析失败

调用前,spec->buffer_time和spec->latency_time应已设置,其中latency_time不能为0。调用方还应传入有效且已协商为具体格式的Caps。原始音频分支要求Caps符合gst_audio_info_from_caps()的固定Caps条件。

最小调用方式如下:

c 复制代码
GstAudioRingBufferSpec spec = { 0 };

spec.buffer_time = 200000;
spec.latency_time = 10000;

if (!gst_audio_ring_buffer_parse_caps (&spec, caps)) {
  /* 按格式协商失败处理 */
}

成功后,spec中包含音频类型、GstAudioInfo、持有引用的Caps、分段大小、分段总数和待确定的分段延迟。调用者仍需检查返回值;函数没有分配RingBuffer内存,也没有调用设备驱动。

🌻3.调用流程剖析

3.1识别媒体类型并提取音频信息

函数首先读取Caps中的第一个GstStructure,获取媒体类型,并初始化临时GstAudioInfo。

遇到audio/x-raw时,函数把Caps交给gst_audio_info_from_caps()。解析成功后将spec->type设为GST_AUDIO_RING_BUFFER_FORMAT_TYPE_RAW。

编码格式按对应媒体类型处理。例如,A-Law和μ-Law需要采样率与声道数,并将BPF设为声道数;IEC 958设置固定BPF;MPEG音频和AAC根据版本及stream-format设置对应类型;DSD则根据字格式宽度换算RingBuffer使用的字率和BPF。

不支持的媒体类型、缺失必需字段或底层音频信息解析失败都会进入错误分支并返回FALSE。
#mermaid-svg-ApsRfqdV0yNuh8Us{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-ApsRfqdV0yNuh8Us .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-ApsRfqdV0yNuh8Us .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-ApsRfqdV0yNuh8Us .error-icon{fill:#552222;}#mermaid-svg-ApsRfqdV0yNuh8Us .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-ApsRfqdV0yNuh8Us .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-ApsRfqdV0yNuh8Us .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-ApsRfqdV0yNuh8Us .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-ApsRfqdV0yNuh8Us .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-ApsRfqdV0yNuh8Us .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-ApsRfqdV0yNuh8Us .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-ApsRfqdV0yNuh8Us .marker{fill:#333333;stroke:#333333;}#mermaid-svg-ApsRfqdV0yNuh8Us .marker.cross{stroke:#333333;}#mermaid-svg-ApsRfqdV0yNuh8Us svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-ApsRfqdV0yNuh8Us p{margin:0;}#mermaid-svg-ApsRfqdV0yNuh8Us .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-ApsRfqdV0yNuh8Us .cluster-label text{fill:#333;}#mermaid-svg-ApsRfqdV0yNuh8Us .cluster-label span{color:#333;}#mermaid-svg-ApsRfqdV0yNuh8Us .cluster-label span p{background-color:transparent;}#mermaid-svg-ApsRfqdV0yNuh8Us .label text,#mermaid-svg-ApsRfqdV0yNuh8Us span{fill:#333;color:#333;}#mermaid-svg-ApsRfqdV0yNuh8Us .node rect,#mermaid-svg-ApsRfqdV0yNuh8Us .node circle,#mermaid-svg-ApsRfqdV0yNuh8Us .node ellipse,#mermaid-svg-ApsRfqdV0yNuh8Us .node polygon,#mermaid-svg-ApsRfqdV0yNuh8Us .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-ApsRfqdV0yNuh8Us .rough-node .label text,#mermaid-svg-ApsRfqdV0yNuh8Us .node .label text,#mermaid-svg-ApsRfqdV0yNuh8Us .image-shape .label,#mermaid-svg-ApsRfqdV0yNuh8Us .icon-shape .label{text-anchor:middle;}#mermaid-svg-ApsRfqdV0yNuh8Us .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-ApsRfqdV0yNuh8Us .rough-node .label,#mermaid-svg-ApsRfqdV0yNuh8Us .node .label,#mermaid-svg-ApsRfqdV0yNuh8Us .image-shape .label,#mermaid-svg-ApsRfqdV0yNuh8Us .icon-shape .label{text-align:center;}#mermaid-svg-ApsRfqdV0yNuh8Us .node.clickable{cursor:pointer;}#mermaid-svg-ApsRfqdV0yNuh8Us .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-ApsRfqdV0yNuh8Us .arrowheadPath{fill:#333333;}#mermaid-svg-ApsRfqdV0yNuh8Us .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-ApsRfqdV0yNuh8Us .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-ApsRfqdV0yNuh8Us .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-ApsRfqdV0yNuh8Us .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-ApsRfqdV0yNuh8Us .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-ApsRfqdV0yNuh8Us .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-ApsRfqdV0yNuh8Us .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-ApsRfqdV0yNuh8Us .cluster text{fill:#333;}#mermaid-svg-ApsRfqdV0yNuh8Us .cluster span{color:#333;}#mermaid-svg-ApsRfqdV0yNuh8Us 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-ApsRfqdV0yNuh8Us .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-ApsRfqdV0yNuh8Us rect.text{fill:none;stroke-width:0;}#mermaid-svg-ApsRfqdV0yNuh8Us .icon-shape,#mermaid-svg-ApsRfqdV0yNuh8Us .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-ApsRfqdV0yNuh8Us .icon-shape p,#mermaid-svg-ApsRfqdV0yNuh8Us .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-ApsRfqdV0yNuh8Us .icon-shape .label rect,#mermaid-svg-ApsRfqdV0yNuh8Us .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-ApsRfqdV0yNuh8Us .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-ApsRfqdV0yNuh8Us .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-ApsRfqdV0yNuh8Us :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} audio x raw
编码音频
其他类型
读取Caps首个Structure
媒体类型
调用AudioInfo解析
提取类型字段并设置BPF
返回解析失败
写入RingBuffer格式类型
进入分段参数计算

3.2计算分段参数并更新Spec

格式解析完成后,函数用gst_caps_replace()让spec->caps持有当前Caps,再检查latency_time是否为0。随后使用采样率、BPF和延迟时间计算单段字节数:

c 复制代码
spec->segsize = gst_util_uint64_scale (
    info.rate * info.bpf,
    spec->latency_time,
    GST_SECOND / GST_USECOND);

/* 将单段大小向下调整到完整Frame边界 */
spec->segsize -= spec->segsize % info.bpf;

spec->segtotal = spec->buffer_time / spec->latency_time;
spec->seglatency = -1;
spec->info = info;

latency_time和buffer_time以微秒计。segsize先按每秒字节率乘单段时长计算,再向下对齐到BPF的整数倍,避免一个音频Frame被切到两个分段中。segtotal是总缓冲时长除以单段时长得到的分段数量。seglatency设为-1表示暂未指定,后续采集资源时可采用默认值。

例如,48kHz、S16LE、双声道音频的BPF为4字节。若latency_time为10000微秒,则单段大小为1920字节。
#mermaid-svg-DmG3bKmnHvM7UFdV{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-DmG3bKmnHvM7UFdV .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-DmG3bKmnHvM7UFdV .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-DmG3bKmnHvM7UFdV .error-icon{fill:#552222;}#mermaid-svg-DmG3bKmnHvM7UFdV .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-DmG3bKmnHvM7UFdV .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-DmG3bKmnHvM7UFdV .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-DmG3bKmnHvM7UFdV .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-DmG3bKmnHvM7UFdV .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-DmG3bKmnHvM7UFdV .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-DmG3bKmnHvM7UFdV .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-DmG3bKmnHvM7UFdV .marker{fill:#333333;stroke:#333333;}#mermaid-svg-DmG3bKmnHvM7UFdV .marker.cross{stroke:#333333;}#mermaid-svg-DmG3bKmnHvM7UFdV svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-DmG3bKmnHvM7UFdV p{margin:0;}#mermaid-svg-DmG3bKmnHvM7UFdV .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-DmG3bKmnHvM7UFdV .cluster-label text{fill:#333;}#mermaid-svg-DmG3bKmnHvM7UFdV .cluster-label span{color:#333;}#mermaid-svg-DmG3bKmnHvM7UFdV .cluster-label span p{background-color:transparent;}#mermaid-svg-DmG3bKmnHvM7UFdV .label text,#mermaid-svg-DmG3bKmnHvM7UFdV span{fill:#333;color:#333;}#mermaid-svg-DmG3bKmnHvM7UFdV .node rect,#mermaid-svg-DmG3bKmnHvM7UFdV .node circle,#mermaid-svg-DmG3bKmnHvM7UFdV .node ellipse,#mermaid-svg-DmG3bKmnHvM7UFdV .node polygon,#mermaid-svg-DmG3bKmnHvM7UFdV .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-DmG3bKmnHvM7UFdV .rough-node .label text,#mermaid-svg-DmG3bKmnHvM7UFdV .node .label text,#mermaid-svg-DmG3bKmnHvM7UFdV .image-shape .label,#mermaid-svg-DmG3bKmnHvM7UFdV .icon-shape .label{text-anchor:middle;}#mermaid-svg-DmG3bKmnHvM7UFdV .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-DmG3bKmnHvM7UFdV .rough-node .label,#mermaid-svg-DmG3bKmnHvM7UFdV .node .label,#mermaid-svg-DmG3bKmnHvM7UFdV .image-shape .label,#mermaid-svg-DmG3bKmnHvM7UFdV .icon-shape .label{text-align:center;}#mermaid-svg-DmG3bKmnHvM7UFdV .node.clickable{cursor:pointer;}#mermaid-svg-DmG3bKmnHvM7UFdV .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-DmG3bKmnHvM7UFdV .arrowheadPath{fill:#333333;}#mermaid-svg-DmG3bKmnHvM7UFdV .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-DmG3bKmnHvM7UFdV .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-DmG3bKmnHvM7UFdV .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-DmG3bKmnHvM7UFdV .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-DmG3bKmnHvM7UFdV .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-DmG3bKmnHvM7UFdV .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-DmG3bKmnHvM7UFdV .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-DmG3bKmnHvM7UFdV .cluster text{fill:#333;}#mermaid-svg-DmG3bKmnHvM7UFdV .cluster span{color:#333;}#mermaid-svg-DmG3bKmnHvM7UFdV 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-DmG3bKmnHvM7UFdV .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-DmG3bKmnHvM7UFdV rect.text{fill:none;stroke-width:0;}#mermaid-svg-DmG3bKmnHvM7UFdV .icon-shape,#mermaid-svg-DmG3bKmnHvM7UFdV .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-DmG3bKmnHvM7UFdV .icon-shape p,#mermaid-svg-DmG3bKmnHvM7UFdV .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-DmG3bKmnHvM7UFdV .icon-shape .label rect,#mermaid-svg-DmG3bKmnHvM7UFdV .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-DmG3bKmnHvM7UFdV .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-DmG3bKmnHvM7UFdV .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-DmG3bKmnHvM7UFdV :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 解析得到rate和BPF
读取buffer_time和latency_time
计算segsize并按BPF对齐
计算segtotal
设置seglatency为待确定
写回Caps和GstAudioInfo

在Sink调用路径中,GstAudioBaseSink先释放旧RingBuffer资源,再解析新Caps,随后调用gst_audio_ring_buffer_acquire()申请资源。Source调用路径也会先解析Caps,但它还会根据rate、BPF和延迟参数计算分段规格,并在采集成功后更新实际缓冲时长。

🌻4.实战案例

4.1准备48kHz双声道Caps和缓冲时长

案例直接调用gst_audio_ring_buffer_parse_caps(),不打开声卡。Caps描述S16LE、交错布局、48kHz、双声道原始音频;规格设置总缓冲时长200000微秒、单段延迟10000微秒。

按这些输入,预期BPF为4字节,单段大小为1920字节,分段总数为20。这个例子用来检查格式解析和规格计算,不代表任何物理设备的能力。

4.2解析Caps并检查计算结果

程序执行以下步骤:

  1. 创建固定的audio/x-rawCaps。
  2. 初始化GstAudioRingBufferSpec的缓冲时长参数。
  3. 调用解析函数。
  4. 检查音频类型、采样率、声道数、BPF、分段大小和分段数量。
  5. 释放解析函数为spec.caps持有的Caps引用。

这里不调用gst_audio_ring_buffer_acquire()。解析完成只表示规格准备好,设备资源申请仍由后续调用者负责。

4.3完整代码
c 复制代码
#include <gst/gst.h>
#include <gst/audio/audio.h>
#include <string.h>

int
main (int argc, char *argv[])
{
  GstAudioRingBufferSpec spec;
  GstCaps *caps;
  gboolean parsed;
  gboolean ok = FALSE;

  gst_init (&argc, &argv);

  /* 准备48kHz、S16LE、双声道交错音频Caps */
  caps = gst_caps_new_simple (
      "audio/x-raw",
      "format", G_TYPE_STRING, "S16LE",
      "layout", G_TYPE_STRING, "interleaved",
      "rate", G_TYPE_INT, 48000,
      "channels", G_TYPE_INT, 2,
      NULL);

  /* 清零规格,并设置解析前必须提供的缓冲时长 */
  memset (&spec, 0, sizeof (spec));
  spec.buffer_time = 200000;
  spec.latency_time = 10000;

  /* 解析Caps并生成RingBuffer音频与分段规格 */
  parsed = gst_audio_ring_buffer_parse_caps (&spec, caps);

  if (parsed) {
    /* 检查格式识别和分段参数计算结果 */
    ok = spec.type == GST_AUDIO_RING_BUFFER_FORMAT_TYPE_RAW
        && GST_AUDIO_INFO_RATE (&spec.info) == 48000
        && GST_AUDIO_INFO_CHANNELS (&spec.info) == 2
        && GST_AUDIO_INFO_BPF (&spec.info) == 4
        && spec.segsize == 1920
        && spec.segtotal == 20
        && spec.seglatency == -1;
  }

  /* parse_caps通过spec.caps持有Caps引用,需要分别释放 */
  if (spec.caps != NULL)
    gst_caps_unref (spec.caps);
  gst_caps_unref (caps);

  return ok ? 0 : 1;
}

🌻5.总结

gst_audio_ring_buffer_parse_caps()就是把协商后的音频Caps转换为RingBuffer格式和分段规格,供后续资源采集流程使用。

相关推荐
l1t1 小时前
DeepSeek总结的 DuckDB 2.0 文档新内容
服务器·网络·数据库
erzong2311 小时前
Linux网络:UDP编程踩坑日记
linux·网络·udp
盐焗鹌鹑蛋1 小时前
【Linux】线程库与封装
linux
lwx9148522 小时前
Deepin操作系统
linux·服务器·网络
Lsetea2 小时前
OpenSSL指定-cipher仍协商TLS1.3:证书排查中的套件与协议边界
运维·https·ssl证书·openssl·tls
先知后行。2 小时前
进程间通信(IPC)
linux·运维·服务器
weixin_571667412 小时前
Windows 通过 SSH 反向隧道向 Ubuntu 转发代理
linux·运维·windows·代理
乔旭伟3 小时前
CentOS 停更迁移实战:vault 源配置、目标选型与迁移工程清单
linux·运维·centos
遇印记3 小时前
应用层,网络管理
运维·网络·windows·学习·安全