Linux 平台 PulseAudio 音频播放数据通路 II

PulseAudio 音频服务中,大部分音频数据缓冲区都用 pa_memblock 结构来管理,包括音频数据在 PulseAudio 音频服务和它的客户端之间的跨进程传递,PulseAudio 音频服务的数据通路中各个节点之间的音频数据传递,及 PulseAudio 音频服务和 ALSA 音频设备之间的音频数据交换。pa_memblock 结构定义 (位于 pulseaudio/src/pulsecore/memblock.c) 如下:

struct pa_memblock {PA_REFCNT_DECLARE; /* the reference counter */pa_mempool *pool;pa_memblock_type_t type;bool read_only:1;bool is_silence:1;pa_atomic_ptr_t data;size_t length;pa_atomic_t n_acquired;pa_atomic_t please_signal;union {struct {/* If type == PA_MEMBLOCK_USER this points to a function for freeing this memory block */pa_free_cb_t free_cb;/* If type == PA_MEMBLOCK_USER this is passed as free_cb argument */void *free_cb_data;} user;struct {uint32_t id;pa_memimport_segment *segment;} imported;} per_type;
};

pa_memblock 结构中,实际保存音频数据的内存缓冲区的地址保存在 data 原子指针字段中,音频数据内存缓冲区的长度保存在 length 字段中。

不同场合下使用的音频数据缓冲区具有不同的特性,音频数据缓冲区因特性不同有多种不同的类型,pa_memblock 结构即有多种不同的类型,类型由 pa_memblock 结构的 type 字段描述。类型主要有如下这些:

typedef enum pa_memblock_type {PA_MEMBLOCK_POOL,             /* Memory is part of the memory pool */PA_MEMBLOCK_POOL_EXTERNAL,    /* Data memory is part of the memory pool but the pa_memblock structure itself is not */PA_MEMBLOCK_APPENDED,         /* The data is appended to the memory block */PA_MEMBLOCK_USER,             /* User supplied memory, to be freed with free_cb */PA_MEMBLOCK_FIXED,            /* Data is a pointer to fixed memory that needs not to be freed */PA_MEMBLOCK_IMPORTED,         /* Memory is imported from another process via shm */PA_MEMBLOCK_TYPE_MAX
} pa_memblock_type_t;

各个 pa_memblock 类型特性如下:

  • PA_MEMBLOCK_POOLpa_memblock 结构本身和它所管理的音频数据内存缓冲区都在 内存池 中分配;
  • PA_MEMBLOCK_POOL_EXTERNALpa_memblock 结构本身在堆上分配,它所管理的音频数据内存缓冲区在 内存池 中分配;
  • PA_MEMBLOCK_APPENDEDpa_memblock 结构本身和它所管理的音频数据内存缓冲区都在堆上分配;
  • PA_MEMBLOCK_USERpa_memblock 结构本身在堆上分配,它所管理的音频数据内存缓冲区由使用方传入,音频数据内存缓冲区的释放方法也由使用方传入;
  • PA_MEMBLOCK_FIXEDpa_memblock 结构本身在堆上分配,它所管理的音频数据内存缓冲区由使用方传入,但这块音频数据内存缓冲区不需要释放,如 PulseAudio 音频服务和 ALSA 音频设备交换音频数据时,通过 mmap 获得的内核音频数据缓冲区;
  • PA_MEMBLOCK_IMPORTEDpa_memblock 结构本身在堆上分配,它所管理的音频数据内存缓冲区来自于通过共享内存获得的其它进程。

内存池 是 PulseAudio 音频服务中使用的基本的音频数据内存管理机制,它的基本思路是,预先分配一块巨大的内存,将这一大块内存分割为大小相等的小内存块,每次需要音频数据缓冲区时,则取一个小内存块来用。音频数据的传递和处理中,所需的音频数据缓冲区大小并不会经常剧烈变化,因而将内存池的内存划分为大小相等的小内存块对于兼顾音频数据缓冲区的分配/释放效率和内存利用率是值得的。

PulseAudio 音频服务中 内存池pa_mempool 结构描述,这个结构定义 (位于 pulseaudio/src/pulsecore/memblock.c) 如下:

struct pa_mempool {/* Reference count the mempool** Any block allocation from the pool itself, or even just imported from* another process through SHM and attached to it (PA_MEMBLOCK_IMPORTED),* shall increase the refcount.** This is done for per-client mempools: global references to blocks in* the pool, or just to attached ones, can still be lingering around when* the client connection dies and all per-client objects are to be freed.* That is, current PulseAudio design does not guarantee that the client* mempool blocks are referenced only by client-specific objects.** For further details, please check:* https://lists.freedesktop.org/archives/pulseaudio-discuss/2016-February/025587.html*/PA_REFCNT_DECLARE;pa_semaphore *semaphore;pa_mutex *mutex;pa_shm memory;bool global;size_t block_size;unsigned n_blocks;bool is_remote_writable;pa_atomic_t n_init;PA_LLIST_HEAD(pa_memimport, imports);PA_LLIST_HEAD(pa_memexport, exports);/* A list of free slots that may be reused */pa_flist *free_slots;pa_mempool_stat stat;
};

内存池 的大内存块由 pa_shm 结构描述,这个结构定义 (位于 pulseaudio/src/pulsecore/shm.h) 如下:

typedef struct pa_shm {pa_mem_type_t type;unsigned id;void *ptr;size_t size;/* Only for type = PA_MEM_TYPE_SHARED_POSIX */bool do_unlink:1;/* Only for type = PA_MEM_TYPE_SHARED_MEMFD** To avoid fd leaks, we keep this fd open only until we pass it* to the other PA endpoint over unix domain socket.** When we don't have ownership for the memfd fd in question (e.g.* pa_shm_attach()), or the file descriptor has now been closed,* this is set to -1.** For the special case of a global mempool, we keep this fd* always open. Check comments on top of pa_mempool_new() for* rationale. */int fd;
} pa_shm;

根据大内存块的创建方式,大内存块分为 3 种类型,如:

typedef enum pa_mem_type {PA_MEM_TYPE_SHARED_POSIX,         /* Data is shared and created using POSIX shm_open() */PA_MEM_TYPE_SHARED_MEMFD,         /* Data is shared and created using Linux memfd_create() */PA_MEM_TYPE_PRIVATE,              /* Data is private and created using classic memory allocation(posi

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/1557667.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

智能电子价签:助力零售效率升级的关键

在竞争日益激烈的零售市场,如何优化运营、提升效率,是每个零售商都在关注的问题。电子价签作为一项创新技术,提供了蒿效的解决方案。今天,我们就来聊聊电子价签如何帮助零售商轻松管理信息、减少人工误差,并展示它在门…

Electron构建桌面应用程序,服务于项目的自主学习记录(持续更新...

无所畏惧地面对未知,并将其视为成长的机会 大纲官网快速入门1.安装node.js -- 这里推荐用nvm管理2.脚手架创建3.electron 包安装到应用的开发依赖4.创建主进程(main.js)并启动项目1.创建页面2.配置main.js3.启动项目 -- 效果 进阶 -- 基于项目场景功能使用场景一&am…

自动猫砂盆有必要买吗?2024年热门风大的自动猫砂盆测评分享!

自动猫砂盆不知道大家尝试过没,就是可以自动给猫咪铲屎的神器东西,而且它能把那些猫屎都集中收集起来,我们这种上班忙碌的人一回家就能收获一个干干净净的猫砂盆,别提有多快乐了。就算出差都不怕,三四天不回来都只用扔…

红黑树源代码(进阶与细节解释)

目录 对于结点的修改 红黑树模板参数的控制 红黑树结点当中存储的数据 对于insert函数的细节修改 迭代器的代码 迭代器类的添加 迭代器的 迭代器的-- 正向迭代器的代码 红黑树代码全部展示: 看完前两篇的文章,相信对于红黑树有了一定的了解&…

飘香水果购物网站:基于SpringBoot的架构设计

2相关技术 2.1 MYSQL数据库 MySQL是一个真正的多用户、多线程SQL数据库服务器。 是基于SQL的客户/服务器模式的关系数据库管理系统,它的有点有有功能强大、使用简单、管理方便、安全可靠性高、运行速度快、多线程、跨平台性、完全网络化、稳定性等,非常适…

【C++】模拟实现hash_table(哈希表)

🦄个人主页:修修修也 🎏所属专栏:实战项目集 ⚙️操作环境:Visual Studio 2022 目录 一.了解项目功能 二.逐步实现项目功能模块及其逻辑详解 📌实现HashNode类模板 🎏构造HashNode类成员变量 🎏实现HashNode类构造函数…

家里养有宠物应该用哪款宠物空气净化器比较好?哪款最能吸毛?

这不是国庆节刚过吗,我的小猫终于是平安的度过了在农村生活的时光,之前还担心会不会被爸妈嫌弃,这下好了,嫌弃也过了国庆节。 但是一把猫咪带回出租房,由于几天不在房子里待,猫咪对熟悉的环境又特别激动&a…

视频怎么做成扫码展示?视频二维码在线做的方法

视频想要快速的分享给其他人,选择生成二维码是一种很方便的形式,其他人只需要扫描二维码就可以在线查看视频,与其他分享方式相比更加的简单、方便。现在日常生活中有很多场景都会有视频二维码的应用,简化了获取视频的流程&#xf…

JavaEE: 深入解析HTTP协议的奥秘(3)

文章目录 HTTP认识 "报头"(Header)认识 "状态码"(status code) HTTP JavaEE: 深入解析HTTP协议的奥秘(2) 书接上文~ 认识 “报头”(Header) Header 的整体的格式是"键值对"结构. 每个键值对占一行,键和值之间使用分号分隔. Host 表示服务器主…

【基础篇】一个键值数据库包含什么?

背景 今天,在构造这个简单的键值数据库时,我们只需要关注整体架构和核心模块。这就相当于医学上在正式解剖人体之前,会先解剖一只小白鼠。我们通过剖析这个最简单的键值数据库,来迅速抓住学习和调优 Redis 的关键。 我们把这个简…

STM32外设应用知识详解

✅作者简介:2022年博客新星 第八。热爱国学的Java后端开发者,修心和技术同步精进。 🍎个人主页:Java Fans的博客 🍊个人信条:不迁怒,不贰过。小知识,大智慧。 💞当前专栏…

RKMEDIA画面质量调节-QP调节

QP是在视频采集编码过程中的量化参数,其值与画面质量成反比,即QP值越大画面质量越小,其具体调整方法如下: typedef struct rkVENC_RC_PARAM_S {RK_U32 u32ThrdI[RC_TEXTURE_THR_SIZE]; // [0, 255]RK_U32 u32ThrdP[RC_TEXTURE_TH…

如何基于 RLHF 来优化 ChatGPT 类型的大语言模型

🚴前言 对于ChatGPT来说,RLHF是其训练的核心。所谓RLHF,即Reinforcement Learning with Human Feedback,基于人类反馈的强化学习。这项技术通过结合模型自身的生成能力和人类专家的反馈,为改进文本生成质量提供了新的…

解决Android Studio中使用lombok插件错误: 找不到符号的问题

问题 主要是想节省实体类的set、get等方法,使用lombok报错如下: 解决方案 由于Android的限制,在Android中使用lombok兼容极其麻烦,如果你只是想减少set、get等代码可以直接使用kotlin的data class 示例 data class KotlinTes…

等级保护等保资料原件合集(word源资料)

第二章 系统定级与安全域 2.1 系统定级 2.1.1 不同等级的安全保护能力 2.1.2 重要信息系统 2.1.3 定级参考 2.2 安全域定义 2.2.1 安全域定义方法 2.2.2 安全域等级描述 第三章 实施方案设计 3.1 三级等保要求 3.2 基本要求的详细技术要求 3.2.1 物理安全 3.2.2 网…

Unity 从零开始的框架搭建1-1 unity中对象调用的三种方式的优缺点分析【干货】

该文章专栏是向QFrameWork作者凉鞋老师学习总结得来,吃水不忘打井人,不胜感激 Unity 框架搭建学习笔记1-1,前一个1代表凉鞋的第一季教程,后一个1代表该季第一篇我的文章 unity中对象调用的三种方式 方法调用,例如&…

Qt设计登录界面

优化登录框: 将两个按钮连接到槽函数 在构造函数中定义 connect(this->btn1,&QPushButton::clicked,this,&Logon::my_slot);connect(this->btn2,&QPushButton::clicked,this,&Logon::my_cancel); 定义登录按钮连接的槽函数 void Logon::my…

基于Java语言的充电桩平台+云快充协议+充电桩管理后台+充电桩小程序

软件架构 1、提供云快充底层桩直连协议,版本为云快充1.5,对于没有对接过充电桩系统的开发者尤为合适; 2、包含:启动充电、结束充电、充电中实时数据获取、报文解析、Netty通讯框架、包解析工具、调试器模拟器软件等;…

CMake 属性之目标属性

【写在前面】 CMake 可以通过属性来存储信息。它就像是一个变量,但它被附加到一些其他的实体上,像是一个目录或者是一个目标。例如一个全局的属性可以是一个有用的非缓存的全局变量。 在 CMake 的众多属性中,目标属性 ( Target Properties ) …

NodeJS智慧社区管理微信小程序-计算机毕业设计源码40623

摘 要 随着中国经济的飞速增长,消费者的智能化水平不断提高,许多智能手机和相关的软件正在得到更多的关注和支持。其中,智慧社区管理微信小程序更是深得社区人员的喜爱,它的出现极大地改善了社区人员的生活质量,同时&…