尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
Linux Gstreamer深度解析之gst_audio_ring_buffer_commit调用流程与实战(七十三)
简介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从公开接口分派到默认实现3.2按分段位置写入并更新进度4.实战案例4.1准备一个内存RingBuffer4.2提交4个Frame并检查写入位置4.3完整代码5.总结1.前言本篇目的理解gst_audio_ring_buffer_commit()如何把输入样本写入GstAudioRingBuffer分析它如何处理环形分段、采样位置和速率换算并通过内存后端观察提交结果。GstAudioRingBuffer保存供音频设备读取或写入的分段缓冲区。gst_audio_ring_buffer_commit()把调用者提供的样本写入指定位置并更新样本位置和换算累加器。它不会打开设备也不会直接把数据写入声卡。输入样本和目标位置gst_audio_ring_buffer_commit按分段位置写入RingBuffer更新样本位置和累加器返回已处理的输入样本数2.应用场景和用法2.1向环形缓冲区提交样本gst_audio_ring_buffer_commit()主要用于把上游已经准备好的音频样本提交到环形缓冲区。场景调用时提供的数据作用常规播放输入样本数与相同数量的输出样本数按样本位置复制到RingBuffer速率换算输入样本数与不同的输出样本数在RingBuffer写入过程中完成样本增减反向播放正数输入样本数与负数输出样本数按反向顺序写入目标位置分段写入跨越一个或多个缓冲段的样本自动处理段边界必要时等待可写段中断后续写上次返回的样本位置和accum从尚未处理的数据继续提交这里的“样本数”指音频Frame数量不是字节数。对于立体声PCM一个样本Frame包含左右声道在同一时刻的值。输入数据的内存布局必须与RingBuffer音频格式一致。2.2函数原型与返回语义函数原型如下guintgst_audio_ring_buffer_commit(GstAudioRingBuffer*buf,guint64*sample,guint8*data,gint in_samples,gint out_samples,gint*accum);参数含义buf已采集并包含可写内存的GstAudioRingBuffersample输入输出参数表示写入位置提交后更新为新的样本位置data待提交的输入样本数据in_samples输入数据中的样本数out_samples目标写入样本数负数表示反向提交accum速率换算的累加状态首次调用前应设为0返回值为已处理的输入样本数。返回值可能小于本次输入样本数例如提交期间RingBuffer被停止或刷新。guint接口用(guint)-1表示错误。当in_samples或out_samples为0时函数直接返回in_samples不会调用类的commit虚函数。正常提交时基类会分派到GstAudioRingBufferClass.commit默认实现负责分段写入、通道重排和按输入输出样本数进行速率换算。子类也可以提供自己的实现。相邻接口的职责不同接口职责gst_audio_ring_buffer_acquire()申请并初始化RingBuffer资源gst_audio_ring_buffer_commit()把样本写入RingBuffer内存gst_audio_ring_buffer_read()从RingBuffer读取样本gst_audio_ring_buffer_advance()通知RingBuffer设备侧已处理的分段gst_audio_ring_buffer_release()停止并释放RingBuffer资源3.调用流程剖析3.1从公开接口分派到默认实现公开接口先检查buf是否为有效的GstAudioRingBuffer。当输入样本数或输出样本数为0时它直接返回输入样本数。其余情况根据对象的实际类型取得GstAudioRingBufferClass再调用commit虚函数。基类默认实现是default_commit()。该实现要求RingBuffer内存和输入数据指针都有效然后读取格式信息、每Frame字节数、每段大小和总段数。默认实现根据sample计算首个写入段和段内偏移。写入长度超过当前段剩余空间时会继续写到下一段。可写段尚未到达时调用等待逻辑目标位置已经落后于设备处理位置时则跳过落后的写入区域。是否调用者提供样本与位置检查样本数量数量是否为零直接返回输入样本数分派到RingBuffer类的commit默认实现计算分段和偏移3.2按分段位置写入并更新进度默认实现使用sample / samples_per_seg确定写入段使用sample % samples_per_seg确定段内偏移。每写入一段可用空间就增加样本位置跨段后从下一段开头继续处理。当in_samples和out_samples相同时默认实现逐Frame复制。两者不同时它依据输入输出数量和accum执行样本速率换算。out_samples为负数时按反向播放路径读取输入数据并写入。GstAudioBaseSink会在渲染音频时调用该接口。若返回值小于本次输入样本数Sink会等待Preroll或恢复条件再根据返回值调整数据偏移和剩余样本数。该循环让提交过程能够处理停止、刷新等中断情况。根据sample定位段和偏移判断目标段是否可写复制或按比例换算样本推进sample和accum返回已处理数量默认实现只写入RingBuffer管理的内存。设备侧如何消费这些分段由对应的RingBuffer子类负责。gst_audio_ring_buffer_commit()本身不会直接调用声卡驱动。4.实战案例4.1准备一个内存RingBuffer案例创建一个测试用GstAudioRingBuffer子类以一段普通内存模拟设备缓冲区。子类只负责打开测试后端、按规格分配内存和释放内存commit虚函数沿用基类默认实现。音频格式为48kHz、S16、双声道。每个Frame占4字节。测试提交4个Frame因此输入数据长度为16字节。4.2提交4个Frame并检查写入位置程序先打开并采集RingBuffer再把sample和accum初始化为0提交4个输入Frame和4个目标Frame。成功后检查三项结果返回值为4表示4个输入Frame均已处理。sample更新为4表示写入位置推进了4个Frame。RingBuffer内存的前16字节与输入数据一致。4.3完整代码#includegst/gst.h#includegst/audio/audio.h#includestring.htypedefstruct_TestRingBuffer{GstAudioRingBuffer parent;}TestRingBuffer;typedefstruct_TestRingBufferClass{GstAudioRingBufferClass parent_class;}TestRingBufferClass;G_DEFINE_TYPE(TestRingBuffer,test_ring_buffer,GST_TYPE_AUDIO_RING_BUFFER);/* 打开测试后端不访问真实音频设备 */staticgbooleantest_open_device(GstAudioRingBuffer*buf){returnTRUE;}/* 按分段规格申请测试用RingBuffer内存 */staticgbooleantest_acquire(GstAudioRingBuffer*buf,GstAudioRingBufferSpec*spec){buf-sizespec-segsize*spec-segtotal;buf-memoryg_malloc0(buf-size);returnTRUE;}/* 释放测试后端分配的内存 */staticgbooleantest_release(GstAudioRingBuffer*buf){g_free(buf-memory);buf-memoryNULL;buf-size0;returnTRUE;}/* 关闭测试后端 */staticgbooleantest_close_device(GstAudioRingBuffer*buf){returnTRUE;}staticvoidtest_ring_buffer_class_init(TestRingBufferClass*klass){GstAudioRingBufferClass*ring_classGST_AUDIO_RING_BUFFER_CLASS(klass);ring_class-open_devicetest_open_device;ring_class-acquiretest_acquire;ring_class-releasetest_release;ring_class-close_devicetest_close_device;}staticvoidtest_ring_buffer_init(TestRingBuffer*ring_buffer){}intmain(intargc,char*argv[]){TestRingBuffer*test_buffer;GstAudioRingBuffer*ring_buffer;GstAudioRingBufferSpec*spec;gint16 pcm[]{100,-100,200,-200,300,-300,400,-400};guint64 sample0;gint accum0;guint written;gboolean openedFALSE;gboolean acquiredFALSE;gboolean okFALSE;gst_init(argc,argv);/* 创建测试用RingBuffer对象 */test_bufferg_object_new(test_ring_buffer_get_type(),NULL);ring_bufferGST_AUDIO_RING_BUFFER(test_buffer);specring_buffer-spec;/* 配置48kHz、S16、双声道的原始音频 */gst_audio_info_init(spec-info);gst_audio_info_set_format(spec-info,GST_AUDIO_FORMAT_S16,48000,2,NULL);spec-typeGST_AUDIO_RING_BUFFER_FORMAT_TYPE_RAW;/* 每段1024字节共4段 */spec-segsize1024;spec-segtotal4;spec-seglatency-1;/* 采集前先打开设备 */if(!gst_audio_ring_buffer_open_device(ring_buffer))gotodone;openedTRUE;/* 申请内存并由基类初始化分段状态 */if(!gst_audio_ring_buffer_acquire(ring_buffer,spec))gotodone;acquiredTRUE;/* 首次提交时样本位置和速率换算累加器都从0开始 */writtengst_audio_ring_buffer_commit(ring_buffer,sample,(guint8*)pcm,4,4,accum);/* 检查输入消费数量、写入位置和RingBuffer内存内容 */okwritten4sample4memcmp(ring_buffer-memory,pcm,sizeof(pcm))0;done:/* 按资源创建顺序的逆序释放RingBuffer资源 */if(acquired)gst_audio_ring_buffer_release(ring_buffer);if(opened)gst_audio_ring_buffer_close_device(ring_buffer);gst_object_unref(ring_buffer);returnok?0:1;}5.总结gst_audio_ring_buffer_commit()根据样本位置和分段规格将输入数据提交到RingBuffer内存并更新写入位置与速率换算状态。
RELATED

相关推荐

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

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

简介: CSDN博客专家、《Android系统多媒体进阶实战》作者 博主新书推荐:《Android系统多媒体进阶实战》🚀 Android Audio工程师专栏地址: Audio工程师进阶系列【原创干货持续更新中……】🚀 Android多媒体专栏地址&a…

📅 2026/10/14 21:10:55
【机器学习案列-45】基于 XGBoost 的鲍鱼年龄预测

【机器学习案列-45】基于 XGBoost 的鲍鱼年龄预测

🧑 博主简介:曾任某智慧城市类企业算法总监,目前在美国市场的物流公司从事高级算法工程师一职,深耕人工智能领域,精通python数据挖掘、可视化、机器学习等,发表过AI相关的专利并多次在AI类比赛中获奖。CSDN人工智能领域的优质创作者,提供AI相关的技术咨询、项目开发和个…

📅 2026/10/14 21:05:54
智能问数 ChatBI:让每个人都能用自然语言分析数据

智能问数 ChatBI:让每个人都能用自然语言分析数据

过去,业务人员想查询销售额、客户数量或转化率,往往需要向数据团队提需求,再等待开发报表。ChatBI 将自然语言、大语言模型和传统 BI 结合起来,让用户可以直接通过对话完成数据查询、指标分析和图表生成。 文章目录一、什么是 Cha…

📅 2026/10/14 21:05:54
MORE NEWS

更多资讯

📰

Python词云实战:jieba分词与wordcloud参数调优指南

1. 从一堆杂乱文本到一张有信息量的词云,中间到底隔着什么很多人第一次接触词云,是看到别人用几百行评论生成了一张花花绿绿的图片,觉得这事挺简单——把文本丢进去,调个库,图片就出来了。但真正动手做过的人都知道&am…

📰

可信数据空间:从数据流通困局到下一代基础设施的关键跃迁

1. 数据流通这件事,为什么一直做不成?先把一个老问题摆到台面上:数据到底该怎么安全地给别人用?过去二十多年,数据共享和交易始终绕不开两堵墙。第一堵墙叫"给了就失控"——你把数据库开放给对方&#xff0c…

📰

十万亿参数模型训推:超节点架构如何拆掉算力、存储、通信三堵墙

1. 十万亿参数模型训推的“三堵墙”到底是什么第一次看到“十万亿参数”这个量级,很多人的第一反应是“这得多少张卡才跑得动”。但真正在一线做过大模型训练的人会告诉你,卡的数量从来不是最要命的问题,真正卡脖子的是三堵墙:算力…

📰

MFC打开PDF/Word:ShellExecute、OLE嵌入与WebBrowser三条路线详解

简介:这是一份面向VC/MFC开发者的源码示例,演示了如何在MFC应用程序中打开PDF与Word文档。工程基于VC6.0搭建,在Windows环境下可直接编译生成测试文件,适合正在学习Windows桌面应用文件操作、或需要借鉴文档启动与进程调用思路的读…

📰

Codex断线重连卡顿?一行配置搞定网络超时与快速重试

1. 先复盘一次"卡到怀疑人生"的断线现场如果你用 Codex 写过稍微长一点的会话,大概率遇到过这种情况:写到一半,终端里输出的流突然停住,光标还在闪,但没有任何新的输出;等上十几秒甚至一两分钟&a…

📰

无人机视觉计数新方案:NGDINO显式数量建模实战

1. 从“找得到”到“数得清”:无人机视觉计数到底难在哪 无人机航拍图像里的目标计数,听起来像是“检测框一画,数一数框就行”的事。但真正做过这类项目的人都知道,检测和计数之间隔着一道巨大的鸿沟。检测模型告诉你“图里有87个…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬