点击下方👇关注 Android系统攻城狮
第206篇原创文章
持续迭代 | Android+Linux多媒体进阶体系
专栏·课程 知识体系持续更新
Linux多媒体框架从PulseAudio过渡到PipeWire是必然趋势,但是开发者第一次切到PipeWire环境时,发现后台多了很多陌生的进程和插件,比如pipewire、pipewire-pulse和wireplumber等。
PipeWire能够兼容PulseAudio旧应用继续运行,同时把JACK和ALSA接入进来,需要把音频、视频、屏幕共享和设备策略放到同一套媒体Graph中处理。那么了解PipeWire架构和核心组件的分工,是学习Node、Port、Link、WirePlumber策略等内容的前提条件,本篇带大家先了解PipeWire核心架构和组件分工。

1


在PulseAudio时代,大多数桌面音频问题可以先归到一个中心进程里,应用把播放流交给PulseAudio,PulseAudio负责混音、音量、路由和设备交接,最后再把数据送到ALSA设备。
那么PipeWire是怎么处理的呢?首先PipeWire系统分工被拆开了,pipewire负责提供媒体对象运行环境和Graph基础,pipewire-pulse负责对接PulseAudio协议应用,WirePlumber负责会话和策略管理,SPA插件负责把ALSA、V4L2、BlueZ这类底层设备能力暴露出来。
这些组件分别负责应用接入、策略管理和底层设备适配,最终统一汇入PipeWire,由PipeWire完成对象管理和媒体Graph组织,下图为PipeWire的整体架构示意图。

PipeWire架构它中,应用接入层负责把不同类型的应用接进来,PipeWire核心层负责承载对象和Graph,WirePlumber策略层负责让系统按策略机制运转,SPA和设备插件层负责对接底层设备能力。

2


PipeWire守护进程启动后创建主循环和pw_context,然后进入运行循环,后续模块、对象、客户端连接和Graph运行都依赖这个上下文。
从职责上看,pipewire负责提供Server和用户态API,处理多媒体pipeline和Graph,让音频、视频和其他媒体对象能在同一个运行环境里交换状态和数据。把PipeWire放在多媒体pipeline和Graph生成这条主线上,而不是传统意义上的音频服务。
PipeWire是运行媒体对象的基础环境,客户端连进来后,系统可以创建Client、Node、Port、Link、Device、Factory等对象,Graph也在这里形成和运行。至于这些对象怎么被发现、配置、连接和恢复,就需要WirePlumber话管理器决定。

所以排查pipewire问题时,重点看PipeWire是否存在、对象是否注册、Graph里是否出现预期Node和Link。pw-cli、pw-dump、pw-top这类工具更适合调试这一层问题。

3


PulseAudio的旧应用可以不使用PipeWire API,它们仍然通过libpulse、JACK或ALSA接口工作。PipeWire虽然要替代PulseAudio,但没有要求所有应用重写,也可以继续使用兼容层API。
Pipewire-pulse不是原来的PulseAudio Daemon,而是PipeWire提供的PulseAudio兼容服务进程。它通常读取pipewire-pulse.conf,并在context.modules中加载libpipewire-module-protocol-pulse。该模块在PipeWire之上实现完整的PulseAudio Server协议,因此旧应用仍然可以使用原来的PulseAudio客户端库libpulse,pactl、pavucontrol、paplay等工具也可以继续工作,而底层实际由PipeWire完成媒体处理。 重点是:pipewire-pulse承接的是PulseAudio协议入口,它不是传统PulseAudio Daemon。应用从libpulse进来以后,后端进入PipeWire的对象和Graph体系。

JACK和ALSA入口也是类似思路,JACK应用可以通过pw-jack或PipeWire的JACK兼容库接入,这一路会把客户端API标记成jack,再创建PipeWire上下文。ALSA应用可以通过PipeWire ALSA插件接入,ALSA PCM插件会把客户端API标记成alsa,并给播放或采集流设置Node名称和媒体属性。
兼容层解决的是旧入口怎么使用新框架,兼容层把旧应用接入PipeWire,关于路由连接和底层设备交接仍然需要PipeWire、WirePlumber策略和SPA插件处理。

4


PipeWire启动后会加载预配置模块,这些模块提供Factory和Native Protocol等能力,除此之外,设备启用、Node配置、Link管理和默认目标选择都需要会话管理处理。
WirePlumber是PipeWire常用的会话和策略管理器。它启动后创建WpCore并连接PipeWire,加载自己的配置和组件,再根据系统事件执行管理操作。
它功能是:启用设备、配置设备、控制客户端权限、配置Node、管理Link、维护Metadata。对音频开发者来说,最常遇到的是设备启用、默认设备选择、播放流自动连接、设备插拔后的重新连接,以及用户在pavucontrol或wpctl里修改默认设备后的状态保存。

比如:一个播放应用创建了Stream/Output/Audio类型的流Node,系统里有多个Audio/Sink设备Node。WirePlumber的Linking Policy会先看有没有配置好的默认目标,如果没有可用默认目标,再选择优先级更高、路由可用的设备Node。如果连可用目标都没有,它不会凭空让声音播放,而是让客户端得到一个没有目标Node问题。
PipeWire负责让Graph可以运行,WirePlumber负责让Graph按系统策略连起来。

5


SPA可以理解为PipeWire用来接入底层媒体能力的一套插件和接口层。ALSA、V4L2、libcamera、BlueZ模块是真实的设备后端,它们不能直接变成PipeWire里的统一对象,需要通过相应插件暴露出设备的能力,再由上层把它们组织成Device、Node和Port。
以ALSA为例,SPA ALSA插件会枚举ALSA Source、ALSA Sink、ALSA Udev、ALSA PCM Device、ALSA Sequencer Bridge、ALSA ACP Device等Factory。WirePlumber的设备监控代码,会使用这些能力发现音频设备,并在PipeWire里创建可交互的对象。
SPA层解决的是底层能力怎么被PipeWire使用,很多底层问题出在这里,例如ALSA设备没有被枚举、声卡Profile或Route不符合预期、设备Node没有创建出来,或者摄像头、蓝牙音频这类设备没有进入PipeWire Graph。

应用处理播放设备、录音设备和音量控制,PipeWire处理Device、Node、Port和Link,底层插件负责把ALSA这类系统能力翻译进这套对象模型。

6


理解PipeWire组件分工以后,PipeWire环境里的排查顺序就清楚了。先判断旧应用接到了哪个服务,再判断PipeWire对象是否存在,然后看WirePlumber是否完成策略,最后再到底层设备插件和ALSA设备。
第1步:确认PipeWire是否存在?
pw-cli ls关键对象:
ClientDeviceNodePortLinkFactory如果应用已经启动,但看不到对应Client或Stream Node,问题可能发生在应用入口或兼容层。如果设备没有对应Device或设备Node,问题在WirePlumber设备启用、SPA设备插件或底层ALSA/V4L2。
第2步:确认WirePlumber默认设备和流状态?
wpctl status关键字段:
SinksSourcesStreamsDefault 如果默认输出、默认输入和应用流是否出现在WirePlumber里。如果pw-cli能看到Node,但wpctl status里没有合理默认设备或流没有挂到目标设备,就要继续检查WirePlumber策略、Metadata和Linking Policy。
第3步:确认进程分工是否完整?
ps -ef | grep -E 'pipewire|wireplumber'关键进程:
pipewirepipewire-pulsewireplumberpipewire缺失时,Graph本身就没有运行。pipewire-pulse缺失时,旧PulseAudio应用可能接不到兼容服务。wireplumber缺失时,设备启用、默认路由、自动Link和Metadata管理都可能不完整,系统可能有对象但不能自动连成可用链路。

7


PipeWire把应用入口、媒体Graph、策略管理和底层设备分成了多层协作处理。pipewire负责Core和Graph运行,pipewire-pulse、JACK兼容层和ALSA插件负责对接旧应用入口,WirePlumber负责设备、权限、默认目标和Link策略,SPA插件负责把ALSA、视频、蓝牙等底层能力适配到PipeWire,使其能够接入Graph。
若读者朋友发现有错误、疑问的地方,或者好的建议,欢迎拍砖!!!