news 2026/7/15 5:30:36

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

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
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. 取出 Buffer
      • 3. 获取底层 spa_buffer
      • 4. 处理 Buffer 数据
      • 5. 重新入队 Buffer
      • 6. PipeWire 接管 Buffer
      • 7. 等待下一轮 process
      • 8. 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_streampw_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 需要处理一轮 Buffer

2. 取出 Buffer

应用调用:

pw_stream_dequeue_buffer(stream);

pw_stream中取出一个可处理的:

structpw_buffer

3. 获取底层 spa_buffer

每个pw_buffer内部会关联:

structspa_buffer

应用通过:

buffer->buffer

访问底层数据区。


4. 处理 Buffer 数据

播放场景通常是:

写入 PCM / 视频帧数据

采集场景通常是:

读取 PCM / 视频帧数据

5. 重新入队 Buffer

处理完成后调用:

pw_stream_queue_buffer(stream,buffer);

6. PipeWire 接管 Buffer

Buffer 重新交还给 PipeWire Stream。

PipeWire 后续根据 Stream 方向完成:

播放输出 采集复用 视频帧继续调度

7. 等待下一轮 process

当前 Buffer 处理完成后,应用返回process回调。

后续 PipeWire 会继续触发下一轮:

process callback

8. Buffer 循环复用

整个过程形成:

dequeue -> process -> queue -> dequeue

的循环。


🌻3.2 调用流程图


🌻3.3 Stream Buffer 入队生命周期图


🌻4. 实战应用案例

#include<pipewire/pipewire.h>#include<spa/param/audio/format-utils.h>#include<stdio.h>#include<string.h>structdata{structpw_stream*stream;structspa_hookstream_listener;};staticvoidon_process(void*userdata){structdata*data=userdata;structpw_buffer*buffer;structspa_buffer*spa_buf;void*dst;uint32_tsize;buffer=pw_stream_dequeue_buffer(data->stream);if(!buffer){printf("dequeue buffer failed\n");return;}spa_buf=buffer->buffer;if(!spa_buf||spa_buf->n_datas==0||!spa_buf->datas[0].data){pw_stream_queue_buffer(data->stream,buffer);return;}dst=spa_buf->datas[0].data;size=spa_buf->datas[0].maxsize;/* * 示例:播放场景中填充静音数据 */memset(dst,0,size);spa_buf->datas[0].chunk->offset=0;spa_buf->datas[0].chunk->size=size;spa_buf->datas[0].chunk->stride=4;/* * 处理完成后,必须把 buffer 重新交还给 PipeWire */pw_stream_queue_buffer(data->stream,buffer);}staticconststructpw_stream_eventsstream_events={PW_VERSION_STREAM_EVENTS,.process=on_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 循环复用中非常关键的基础接口之一。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/15 5:29:54

TI TPS6594-Q1 ESM模块深度解析:电平与PWM模式配置及功能安全实践

1. 项目概述与ESM核心价值在汽车电子和工业控制这类对可靠性要求极高的领域&#xff0c;系统失效的后果往往是灾难性的。想象一下&#xff0c;一辆高速行驶的汽车&#xff0c;其发动机控制单元&#xff08;ECU&#xff09;或高级驾驶辅助系统&#xff08;ADAS&#xff09;的某个…

作者头像 李华
网站建设 2026/7/15 5:29:48

TDA4VM嵌入式系统设计:电源、复位与时钟“铁三角”实战解析

1. 项目概述&#xff1a;为什么电源、复位与时钟是嵌入式系统的“铁三角”&#xff1f;干了十几年嵌入式硬件设计&#xff0c;从早期的8位单片机玩到现在的多核异构SoC&#xff0c;我越来越深刻地认识到一个道理&#xff1a;无论芯片的性能多强悍、功能多复杂&#xff0c;其稳定…

作者头像 李华
网站建设 2026/7/15 5:28:25

Go面试官:如何设计百万级别的消息推送系统?

两年前&#xff0c;我去一家做海外电商的公司面试。面试官是位看起来比我大不了几岁的技术负责人&#xff0c;话不多&#xff0c;但问问题的方式很特别。 他递给我一张纸&#xff0c;上面写着一行字&#xff1a;“午夜 12 点&#xff0c;给 100 万用户发一条推送。你怎么设计&a…

作者头像 李华
网站建设 2026/7/15 5:28:18

研0day2----联邦学习论文一篇

开启看第二篇论文&#xff0c;感觉对联邦学习有一点感兴趣 先看了一个50分钟的课&#xff0c;讲联邦学习 联邦学习分布式加密技术 同态加密&#xff1a; Ftop-k 梯度欠账本”。这一轮没上传的小梯度先欠着&#xff0c;下一轮继续累积&#xff0c;直到它的重要性足够大&…

作者头像 李华
网站建设 2026/7/15 5:28:03

从零构建生信分析基石:参考基因组与注释文件权威指南与实战下载

1. 参考基因组与注释文件&#xff1a;生物信息学的基石刚接触RNA-seq或重测序项目时&#xff0c;我完全被各种数据库和版本搞晕了。参考基因组就像一本用ATCG四个字母写成的天书&#xff0c;而注释文件就是解读这本天书的字典。没有它们&#xff0c;后续的分析工作根本无法开展…

作者头像 李华
网站建设 2026/7/15 5:27:34

从根源到修复:深入剖析HTTP 40X与50X状态码的实战诊断指南

1. HTTP状态码基础&#xff1a;40X与50X的定位与区别HTTP状态码是服务器对客户端请求的响应标识&#xff0c;用三位数字表示请求的处理结果。40X和50X这两类状态码分别代表了客户端错误和服务器错误&#xff0c;是开发运维人员日常最常遇到的故障信号。先说40X系列&#xff0c;…

作者头像 李华