ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

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

Linux PipeWire深度解析之pw_main_loop_get_loop调用流程与实战(八十五) 简介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_get_loop调用流程与实战。要点概括核心功能取得pw_main_loop内部持有的pw_loop指针让Context、事件源和后续任务绑定到同一个事件循环。工作机制该函数不创建新的Loop只返回pw_main_loop对象内部已经创建好的pw_loop。典型用途创建pw_context、注册signal/timer/io/defer事件源、统一驱动PipeWire客户端主循环。pw_main_loop_get_loop的本质是“从主循环封装对象中取出底层事件循环”。它不是运行主循环的接口也不是创建Loop的接口。pw_main_loop_new负责创建pw_main_loop对象并在内部准备pw_loop。pw_main_loop_get_loop只负责暴露这个内部pw_loop指针。pw_main_loop_run才负责进入事件循环并驱动事件分发。它和pw_main_loop_run不同。pw_main_loop_run会阻塞当前线程并持续处理事件pw_main_loop_get_loop只返回指针不会进入事件循环。它和pw_main_loop_quit也不同。pw_main_loop_quit用于请求主循环退出pw_main_loop_get_loop不改变运行状态。它和pw_loop_new也不同。pw_loop_new创建独立的pw_loop对象pw_main_loop_get_loop返回的是pw_main_loop内部已经拥有的pw_loop调用方不能销毁这个返回指针。2.应用场景与用法pw_main_loop_get_loop是PipeWire Main Loop API中用于获取底层pw_loop的接口。它位于PipeWire客户端初始化主链路中。应用先通过pw_main_loop_new创建主循环对象再通过pw_main_loop_get_loop取得内部pw_loop然后把该pw_loop传给pw_context_new保证Context、Core连接、Registry事件、Stream事件和自定义事件源都在同一个事件循环中调度。pw_main_loop_get_loop用于从pw_main_loop中取得内部pw_loop指针。函数原型structpw_loop*pw_main_loop_get_loop(structpw_main_loop*loop);参数说明structpw_main_loop*loop;loop表示已经通过pw_main_loop_new创建的主循环对象。该对象负责管理PipeWire客户端常用的主循环封装。它内部持有一个pw_looppw_main_loop_get_loop返回的就是这个内部pw_loop。调用前需要保证loop有效。不能把已经destroy的pw_main_loop继续传给该函数。返回值成功时返回structpw_loop*表示pw_main_loop内部持有的底层事件循环对象。该返回值是借用指针不表示调用方获得所有权。调用方不能直接释放它也不能在pw_main_loop_destroy之后继续使用它。返回NULL通常表示传入对象无效或者主循环对象没有正确创建。实际开发中应优先保证pw_main_loop_new成功再调用pw_main_loop_get_loop。应用场景第一类场景是创建PipeWire Context。PipeWire客户端通常先创建pw_main_loop再通过pw_main_loop_get_loop取得pw_loop最后把pw_loop传给pw_context_new。这样Context后续产生的事件可以由同一个主循环驱动。第二类场景是注册事件源。应用可以基于返回的pw_loop注册signal、timer、io、defer等事件源。这些事件源和PipeWire内部事件运行在同一个事件循环中方便统一调度。第三类场景是客户端程序主循环封装。简单PipeWire客户端不一定直接管理pw_loop可以使用pw_main_loop作为上层封装。pw_main_loop_get_loop提供了向底层事件系统对接的入口。第四类场景是Stream事件调度。应用创建Context并连接PipeWire服务端后后续Registry事件、Stream状态变化、process回调等都依赖事件循环驱动。pw_main_loop_get_loop虽然不直接处理Stream数据但它决定了这些事件挂在哪个Loop上运行。3.调用流程剖析3.1核心步骤1.应用调用pw_init初始化PipeWire库环境。2.应用调用pw_main_loop_new创建pw_main_loop对象。3.pw_main_loop_new内部创建并保存一个pw_loop对象。4.应用调用pw_main_loop_get_loop取得pw_main_loop内部的pw_loop指针。5.应用把该pw_loop传给pw_context_new创建PipeWire Context。6.Context后续基于同一个pw_loop处理连接、Registry、Proxy和Stream事件。7.应用也可以基于该pw_loop注册timer、signal、io、defer等事件源。8.应用调用pw_main_loop_run进入主循环。9.pw_main_loop_run驱动底层pw_loop进行poll和dispatch。10.应用调用pw_main_loop_quit请求主循环退出。11.应用调用pw_main_loop_destroy销毁主循环对象。12.pw_main_loop_destroy完成后pw_main_loop_get_loop返回过的pw_loop指针失效。3.2调用流程图3.3生命周期图4.实战应用案例下面以“创建PipeWire客户端主循环和Context”为例说明pw_main_loop_get_loop在真实开发中的位置。这个案例只保留主链路创建主循环、取得内部pw_loop、创建Context、连接PipeWire服务端、运行主循环。#includepipewire/pipewire.hstructapp_data{structpw_main_loop*main_loop;structpw_context*context;structpw_core*core;};staticvoidinit_pipewire_client(structapp_data*data){structpw_loop*loop;pw_init(NULL,NULL);data-main_looppw_main_loop_new(NULL);if(data-main_loopNULL)return;/* * 此API在主链路作用 * 从pw_main_loop中取得内部pw_loop * 后续Context和事件源都绑定到这个loop。 */looppw_main_loop_get_loop(data-main_loop);if(loopNULL)return;/* * 此API在主链路作用 * 创建PipeWire Context并使用上面取得的pw_loop驱动Context事件。 */data-contextpw_context_new(loop,NULL,0);if(data-contextNULL)return;/* * 此API在主链路作用 * 通过Context连接PipeWire服务端得到Core代理对象。 */data-corepw_context_connect(data-context,NULL,0);if(data-coreNULL)return;/* * 此API在主链路作用 * 进入主循环驱动Core、Registry、Stream等事件回调执行。 */pw_main_loop_run(data-main_loop);}staticvoiddestroy_pipewire_client(structapp_data*data){if(data-core!NULL)pw_core_disconnect(data-core);if(data-context!NULL)pw_context_destroy(data-context);if(data-main_loop!NULL)pw_main_loop_destroy(data-main_loop);pw_deinit();}这个案例中pw_main_loop_get_loop不负责连接PipeWire服务端也不负责运行事件循环。它只是把pw_main_loop内部的pw_loop取出来交给pw_context_new使用。实际开发中最容易出现的问题是把pw_main_loop和pw_loop的所有权搞混。pw_main_loop_get_loop返回的pw_loop不需要手动destroy。它由pw_main_loop管理。应用只需要在最后调用pw_main_loop_destroy内部资源会跟随主循环对象一起释放。另一个常见问题是创建了多个Loop。比如Context使用一个Loop自定义timer使用另一个Loop最后只有一个Loop被run。这样部分事件永远不会被调度。工程上建议简单客户端优先使用同一个pw_main_loop并通过pw_main_loop_get_loop取得同一个pw_loop。如果只是创建普通Stream客户端典型结构通常是data.main_looppw_main_loop_new(NULL);looppw_main_loop_get_loop(data.main_loop);data.contextpw_context_new(loop,NULL,0);data.corepw_context_connect(data.context,NULL,0);data.streampw_stream_new(data.core,playback,props);pw_stream_connect(data.stream,PW_DIRECTION_OUTPUT,PW_ID_ANY,flags,params,n_params);pw_main_loop_run(data.main_loop);在这条链路中pw_main_loop_get_loop处在主循环创建之后、Context创建之前。它是PipeWire客户端从“主循环封装层”进入“底层事件循环层”的连接点。5.一句话总结pw_main_loop_get_loop是PipeWire主循环链路中的取Loop接口它从pw_main_loop中返回内部pw_loop指针用于创建Context和注册事件源但不创建Loop、不运行Loop也不转移Loop所有权。
返回列表