news 2026/8/28 17:55:36

Linux PipeWire深度解析之pw_main_loop_run调用流程与实战(八十六)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Linux PipeWire深度解析之pw_main_loop_run调用流程与实战(八十六)

简介:CSDN博客专家、《Android系统多媒体进阶实战》作者

博主新书推荐:《Android系统多媒体进阶实战》🚀
Android Audio工程师专栏地址:Audio工程师进阶系列原创干货持续更新中……】🚀
Android多媒体专栏地址:多媒体系统工程师系列原创干货持续更新中……】🚀
专题一 二:AAOS车载系统+AOSP14系统攻城狮入门视频实战课🚀
专题三:Android14 Binder之HIDL与AIDL通信实战课🚀
专题四:Android15快速自定义与集成音效实战课🚀
专题五:Android15音频策略实战课🚀
专题六:Android15音频性能实战课(无声/杂音/断音/爆音实战案例)🚀

人生格言:人生从来没有捷径,只有行动才是治疗恐惧和懒惰的唯一良药.

更多原创,欢迎关注:Android系统攻城狮


🍉🍉🍉文章目录🍉🍉🍉

  • 🌻1.前言
      • 要点概括
  • 🌻2.应用场景与用法
    • 函数原型
    • 参数说明
    • 返回值
    • 应用场景
  • 🌻3.调用流程剖析
    • 🌻3.1核心步骤
    • 🌻3.2调用流程图
    • 🌻3.3生命周期图
  • 🌻4.实战应用案例
  • 🌻5.一句话总结

🌻1.前言

本篇目的:

Linux PipeWire深度解析之pw_main_loop_run调用流程与实战。

要点概括

  • 核心功能:运行PipeWire主循环,让当前线程进入事件等待和事件分发流程。

  • 工作机制:内部持续迭代pw_loop,等待IO、Timer、Signal、Defer等事件源就绪,并把事件派发到对应回调。

  • 典型用途:PipeWire客户端程序、测试Demo、命令行工具、音频播放/录音示例程序中的主事件循环。

pw_main_loop_run的本质是“运行主循环”,不是创建主循环,也不是创建Context、Core或Stream。主循环对象由pw_main_loop_new创建,底层pw_loop可以通过pw_main_loop_get_loop取得,事件循环真正开始运行时才调用pw_main_loop_run。

它和pw_main_loop_get_loop不同。pw_main_loop_get_loop只返回底层pw_loop指针,用于注册Signal、IO、Timer等事件源;pw_main_loop_run会阻塞当前线程,并持续驱动事件分发。

它和pw_main_loop_quit也不同。pw_main_loop_quit只负责请求主循环退出,不负责销毁资源。pw_main_loop_run返回后,应用仍然需要按顺序销毁Stream、Core、Context和MainLoop对象。

🌻2.应用场景与用法

pw_main_loop_run

是PipeWireMainLoop API中用于运行主事件循环的接口。

它位于PipeWire客户端程序的最外层调度位置。应用完成pw_init、pw_main_loop_new、pw_context_new、pw_context_connect、Stream创建或Registry监听后,通常调用pw_main_loop_run让当前线程进入事件循环。后续PipeWire服务端消息、Stream状态变化、Registry对象通知、Signal退出事件都会在该循环中被分发。

pw_main_loop_run用于启动并运行PipeWire主事件循环。

函数原型

intpw_main_loop_run(structpw_main_loop*loop);

参数说明

structpw_main_loop*loop;

loop表示由pw_main_loop_new创建的PipeWire主循环对象。

该对象内部维护底层pw_loop和退出事件源。应用可以通过pw_main_loop_get_loop取得底层pw_loop,然后注册Signal、Timer、IO等事件源。pw_main_loop_run运行时,会基于这些事件源持续等待和分发事件。

返回值

成功退出时返回:

0

表示主循环被正常退出请求打断,例如调用pw_main_loop_quit。

失败时返回负错误码,通常表示底层事件迭代过程出现错误。实际开发中,常见用法是把pw_main_loop_run作为客户端程序的主阻塞点,退出后再进入资源清理流程。

应用场景

第一类场景是PipeWire客户端常驻程序。

客户端连接PipeWire服务端后,需要持续接收Core、Registry、Node、Stream等事件。pw_main_loop_run负责让客户端线程一直等待事件,并在事件到达时分发回调。

第二类场景是音频播放和录音Demo。

应用创建pw_stream后,播放或录音过程依赖process、state_changed、param_changed等回调。pw_main_loop_run运行后,这些回调才会被持续触发。

第三类场景是命令行测试工具。

很多PipeWire测试程序需要等待异步结果,例如等待Registry枚举完成、等待Stream进入STREAMING状态、等待用户按Ctrl+C退出。pw_main_loop_run负责把这些异步事件串到同一个主循环里。

第四类场景是信号退出控制。

应用可以通过pw_main_loop_get_loop取得底层pw_loop,再注册SIGINT和SIGTERM信号处理。收到退出信号时调用pw_main_loop_quit,pw_main_loop_run随后返回,程序进入清理流程。

🌻3.调用流程剖析

🌻3.1核心步骤

1.应用调用pw_init初始化PipeWire库运行环境。

2.应用调用pw_main_loop_new创建主循环对象。

3.应用调用pw_main_loop_get_loop取得底层pw_loop,用于后续创建Context或注册事件源。

4.应用调用pw_context_new创建PipeWireContext。

5.应用调用pw_context_connect连接PipeWire服务端,得到Core连接对象。

6.应用根据业务需要创建Registry、Stream、Signal、Timer或IO事件源。

7.应用调用pw_main_loop_run,当前线程进入主循环运行态。

8.主循环内部持续等待事件源就绪。

9.事件就绪后,底层pw_loop把事件派发给对应回调。

10.回调中可以处理PipeWire消息、Stream数据、Registry对象变化或退出信号。

11.如果没有退出请求,pw_main_loop_run继续进入下一轮事件等待。

12.如果调用pw_main_loop_quit,主循环退出,pw_main_loop_run返回。

13.应用在run返回后销毁Core、Context、MainLoop等资源。

🌻3.2调用流程图

🌻3.3生命周期图

🌻4.实战应用案例

下面以“创建PipeWire客户端主循环并支持Ctrl+C退出”为例,说明pw_main_loop_run在真实程序中的位置。

这个案例的目标是:应用完成PipeWire初始化、创建MainLoop、创建Context、连接PipeWire服务端,然后调用pw_main_loop_run进入事件循环。用户按Ctrl+C后,Signal回调调用pw_main_loop_quit,主循环返回,程序进入清理阶段。

#include<signal.h>#include<pipewire/pipewire.h>structapp_data{structpw_main_loop*main_loop;structpw_context*context;structpw_core*core;};staticvoidon_signal(void*userdata,intsignal_number){structapp_data*data=userdata;(void)signal_number;pw_main_loop_quit(data->main_loop);}

on_signal是Signal事件回调。它不直接销毁PipeWire对象,只调用pw_main_loop_quit请求主循环退出。真正的资源释放放在pw_main_loop_run返回之后执行,这样可以避免在事件回调中提前释放仍在使用的对象。

intmain(intargc,char*argv[]){structapp_datadata={0};structpw_loop*loop;pw_init(&argc,&argv);data.main_loop=pw_main_loop_new(NULL);if(data.main_loop==NULL)gotoout_deinit;loop=pw_main_loop_get_loop(data.main_loop);pw_loop_add_signal(loop,SIGINT,on_signal,&data);pw_loop_add_signal(loop,SIGTERM,on_signal,&data);data.context=pw_context_new(loop,NULL,0);if(data.context==NULL)gotoout_main_loop;data.core=pw_context_connect(data.context,NULL,0);if(data.core==NULL)gotoout_context;pw_main_loop_run(data.main_loop);pw_core_disconnect(data.core);out_context:pw_context_destroy(data.context);out_main_loop:pw_main_loop_destroy(data.main_loop);out_deinit:pw_deinit();return0;}

这段代码中,pw_main_loop_run是程序的主阻塞点。它开始运行后,当前线程不会继续向下执行,直到主循环收到退出请求或底层事件循环出现错误。

主循环运行期间,PipeWire服务端消息、Signal事件和业务事件都会通过同一个pw_loop分发。客户端不需要自己写poll、epoll或事件等待逻辑,只需要把事件源注册到pw_loop,然后交给pw_main_loop_run统一驱动。

在播放或录音程序中,pw_main_loop_run的位置也类似。应用先创建Stream并注册Stream事件回调,再调用pw_main_loop_run。运行期间,Stream的state_changed、param_changed和process回调会被PipeWire事件循环持续触发。

staticvoidon_stream_process(void*userdata){/* * 播放流:通常在这里dequeue buffer并填充PCM数据。 * 录音流:通常在这里dequeue buffer并读取PCM数据。 */(void)userdata;}

对于音频程序来说,pw_main_loop_run不直接处理PCM数据。它只负责运行事件循环。真正的数据处理发生在Stream回调中,例如process回调。主循环负责调度回调,Stream回调负责处理媒体数据。

工程上需要注意三点。

第一,pw_main_loop_run会阻塞当前线程。它适合放在主线程末尾,或者放在专门的PipeWire线程中运行。

第二,不要把资源销毁逻辑直接塞进Signal回调。Signal回调中只请求退出,等pw_main_loop_run返回后再统一清理资源。

第三,pw_main_loop_run不等于Graph调度本身。它运行的是客户端事件循环,负责接收服务端消息、分发回调和驱动客户端侧状态变化。PipeWire服务端Graph的实时处理由服务端和相关Driver Node调度完成。

🌻5.一句话总结

pw_main_loop_run是PipeWire客户端程序的主事件循环入口:它阻塞当前线程并持续分发pw_loop事件,让Core、Registry、Stream和Signal回调能够被触发,直到pw_main_loop_quit请求主循环退出。

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

C++国赛大题实战:动态规划与哈希表解决区间划分计数问题

1. 从赛场到复盘&#xff1a;一份C国赛大题的个人实战拆解又到了每年这个时候&#xff0c;各大编程竞赛的国赛阶段尘埃落定&#xff0c;朋友圈里几家欢喜几家愁。我作为一枚在算法和工程领域摸爬滚打多年的老码农&#xff0c;虽然早已过了亲自上阵打比赛的年纪&#xff0c;但每…

作者头像 李华
网站建设 2026/8/28 17:54:24

189、车载摄像头-40°C冷启动下的ISP黑电平漂移补偿——基于海思Hi3516的温控BLC查表设计

189、车载摄像头-40C冷启动下的ISP黑电平漂移补偿——基于海思Hi3516的温控BLC查表设计 凌晨四点的黑河试车场,零下四十一度。我裹着军大衣蹲在工程车里,盯着屏幕上的画面——整个画面像蒙了一层灰紫色的纱,暗部噪点跟下雪似的。客户那边测试员冻得直跺脚,嘴里哈着白气问:…

作者头像 李华
网站建设 2026/8/28 17:51:42

林业固碳技术建模:从碳汇量化到多目标优化的数学实践

1. 从“碳汇”到“碳汇经济”&#xff1a;为什么林业固碳技术是2022美赛E题的核心 如果你在2022年关注过美国大学生数学建模竞赛&#xff08;MCM/ICM&#xff09;&#xff0c;或者对“双碳”目标下的技术路径有所了解&#xff0c;那么“林业固碳技术”这个题目一定不陌生。它不…

作者头像 李华
网站建设 2026/8/28 17:48:37

PRISM:多变量时间序列转图像表示与异常检测

这次我们来看一个面向多变量时间序列异常检测的表示学习方法&#xff1a;PRISM。项目全称是PRISM: Powerful Time Series to Image (TS2I) Representations for Multivariate Anomaly Detection&#xff0c;核心思路一句话能说清&#xff1a;把多变量时间序列转换成图像&#x…

作者头像 李华
网站建设 2026/8/28 17:48:24

Transformer驱动的3D场景生成:从稀疏照片到可探索空间

有没有想过&#xff0c;未来搭建一个 3D 场景&#xff0c;可能不再需要专业的建模师、扫描仪和漫长的渲染流程&#xff1f;只需要一部普通手机&#xff0c;绕着房间走动拍几张照片&#xff0c;然后等上几秒钟&#xff0c;就能得到一个可以自由旋转、行走、预览的 3D 空间。这个…

作者头像 李华
网站建设 2026/8/28 17:45:47

LoRaWAN物联网组网实战:从频谱规划到海量设备稳定接入

前天刷到 Senet 拿到物联网组网专利的消息&#xff0c;作为一个常年跟 LoRaWAN 和低功耗广域网打交道的工程师&#xff0c;我第一反应是&#xff1a;这个方向终于有人认真做体系化了。很多人对物联网项目的理解停留在“买一批传感器&#xff0c;配好网关&#xff0c;数据能上云…

作者头像 李华