Linux PipeWire深度解析之pw_stream_queue_buffer调用流程与实战(九)

发布时间:2026/7/15 5:30:39

Linux PipeWire深度解析之pw_stream_queue_buffer调用流程与实战(九) 简介CSDN博客专家、《Android系统多媒体进阶实战》作者博主新书推荐《Android系统多媒体进阶实战》Android Audio工程师专栏地址Audio工程师进阶系列【原创干货持续更新中……】Android多媒体专栏地址多媒体系统工程师系列【原创干货持续更新中……】专题一 二AAOS车载系统AOSP14系统攻城狮入门视频实战课专题三Android14 Binder之HIDL与AIDL通信实战课专题四Android15快速自定义与集成音效实战课专题五Android15音频策略实战课专题六Android15音频性能实战课(无声/杂音/断音/爆音实战案例)人生格言人生从来没有捷径只有行动才是治疗恐惧和懒惰的唯一良药.更多原创,欢迎关注Android系统攻城狮文章目录1. 前言要点概括2. 应用场景与用法函数原型参数说明返回值应用场景3. 调用流程剖析3.1 核心步骤1. process 回调触发2. 取出 Buffer3. 获取底层 spa_buffer4. 处理 Buffer 数据5. 重新入队 Buffer6. PipeWire 接管 Buffer7. 等待下一轮 process8. Buffer 循环复用3.2 调用流程图3.3 Stream Buffer 入队生命周期图4. 实战应用案例5. 一句话总结1. 前言本篇目的Linux PipeWire 深度解析之pw_stream_queue_buffer调用流程与实战。要点概括核心功能把已经处理完成的pw_buffer重新提交回pw_stream。工作机制应用在process回调中通过pw_stream_dequeue_buffer()取出 Buffer完成音频/视频数据填充或消费后再调用pw_stream_queue_buffer()把 Buffer 归还给 PipeWire。典型用途音频播放、音频采集、Camera 视频帧处理、低延迟媒体流 Buffer 循环复用。2. 应用场景与用法pw_stream_queue_buffer()是 PipeWire Stream Buffer 管理体系中的核心接口。在 PipeWire 中音频播放、录音采集、摄像头视频流、屏幕采集这类实时媒体数据最终都会通过pw_stream和pw_buffer完成数据交换。而该接口用于把已经处理完成的pw_buffer重新入队交还给 PipeWire Stream 继续调度。函数原型intpw_stream_queue_buffer(structpw_stream*stream,structpw_buffer*buffer);参数说明stream:目标 pw_stream buffer:需要重新入队的 pw_buffer返回值返回int通常用于判断 Buffer 是否成功重新提交给 Stream。0 - 成功 0 - 失败应用场景pw_stream_queue_buffer()常见应用场景主要有三类。第一类是音频播放。在播放场景中PipeWire 通过process回调通知应用准备写入音频数据应用调用pw_stream_dequeue_buffer()取出可写 Buffer把 PCM 数据写入spa_buffer-datas[]后再调用pw_stream_queue_buffer()把 Buffer 交还给 PipeWire后续由 PipeWire 调度到音频设备输出。第二类是音频采集。在录音场景中PipeWire 把已经采集到的音频帧放入 Buffer应用在process回调中取出 Buffer读取其中的 PCM 数据并完成编码、保存或网络发送处理完成后仍然需要调用pw_stream_queue_buffer()归还 Buffer否则 Buffer 队列会被耗尽录音流会出现停顿或异常。第三类是 Camera 与视频帧处理。在摄像头、屏幕采集或视频处理场景中每一帧图像也通过 Buffer 流转。应用从 Stream 中取出 Buffer完成图像读取、格式转换、编码或渲染后再调用pw_stream_queue_buffer()重新入队使 PipeWire 可以继续复用该 Buffer维持实时视频流的持续运行。3. 调用流程剖析3.1 核心步骤1. process 回调触发staticvoidon_process(void*userdata){}PipeWire 通知应用当前 Stream 需要处理一轮 Buffer2. 取出 Buffer应用调用pw_stream_dequeue_buffer(stream);从pw_stream中取出一个可处理的structpw_buffer3. 获取底层 spa_buffer每个pw_buffer内部会关联structspa_buffer应用通过buffer-buffer访问底层数据区。4. 处理 Buffer 数据播放场景通常是写入 PCM / 视频帧数据采集场景通常是读取 PCM / 视频帧数据5. 重新入队 Buffer处理完成后调用pw_stream_queue_buffer(stream,buffer);6. PipeWire 接管 BufferBuffer 重新交还给 PipeWire Stream。PipeWire 后续根据 Stream 方向完成播放输出 采集复用 视频帧继续调度7. 等待下一轮 process当前 Buffer 处理完成后应用返回process回调。后续 PipeWire 会继续触发下一轮process callback8. Buffer 循环复用整个过程形成dequeue - process - queue - dequeue的循环。3.2 调用流程图3.3 Stream Buffer 入队生命周期图4. 实战应用案例#includepipewire/pipewire.h#includespa/param/audio/format-utils.h#includestdio.h#includestring.hstructdata{structpw_stream*stream;structspa_hookstream_listener;};staticvoidon_process(void*userdata){structdata*datauserdata;structpw_buffer*buffer;structspa_buffer*spa_buf;void*dst;uint32_tsize;bufferpw_stream_dequeue_buffer(data-stream);if(!buffer){printf(dequeue buffer failed\n);return;}spa_bufbuffer-buffer;if(!spa_buf||spa_buf-n_datas0||!spa_buf-datas[0].data){pw_stream_queue_buffer(data-stream,buffer);return;}dstspa_buf-datas[0].data;sizespa_buf-datas[0].maxsize;/* * 示例播放场景中填充静音数据 */memset(dst,0,size);spa_buf-datas[0].chunk-offset0;spa_buf-datas[0].chunk-sizesize;spa_buf-datas[0].chunk-stride4;/* * 处理完成后必须把 buffer 重新交还给 PipeWire */pw_stream_queue_buffer(data-stream,buffer);}staticconststructpw_stream_eventsstream_events{PW_VERSION_STREAM_EVENTS,.processon_process,};voidsetup_stream_callback(structdata*data){pw_stream_add_listener(data-stream,data-stream_listener,stream_events,data);}intmain(){structdatadata;/* * 假设 PipeWire 已初始化 * 假设 pw_stream 已创建并 connect 成功 */setup_stream_callback(data);return0;}5. 一句话总结pw_stream_queue_buffer()本质上是“把已经处理完成的 pw_buffer 重新提交回 pw_stream”。它负责完成 Buffer 从应用侧到 PipeWire Stream 侧的归还动作是 PipeWire 音频播放、录音采集、Camera 视频帧处理和实时媒体流 Buffer 循环复用中非常关键的基础接口之一。

相关新闻