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

Android11 AudioTrack 创建过程

Android 系统播放声音,需要创建AudioTrack来和AudioFlinger通信,其创建过程如下
在这里插入图片描述

  1. 根据传入的声音属性得到output
  2. 通过得到的output,找到播放线程
  3. AudioFlinger在播放线程内,创建Track,和AudioTrack对应。后续通过它们进行通信

接下来分别看下其过程

找到output
在getOutputForAttr函数内,直接调用getOutputForAttrInt函数

//frameworks/av/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
status_t AudioPolicyManager::getOutputForAttrInt(audio_attributes_t *resultAttr,audio_io_handle_t *output,audio_session_t session,const audio_attributes_t *attr,audio_stream_type_t *stream,uid_t uid,const audio_config_t *config,audio_output_flags_t *flags,audio_port_handle_t *selectedDeviceId,bool *isRequestedDeviceForExclusiveUse,std::vector<sp<AudioPolicyMix>> *secondaryMixes,output_type_t *outputType)
{DeviceVector outputDevices;const audio_port_handle_t requestedPortId = *selectedDeviceId;DeviceVector msdDevices = getMsdAudioOutDevices();const sp<DeviceDescriptor> requestedDevice =mAvailableOutputDevices.getDeviceFromId(requestedPortId);*outputType = API_OUTPUT_INVALID;status_t status = getAudioAttributes(resultAttr, attr, *stream);//将attr赋值给resultAttr//省略outputDevices = mEngine->getOutputDevicesForAttributes(*resultAttr, requestedDevice, false);//根据resultAttr,找到device//省略if (*output == AUDIO_IO_HANDLE_NONE) {*output = getOutputForDevices(outputDevices, session, *stream, config,flags, resultAttr->flags & AUDIO_FLAG_MUTE_HAPTIC);//根据device,找到output}//省略
}

1,找到device

//frameworks/av/services/audiopolicy/enginedefault/src/Engine.cpp
DeviceVector Engine::getOutputDevicesForAttributes(const audio_attributes_t &attributes,const sp<DeviceDescriptor> &preferredDevice,bool fromCache) const
{product_strategy_t strategy = getProductStrategyForAttributes(attributes);//省略return fromCache? mDevicesForStrategies.at(strategy) : getDevicesForProductStrategy(strategy);
}

首先,通过声音属性,从mProductStrategies中找到strategy,然后根据strategy,找到对应的device。getDevicesForProductStrategy这个函数由厂商自定义,修改声音的音频策略,大多数情况下可以修改这个函数。

2,根据device,找到output

//frameworks/av/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
audio_io_handle_t AudioPolicyManager::getOutputForDevices(const DeviceVector &devices,audio_session_t session,audio_stream_type_t stream,const audio_config_t *config,audio_output_flags_t *flags,bool forceMutingHaptic)
{//省略if (audio_is_linear_pcm(config->format)) {SortedVector<audio_io_handle_t> outputs = getOutputsForDevices(devices, mOutputs);*flags = (audio_output_flags_t)(*flags & ~AUDIO_OUTPUT_FLAG_DIRECT);output = selectOutput(outputs, *flags, config->format, channelMask, config->sample_rate);}return output;}

mOutputs中,支持该device的output可能有多个,通过getOutputsForDevices把它们找出来,然后调用selectOutput从中选择一个最符合的。怎么从中找到最合适的output,可以看其注释

	// select one output among several that provide a path to a particular device or set of// devices (the list was previously build by getOutputsForDevices()).// The priority is as follows:// 1: the output supporting haptic playback when requesting haptic playback// 2: the output with the highest number of requested functional flags// 3: the output supporting the exact channel mask// 4: the output with a higher channel count than requested// 5: the output with a higher sampling rate than requested// 6: the output with the highest number of requested performance flags// 7: the output with the bit depth the closest to the requested one// 8: the primary output// 9: the first output in the list

综上,找到output的流程为: audio_attributes_t >>> strategy >>> device >>> output

找到播放线程

AudioFlinger::PlaybackThread *AudioFlinger::checkPlaybackThread_l(audio_io_handle_t output) const
{return mPlaybackThreads.valueFor(output).get();
}

根据output,从mPlaybackThreads中找到对应的播放线程

创建Track

//frameworks/av/services/audioflinger/Threads.cpp
sp<AudioFlinger::PlaybackThread::Track> AudioFlinger::PlaybackThread::createTrack_l(/*省略*/)
{//省略track = new Track(this, client, streamType, attr, sampleRate, format,channelMask, frameCount,nullptr /* buffer */, (size_t)0 /* bufferSize */, sharedBuffer,sessionId, creatorPid, uid, *flags, TrackBase::TYPE_DEFAULT, portId,SIZE_MAX /*frameCountToBeReady*/, opPackageName);//省略mTracks.add(track);//省略
}

AudioFlinger的PlaybackThread中有一个mTracks数组,先创建Track,然后将该Track保存到mTracks中。

总结
应用程序创建AudioTrack,导致在对应的播放线程内,创建Track和其对应。如何找到对应的播放线程?

  1. 根据传入的声音属性,找到strategy
  2. 根据strategy ,找到device
  3. 根据device找到output
  4. 根据output,从mPlaybackThreads中找到对应的播放线程

相关文章:

Android11 AudioTrack 创建过程

Android 系统播放声音&#xff0c;需要创建AudioTrack来和AudioFlinger通信&#xff0c;其创建过程如下 根据传入的声音属性得到output通过得到的output&#xff0c;找到播放线程AudioFlinger在播放线程内&#xff0c;创建Track&#xff0c;和AudioTrack对应。后续通过它们进…...

数学建模 —— 层次分析法(2)

目录 一、层次分析法&#xff08;AHP&#xff09; 二、构造比较判断矩阵 2.1 两两比较法 三、单准则下的排序及一致检验 3.1 单准则下的排序 3.2 一致性检验 四、层次总排序 4.1 层次总排序的步骤 4.2 总排序一致性检验 一、层次分析法&#xff08;AHP&#xff09; 方…...

Nvidia Jetson/Orin +FPGA+AI大算力边缘计算盒子:人工智能消防应用

青鸟消防股份有限公司成立于2001年6月&#xff0c;于2019年8月在深圳证券交易所挂牌上市&#xff0c;成为中国消防报警行业首家登陆A股的企业。公司始终聚焦于消防安全与物联网领域&#xff0c;主营业务为“一站式”消防安全系统产品的研发、生产和销售。公司产品已覆盖了火灾报…...

Flutter 中的 KeepAlive 小部件:全面指南

Flutter 中的 KeepAlive 小部件&#xff1a;全面指南 Flutter 是一个由 Google 开发的跨平台 UI 框架&#xff0c;它允许开发者使用 Dart 语言构建高性能、美观的移动、Web 和桌面应用。在 Flutter 的丰富组件库中&#xff0c;KeepAlive 是一个用于维护组件活跃状态的组件&…...

C语言 恼人的结合性和优先级和副作用

结合性和优先级和副作用 1.优先级2.结合性3.副作用4.简单区分i&#xff0c;i&#xff0c;i1&#xff1b;ii1&#xff1b;ii 1.优先级 优先级指的是&#xff0c;如果⼀个表达式包含多个运算符&#xff0c;哪个运算符应该优先执⾏。各种运算符的优先级是 不⼀样的。 在C语言中&a…...

Vue——初识组件

文章目录 前言页面的构成何为组件编写组件组件嵌套注册 效果展示 前言 在官方文档中&#xff0c;对组件的知识点做了一个很全面的说明。本篇博客主要写一个自己的案例讲解。 vue 官方文档 组件基础 页面的构成 说到组件之前&#xff0c;先大致说明下vue中页面的构成要素。 在…...

MQ消息丢失/重复/顺序/挤压

rabbitmq消息丢失解决 rocketMq解决消息丢失 RocketMQ事务消息概要 RocketMQ事务消息是指应用本地事务和发送消息操作可以被定义到全局事务中&#xff0c;要么同时成功&#xff0c;要么同时失败。 采用了2PC&#xff08;两阶段提交&#xff09; 补偿机制&#xff08;事务状态回…...

利用Quarkus构建高效微服务——Java的云原生革新

引言&#xff1a; 在微服务架构和容器技术日益成为企业开发标准的今天&#xff0c;Java开发者面临着如何将传统Java应用转型为高效、轻量级且易于扩展的云原生应用的挑战。Quarkus框架的出现&#xff0c;正是为了解决这一问题&#xff0c;它不仅能够提升Java在Kubernetes环境中…...

python 批量ts合并成一个mp4

首先&#xff0c;确保你已经安装了ffmpeg。 然后再次保证所有ts文件放在同一个文件夹中&#xff0c;并且依次命名为 1.ts 、 2.ts 、 3.ts 、 4.ts 、 4.ts 。。。 Python完整代码如下&#xff1a;(ffmpeg_batch_merge_ts.py文件) #!/usr/bin/python3 # -*- coding: UTF-8 -*…...

Java | Leetcode Java题解之第129题求根节点到叶节点数字之和

题目&#xff1a; 题解&#xff1a; class Solution {public int sumNumbers(TreeNode root) {if (root null) {return 0;}int sum 0;Queue<TreeNode> nodeQueue new LinkedList<TreeNode>();Queue<Integer> numQueue new LinkedList<Integer>();…...

SpringBoot【注解 01】@Scheduled实现定时任务的串行和并行执行

在SpringBoot中&#xff0c;如果使用Scheduled注解来定义多个定时任务&#xff0c;默认情况下这些任务将会被安排在一个单线程的调度器中执行。这意味着&#xff0c;这些任务将会串行执行&#xff0c;而不是并行执行。当一个任务正在执行时&#xff0c;其他被触发的任务将会等待…...

【工具】redis的安装使用

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、Redis简介二、Redis的安装使用三、本文总结 前言 提示&#xff1a;这里可以添加本文要记录的大概内容&#xff1a; 随着开发语言及人工智能工具的普及&am…...

汇编:数据定义数据填充

数组的定义 在32位汇编语言中&#xff0c;定义数组时&#xff0c;通常使用定义数据指令&#xff08;如 DB, DW, DD,DQ &#xff09;和标签来指定数组的名称和内容。DB定义字节数组&#xff08;每个元素占1字节&#xff09;、DW定义字数组&#xff08;每个元素占2字节&#xff…...

Python画图(多图展示在一个平面)

天行健&#xff0c;君子以自强不息&#xff1b;地势坤&#xff0c;君子以厚德载物。 每个人都有惰性&#xff0c;但不断学习是好好生活的根本&#xff0c;共勉&#xff01; 文章均为学习整理笔记&#xff0c;分享记录为主&#xff0c;如有错误请指正&#xff0c;共同学习进步。…...

python-web应用程序-Django数据库-操作表中的数据

python-web应用程序-Django数据库-操作表中的数据 一、新增数据 类.objects.create(字段名 字段值&#xff0c;字段名 字段值&#xff0c;...)导入models包 models.User.objects.create(nameyulin,sex0,info三好学生)即可对数据进行操作 二、删除数据 类.objects.filter(…...

绕过WAF(Web应用程序防火墙)--介绍、主要功能、部署模式、分类及注入绕过方式等

网站WAF是一款集网站内容安全防护、网站资源保护及网站流量保护功能为一体的服务器工具。功能涵盖了网马/木马扫描、防SQL注入、防盗链、防CC攻击、网站流量实时监控、网站CPU监控、下载线程保护、IP黑白名单管理、网页防篡改功能等模块。能够为用户提供实时的网站安全防护&…...

11.7 堆排序

目录 11.7 堆排序 11.7.1 算法流程 11.7.2 算法特性 11.7 堆排序 Tip 阅读本节前&#xff0c;请确保已学完“堆“章节。 堆排序&#xff08;heap sort&#xff09;是一种基于堆数据结构实现的高效排序算法。我们可以利用已经学过的“建堆操作”和“元素出堆操作”…...

Patchwork++:基于点云的快速、稳健的地面分割方法

1. 背景 论文发表在2022IROS&#xff0c;是Patchwork的改进版本。算法通过数学方法进行快速而鲁棒性很强的地面分割&#xff0c;在智能机器人上的可操作性非常强。通过微调算法&#xff0c;可以应用于16-beams等多种规格的激光雷达。由于激光雷达点云数据标注的难度非常大&…...

Llama改进之——分组查询注意力

引言 今天介绍LLAMA2模型引入的关于注意力的改进——分组查询注意力(Grouped-query attention,GQA)1。 Transformer中的多头注意力在解码阶段来说是一个性能瓶颈。多查询注意力2通过共享单个key和value头&#xff0c;同时不减少query头来提升性能。多查询注意力可能导致质量下…...

英伟达开源新利器NV-Embed向量模型,基于双向注意力的LLM嵌入模型,MTEB 56项任务排名第一

前言 文本嵌入模型能够将文本信息转化为稠密的向量表示&#xff0c;并在信息检索、语义相似度计算、文本分类等众多自然语言处理任务中发挥着关键作用。近年来&#xff0c;基于解码器的大型语言模型 (LLM) 开始在通用文本嵌入任务中超越传统的 BERT 或 T5 嵌入模型&#xff0c…...

JVM之【GC-垃圾清除算法】

Java虚拟机&#xff08;JVM&#xff09;中的垃圾收集算法主要分为以下几种&#xff1a; 标记-清除算法&#xff08;Mark-Sweep&#xff09;复制算法&#xff08;Copying&#xff09;标记-整理算法&#xff08;Mark-Compact&#xff09;分代收集算法&#xff08;Generational C…...

数据分析每周挑战——心衰患者特征数据集

这是一篇关于医学数据的数据分析&#xff0c;但是这个数据集数据不是很多。 背景描述 本数据集包含了多个与心力衰竭相关的特征&#xff0c;用于分析和预测患者心力衰竭发作的风险。数据集涵盖了从40岁到95岁不等年龄的患者群体&#xff0c;提供了广泛的生理和生活方式指标&a…...

单例模式(Java实现)

我的相关文章&#xff1a; JavaSE 学习记录-CSDN博客 多线程笔记-CSDN博客 单例模式&#xff08;Java实现&#xff09;-CSDN博客 JUC笔记-CSDN博客 注解与反射&#xff08;Java&#xff0c;类加载机制&#xff0c;双亲委派机制&#xff09;-CSDN博客 1. 懒汉式线程不安全 pu…...

24.面向对象六大原则

目录介绍 00.面向对象六大原则01.代码单一职责原则02.代码开放封闭原则03.代码里氏替换原则04.代码依赖倒置原则05.代码接口隔离原则06.代码迪米特原则00.面向对象六大原则 六大原则一句话介绍 单一职责原则:指一个类的功能要单一,不能包罗万象。开放封闭原则:指一个模块在扩…...

Vue3-shallowRef与shallowReactive

shallowRef 作用&#xff1a;创建一个响应式数据&#xff0c;但只对顶层属性进行响应式处理。 用法&#xff1a; let myVar shallowRef(initialValue);特点&#xff1a;只跟踪引用值的变化&#xff0c;不关心值内部的属性变化。 shallowReactive 作用&#xff1a;创建一个浅…...

CI/CD(基于ESP-IDF)

主要参考资料 B站乐鑫信息科技《【乐鑫全球开发者大会】DevCon23 #15 &#xff5c;通过 CI/CD 进行流水线开发》 pytest-embedded乐鑫文档: https://docs.espressif.com/projects/pytest-embedded/en/latest/api.html 目录 CI/CD简介乐鑫内部CI/CD测试GitLab CI/CDGitHub Actio…...

聚观早报 | 东风奕派eπ008将上市;苹果Vision Pro发布会

聚观早报每日整理最值得关注的行业重点事件&#xff0c;帮助大家及时了解最新行业动态&#xff0c;每日读报&#xff0c;就读聚观365资讯简报。 整理丨Cutie 6月3日消息 东风奕派eπ008将上市 苹果Vision Pro发布会 特斯拉Model 3高性能版开售 小米14推送全新澎湃OS系统 …...

k8s牛客面经篇

k8s的pod版块: k8s的网络版块: k8s的deployment版块: k8s的service版块: k8s的探针板块: k8s的控制调度板块: k8s的日志监控板块: k8s的流量转发板块: k8s的宏观版块:...

第9周 基于MinIO与OSS实现分布式与云存储

第9周 基于MinIO与OSS实现分布式与云存储 1. 基于mybatis-plus数据修改非空属性忽略更新2. 文件上传3. 分布式文件存储3.1 文件存储架构演变4. Minio docker安装5. 文件服务整合minio依赖minio API测试yml配置minio信息minio配置类业务:上传文件6. 云存储阿里OSS:要钱6.1 依赖6…...

【Linux内核-编程指南】

■ IPC组件 添加链接描述 ■ ■ ■ ■ ■...