蓝牙开发那些事儿(8)——avdtp连接过程

时间:2024-05-23 14:55:29

上一章中的最后,我们看到一条avdtp的l2cap channel已经建立好了,接下来avdtp可以开始走起来了。

Avdtp的文档又是一个140多页的庞然大物,全部看下来东西还是挺多的。

Avdtp是a2dp(advanced audio distribution protocol)的基础协议,一般来说,avdtp的l2cap channel是需要建立两条的,这里先建立第一条,也就是signal channel(这个说法和l2cap的signal channel好接近,大体上,可以认为signal channel的功能都是控制),之后还要建立另外一条stream channel,顾名思义是用来传码流的。

我们来看一下avdtp signal的连接过程,其实和l2cap的连接过程蛮像的,l2cap是双方设备得确定对方的cid,然后进行一番配置,友好协商之后,建立连接。

Avdtp有一个sep的概念,stream end point,每个设备都虚拟出若干个sep(一般是1个),每个sep分配独立的seid,类似于l2cap的cid,只不过sep、seid是预设的,而cid是在连接时动态分配的。

连接的时候,首先通过discover命令发现对端设备有几个sep,每个sep的媒体类型(audio?video?multi?),打个比方说,本地的sep是个audio sink(音频播放设备,比如说音箱),远端的sep是个audio source(音源设备,比如说手机),那么这两个sep就可以连接了。

如下图,发送的这个discover命令其实就两个字节,但是两个字节按位取值,包含了很多信息的,比如说transaction,packet type是个single,message type是command等等,这些不展开讲了。插一句,这里的packet type也是支持分包的,除了single之外,还有start ,continue,end包,是不是很类似l2cap的分包机制?不过这里基本用不上的,signal channel的包通常很小。

蓝牙开发那些事儿(8)——avdtp连接过程

然后远端回复了,对方共有6个sep,每个sep的类型都是audio src,可以看一下每个sep都是有分配对立的seid的。

蓝牙开发那些事儿(8)——avdtp连接过程

接下来的get capability和set configuration的过程类似l2cap的配置过程,首先INT端(发起avdtp连接的一方叫INT)向ACP端(接受avdtp连接的一方)发送get capability command:

蓝牙开发那些事儿(8)——avdtp连接过程

然后对方回复支持的codec信息,包括编码格式是sbc(蓝牙sink默认必须支持的一项选项了),采样率、压缩比等等,都是音频领域的东西。

蓝牙开发那些事儿(8)——avdtp连接过程

INT端收到ACP端的信息之后,与本地的capablity进行一个与的操作,(通常是上层profile去做这个事情),然后进一步进行最终配置

蓝牙开发那些事儿(8)——avdtp连接过程

收到如下这条ACP接受配置的消息后,配置过程完成了。

蓝牙开发那些事儿(8)——avdtp连接过程

接下来,就进入stream establishment的阶段了。

首先,INT发送stream OPEN命令

蓝牙开发那些事儿(8)——avdtp连接过程

当收到回复后,进入关键操作,我们可以建立stream channel了,也就是所谓的transport session,avdtp规定的tranport session其实不止stream channel,还可能有recovery channel和report channel,虽然后面两种不常用,我们还是插一句。Report channel顾名思义是用来汇报的,汇报的内容包括一些统计信息、时间对齐、信道质量等等,以帮助上层软件对于错误恢复有一个更好的策略。

Recovery channel和纠错有关,蓝牙传输既可以说是可靠的,也可以说是不可靠的。

可靠是因为其有ARQ重传机制,不可靠是因为这种重传也不是无限制的,特别是对于acl链路来说,是有一个flush timeout的,我们之前也提到过l2cap的配置过程,说到MTU这个选项,这里就要提到flush timeout这个选项了,如果设置了这个选项,那么就意味着重传是有上限的,当超过这个上限的时候,重传一直没有成功的话,这个包就会被清除掉。蓝牙本身提供的纠错码FEC功能受限,所以avdtp有个recovery channel进一步提供纠错功能。

闲言少叙,建立stream channel和建立signal channel也是类似的,l2cap channel建立的一套流程。

蓝牙开发那些事儿(8)——avdtp连接过程

当stream channel建立好之后,只要signal channel发出start命令,就意味着开始播放音乐了,可以在stream channel上面传stream码流了,遵循的又是一套RTP的格式(real-time transport protocol),不再赘述。如下图,这就是一包stream数据,包含了7帧,大概20多ms的数据。

蓝牙开发那些事儿(8)——avdtp连接过程

在播歌的中间,还可以暂停、重新配置等等,也是通过signal channel下发对应的命令suspend、reconfigure等等。

基本的流程大概是下图这个样子滴:

蓝牙开发那些事儿(8)——avdtp连接过程

具体的格式太过复杂了,我们不准备一一去分析,spec中都是有的,只是拎了一下提纲。下一章中我们结合代码进一步分析。