Linux PipeWire深度解析之pw_stream_get_properties调用流程与实战(四十七)
简介CSDN博客专家、《Android系统多媒体进阶实战》作者博主新书推荐《Android系统多媒体进阶实战》Android Audio工程师专栏地址Audio工程师进阶系列【原创干货持续更新中……】Android多媒体专栏地址多媒体系统工程师系列【原创干货持续更新中……】专题一 二AAOS车载系统AOSP14系统攻城狮入门视频实战课专题三Android14 Binder之HIDL与AIDL通信实战课专题四Android15快速自定义与集成音效实战课专题五Android15音频策略实战课专题六Android15音频性能实战课(无声/杂音/断音/爆音实战案例)人生格言人生从来没有捷径只有行动才是治疗恐惧和懒惰的唯一良药.更多原创,欢迎关注Android系统攻城狮文章目录1. 前言要点概括2. 应用场景与用法函数原型参数说明返回值应用场景3. 调用流程剖析3.1 核心步骤1. 创建 Stream 属性表2. 创建 PipeWire Stream3. Stream 进入连接或运行阶段4. 调用 pw_stream_get_properties5. 返回 Stream 内部属性表6. 读取目标属性键值7. 根据属性执行策略判断8. Stream 销毁后属性指针失效3.2 调用流程图3.3 生命周期图4. 实战应用案例5. 一句话总结1. 前言本篇目的Linux PipeWire 深度解析之pw_stream_get_properties调用流程与实战。要点概括核心功能获取pw_stream对象当前保存的属性表用于读取 Stream 的媒体类型、媒体角色、节点名称、应用信息等属性。工作机制pw_stream_get_properties()从 Stream 内部直接返回struct pw_properties指针调用者再通过pw_properties_get()读取具体键值。典型用途Stream 创建后属性确认、回调中读取媒体信息、调试音频流分类、根据media.role或media.category执行业务策略。2. 应用场景与用法pw_stream_get_properties()是 PipeWire Stream 属性查询中的基础接口。应用创建 Stream 时通常会通过pw_properties_new()设置一组属性pw_properties_new(PW_KEY_MEDIA_TYPE,Audio,PW_KEY_MEDIA_CATEGORY,Playback,PW_KEY_MEDIA_ROLE,Music,NULL);这些属性会跟随 Stream 一起保存用于描述该流的媒体类型、媒体类别、业务角色、节点名称和应用信息。当程序需要读取这些属性时可以调用propspw_stream_get_properties(stream);而该接口用于获取当前pw_stream内部保存的属性表指针使调用者可以读取 Stream 的属性键值。需要注意pw_stream_get_properties()只负责返回 Stream 内部属性表不会复制属性对象也不会向 PipeWire Server 查询远程属性。函数原型conststructpw_properties*pw_stream_get_properties(structpw_stream*stream);参数说明stream:由pw_stream_new()或pw_stream_new_simple()创建的 Stream 对象返回值查询成功:返回 Stream 当前保存的 properties 指针 查询失败:返回NULL返回值类型为conststructpw_properties*表示调用者应当只读访问该属性表。调用者可以通过pw_properties_get(props,key);读取具体属性值。应用场景pw_stream_get_properties()常见应用场景主要有三类。第一类是 Stream 创建后的属性确认。应用创建播放流或录音流时通常会设置media.type、media.category、media.role、node.name等属性。创建完成后可以通过pw_stream_get_properties()读取属性表确认当前 Stream 的媒体描述是否符合预期。第二类是回调中的业务判断。在 Stream 状态变化、参数变化或处理流程中业务模块可以读取 Stream 属性根据media.role判断当前流是音乐、通话、通知还是导航语音再决定是否进入对应的音频策略分支。第三类是调试与问题定位。音频流路由错误、Stream 分类异常、策略未生效时可以通过该接口读取 Stream 属性确认应用传入的属性是否正确避免把路由问题误判为 PipeWire Server 或 WirePlumber 策略问题。3. 调用流程剖析3.1 核心步骤1. 创建 Stream 属性表应用首先创建 Stream 属性表propspw_properties_new(PW_KEY_MEDIA_TYPE,Audio,PW_KEY_MEDIA_CATEGORY,Playback,PW_KEY_MEDIA_ROLE,Music,PW_KEY_NODE_NAME,demo.playback,NULL);该属性表用于描述 Stream 的媒体属性和业务身份。常见属性包括media.type: 媒体类型例如 Audio media.category: 媒体类别例如 Playback 或 Capture media.role: 媒体角色例如 Music、Communication、Notification node.name: PipeWire 图中的节点名称2. 创建 PipeWire Stream应用通过属性表创建 Streamstreampw_stream_new_simple(pw_main_loop_get_loop(main_loop),demo-stream,props,stream_events,data);创建过程中属性表会与pw_stream对象绑定。从业务视角看关系可以表示为pw_stream └── properties ├── media.type ├── media.category ├── media.role └── node.name3. Stream 进入连接或运行阶段应用可以继续调用pw_stream_connect(stream,PW_DIRECTION_OUTPUT,PW_ID_ANY,flags,params,n_params);此时 Stream 会进入连接流程并逐步参与 PipeWire 图中的节点创建、端口协商和参数协商。pw_stream_get_properties()本身不依赖 Stream 必须处于运行状态只要 Stream 对象有效就可以读取其属性。4. 调用 pw_stream_get_properties应用或回调中执行propspw_stream_get_properties(stream);该调用直接进入 PipeWire Stream API。这是一个本地同步查询不需要等待 Main Loop也不会向 PipeWire Server 发送新的请求。5. 返回 Stream 内部属性表pw_stream_get_properties()返回 Stream 当前保存的属性表指针。逻辑上可以理解为returnstream-properties;这里返回的是内部对象指针不是属性表副本。因此调用者不应该修改或释放该返回值。6. 读取目标属性键值调用者拿到属性表后通过pw_properties_get()读取具体键值media_typepw_properties_get(props,PW_KEY_MEDIA_TYPE);media_rolepw_properties_get(props,PW_KEY_MEDIA_ROLE);如果目标键不存在则pw_properties_get()返回NULL。7. 根据属性执行策略判断读取属性后业务模块可以根据不同字段进入不同处理逻辑if(media_rolespa_streq(media_role,Music)){/* * 音乐流策略 */}例如Music: 普通音乐播放 Communication: 语音通话 Notification: 系统提示音 Movie: 视频播放这些属性通常会影响后续路由策略、音量策略、优先级策略和调试判断。8. Stream 销毁后属性指针失效当 Stream 被销毁后pw_stream_destroy(stream);之前通过pw_stream_get_properties()获取的属性指针也随之失效。应用不能在 Stream 销毁后继续访问该指针。3.2 调用流程图3.3 生命周期图4. 实战应用案例#includepipewire/pipewire.h// PipeWire核心API#includestdio.h#includestdlib.h#includestring.hstructapp_data{structpw_main_loop*main_loop;structpw_stream*stream;constchar*media_type;constchar*media_category;constchar*media_role;constchar*node_name;};staticvoidread_stream_properties(structapp_data*data){conststructpw_properties*props;propspw_stream_get_properties(data-stream);if(!props){return;}data-media_typepw_properties_get(props,PW_KEY_MEDIA_TYPE);data-media_categorypw_properties_get(props,PW_KEY_MEDIA_CATEGORY);data-media_rolepw_properties_get(props,PW_KEY_MEDIA_ROLE);data-node_namepw_properties_get(props,PW_KEY_NODE_NAME);}staticvoidstream_state_changed_cb(void*userdata,enumpw_stream_stateold_state,enumpw_stream_statestate,constchar*error){structapp_data*datauserdata;read_stream_properties(data);if(statePW_STREAM_STATE_ERROR){pw_main_loop_quit(data-main_loop);}}staticconststructpw_stream_eventsstream_events{PW_VERSION_STREAM_EVENTS,.state_changedstream_state_changed_cb,};intmain(intargc,char*argv[]){structapp_datadata{0};structpw_properties*props;intresultEXIT_FAILURE;pw_init(argc,argv);data.main_looppw_main_loop_new(NULL);if(!data.main_loop){pw_deinit();returnEXIT_FAILURE;}propspw_properties_new(PW_KEY_MEDIA_TYPE,Audio,PW_KEY_MEDIA_CATEGORY,Playback,PW_KEY_MEDIA_ROLE,Music,PW_KEY_NODE_NAME,demo.playback.stream,NULL);data.streampw_stream_new_simple(pw_main_loop_get_loop(data.main_loop),demo-playback-stream,props,stream_events,data);if(!data.stream){pw_main_loop_destroy(data.main_loop);pw_deinit();returnEXIT_FAILURE;}read_stream_properties(data);if(data.media_typestrcmp(data.media_type,Audio)0){resultEXIT_SUCCESS;}pw_stream_destroy(data.stream);pw_main_loop_destroy(data.main_loop);pw_deinit();returnresult;}5. 一句话总结pw_stream_get_properties()本质上是“返回 PipeWire Stream 内部保存的属性表指针使调用者可以读取该流的媒体描述和业务属性”。它负责获取 Stream 当前属性但不负责创建属性对象、复制属性表、更新远程节点属性或管理属性生命周期是 PipeWire Stream 创建、调试、策略判断和音频流分类中的基础接口。

相关新闻

格雷码原理、转换算法与工程应用全解析

格雷码原理、转换算法与工程应用全解析

1. 格雷码:从理论到实践的深度解析 如果你接触过数字电路、旋转编码器,或者研究过某些特定的算法问题,那么“格雷码”这个词对你来说一定不陌生。它不像二进制码那样广为人知,但在许多特定的工程和计算场景下,格雷码却…

2026/10/3 7:47:30 阅读更多 →
数据中心隐藏的攻击面:OT安全防护刻不容缓

数据中心隐藏的攻击面:OT安全防护刻不容缓

数据中心的韧性正日益受到关注,而安全则是其中的核心议题。由于经济增长和安全运营对数据中心的依赖程度不断提升,这些设施越来越被视为关键基础设施。然而,相关讨论往往止步于外部边界。在围栏之内,另一类尚未得到充分审视的风险…

2026/10/13 15:08:51 阅读更多 →
平面透镜天线设计(含HFSS模型和自动建模程序)

平面透镜天线设计(含HFSS模型和自动建模程序)

简介 平面透镜天线是一种将传统曲面透镜“压扁”的平板天线。它利用平面结构上无数个微小的单元,模拟透镜对电磁波的相位调整功能。其核心任务是:将馈源发出的球面波,在校正后变成定向辐射的平面波,从而实现高增益。 平面透镜天线…

2026/10/13 9:24:31 阅读更多 →

最新新闻

Django+LLM+遗传算法:打造AI驱动的旅游路线规划与推荐系统

Django+LLM+遗传算法:打造AI驱动的旅游路线规划与推荐系统

每年毕业设计的选题库里,“旅游网站”几乎是大热门,但说实话,十个里面至少有八个做成了标准的增删改查演示——用户注册登录、景点列表、后台维护,顶多再加一个关键字搜索。答辩的时候老师问一句“技术亮点在哪里”,很…

2026/10/13 23:01:16 阅读更多 →
PyBullet物理仿真入门:刚体模型创建、URDF加载与多体组装实战指南

PyBullet物理仿真入门:刚体模型创建、URDF加载与多体组装实战指南

1. 从零理解 pybullet 的模型体系pybullet 这个物理仿真库,刚上手的人最容易卡在“怎么把东西放进场景里”这一步。官方文档给了一堆 API,但真正落到项目里,你会发现创建模型这件事远比想象中要讲究。我最初接触 pybullet 的时候,…

2026/10/13 23:01:16 阅读更多 →
BERT预训练模型句向量与词向量提取:从[CLS]到池化的避坑指南

BERT预训练模型句向量与词向量提取:从[CLS]到池化的避坑指南

简介:面向自然语言处理初学者与开发者,这份压缩包提供一套基于BERT预训练模型生成句向量与词向量的轻量实践脚本,解决从模型加载到向量抽取的关键流程。BERT采用Transformer双向编码结构,能充分捕捉词语的上下文语义,这…

2026/10/13 23:01:16 阅读更多 →
Qt编译MySQL驱动完整指南:解决QMYSQL driver not loaded

Qt编译MySQL驱动完整指南:解决QMYSQL driver not loaded

如果你在 Qt 里写过QSqlDatabase::addDatabase("QMYSQL"),大概率见过这行让人头疼的输出:QSqlDatabase: QMYSQL driver not loaded。即便把官方 SDK 完整装了一遍,插件目录里也只有 qsqlite、qsqlodbc 那几个 dll,唯独没…

2026/10/13 23:01:16 阅读更多 →
AnyPS5项目解析:PS5手柄协议与Linux HID驱动适配

AnyPS5项目解析:PS5手柄协议与Linux HID驱动适配

我无法基于当前输入内容生成符合要求的博文。原因如下:输入中仅提供了项目标题"AnyPS5",但未提供任何实质性的【项目正文】、【关键词】或【摘要描述】;所谓“相关热搜词”和“最新网络热词”字段为空,无实际文本&#…

2026/10/13 23:01:15 阅读更多 →
Oracle 实战速查:表空间、索引与 PL/SQL 避坑指南

Oracle 实战速查:表空间、索引与 PL/SQL 避坑指南

简介:这份PDF面向Oracle数据库初学者与需要系统梳理基础知识的开发、运维人员,围绕表管理、SQL查询、事务、索引、权限角色、表空间与数据字典、PL/SQL编程等核心主题展开,帮助读者从建库建表到编写过程、函数、触发器逐步建立完整知识框架。…

2026/10/13 23:00:15 阅读更多 →

日新闻

物联网系统集成避坑指南:从选型到验收的关键要点

物联网系统集成避坑指南:从选型到验收的关键要点

做了这么多年物联网系统集成的项目,我最大的感受是,大部分坑不是出在技术前沿,而是出在一些看起来很平常的地方。设备选了便宜的、协议没问清楚、现场没摸透、验收标准写得含糊——这些细枝末节,最后都会变成延期、超支和扯皮的大…

2026/10/13 0:00:57 阅读更多 →
ESP32舵机控制全攻略:从PWM原理到高级玩法与常见故障排查

ESP32舵机控制全攻略:从PWM原理到高级玩法与常见故障排查

如果你玩ESP32有一阵子了,很难不碰到舵机控制这道坎。做智能小车要转方向,做机械臂要抬关节,做云台要偏航俯仰,背后都是同一个东西在干活:舵机。而我见过太多人卡在“代码能编译、舵机就是不听话”这个阶段&#xff0c…

2026/10/13 0:00:57 阅读更多 →
CAN总线原理与STM32实战:抗干扰、仲裁、错误处理全解析

CAN总线原理与STM32实战:抗干扰、仲裁、错误处理全解析

1. 为什么CAN总线至今仍是工业现场的“硬通货”?——从汽车底盘到智能温室的真实需求你有没有拆过一辆老款燃油车的中控台?或者调试过某高校实验室里那台跑着Modbus协议却频频丢帧的PLC控制柜?又或者,在某个农业物联网项目里&…

2026/10/13 0:00:57 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/13 2:54:56 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/13 16:22:04 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/13 1:58:08 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/13 22:01:27 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/13 14:57:39 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/12 18:11:17 阅读更多 →