当前位置: 首页 > news >正文

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

简介: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_properties_new_dict调用流程与实战。

要点概括

  • 核心功能:根据已有spa_dict创建一个新的pw_properties对象,用于承载PipeWire对象属性。

  • 工作机制:读取spa_dict中的key/value条目,复制为pw_properties内部可管理的属性集合,并返回新的properties对象。

  • 典型用途:把已有SPA字典转换成PipeWire属性对象,再传给Context、Stream、Filter、Node、Proxy等创建接口。

pw_properties_new_dict的本质是“属性对象构造函数”。它不负责连接PipeWireCore,不负责创建Stream,不负责解析完整配置文件,也不负责改变已有对象状态。它只做一件事:把一个spa_dict形式的只读键值集合,转换成PipeWire可拥有、可传递、可释放的pw_properties对象。

它和pw_properties_new的区别在于:pw_properties_new适合直接用变参方式手写少量key/value;pw_properties_new_dict适合已经有spa_dict的场景,尤其是在SPA、模块、回调、对象信息复制等链路中更自然。

它和pw_properties_update的区别在于:pw_properties_new_dict创建新对象,pw_properties_update更新已有对象。前者解决“从dict生成properties”,后者解决“把dict合并到已有properties”。

它和pw_properties_new_string也不同。pw_properties_new_string面向字符串解析,适合配置文本;pw_properties_new_dict面向结构化字典,适合C代码内部已有的spa_dict数据。

🌻2.应用场景与用法

pw_properties_new_dict

是PipeWire通用Properties API中用于从spa_dict创建pw_properties对象的接口。

它位于PipeWire对象创建链路的前置位置。PipeWire中大量对象都需要属性描述,例如应用名、媒体类型、媒体角色、节点名称、流名称、对象序列、设备属性、模块属性等。这些属性通常以key/value形式存在。pw_properties_new_dict把已有spa_dict转换成pw_properties之后,就可以继续传入PipeWire对象创建接口。

pw_properties_new_dict用于根据已有spa_dict构造新的pw_properties对象。

函数原型

structpw_properties*pw_properties_new_dict(conststructspa_dict*dict);

参数说明

conststructspa_dict*dict;

dict表示输入字典。

它通常由若干个spa_dict_item组成,每个item包含一个key和一个value。key/value都以字符串形式表达。该函数只读取dict内容,不修改输入dict本身。

典型spa_dict结构如下:

structspa_dict_item{constchar*key;constchar*value;};structspa_dict{uint32_tflags;uint32_tn_items;conststructspa_dict_item*items;};

工程上要注意三点。

第一,dict只是初始化来源,不是输出对象本身。

第二,dict中的key/value应保持有效字符串语义,不要依赖NULLvalue表达复杂逻辑。

第三,dict中不要设计重复key。pw_properties是属性集合,不适合表达同名多值语义。

返回值

成功时返回:

structpw_properties*

表示新创建的pw_properties对象。

返回NULL表示创建失败,常见原因是内存分配失败。调用者必须检查返回值,不能直接把NULL传给后续对象创建接口。

返回的pw_properties拥有自己的生命周期。未交给其他PipeWire对象接管时,调用者需要使用pw_properties_free释放。若传入某些PipeWire创建接口,并且该接口声明会接管properties所有权,则调用者不应再次释放。

应用场景

第一类场景是从静态属性表创建Stream属性。

例如播放器、录音器、测试音源、虚拟音频节点等应用,通常先准备一组media.type、media.category、media.role、application.name等属性,再创建PipeWireStream。

第二类场景是从已有对象属性复制一份可修改属性。

PipeWire对象信息中经常携带spa_dict形式的属性。如果业务需要基于已有属性派生新对象,可以先用pw_properties_new_dict复制,再通过pw_properties_set增加或覆盖部分字段。

第三类场景是模块加载和对象创建。

PipeWire模块、会话管理器、设备监控器、Filter、Node、Port、Metadata等对象创建时,通常都需要一组属性描述。pw_properties_new_dict可以把已有字典快速转换成创建接口可接收的properties对象。

第四类场景是测试代码和最小化示例。

当测试代码已经用spa_dict_item数组描述属性时,pw_properties_new_dict比变参形式更清晰,也更适合复用和封装。

🌻3.调用流程剖析

🌻3.1核心步骤

1.调用者准备spa_dict_item数组,每个条目包含一个key和一个value。

2.调用者用spa_dict封装items和n_items,形成输入字典。

3.调用pw_properties_new_dict并传入dict。

4.函数内部创建新的pw_properties对象。

5.函数读取dict中的每个spa_dict_item。

6.函数把key/value复制到pw_properties内部属性集合。

7.如果dict为空或没有条目,则返回一个空properties对象。

8.如果内存分配失败,则返回NULL。

9.调用者根据返回值判断是否创建成功。

10.调用者可以继续通过pw_properties_set修改属性。

11.调用者把properties传给Context、Stream、Filter、Node等对象创建接口。

12.如果properties没有被后续API接管,调用者负责释放。

🌻3.2调用流程图

🌻3.3生命周期图

🌻4.实战应用案例

下面以“从spa_dict创建Stream属性”为例,说明pw_properties_new_dict的典型用法。

这个场景常见于音频播放、音频采集、虚拟节点、测试音源、媒体桥接等PipeWire客户端代码中。应用先把属性写成spa_dict_item数组,然后调用pw_properties_new_dict生成pw_properties,最后交给pw_stream_new或pw_stream_new_simple创建Stream。

#include<pipewire/pipewire.h>structapp_data{structpw_core*core;structpw_stream*stream;};staticintcreate_audio_stream(structapp_data*data){staticconststructspa_dict_itemitems[]={{PW_KEY_MEDIA_TYPE,"Audio"},{PW_KEY_MEDIA_CATEGORY,"Playback"},{PW_KEY_MEDIA_ROLE,"Music"},{PW_KEY_APP_NAME,"pipewire-properties-demo"},{PW_KEY_NODE_NAME,"demo.playback.stream"},{PW_KEY_NODE_DESCRIPTION,"Demo Playback Stream"},};staticconststructspa_dictdict={.flags=0,.n_items=SPA_N_ELEMENTS(items),.items=items,};structpw_properties*props;props=pw_properties_new_dict(&dict);if(props==NULL)return-ENOMEM;pw_properties_set(props,PW_KEY_STREAM_IS_LIVE,"true");data->stream=pw_stream_new(data->core,"demo-playback",props);if(data->stream==NULL)return-EIO;return0;}

这段代码的关键点不在Stream创建,而在properties构造方式。

items是静态属性表,适合表达一组固定的对象属性。dict只是对items的轻量封装。pw_properties_new_dict根据dict创建新的pw_properties对象。创建完成后,应用仍然可以调用pw_properties_set继续补充属性。

需要特别注意所有权问题。

在上面的场景中,props传给pw_stream_new之后,Stream创建接口会接管props所有权。调用者不应再对同一个props调用pw_properties_free,否则容易造成重复释放。

如果只是临时创建properties,并没有传给接管所有权的PipeWireAPI,就应由调用者释放:

staticintbuild_temp_properties(void){staticconststructspa_dict_itemitems[]={{"object.name","temporary-object"},{"object.serial","1001"},};staticconststructspa_dictdict={.flags=0,.n_items=SPA_N_ELEMENTS(items),.items=items,};structpw_properties*props;props=pw_properties_new_dict(&dict);if(props==NULL)return-ENOMEM;pw_properties_set(props,"object.description","Temporary Properties");/* * 这里可以读取、检查、修改或传递props。 * 如果没有把props交给会接管所有权的API,必须主动释放。 */pw_properties_free(props);return0;}

还可以用它从已有对象属性派生新属性:

staticstructpw_properties*clone_and_extend_properties(conststructspa_dict*src){structpw_properties*props;props=pw_properties_new_dict(src);if(props==NULL)returnNULL;pw_properties_set(props,"application.name","derived-client");pw_properties_set(props,"node.description","Derived PipeWire Node");returnprops;}

这个写法在对象代理、模块封装、调试工具和会话管理逻辑中很常见。它的优势是:原始spa_dict保持只读,新对象拥有独立pw_properties,后续修改不会反向污染原始属性来源。

工程实践中,pw_properties_new_dict最容易踩的坑主要有三个。

第一,把dict误认为properties。spa_dict只是轻量字典视图,pw_properties才是PipeWire可管理的属性对象。

第二,忽略返回值。该函数可能返回NULL,后续直接传入对象创建接口会放大错误。

第三,混淆所有权。props一旦交给会接管所有权的API,调用者就不应再释放;props如果没有被接管,调用者就必须释放。

🌻5.一句话总结

pw_properties_new_dict是PipeWire中把已有spa_dict转换成新pw_properties对象的属性构造接口,核心价值是完成结构化key/value属性复制,并为Context、Stream、Filter、Node等对象创建链路提供可拥有、可传递、可释放的properties对象。

http://www.jsqmd.com/news/1380201/

相关文章:

  • 神州数码交换机配置实战:从VLAN划分到安全策略全解析
  • Linux 终端命令速查表 -- 07 文件与文件夹速查表
  • LangGraph核心三要素与智能体构建实战:从状态管理到复杂工作流编排
  • 《专利法》规定,专利申请必须提交至国家知识产权局(CNIPA),由其依法进行形式审查和实质审查
  • BilibiliDown终极指南:如何轻松下载B站视频与高质量音频
  • 实点科技5系列一体式I/O EI5R模块介绍
  • 上证3966点,三拨人的三种活法
  • 无人机IC认证怎么选:沃德检测一站式路径解析 - 生活动态圈
  • 【面试】【数字IC基础】跨时钟域处理一(CDC,Clock Domain Crossing)(一)
  • GetQzonehistory:5分钟快速备份你的QQ空间完整历史记录
  • 【2014-04-27】使用SQLMAP注入DVWA
  • 视频字幕翻译成中文怎么做?10个常用工具的功能、价格与适用人群
  • 电动车托运要拆电池吗?2026跨省寄电瓶车避坑全攻略,5家物流实测对比 - 快递物流资讯
  • 微信小程序云函数调用第三方API:绕过域名限制与安全实践指南
  • Linux PipeWire深度解析之pw_properties_copy调用流程与实战(五十八)
  • NS-Scope上位机软件:解锁泰克TDS1000/2000示波器数据采集与自动化潜能
  • C++项目工程化实战:gflags配置管理与gtest单元测试框架详解
  • 英文essay交之前用哪种检测自查AI率
  • LeetCode双指针技巧:原地删除有序数组重复项
  • linux系统中项目工程中的多文件管理(makfile)
  • Wi-Fi信道与频宽详解:从5GHz到6GHz,优化网络速度与稳定性的核心指南
  • oracle系统表
  • VC++ MFC文件对话框自定义预览功能实现与优化指南
  • JeecgBoot项目迁移宝兰德BES:WAR包部署与国产化适配实战
  • Harepacker复活版:你的MapleStory游戏编辑神器,3步打造专属游戏世界
  • ProperTree:你的跨平台Plist编辑器终极解决方案,轻松管理Hackintosh配置
  • 2026互联网人才求职APP大盘点:靠谱平台选型攻略、避坑指南及优质服务商甄选详解 - 商业大观
  • GEPA方法论:从玄学到工程化,系统优化AI应用Prompt与Skill
  • 2026年学术论文降AI率工具评测与实战指南
  • 2026 年全屋整装甄选指南,成都本土整装企业实力对比 - 市场沸点