资讯详情

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

📅 2026/10/17 14:15:53 | 华诺云谱 👁 阅读
Linux Gstreamer深度解析之gst_audio_ring_buffer_may_start调用流程与实战(七十八)
简介CSDN博客专家、《Android系统多媒体进阶实战》作者博主新书推荐《Android系统多媒体进阶实战》Android Audio工程师专栏地址Audio工程师进阶系列【原创干货持续更新中……】Android多媒体专栏地址多媒体系统工程师系列【原创干货持续更新中……】专题一 二AAOS车载系统AOSP14系统攻城狮入门视频实战课专题三Android14 Binder之HIDL与AIDL通信实战课专题四Android15快速自定义与集成音效实战课专题五Android15音频策略实战课专题六Android15音频性能实战课(无声/杂音/断音/爆音实战案例)人生格言人生从来没有捷径只有行动才是治疗恐惧和懒惰的唯一良药.更多原创,欢迎关注Android系统攻城狮文章目录1.前言2.应用场景和用法2.1控制RingBuffer启动时机2.2函数原型与返回语义3.调用流程剖析3.1原子更新启动许可3.2启动流程读取许可4.实战案例4.1准备一个带启动计数的RingBuffer4.2切换许可并检查启动回调4.3完整代码5.总结1.前言本篇目的理解gst_audio_ring_buffer_may_start()如何控制GstAudioRingBuffer是否允许启动并通过状态和启动回调观察这个许可如何影响播放流程。RingBuffer既保存音频数据也管理设备启动状态。gst_audio_ring_buffer_may_start()只修改一个原子许可标志不会直接启动设备或改变RingBuffer状态。真正启动时gst_audio_ring_buffer_start()和内部等待流程会读取这个标志再决定是否继续。允许不允许音频基类状态变化gst_audio_ring_buffer_may_start更新may_start许可标志RingBuffer启动流程读取许可是否允许启动调用设备启动处理保持未启动状态2.应用场景和用法2.1控制RingBuffer启动时机音频播放和录制通常要等到元素状态进入PLAYING后才允许底层RingBuffer启动。元素还在PAUSED时音频基类会暂时关闭启动许可避免设备过早开始处理数据。场景许可状态作用元素进入READY_TO_PAUSEDFALSE阻止RingBuffer提前启动元素进入PAUSED_TO_PLAYINGTRUE允许启动或恢复RingBuffer元素进入PLAYING_TO_PAUSEDFALSE阻止后续启动并配合暂停RingBuffer数据路径需要等待空闲或可读分段检查当前许可决定等待流程能否触发启动may_start是启动许可不等于RingBuffer当前的运行状态。许可为TRUE只表示可以启动设备是否已经启动还要看state以及底层启动回调结果。2.2函数原型与返回语义函数原型如下voidgst_audio_ring_buffer_may_start(GstAudioRingBuffer*buf,gboolean allowed);参数含义buf要控制启动许可的GstAudioRingBuffer对象allowedTRUE允许启动FALSE暂不允许启动函数没有返回值。实现会检查buf类型再通过g_atomic_int_set()更新buf-may_start。该标志以原子方式读写函数本身不获取对象锁也不调用设备的start虚函数。相邻接口的职责不同接口职责gst_audio_ring_buffer_may_start()设置是否允许启动gst_audio_ring_buffer_start()检查许可、状态和采集情况再执行启动或恢复gst_audio_ring_buffer_pause()暂停当前RingBuffergst_audio_ring_buffer_stop()停止当前RingBuffer3.调用流程剖析3.1原子更新启动许可gst_audio_ring_buffer_may_start()本身非常短先检查传入对象再把allowed写入buf-may_start。voidgst_audio_ring_buffer_may_start(GstAudioRingBuffer*buf,gboolean allowed){g_return_if_fail(GST_IS_AUDIO_RING_BUFFER(buf));g_atomic_int_set(buf-may_start,allowed);}它不做以下操作不调用gst_audio_ring_buffer_start()。不切换GST_AUDIO_RING_BUFFER_STATE_STOPPED或GST_AUDIO_RING_BUFFER_STATE_STARTED。不调用设备子类的start或resume回调。因此设置许可和实际启动是两个阶段。设置为TRUE后RingBuffer仍可能处于停止状态直到后续启动流程读取许可并执行启动。3.2启动流程读取许可显式调用gst_audio_ring_buffer_start()时RingBuffer会依次检查是否正在刷新、是否已经采集以及may_start是否为真。许可为FALSE时启动请求返回失败不会调用子类的设备启动回调。数据读写流程中的wait_segment()也会读取同一标志。当RingBuffer尚未启动且数据路径需要等待分段时只有许可为TRUE内部流程才会尝试启动RingBuffer。GstAudioBaseSink和GstAudioBaseSrc都会在READY_TO_PAUSED时关闭许可在PAUSED_TO_PLAYING时打开许可在PLAYING_TO_PAUSED时再次关闭许可。Sink在特定路径下还会主动调用启动接口。是否READY_TO_PAUSED设置许可为FALSEPAUSED阶段准备数据PAUSED_TO_PLAYING设置许可为TRUE显式启动或等待流程尝试启动许可与状态检查通过调用start或resume回调不调用设备启动回调PLAYING_TO_PAUSED关闭许可并暂停RingBuffer4.实战案例4.1准备一个带启动计数的RingBuffer案例创建一个测试用GstAudioRingBuffer子类。子类提供最小的设备打开、采集、启动、停止和释放回调启动回调只增加计数不连接真实音频设备。这样可以直接观察许可关闭时启动请求被拦截许可打开后启动回调才被调用。4.2切换许可并检查启动回调测试使用以下顺序打开测试设备并采集RingBuffer资源。将许可设为FALSE调用gst_audio_ring_buffer_start()检查启动失败且回调计数仍为0。将许可设为TRUE再次调用启动接口检查启动成功且回调计数变为1。释放RingBuffer资源并关闭测试设备。这个案例验证的是通用基类的许可门控。实际ALSA、PulseAudio或其他设备后端的启动行为还取决于对应子类的回调实现。4.3完整代码#includegst/gst.h#includegst/audio/audio.h#includestring.htypedefstruct_TestRingBuffer{GstAudioRingBuffer parent;guint start_calls;}TestRingBuffer;typedefstruct_TestRingBufferClass{GstAudioRingBufferClass parent_class;}TestRingBufferClass;G_DEFINE_TYPE(TestRingBuffer,test_ring_buffer,GST_TYPE_AUDIO_RING_BUFFER);/* 测试后端打开设备不访问真实硬件 */staticgbooleantest_ring_buffer_open_device(GstAudioRingBuffer*buf){returnTRUE;}/* 为基类分段初始化提供一块模拟缓冲区 */staticgbooleantest_ring_buffer_acquire(GstAudioRingBuffer*buf,GstAudioRingBufferSpec*spec){buf-sizespec-segsize*spec-segtotal;buf-memoryg_malloc0(buf-size);returnTRUE;}/* 记录真正进入设备启动回调的次数 */staticgbooleantest_ring_buffer_start(GstAudioRingBuffer*buf){TestRingBuffer*test_buffer(TestRingBuffer*)buf;test_buffer-start_calls;returnTRUE;}/* 测试后端停止处理 */staticgbooleantest_ring_buffer_stop(GstAudioRingBuffer*buf){returnTRUE;}/* 释放模拟缓冲区 */staticgbooleantest_ring_buffer_release(GstAudioRingBuffer*buf){g_free(buf-memory);buf-memoryNULL;buf-size0;returnTRUE;}/* 测试后端关闭设备 */staticgbooleantest_ring_buffer_close_device(GstAudioRingBuffer*buf){returnTRUE;}staticvoidtest_ring_buffer_class_init(TestRingBufferClass*klass){GstAudioRingBufferClass*ring_buffer_classGST_AUDIO_RING_BUFFER_CLASS(klass);ring_buffer_class-open_devicetest_ring_buffer_open_device;ring_buffer_class-acquiretest_ring_buffer_acquire;ring_buffer_class-starttest_ring_buffer_start;ring_buffer_class-stoptest_ring_buffer_stop;ring_buffer_class-releasetest_ring_buffer_release;ring_buffer_class-close_devicetest_ring_buffer_close_device;}staticvoidtest_ring_buffer_init(TestRingBuffer*test_buffer){}intmain(intargc,char*argv[]){TestRingBuffer*test_buffer;GstAudioRingBuffer*ring_buffer;GstAudioRingBufferSpec*spec;gboolean openedFALSE;gboolean acquiredFALSE;gboolean okFALSE;gboolean blocked_start;gboolean allowed_start;gst_init(argc,argv);test_bufferg_object_new(test_ring_buffer_get_type(),NULL);ring_bufferGST_AUDIO_RING_BUFFER(test_buffer);specring_buffer-spec;/* 准备S16双声道格式和4个缓冲段 */memset(spec,0,sizeof(*spec));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;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;/* 许可关闭时启动接口不应进入子类回调 */gst_audio_ring_buffer_may_start(ring_buffer,FALSE);blocked_startgst_audio_ring_buffer_start(ring_buffer);if(blocked_start||test_buffer-start_calls!0)gotodone;/* 打开许可后启动接口才会调用子类start回调 */gst_audio_ring_buffer_may_start(ring_buffer,TRUE);allowed_startgst_audio_ring_buffer_start(ring_buffer);okallowed_starttest_buffer-start_calls1g_atomic_int_get(ring_buffer-state)GST_AUDIO_RING_BUFFER_STATE_STARTED;done:/* 按照资源生命周期逆序清理 */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_may_start()通过原子标志控制RingBuffer是否获准启动实际启动仍由后续的gst_audio_ring_buffer_start()或等待流程完成。
📝

华诺云谱内容团队

资深建站顾问 · 行业研究员

10年+企业数字化服务经验,专注智能建站、SEO优化与品牌营销,持续输出建站技巧、行业洞察与营销干货,已帮助5000+企业实现数字化增长。

你可能需要的服务

订阅华诺云谱资讯周报

每周一封,精选建站技巧、SEO与营销干货,直达邮箱。已有 8,000+ 企业主订阅,助你少走弯路。

↑