A2DP音频流在安卓系统中的实现




android的exoplayer获取音频流数据 android播放音频流_音频流


通过前一篇文章《蓝牙音乐之A2DP音频流》的分享,大家都清楚了A2DP音频流的开启、暂停、数据传输等一系列协议规定,今天就带大家一探安卓系统中这部分是如何实现的。

这篇文章主要分享下A2DP协议中SNK端的音频流的工作,那这就离不开 AudioTrack。AudioTrack的工作原理这里就不做说明,对安卓系统中的音频感兴趣的小伙伴相信你们可以找到学习渠道的。SNK端的AudioTrack是如何创建的已经在《A2DP连接在安卓系统中的实现》中讲解地很清楚了,A2DP音频流的传输主要是通过AudioTrack将音频流从蓝牙系统发送到安卓的音频系统中进行播放。

AVDTP协议规定A2DP连接的两端都可以启动音频流 AVDTP_START,但是在安卓系统中一般是由SRC作为INT角色启动这一过程,如果是SNK端主动播放蓝牙音乐的话,SNK首先通过AVRCP协议告知SRC播放音乐(控制协议AVRCP等以后再做分享),然后再由SRC启动该过程。

A2DP音频流的传输主要有两个步骤:

  1. SRC端开启音频流
  2. SRC发送音频数据

SRC通过AVDTP的信令通道开启音频流的目的是让连接双方将各自的AVDTP状态从OPEN切换到STREAMING,为SRC通过AVDTP数据通道传输音频数据做准备。如下为整个A2DP音频流的简单时序图:


android的exoplayer获取音频流数据 android播放音频流_安卓系统_02


开启A2DP音频流后,SRC端每隔20ms给SNK发送一包音频数据,而SNK端接收到音频数据包后并不会立即对数据进行解码,而是先存储在音频数据接收队列中,等队列中达到 5 包数据后才会开始解码。

/* In case of A2DP Sink, we will delay start by 5 AVDTP Packets */#define MAX_A2DP_DELAYED_START_FRAME_COUNT 5

最终将解码后的数据写入 AudioTrack 进行播放,SRC端持续不断的传输音频数据,同时SNK也会持续性的接受数据解码写入AudioTrack,从而蓝牙音乐就从SNK端的音频系统中源源不断地播放。

由于蓝牙音乐也是使用AudioTrack进行播放的,所以开发音乐随动氛围灯的同学也可实现蓝牙音乐播放过程中,氛围灯随着蓝牙音乐的节奏动起来。该功能主要是获取音频跟踪会话ID,也就是AudioTrack Session ID,感兴趣的同学可以参考我的另一篇文章《蓝牙音乐AudioTrack Session ID的获取》实现此功能。

因为蓝牙音乐的数据解析解码处理都是在蓝牙协议栈bluedroid中进行的,所以可以将解码后的音频流数据以文件的形式保存起来,有利于后续定位蓝牙音乐卡顿等音频问题,同时蓝牙的HCI中也会保存有音乐数据,使用相关软件(推荐Ellisys)就可打开查看,非常直观方便。