Linux PipeWire深度解析之pw_stream_new调用流程与实战(五)
简介CSDN博客专家、《Android系统多媒体进阶实战》作者博主新书推荐《Android系统多媒体进阶实战》Android Audio工程师专栏地址Audio工程师进阶系列【原创干货持续更新中……】Android多媒体专栏地址多媒体系统工程师系列【原创干货持续更新中……】专题一 二AAOS车载系统AOSP14系统攻城狮入门视频实战课专题三Android14 Binder之HIDL与AIDL通信实战课专题四Android15快速自定义与集成音效实战课专题五Android15音频策略实战课专题六Android15音频性能实战课(无声/杂音/断音/爆音实战案例)人生格言人生从来没有捷径只有行动才是治疗恐惧和懒惰的唯一良药.更多原创,欢迎关注Android系统攻城狮文章目录1. 前言要点概括2. 应用场景与用法函数原型参数说明返回值应用场景3. 调用流程剖析3.1 核心步骤1. 应用层发起请求2. 检查 core 与参数3. 分配 pw_stream 对象4. 绑定 core、name、props5. 初始化 Stream 内部状态6. 等待后续注册 listener7. 等待后续连接 PipeWire 图8. 返回 Stream 句柄3.2 调用流程图3.3 PipeWire Stream 创建生命周期图4. 实战应用案例5. 一句话总结1. 前言本篇目的Linux PipeWire 深度解析之pw_stream_new调用流程与实战。要点概括核心功能创建一个 PipeWire 客户端侧的pw_stream流对象。工作机制应用程序基于已连接的pw_core调用pw_stream_new()分配并初始化struct pw_stream绑定 Stream 名称和属性为后续pw_stream_connect()接入 PipeWire 图做准备。典型用途播放器建流、录音程序建流、音频插件开发、PipeWire 客户端框架封装。2. 应用场景与用法pw_stream_new()是 PipeWire Stream 创建体系中的核心接口。在 PipeWire 中播放器、录音程序、音频处理插件、虚拟音频节点等通常都会通过pw_stream表示一个客户端侧音频流对象。而该接口用于基于pw_core创建一个新的pw_stream对象。函数原型structpw_stream*pw_stream_new(structpw_core*core,constchar*name,structpw_properties*props);参数说明core:已经连接 PipeWire Server 的 pw_core 对象 name:Stream 名称用于标识当前流 props:Stream 属性集合例如 media.type、media.category、media.role 等返回值返回structpw_stream*对象用于后续注册事件监听、连接 PipeWire 图、处理 buffer、销毁 Stream 等操作。应用场景pw_stream_new()常见应用场景主要有三类。第一类是播放器和录音程序建流。播放器在向 PipeWire 输出 PCM 数据之前需要先创建一个pw_stream播放流对象录音程序在从 PipeWire 采集音频之前也需要先创建一个pw_stream录音流对象。pw_stream_new()只负责创建本地 Stream 句柄真正连接到 PipeWire 图通常由后续的pw_stream_connect()完成。第二类是音频客户端框架封装。在自研播放器、录音工具、低延迟音频程序或多媒体框架中通常会把 PipeWire 的初始化流程封装成“创建 core → 创建 stream → 注册 listener → connect → process buffer”这一套固定流程其中pw_stream_new()就是 Stream 生命周期的起点。第三类是音频调试与节点属性分析。开发者可以通过pw_stream_new()创建带有明确属性的 Stream例如设置media.typeAudio、media.categoryPlayback、media.roleMusic后续连接后可以观察 PipeWire 图中生成的节点属性、路由行为、buffer 协商过程和调度状态。3. 调用流程剖析3.1 核心步骤1. 应用层发起请求pw_stream_new(core,demo-stream,props);2. 检查 core 与参数pw_stream_new()需要依赖已经连接成功的structpw_core同时接收 Stream 名称和属性集合。3. 分配 pw_stream 对象内部创建structpw_stream表示一个客户端侧 Stream 对象。4. 绑定 core、name、propsStream 会记录当前所属的pw_core stream name stream properties这些信息会影响后续连接 PipeWire 图时的节点属性。5. 初始化 Stream 内部状态内部会准备 Stream 的状态机、事件 hook、listener、buffer 管理结构和控制信息。此时 Stream 还没有真正接入 PipeWire 图。6. 等待后续注册 listener应用通常会继续调用pw_stream_add_listener(...)注册 state_changed、process、param_changed 等事件回调。7. 等待后续连接 PipeWire 图真正进入 PipeWire 图通常发生在pw_stream_connect(...)之后才会进入格式协商、buffer 分配、节点连接和调度执行阶段。8. 返回 Stream 句柄函数返回structpw_stream*应用后续基于该句柄继续完成播放、录音或音频处理流程。3.2 调用流程图3.3 PipeWire Stream 创建生命周期图4. 实战应用案例#includepipewire/pipewire.h#includestdio.hstructapp_data{structpw_main_loop*loop;structpw_context*context;structpw_core*core;structpw_stream*stream;};staticvoidcreate_stream(structapp_data*data){structpw_properties*props;propspw_properties_new(PW_KEY_MEDIA_TYPE,Audio,PW_KEY_MEDIA_CATEGORY,Playback,PW_KEY_MEDIA_ROLE,Music,NULL);data-streampw_stream_new(data-core,pw_stream_new_demo,props);if(!data-stream){printf(create pw_stream failed\n);return;}printf(create pw_stream success\n);}intmain(intargc,char*argv[]){structapp_datadata{0};pw_init(argc,argv);data.looppw_main_loop_new(NULL);if(!data.loop){printf(create main loop failed\n);return-1;}data.contextpw_context_new(pw_main_loop_get_loop(data.loop),NULL,0);if(!data.context){printf(create context failed\n);return-1;}data.corepw_context_connect(data.context,NULL,0);if(!data.core){printf(connect pipewire core failed\n);return-1;}create_stream(data);/* * 注意 * pw_stream_new() 只创建 Stream 对象。 * * 后续通常还需要 * * 1. pw_stream_add_listener() * 2. pw_stream_connect() * 3. 在 process 回调中处理 buffer */if(data.stream)pw_stream_destroy(data.stream);if(data.core)pw_core_disconnect(data.core);if(data.context)pw_context_destroy(data.context);if(data.loop)pw_main_loop_destroy(data.loop);pw_deinit();return0;}5. 一句话总结pw_stream_new()本质上是“基于 pw_core 创建一个客户端侧 PipeWire Stream 对象”。它负责完成struct pw_stream的分配、属性绑定和内部状态初始化但不会立即完成音频图连接、格式协商和 buffer 流转真正进入 PipeWire 音频图通常要等后续调用pw_stream_connect()。