A2DP Source如何从android系统拿到音频数据

Android 13

简单来说就是两条本地socket通道,分别使用文件:

#define A2DP_CTRL_PATH "/data/misc/bluedroid/.a2dp_ctrl"

#define A2DP_DATA_PATH "/data/misc/bluedroid/.a2dp_data"

A2DP_CTRL_PATH是控制通道,A2DP_DATA_PATH是数据通道。

packages\modules\Bluetooth\system\audio_a2dp_hw\include\audio_a2dp_hw.h

1、首先需要关注一个文件 btif_a2dp_control.cc

// packages\modules\Bluetooth\system\btif\src\btif_a2dp_control.cc
void btif_a2dp_control_init(void) {a2dp_uipc = UIPC_Init();UIPC_Open(*a2dp_uipc, UIPC_CH_ID_AV_CTRL, btif_a2dp_ctrl_cb, A2DP_CTRL_PATH);
}

里面的函数UIPC_Init

// packages\modules\Bluetooth\system\udrv\ulinux\uipc.ccstd::unique_ptr<tUIPC_STATE> UIPC_Init() {std::unique_ptr<tUIPC_STATE> uipc = std::make_unique<tUIPC_STATE>();LOG_DEBUG("UIPC_Init");std::lock_guard<std::recursive_mutex> lock(uipc->mutex);uipc_main_init(*uipc);uipc_start_main_server_thread(*uipc);return uipc;
}

初始化一些uipc的变量,然后启动主线程uipc_read_task

int uipc_start_main_server_thread(tUIPC_STATE& uipc) {uipc.running = 1;if (pthread_create(&uipc.tid, (const pthread_attr_t*)NULL, uipc_read_task,&uipc) != 0) {LOG_ERROR("uipc_thread_create pthread_create failed:%d", errno);return -1;}return 0;
}

这里面的实现不太需要关注。

2、UIPC_Open(UIPC_CH_ID_AV_CTRL, btif_a2dp_ctrl_cb);启动控制通道。注册回调btif_a2dp_ctrl_cb

packages\modules\Bluetooth\system\btif\src\btif_a2dp_control.cc

static void btif_a2dp_ctrl_cb(UNUSED_ATTR tUIPC_CH_ID ch_id,tUIPC_EVENT event) {// Don't log UIPC_RX_DATA_READY_EVT by default, because it// could be very chatty when audio is streaming.if (event == UIPC_RX_DATA_READY_EVT) {APPL_TRACE_DEBUG("%s: A2DP-CTRL-CHANNEL EVENT %s", __func__,dump_uipc_event(event));} else {APPL_TRACE_WARNING("%s: A2DP-CTRL-CHANNEL EVENT %s", __func__,dump_uipc_event(event));}switch (event) {case UIPC_OPEN_EVT:break;case UIPC_CLOSE_EVT:/* restart ctrl server unless we are shutting down */if (btif_a2dp_source_media_task_is_running())UIPC_Open(*a2dp_uipc, UIPC_CH_ID_AV_CTRL, btif_a2dp_ctrl_cb,A2DP_CTRL_PATH);break;case UIPC_RX_DATA_READY_EVT:btif_a2dp_recv_ctrl_data();break;default:APPL_TRACE_ERROR("%s: ### A2DP-CTRL-CHANNEL EVENT %d NOT HANDLED ###",__func__, event);break;}
}

3、btif_a2dp_recv_ctrl_data(); 这个函数就是处理收到的控制指令,例如get configure,set configure、stream start、stream suspend等。

4、当收到stream start的时候就会启动数据通道

static void btif_a2dp_recv_ctrl_data(void) {tA2DP_CTRL_CMD cmd = A2DP_CTRL_CMD_NONE;int n;...a2dp_cmd_pending = cmd;switch (cmd) {...case A2DP_CTRL_CMD_START:btif_a2dp_command_ack(btif_a2dp_control_on_start());break;...
}

 

static tA2DP_CTRL_ACK btif_a2dp_control_on_start() {/** Don't send START request to stack while we are in a call.* Some headsets such as "Sony MW600", don't allow AVDTP START* while in a call, and respond with BAD_STATE.*/if (!bluetooth::headset::IsCallIdle()) {APPL_TRACE_WARNING("%s: A2DP command start while call state is busy",__func__);return A2DP_CTRL_ACK_INCALL_FAILURE;}if (btif_a2dp_source_is_streaming()) {APPL_TRACE_WARNING("%s: A2DP command start while source is streaming",__func__);return A2DP_CTRL_ACK_FAILURE;}if (btif_av_stream_ready()) {/* Setup audio data channel listener */UIPC_Open(*a2dp_uipc, UIPC_CH_ID_AV_AUDIO, btif_a2dp_data_cb,A2DP_DATA_PATH);/** Post start event and wait for audio path to open.* If we are the source, the ACK will be sent after the start* procedure is completed, othewise send it now.*/btif_av_stream_start();if (btif_av_get_peer_sep() == AVDT_TSEP_SRC) return A2DP_CTRL_ACK_SUCCESS;}if (btif_av_stream_started_ready()) {/** Already started, setup audio data channel listener and ACK* back immediately.*/UIPC_Open(*a2dp_uipc, UIPC_CH_ID_AV_AUDIO, btif_a2dp_data_cb,A2DP_DATA_PATH);return A2DP_CTRL_ACK_SUCCESS;}APPL_TRACE_WARNING("%s: A2DP command start while AV stream is not ready",__func__);return A2DP_CTRL_ACK_FAILURE;
}

5、启动数据通道后,会通过回调btif_a2dp_data_cb通知,进行一些必要的操作后(具体参考原生代码btif_a2dp_data_cb的实现),就可以使用UIPC_Read(UIPC_CH_ID_AV_AUDIO, &event, p_buf, len);读取到数据了。这里如果要使用自己的蓝牙可以建立线程读取数据,当stream stop或者stream suspend时cancel掉线程即可

6、注意:如果静音模式audio manager不会向控制发送stream start,所以如果其他指令都收到了没有收到stream start可以调节下声音试试。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

物联网协议Coap中Californium CoapClient解析

目录 前言 一、CoapClient对象 1、类定义 2、Client方法调用 二、发送请求 1、构建请求 2、发起请求 3、接收响应 总结 前言 在之前的博客中物联网协议Coap之Californium CoapServer解析&#xff0c;文中简单介绍了CoapServer的实现。在物联网开发环境中&#xff0c;除了…

给Flutter + FireBase 增加 badge 徽章,App启动器 通知红点。

在此之前需要配置好 firebase 在flutter 在项目中。&#xff08;已经配置好的可以忽略此提示&#xff09; Firebase 配置教程&#xff1a;flutter firebase 云消息通知教程 (android-安卓、ios-苹果)_flutter firebase_messaging ios环境配置-CSDN博客 由于firebase 提供的消息…

在Gitee上维护Erpnext源

在Gitee上维护Erpnext源 官方的frappe和erpnext地址: GitHub - frappe/frappe: Low code web framework for real world applications, in Python and Javascript GitHub - frappe/erpnext: Free and Open Source Enterprise Resource Planning (ERP) 1, 仓库地址输入frappe的官…

HAL——SPI

学习目标 掌握SPI配置方式掌握SPI读写操作 学习内容 需求 SPI配置 打开SPI1,选中全双工模式。观察下方自动生成的引脚&#xff0c;是否和自己开发板引脚对应。 修改引脚&#xff0c;来动右侧芯片引脚视图&#xff0c;找到开发板对应引脚&#xff0c;进行修改。 观察修改后的…

SpringBoot-Redis

依赖 <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId>配置 # 服务器连接端口 spring.redis.port6379 # 服务器地址 spring.redis.host127.0.0.1 # 数据库索引&#xff08;默认为0&#xff09…

【GitHub】-design-pattern-extend(设计模式扩展)

写在前面 偶然间看到一篇文章 《Java 中保持扩展性的几种套路和实现》&#xff0c;写的不错&#xff0c;但是类图画的差了点儿意思。于是&#xff0c;自己动手画了画&#xff0c;对其中的内容作了一些调整&#xff0c;对包做了进一步划分&#xff0c;便于理解消化。以下是对Git…

Linux rsh命令教程:远程shell命令的使用和注意事项(附案例详解和注意事项)

Linux rsh命令介绍 rsh&#xff08;remote shell&#xff09;提供用户环境&#xff0c;也就是Shell&#xff0c;以便指令能够在指定的远端主机上执行。rsh连接到指定的主机&#xff0c;并执行指定的命令。rsh将其标准输入复制到远程命令&#xff0c;将远程命令的标准输出复制到…

文章解读与仿真程序复现思路——电网技术EI\CSCD\北大核心《考虑多元不确定性和备用需求的微电网双层鲁棒容量规划》

本专栏栏目提供文章与程序复现思路&#xff0c;具体已有的论文与论文源程序可翻阅本博主免费的专栏栏目《论文与完整程序》 这个标题涉及微电网&#xff08;Microgrid&#xff09;的双层鲁棒容量规划&#xff0c;考虑了多元不确定性和备用需求。让我们逐步解读这个标题&#xf…

【KD】知识蒸馏(knowledge distillation)简单介绍

最近学到了知识蒸馏的相关知识&#xff0c;来简单总结一下૮꒰ ˶• ༝ •˶꒱ა。 知识蒸馏 知识蒸馏&#xff0c;是一种模型压缩的手段。通过训练学生模仿教师的行为&#xff0c;将嵌入在大的教师模型中的知识迁移到小的学生模型。 例如&#xff0c;TinyBERT(Jiao et al.,2…

RocketMQ源码 发送顺序消息源码分析

前言 rocketmq 发送顺序消息和普通消息的主流程区别大部分一致的&#xff0c;区别在于&#xff1a;普通消息发送时&#xff0c;从所有broker的队列集合中 轮询选择一个队列&#xff0c;而顺序队列可以提供用户自定义消息队列选择器&#xff0c;从NameServer 分配的顺序 broker…

使用JavaScript实现动态生成并管理购物车的深入解析

一、引言 在当前的互联网时代&#xff0c;电子商务已成为我们日常生活的重要组成部分。购物车作为电子商务网站的核心功能之一&#xff0c;其实现方式对于用户体验至关重要。本文将深入探讨如何使用JavaScript实现一个动态生成并管理购物车的功能&#xff0c;并详细介绍其实现…

Linux Shell数学运算与条件测试

一、Shell数学运算 1.Shell常见的算术运算符号 序号算术运算符号意义1、-、*、/、%加、减、乘、除、取余2**幂运算3、–自增或自减4&&、||、&#xff01;与、或、非5、!相等、不相等&#xff0c;也可写成6、、-、*、/、%赋值运算符&#xff0c;a1相等于aa1 2.Shell常…

.NET Standard 支持的 .NET Framework 和 .NET Core

.NET Standard 是针对多个 .NET 实现推出的一套正式的 .NET API 规范。 推出 .NET Standard 的背后动机是要提高 .NET 生态系统中的一致性。 .NET 5 及更高版本采用不同的方法来建立一致性&#xff0c;这种方法在大多数情况下都不需要 .NET Standard。 但如果要在 .NET Framewo…

QT 高DPI解决方案

一、根据DPI实现动态调整控件大小&#xff08;三种方式&#xff09; 1、QT支持高DPI&#xff08;针对整个进程中所有的UI&#xff09; // main函数中 QApplication::setAttribute(Qt::AA_EnableHighDpiScaling)tips&#xff1a;&#xff08;1&#xff09;如果不想全局设置&am…

Nodejs搭配axios下载图片

新建一个文件夹&#xff0c;npm i axios 实测发现只需保留node_modules文件夹&#xff0c;删除package.json不影响使用 1.纯下载图片 其实该方法不仅可以下载图片&#xff0c;其他的文件都可以下载 const axios require(axios) const fs require(fs) var arrPic [https:…

最大输出 18W,集成 Type-C PD 输出和各种快充输出协议

一、产品简介 IP6510是一款集成同步开关的降压转换器、支持 9 种输出快充协议、支持 Type-C 输出和 USB PD协议&#xff0c;为车载充电器、快充适配器、智能排插提供完整的解决方案。 IP6510 内置功率 MOS&#xff0c;输入电压范围是 4.5V到 32V&#xff0c;输出电压范围是 3…

案例101:基于微信小程序的停车共享管理系统设计与实现

文末获取源码 开发语言&#xff1a;Java 框架&#xff1a;SSM JDK版本&#xff1a;JDK1.8 数据库&#xff1a;mysql 5.7 开发软件&#xff1a;eclipse/myeclipse/idea Maven包&#xff1a;Maven3.5.4 小程序框架&#xff1a;uniapp 小程序开发软件&#xff1a;HBuilder X 小程序…

一个命令查看linux系统是Centos还是Ubuntu

目 录 一、 背景介绍 二、一个命令查看linux系统的简单方法 1、 uname -a 2、cat /etc/issue 3、lsb_release -a 4、 dmesg | grep Ubuntu 一、 背景介绍 Linux 系统基本上分为两大类&#xff1a; 1. Red Hat 系列&#xff1a;包括 Red Ha…

使用pytorch-superpoint与pytorch-superglue项目实现训练自己的数据集

superpoint与superglue的组合可以实现基于深度学习的图像配准,官方发布的superpoint与superglue模型均基于coco数据训练,与业务中的实际数据或许存在差距,为此实现基于开源的pytorch-superpoint与pytorch-superglue项目实现训练自己的数据集。然而,在训练pytorch-superpoin…

电缆线标书:打造高质量工程的关键一步

电缆线标书制作是工程项目中至关重要的一环&#xff0c;它不仅仅是一份文件&#xff0c;更是对工程质量和实施过程的全面规划和控制。在电缆线标书中&#xff0c;涉及到的内容十分丰富&#xff0c;包括但不限于工程概况、技术要求、材料清单、施工方案、质量控制等多个方面。 …