Le audio之媒体控制(Media control)介绍,涵盖MCP/MCS的技术细节

在无线音频的世界里,一场静默却深刻的革命正在进行。

它,就是LE Audio。

这不仅仅是一次技术迭代,而是从底层重新定义声音如何被创造、传输和体验的范式转移。其复杂性令人敬畏------它并非单一技术,而是一套精密的生态系统:全新的LC3编解码器以超凡效率重塑音质与功耗的平衡,多重串流音频让真无线立体声达到前所未有的稳定与同步,而音频广播功能则打破了"一对一"连接的百年窠臼,让声音如电台般自由播撒。

然而,正是这种复杂性,构成了我们必须深入学习它的不可辩驳的理由。未来的声音图景将由它绘制:从下一代真无线耳机、无障碍助听设备到公共场所的沉浸式音频导览、多语言广播,乃至元宇宙中清晰无缝的语音交互。不了解LE Audio,将意味着在即将到来的音频浪潮中失去对话的基石。

这不仅仅关乎技术本身,更关乎我们如何连接彼此,如何感知世界。让我们共同开启这段探索之旅,揭开LE Audio的复杂面纱,看清它为何必将成为未来数年里,每一个科技从业者、音频爱好者乃至普通用户都无法忽视的关键命题。

接下来的系列文章,我们将逐步拆解这座精妙的技术大厦。

同时我也录制了一系列的Le audio视频,有兴趣的可以咨询,我会带领你们入门Le audio!翻过大山,眼下皆是风景!!!


VX: 15712795029

视频链接: https://item.taobao.com/item.htm?id=1001969040805&mi_id=000032T4qZX9WZoRwX6YbxlNUaZOfOI6XoxDx0jxsfnwlEc&spm=a21xtw.29178619.0.0


一. 概念

1. 概念

媒体控制配置文件(Media Control Profile, 简称MCP)包括媒体控制客户端(Media Control Client)和媒体控制服务端(Media Control Server)两个角色,前者作为GATT客户端,后者作为GATT服务端。

  • Media Control Profile (MCP)
  • Media Control Service (MCS)

说直白点就是媒体控制服务,此协议的前提就是类似于传统蓝牙的AVRCP,如果你熟悉AVRCP,那么此协议会觉得非常容易理解,另外依赖于OTS(Object Transfer Service)协议,主要用于传输一些图片类的内容,这个跟AVRCP依赖BIP传输专辑图片非常相似哈·,在整个le audio的架构如下:

另外补充一点学习BLE或者LE audio的学习思路哈,这个可能会贯穿所有的LE audio的学习,就是一般对应功能对应的service跟client要一起学习,比如MCS跟MCP一起学习,这个一般S(service)会告知有哪些attribute,C(client)会告知你怎么进行交互,一起结合着学习,事半功倍!!

本规范定义了两个角色:媒体控制客户端(MCP) 与媒体控制服务器(MCS)

媒体控制服务器是设备,与媒体控制客户端交互以管理媒体轨道,并向媒体控制客户端传递各类状态与设置。

媒体控制客户端是设备,负责发起播放和暂停操作,决定播放顺序,并从媒体控制服务器收集搜索结果。

媒体控制服务器应为GATT服务器。

媒体控制客户端应为GATT客户端。

MCP的角色划分及各角色内含的服务如下图所示:

媒体控制服务端必须支持一个通用媒体控制服务(Generic Media Control Service, 简称GMCS), 并可同时支持多个媒体控制服务(Media Control Service, 简称MCS). 例如一种音频播放器(例如音乐应用)的功能手机作为媒体控制服务端仅支持一个GMCS,而同时支持多个音频播放器(例如音乐+微信+Webex Meet等应用)的智能手机支持一个GMCS和多个MCS. GMCS和MCS的蓝牙技术规范都是媒体控制服务(Media Control Service).

2. 服务属性

|-----------------------------------------------------|-----------------|---------------------------------------|-------------------------|--------------------------|
| 特性名称 (Characteristic Name) | Requirement | Mandatory Properties | Optional Properties | Security Permissions |
| 媒体播放器名称 (Media Player Name) | M | Read | Notify (C.4) | Encryption required |
| 媒体播放器图标对象ID (Media Player Icon Object ID) | O | Read | -- | Encryption required |
| 媒体播放器图标URL (Media Player Icon URL) | O | Read | -- | Encryption required |
| 曲目变更 (Track Changed) | M | Notify | -- | Encryption required |
| 曲目标题 (Track Title) | M | Read | Notify | Encryption required |
| 曲目时长 (Track Duration) | M | Read | Notify | Encryption required |
| 曲目位置 (Track Position) | M | Read, Write, Write Without Response | Notify | Encryption required |
| 播放速度 (Playback Speed) | O | Read, Write, Write Without Response | Notify | Encryption required |
| 搜索速度 (Seeking Speed) | O | Read | Notify | Encryption required |
| 当前曲目分段对象ID (Current Track Segments Object ID) | C.1 | Read | -- | Encryption required |
| 当前曲目对象ID (Current Track Object ID) | O | Read, Write, Write Without Response | Notify | Encryption required |
| 下一曲目对象ID (Next Track Object ID) | C.1 | Read, Write, Write Without Response | Notify | Encryption required |
| 父组对象ID (Parent Group Object ID) | C.1 | Read | Notify | Encryption required |
| 当前组对象ID (Current Group Object ID) | C.1 | Read, Write, Write Without Response | Notify | Encryption required |
| 播放顺序 (Playing Order) | O | Read, Write, Write Without Response | Notify | Encryption required |
| 支持的播放顺序 (Playing Orders Supported) | O | Read | -- | Encryption required |
| 媒体状态 (Media State) | M | Read, Notify | -- | Encryption required |
| 媒体控制点 (Media Control Point) | O | Write, Write Without Response, Notify | -- | Encryption required |
| 媒体控制点支持的操作码 (Media Control Point Opcodes Supported) | C.2 | Read | Notify | Encryption required |
| 搜索控制点 (Search Control Point) | C.3 | Write, Write Without Response, Notify | -- | Encryption required |
| 搜索结果对象ID (Search Results Object ID) | O | Read, Notify | -- | Encryption required |
| 内容控制ID (Content Control ID) | M | Read | -- | Encryption required |

需要注意的是:带notify的charactistic,都要附带一个charactisitic client conf的uuid(0x2902)的descriptor

具体服务跟属性的UUID在assign number文档中,其中MCS跟GMCS的primary service的UUID如下:

我们来贴一个btsnoop来举例下,这个btsnoop,我们本地角色是做类似于耳机的角色,对端是手机,所以手机是支持MCS的,所以我们来看下我们discovery对方的MCS的btsnoop

可以看到对端是支持GMCS的UUID的primary service的。

另外表格中所有attribute的uuid如下:

二. 具体的属性介绍

在介绍这些attribute之前,我们先来看下一些基本的概念,看这张图一目了然就可以看出来group/track/segment的层级关系

1. Media Player Name

媒体播放器名称(Media Player Name)特性用于显示提供媒体轨道的媒体播放器应用的名称。特性值应为 UTF-8 字符串。

我们可以展开下read request跟response

Read request

这里是通过属性的handle 0x002A读取播放器名称,为什么是0x002A呢?

是因为前面characteristic discovery的过程发现的,可以发现handle也是0x002A

Read response

这个没啥好介绍的,就是播放器UTF-8字符串

2. Media Player Icon Object ID

媒体播放器图标对象ID(Media Player Icon Object ID)特性用于访问符合第4.1节定义的媒体播放器图标对象类型。该特性标识了包含可向用户代表此媒体播放器的图标对象的对象ID。

若媒体播放器无图标,则该特性的长度应为零。若媒体播放器有图标,则特性长度为六个字节(即 uint48 类型的大小),且特性值应为 uint48 类型的数值,其范围应符合 OTS(对象传输服务)中定义的有效对象ID范围。如存在此值,可在所包含的 OTS 中的对象ID特性中使用该值,以允许访问图标的内容。

3. Media Player Icon URL

媒体播放器图标URL(Media Player Icon URL)特性用于提供可向用户标识该媒体播放器的图标URL。该特性值应格式化为UTF-8字符串。

4. Track Changed

曲目变更(Track Changed)特性 用于在当前曲目发生更改时通知客户端。该特性为空特性(大小为0)。

客户端可通过在客户端特性配置描述符(Client Characteristic Configuration descriptor) 上执行 GATT 写入描述符(Write Characteristic Descriptors) 子过程,来配置该特性的通知功能。配置完成后,在连接期间可发送该特性的通知。

当曲目发生变更时,服务器设备应根据客户端特性配置描述符的值,向客户端设备发送该特性的通知。

在通知曲目变更特性之前,所有会因当前曲目切换至下一曲目而变化的特性,均须先行更新。

5. Track Title

曲目标题(Track Title)特性用于提供当前曲目的标题。特性值应为UTF-8字符串。

若媒体播放器当前无曲目或曲目标题不可用,则曲目标题特性值应为空字符串(零长度)。

客户端读取该特性时,曲目标题特性将返回其关联值。

客户端可通过在客户端特性配置描述符(Client Characteristic Configuration descriptor) 上执行 GATT 写入描述符(Write Characteristic Descriptors) 子过程来配置该特性的通知功能。配置完成后,在连接期间可发送该特性的通知。

6. Track Duration

曲目时长(Track Duration)特性以0.01秒为单位、以32位有符号整数形式提供当前曲目的长度。

若媒体播放器当前无曲目或当前曲目时长未知,则曲目时长特性值应设为 0xFFFFFFFF。否则,曲目时长应为零或正值。

客户端读取该特性时,曲目时长特性将返回其关联值。

若曲目时长特性支持通知功能,客户端可通过在客户端特性配置描述符(Client Characteristic Configuration descriptor) 上执行 GATT 写入描述符(Write Characteristic Descriptors) 子过程来配置该特性的通知功能。配置完成后,在连接期间可发送该特性的通知。

若曲目时长特性支持通知功能,当曲目时长特性值发生变化时,服务器设备应向客户端设备发送该特性的通知。

7. Track Position

曲目位置(Track Position)特性 以0.01秒为单位、以32位有符号整数形式提供当前曲目的播放位置。该特性表示从曲目起始点到当前播放点的偏移量。若曲目起始点未明确定义(例如在直播流中),服务器将设定一个起始位置(此时曲目位置值为0)或将其设为不可用(0xFFFFFFFF)

当前曲目的位置信息不用于多设备间的音频同步,仅用于向用户显示当前播放位置,并支持快速跳转定位(例如实现客户端书签功能)。若媒体播放器当前无曲目,则曲目位置特性值应设为 0xFFFFFFFF

曲目位置(Track Position)特性在客户端读取时将返回其关联值。

当向曲目位置特性写入数值时,服务器可调整当前曲目的播放位置。若写入值为零或正数,则当前播放位置应设为从曲目起始点的偏移量。若写入值为负数,则当前播放位置应设为从曲目结尾的偏移量,且曲目位置特性的值应更新为从曲目起始点到新播放位置的偏移量。若写入值对应无效的曲目位置,服务器应将曲目位置特性设为有效值。

若曲目位置特性支持通知功能,客户端可通过在客户端特性配置描述符(Client Characteristic Configuration descriptor) 上执行 GATT 写入描述符(Write Characteristic Descriptors) 子过程来配置该特性的通知功能。配置完成后,在连接期间可发送该特性的通知。

若曲目位置特性支持通知功能,当曲目位置特性值发生变化、曲目暂停或播放速度改变时,服务器设备应根据客户端特性配置描述符的值,向客户端设备发送该特性的通知。为避免通知过于频繁,在媒体状态(Media State) 设为"播放中"且以恒定速度播放时,不应发送曲目位置通知。当媒体状态特性设为"定位中(Seeking)"时,应发送曲目位置通知。定位期间的通知频率由服务器实现决定。

8. Playback Speed

播放速度(Playback Speed)特性 用于显示当前曲目的播放速度。该特性值为一个有符号8位整数(p),通过计算 2 的 p 次方除以 64 来确定播放速度的倍数(s):

播放速度(Playback Speed)特性在客户端读取时将返回其关联值(p)。

当向播放速度特性写入数值时,服务器应调整当前曲目的播放速度。若服务器支持所写入的值,则应将播放速度特性设为该写入值。若服务器不支持所写入的值,则应将该特性设为支持的值。如果写入的值不被支持且大于当前播放速度特性值,服务器宜将其设为下一个更高的支持速度;如果写入的值不被支持且小于当前特性值,则宜设为下一个更低的支持速度。

对于流媒体,播放速度可能固定为正常速度的1倍(即原速)。

若播放速度特性支持通知功能,客户端可通过在客户端特性配置描述符(Client Characteristic Configuration descriptor) 上执行 GATT 写入描述符(Write Characteristic Descriptors) 子过程来配置该特性的通知功能。配置完成后,在连接期间可发送该特性的通知。

若播放速度特性支持通知功能,当播放速度特性值被更改或写入时,服务器设备应根据客户端特性配置描述符的值,向客户端设备发送该特性的通知。

9. Seeking Speed

搜索速度(Seeking Speed)特性 用于显示当前曲目的定位速度。该特性值应为有符号8位整数,表示当前进行快进或快退时相对于实时播放速度的倍数("实时"指播放速度特性计算中 p=0 的状态)。快进时搜索速度为正值,快退时搜索速度为负值。若媒体播放器未处于定位状态,该特性值应为0。在定位过程中,当前曲目的音频可能不被使用

客户端读取该特性时,搜索速度特性将返回其关联值。

若搜索速度特性支持通知功能,客户端可通过在客户端特性配置描述符(Client Characteristic Configuration descriptor) 上执行 GATT 写入描述符(Write Characteristic Descriptors) 子过程来配置该特性的通知功能。配置完成后,在连接期间可发送该特性的通知。

若搜索速度特性支持通知功能,当搜索速度特性值发生变化时,服务器设备应根据客户端特性配置描述符的值,向客户端设备发送该特性的通知。

10. Current Track Segments Object ID

当前曲目分段对象ID(Current Track Segments Object ID)特性 用于访问符合**曲目分段对象(Track Segment Object)**类型。该特性通过所包含的OTS(对象传输服务)中的一个对象来标识当前曲目的分段信息。

若媒体播放器当前无曲目,则该特性的长度应为零。若媒体播放器有当前曲目,则特性长度为六个字节(即 uint48 类型的大小),且特性值应为 uint48 类型的数值,其范围应符合 OTS 中定义的有效对象ID范围。如存在此值,可在所包含的 OTS 中的对象ID特性中使用该值,以允许访问当前曲目的分段信息。

OTS 中用于提供曲目分段信息的对象可被各曲目重复使用。

客户端读取该特性时,当前曲目分段对象ID特性将返回其关联值。

11. Current Track Object ID

当前曲目对象ID(Current Track Object ID)特性 用于访问符合**曲目对象(Track Object)**类型。该特性通过所包含的OTS(对象传输服务)中的一个对象来标识当前曲目。

若媒体播放器当前无曲目,则该特性的长度应为零。若媒体播放器有当前曲目,则特性长度为六个字节(即 uint48 类型的大小),且特性值应为 uint48 类型的数值,其范围应符合 OTS 中定义的有效对象ID范围。如存在此值,可在所包含的 OTS 中的对象ID特性 中使用该值,以允许访问曲目相关内容(例如曲目内嵌的专辑插图)。

客户端读取该特性时,当前曲目对象ID特性将返回其关联值。

当向当前曲目对象ID特性写入数值时,服务器应将当前曲目切换为该值所标识的曲目,并执行第3.18.1.16节中 "跳转至曲目(Goto Track)" 命令所述的操作。

若当前曲目对象ID特性支持通知功能,客户端可通过在客户端特性配置描述符(Client Characteristic Configuration descriptor) 上执行 GATT 写入描述符(Write Characteristic Descriptors) 子过程来配置该特性的通知功能。配置完成后,在连接期间可发送该特性的通知。

若当前曲目对象ID特性支持通知功能,当特性值发生变化时(客户端主动写入更改的情况除外),服务器设备应向客户端设备发送该特性的通知。

12. Next Track Object ID

下一曲目对象ID(Next Track Object ID)特性 用于访问符合**曲目对象(Track Object)**类型。该特性通过所包含的OTS(对象传输服务)中的一个对象,根据播放顺序和当前组对象定义来标识下一首曲目。

若媒体播放器无下一曲目,则该特性的长度应为零。若媒体播放器有下一曲目,则特性长度为六个字节(即 uint48 类型的大小),且特性值应为 uint48 类型的数值,其范围应符合 OTS 中定义的有效对象ID范围。如存在此值,可在所包含的 OTS 中的对象ID特性 中使用该值,以允许访问曲目相关内容(例如曲目内嵌的专辑插图)。

客户端读取该特性时,下一曲目对象ID特性将返回其关联值。

当向下一曲目对象ID特性写入数值时,服务器应将下一曲目更改为客户端写入该特性值所标识的曲目。

若下一曲目对象ID特性支持通知功能,客户端可通过在客户端特性配置描述符(Client Characteristic Configuration descriptor) 上执行 GATT 写入描述符(Write Characteristic Descriptors) 子过程来配置该特性的通知功能。配置完成后,在连接期间可发送该特性的通知。

若下一曲目对象ID特性支持通知功能,当特性值发生变化时(因客户端向该特性写入值而导致的更改除外),服务器设备应向客户端设备发送该特性的通知。

13. Parent Group Object ID

父组对象ID(Parent Group Object ID)特性 用于访问符合**组对象(Group Object)**类型。该特性通过所包含的OTS(对象传输服务)中的一个组对象来标识当前组对象的父组。

若媒体播放器未创建父组或当前组,则该特性的长度应为零。若媒体播放器存在父组,则特性长度为六个字节(即 uint48 类型的大小),且特性值应为 uint48 类型的数值,其范围应符合 OTS 中定义的有效对象ID范围。如存在此值,可在所包含的 OTS 中的对象ID特性中使用该值,以允许访问当前父组的内容。

对于没有父组的组,父组对象ID 的值应等于当前组对象ID的值。

当前组对象ID 发生变化时,父组对象ID 的值也可能随之改变。

客户端读取该特性时,父组对象ID特性将返回其关联值。

客户端可通过在客户端特性配置描述符(Client Characteristic Configuration descriptor) 上执行 GATT 写入描述符(Write Characteristic Descriptors) 子过程来配置该特性的通知功能。配置完成后,在连接期间可发送该特性的通知。

当父组对象ID特性值发生变化时,服务器设备应向客户端设备发送该特性的通知。

14. Current Group Object ID

当前组对象ID(Current Group Object ID)特性 用于访问符合**组对象(Group Object)**类型。该特性通过所包含的OTS(对象传输服务)中的一个组对象来标识当前组。

若媒体播放器未创建当前组,则该特性的长度应为零。若媒体播放器存在当前组,则特性长度为六个字节(即 uint48 类型的大小),且特性值应为 uint48 类型的数值,其范围应符合 OTS 中定义的有效对象ID范围。如存在此值,可在所包含的 OTS 中的对象ID特性 中使用该值,以允许访问组内的曲目和/或其他子组。

客户端读取该特性时,当前组对象ID特性将返回其关联值。

当向当前组对象ID特性写入数值时,服务器应切换当前组,并根据当前播放顺序将当前曲目 设为该组的首曲目,同时将曲目位置重置为0。

若当前组对象ID特性支持通知功能,客户端可通过在客户端特性配置描述符(Client Characteristic Configuration descriptor) 上执行 GATT 写入描述符(Write Characteristic Descriptors) 子过程来配置该特性的通知功能。配置完成后,在连接期间可发送该特性的通知。

若当前组对象ID特性支持通知功能,当特性值发生变化时(因客户端写入值而导致的更改除外),服务器设备应向客户端设备发送该特性的通知。

15. Playing Order

播放顺序(Playing Order)特性用于显示媒体播放器的播放顺序。该特性值为枚举类型,定义如表所示。表"名称"列中涉及的"最早(Oldest)"与"最新(Newest)"所对应的具体播放顺序由实现方自行定义。

|---------------|------------------------|----------------------|
| 值 (Value) | 名称 (Name) | 说明 (Description) |
| 0x01 | 单曲一次 (Single once) | 单曲播放一次;无下一曲目。 |
| 0x02 | 单曲循环 (Single repeat) | 单曲循环播放;下一曲目即当前曲目。 |
| 0x03 | 顺序一次 (In order once) | 组内曲目按顺序播放一次。 |
| 0x04 | 顺序循环 (In order repeat) | 组内曲目按顺序循环播放。 |
| 0x05 | 最旧一次 (Oldest once) | 组内曲目从最旧开始播放一次。 |
| 0x06 | 最旧循环 (Oldest repeat) | 组内曲目从最旧开始循环播放。 |
| 0x07 | 最新一次 (Newest once) | 组内曲目从最新开始播放一次。 |
| 0x08 | 最新循环 (Newest repeat) | 组内曲目从最新开始循环播放。 |
| 0x09 | 随机一次 (Shuffle once) | 组内曲目随机播放一次。 |
| 0x0A | 随机循环 (Shuffle repeat) | 组内曲目随机循环播放。 |
| 其他值 | 保留 (RFU) | 预留将来使用。 |

16. Playing Orders Supported

支持的播放顺序(Playing Orders Supported)特性是一个 16 位的位字段,用于表示表中描述的受支持的播放顺序。该位字段包含了播放器支持的所有播放顺序。

|------------------|------------------------|----------------------|
| 值 (Value) | 名称 (Name) | 说明 (Description) |
| 0x0001 | 单曲一次 (Single once) | 单曲播放一次;无下一曲目。 |
| 0x0002 | 单曲循环 (Single repeat) | 单曲循环播放;下一曲目即当前曲目。 |
| 0x0004 | 顺序一次 (In order once) | 组内曲目按顺序播放一次。 |
| 0x0008 | 顺序循环 (In order repeat) | 组内曲目按顺序循环播放。 |
| 0x0010 | 最旧一次 (Oldest once) | 组内曲目从最旧开始播放一次。 |
| 0x0020 | 最旧循环 (Oldest repeat) | 组内曲目从最旧开始循环播放。 |
| 0x0040 | 最新一次 (Newest once) | 组内曲目从最新开始播放一次。 |
| 0x0080 | 最新循环 (Newest repeat) | 组内曲目从最新开始循环播放。 |
| 0x0100 | 随机一次 (Shuffle once) | 组内曲目随机播放一次。 |
| 0x0200 | 随机循环 (Shuffle repeat) | 组内曲目随机循环播放。 |
| 0x0400 -- 0x8000 | 保留 (RFU) | 预留将来使用。 |

17. Media State

媒体状态(Media State)特性定义为8位枚举值。以下状态定义如表

|---------------|----------------|--------------------------|
| 值 (Value) | 名称 (Name) | 说明 (Description) |
| 0x00 | 未激活 (Inactive) | 当前曲目无效,未选择任何曲目。 |
| 0x01 | 播放中 (Playing) | 媒体播放器正在播放当前曲目。 |
| 0x02 | 已暂停 (Paused) | 当前曲目已暂停。媒体播放器拥有当前曲目但未播放。 |
| 0x03 | 定位中 (Seeking) | 当前曲目正处于快进或快退状态。 |
| 0x04-0xFF | 保留 (RFU) | 预留将来使用。 |

媒体播放器拥有一个状态机,用于表示其控制状态及状态间的转换。这些状态包括未激活(Inactive)播放中(Playing)已暂停(Paused)定位中(Seeking),如图

这些状态与用于播放音频的音频流无关。媒体播放器可能处于播放中(Playing) 状态而没有相关的音频流,也可能处于未激活(Inactive)已暂停(Paused) 状态而存在相关的音频流。媒体播放器应管理相关音频流的状态以与媒体播放器状态保持一致,但此关系在本服务中未作定义,由具体实现决定。

客户端通过 GATT 读取特性值(Read Characteristic Value) 子过程读取时,媒体状态(Media State) 特性将返回其关联值。

客户端可通过在客户端特性配置描述符(Client Characteristic Configuration descriptor) 上执行 GATT 写入描述符(Write Characteristic Descriptors) 子过程来配置该特性的通知功能。配置完成后,在连接期间可发送该特性的通知。

当媒体状态特性值发生变化时,服务器设备应向客户端设备发送该特性的通知。

18. Media Control Point

媒体控制点(Media Control Point)特性 定义为8位枚举值(称为操作码(opcode)),后接零个或多个参数字节。操作码定义如表

|------------------|-------------------------|--------|---------------------------------|
| 操作码 (Opcode) | 名称 (Name) | 需求 | 说明 (Description) |
| 0x01 | 播放 (Play) | C.1 | 开始播放当前曲目。 |
| 0x02 | 暂停 (Pause) | C.1 | 暂停播放当前曲目。 |
| 0x03 | 快退 (Fast Rewind) | C.1 | 对当前曲目执行快退。 |
| 0x04 | 快进 (Fast Forward) | C.1 | 对当前曲目执行快进。 |
| 0x05 | 停止 (Stop) | C.1 | 停止当前活动并返回暂停状态,将曲目位置设为当前曲目的起始位置。 |
| 0x10 | 相对移动 (Move Relative) | C.1 | 根据当前曲目位置设置一个新的相对曲目位置。 |
| 0x20 | 上一分段 (Previous Segment) | C.1 | 将曲目位置设为当前曲目的上一个分段的起始位置。 |
| 0x21 | 下一分段 (Next Segment) | C.1 | 将曲目位置设为当前曲目的下一个分段的起始位置。 |
| 0x22 | 第一分段 (First Segment) | C.1 | 将曲目位置设为当前曲目的第一个分段的起始位置。 |
| 0x23 | 最后分段 (Last Segment) | C.1 | 将曲目位置设为当前曲目的最后一个分段的起始位置。 |
| 0x24 | 跳转到分段 (Goto Segment) | C.1 | 将曲目位置设为当前曲目的第 n 个分段的起始位置。 |
| 0x30 | 上一曲目 (Previous Track) | C.1 | 根据播放顺序将当前曲目设为上一曲目。 |
| 0x31 | 下一曲目 (Next Track) | C.1 | 根据播放顺序将当前曲目设为下一曲目。 |
| 0x32 | 第一曲目 (First Track) | C.1 | 根据播放顺序将当前曲目设为第一曲目。 |
| 0x33 | 最后曲目 (Last Track) | C.1 | 根据播放顺序将当前曲目设为最后曲目。 |
| 0x34 | 跳转到曲目 (Goto Track) | C.1 | 根据播放顺序将当前曲目设为第 n 曲目。 |
| 0x40 | 上一组 (Previous Group) | C.1 | 将当前组设为组序列中的上一组。 |
| 0x41 | 下一组 (Next Group) | C.1 | 将当前组设为组序列中的下一组。 |
| 0x42 | 第一组 (First Group) | C.1 | 将当前组设为组序列中的第一组。 |
| 0x43 | 最后一组 (Last Group) | C.1 | 将当前组设为组序列中的最后一组。 |
| 0x44 | 跳转到组 (Goto Group) | C.1 | 将当前组设为组序列中的第 n 组。 |
| 其他值 | 保留 (RFU) | -- | 预留将来使用。 |

当写入媒体控制点(Media Control Point) 特性时,服务器应执行该值的第一个字节所定义的行为。

如果控制点写入的操作码为 RFU 或服务器不支持,服务器应发送带有**"操作码不支持"(OPCODE NOT SUPPORTED)** 结果码的媒体控制点通知。

如果因播放器内部错误(非因播放器处于"未激活"状态导致)导致任何控制点写入的请求操作无法成功完成,服务器应发送带有**"命令无法完成"(COMMAND CANNOT BE COMPLETED)** 结果码的媒体控制点通知。

如果在控制点写入发生时媒体状态为"未激活",服务器应执行以下操作之一:

  • 发送带有**"媒体播放器未激活"(MEDIA PLAYER INACTIVE)** 结果码的媒体控制点通知,不执行控制点写入的请求操作。
  • 执行或尝试执行 控制点写入的请求操作,并将媒体状态设为适当状态,并回复相应的媒体控制点通知。

播放(Play)

播放操作码无参数。如果媒体状态 特性值为"已暂停"或"定位中",媒体播放器应开始播放当前曲目,且媒体状态 特性值应设为"播放中"。

如果媒体状态特性值已为"播放中",则保持为"播放中"。

暂停(Pause)

暂停操作码无参数。如果媒体状态 特性值为"播放中",媒体播放器应暂停播放当前曲目,且媒体状态 特性值应设为"已暂停"。

如果媒体状态 特性值为"定位中",媒体播放器应停止定位,根据定位结果设置当前曲目和曲目位置,且媒体状态 特性值应设为"已暂停"。

如果媒体状态特性值已为"已暂停",则保持为"已暂停"。

快退(Fast Rewind)

快退操作码无参数。如果媒体状态 特性值为"已暂停"或"播放中",媒体播放器应将当前曲目位置向后移动。媒体播放器应停止播放当前曲目,将媒体状态 特性设为"定位中",并以实现定义的速率向后移动当前曲目位置。

如果媒体状态 特性值已为"定位中",则应以负方向调整定位速度。媒体播放器处理多次快退操作码写入的方式由实现定义。

如支持,搜索速度(Seeking Speed) 特性应按第3.9节所述进行更新。

快进(Fast Forward)

快进操作码无参数。如果媒体状态 特性值为"已暂停"或"播放中",媒体播放器应将当前曲目位置向前移动。媒体播放器应停止播放当前曲目,将媒体状态 特性设为"定位中",并以实现定义的速率向前移动当前曲目位置。

如果媒体状态 特性值已为"定位中",则应以正方向调整定位速度。媒体播放器处理多次快进操作码写入的方式由实现定义。

如支持,搜索速度(Seeking Speed) 特性应按第3.9节所述进行更新。

停止(Stop)

停止操作码无参数。如果媒体状态 特性值为"播放中"、"已暂停"或"定位中",媒体播放器应停止所有活动,且媒体状态特性应设为"已暂停"。曲目位置应设为当前曲目的起始位置。

相对移动(Move Relative)

相对移动操作码有一个名为"偏移量(offset)"的32位有符号整数参数。如果媒体状态 特性值为"播放中"、"已暂停"或"定位中",应将当前曲目的曲目位置设为当前曲目位置加上偏移量后的值。当前曲目位置不应移动到曲目开始之前,也不应移动到曲目结束之后,且不应回绕。

如果当前曲目位置加上偏移量导致负的曲目位置,则曲目位置 特性应设为0。如果导致超过当前曲目结束的位置,则曲目位置特性应设为曲目结束位置。

上一分段(Previous Segment)

上一分段操作码无参数。如果媒体状态 特性值为"播放中"、"已暂停"或"定位中",应将当前曲目位置设为该曲目的上一个分段的起始位置或当前分段的起始位置,具体由实现决定。"上一分段"定义为分段位置小于当前曲目位置的分段。比较时应考虑合理的用户误差容限,例如,若在分段开始后的几秒内使用上一分段操作码,则上一分段为当前分段之前的分段;但若几秒后使用,则上一分段为当前分段的开始。误差容限的具体时间由实现定义。

如果在第一个分段内收到此操作码,当前曲目位置应设为第一个分段的起始位置。

操作后媒体状态特性值由实现决定。

下一分段(Next Segment)

下一分段操作码无参数。如果媒体状态 特性值为"播放中"、"已暂停"或"定位中",应将当前曲目位置设为该曲目的下一个分段的起始位置。"下一分段"定义为分段位置大于当前曲目内当前位置的分段。如果在最后一个分段内收到此操作码,当前曲目位置应设为该分段结束的位置。

操作后媒体状态特性值由实现决定。

第一分段(First Segment)

第一分段操作码无参数。如果媒体状态 特性值为"播放中"、"已暂停"或"定位中",应将当前曲目位置设为该曲目的第一个分段的起始位置。

操作后媒体状态特性值由实现决定。

最后分段(Last Segment)

最后分段操作码无参数。如果媒体状态 特性值为"播放中"、"已暂停"或"定位中",应将当前曲目位置设为该曲目的最后一个分段的起始位置。

操作后媒体状态特性值由实现决定。

跳转到分段(Goto Segment)

跳转到分段操作码有一个名为"n"的32位有符号整数参数。如果媒体状态 特性值为"播放中"、"已暂停"或"定位中",应将当前曲目位置设为当前曲目内第n个分段的起始位置。如果n为正数,设置当前曲目位置等价于发送一次第一分段操作码,再发送|n|-1次下一分段操作码。如果n为负数,设置当前曲目位置等价于发送一次最后分段操作码,再发送|n|-1次上一分段操作码。如果n为零,当前曲目位置不应改变。

操作后媒体状态特性值由实现决定。

上一曲目(Previous Track)

上一曲目操作码无参数。如果媒体状态 特性值为"播放中"、"已暂停"或"定位中",应将当前曲目设为基于播放顺序的上一个曲目,或保持在当前曲目,具体由实现决定。曲目位置 特性应设为0。操作后媒体状态特性值由实现决定。

下一曲目(Next Track)

下一曲目操作码无参数。如果媒体状态 特性值为"播放中"、"已暂停"或"定位中",应将当前曲目设为基于播放顺序的下一个曲目,且曲目位置 应设为0。操作后媒体状态特性值由实现决定。

第一曲目(First Track)

第一曲目操作码无参数。如果媒体状态 特性值为"播放中"、"已暂停"或"定位中",应将当前曲目设为基于播放顺序的第一个曲目,且曲目位置 应设为0。操作后媒体状态特性值由实现决定。

最后曲目(Last Track)

最后曲目操作码无参数。如果媒体状态 特性值为"播放中"、"已暂停"或"定位中",应将当前曲目设为基于播放顺序的最后一个曲目,且曲目位置 应设为0。操作后媒体状态特性值由实现决定。

跳转到曲目(Goto Track)

跳转到曲目操作码有一个名为"n"的32位有符号整数参数。如果媒体状态 特性值为"播放中"、"已暂停"或"定位中",应将当前曲目设为基于播放顺序的第n个曲目。如果n为正数,设置当前曲目等价于发送一次第一曲目操作码,再发送|n|-1次下一曲目操作码。如果n为负数,则设置当前曲目等价于发送一次最后曲目操作码,再发送|n|-1次上一曲目操作码。如果n为零,当前曲目不应改变。在所有情况下,曲目位置 应设为0。操作后媒体状态特性值由实现决定。

上一组(Previous Group)

上一组操作码无参数。如果媒体状态 特性值为"播放中"、"已暂停"或"定位中",应将当前组设为当前父组中的上一组。当前曲目应设为执行上一组命令后所得当前组的第一个曲目,且曲目位置 应设为0。操作后媒体状态特性值由实现决定。

下一组(Next Group)

下一组操作码无参数。如果媒体状态 特性值为"播放中"、"已暂停"或"定位中",应将当前组设为当前父组中的下一组。当前曲目应设为执行下一组命令后所得当前组的第一个曲目,且曲目位置 应设为0。操作后媒体状态特性值由实现决定。

第一组(First Group)

第一组操作码无参数。如果媒体状态 特性值为"播放中"、"已暂停"或"定位中",应将当前组设为当前父组中的第一组。如果当前组已是当前父组中的第一组,则不应改变。当前曲目应设为执行第一组命令后所得当前组的第一个曲目,且曲目位置 应设为0。操作后媒体状态特性值由实现决定。

最后一组(Last Group)

最后一组操作码无参数。如果媒体状态 特性值为"播放中"、"已暂停"或"定位中",应将当前组设为当前父组中的最后一组。如果当前组已是当前父组中的最后一组,则不应改变。当前曲目应设为执行最后一组命令后所得当前组的第一个曲目,且曲目位置 应设为0。操作后媒体状态特性值由实现决定。

跳转到组(Goto Group)

跳转到组操作码有一个名为"n"的32位有符号整数参数。如果媒体状态 特性值为"播放中"、"已暂停"或"定位中",应将当前组设为当前父组中的第n组。如果n为正数,设置当前组等价于发送一次第一组操作码,再发送|n|-1次下一组操作码。如果n为负数,设置当前组等价于发送一次最后一组操作码,再发送|n|-1次上一组操作码。当前曲目应设为执行跳转到组命令后所得当前组的第一个曲目,且曲目位置 应设为0。如果n为零,当前组不应改变。操作后媒体状态特性值由实现决定。

发送了Media Control Point肯定要有一个ack机制,那么ack就是用notification

媒体控制点(Media Control Point) 特性可通过在客户端特性配置描述符(Client Characteristic Configuration descriptor) 上执行 GATT 写入描述符(Write Characteristic Descriptors) 子过程来配置通知功能。配置完成后,在连接期间可发送该特性的通知。

表展示了媒体控制点通知所需的结构。每次媒体控制点操作码写入后,服务器应向客户端发送媒体控制点通知。如果请求的操作码过程成功完成,则媒体控制点通知的结果码(Result Code) 应设为 "成功(SUCCESS)"。如果请求的操作码过程未能成功完成,则结果码应设为表中的某个值。

|-----------------------|--------------------------------------|------------------------------------------------|
| 结果码 (Result Code) | 定义 (Definition) | 说明 (Description) |
| 0x01 | 成功 (SUCCESS) | 操作码写入请求的动作已成功完成。 |
| 0x02 | 操作码不支持 (OPCODE NOT SUPPORTED) | 媒体控制点写入使用了无效或不支持的操作码。 |
| 0x03 | 媒体播放器未激活 (MEDIA PLAYER INACTIVE) | 收到操作码时媒体状态特性值为"未激活",或操作码请求的动作导致媒体状态特性被设为"未激活"。 |
| 0x04 | 命令无法完成 (COMMAND CANNOT BE COMPLETED) | 因播放器内部状态,媒体控制点写入请求的动作无法成功完成。 |
| 其他值 | 保留 (RFU) | 预留将来使用。 |

19. Media Control Point Opcodes Supported

媒体控制点支持的操作码(Media Control Point Opcodes Supported)特性用于显示服务器当前支持的媒体控制操作码。该特性值为一个32位的位字段,其中第 n 位为 1 表示支持操作码 n,否则为 0。操作码与位字段的对应关系如表所示。

|---------------------------|-------------------------|
| 支持值 (Supported Value) | 名称 (Name) |
| 0x00000001 | 播放 (Play) |
| 0x00000002 | 暂停 (Pause) |
| 0x00000004 | 快退 (Fast Rewind) |
| 0x00000008 | 快进 (Fast Forward) |
| 0x00000010 | 停止 (Stop) |
| 0x00000020 | 相对移动 (Move Relative) |
| 0x00000040 | 上一分段 (Previous Segment) |
| 0x00000080 | 下一分段 (Next Segment) |
| 0x00000100 | 第一分段 (First Segment) |
| 0x00000200 | 最后分段 (Last Segment) |
| 0x00000400 | 跳转到分段 (Goto Segment) |
| 0x00000800 | 上一曲目 (Previous Track) |
| 0x00001000 | 下一曲目 (Next Track) |
| 0x00002000 | 第一曲目 (First Track) |
| 0x00004000 | 最后曲目 (Last Track) |
| 0x00008000 | 跳转到曲目 (Goto Track) |
| 0x00010000 | 上一组 (Previous Group) |
| 0x00020000 | 下一组 (Next Group) |
| 0x00040000 | 第一组 (First Group) |
| 0x00080000 | 最后一组 (Last Group) |
| 0x00100000 | 跳转到组 (Goto Group) |
| 0x00200000 -- 0x80000000 | 保留 (RFU) |

搜索控制点(Search Control Point)特性 的结构定义为一组搜索控制项序列。该特性值的最大长度为64字节。每个搜索控制项由长度(Length)字段类型(Type)字段参数(Parameter)字段组成,具体如表所示。

搜索控制项被连接成一个单一的字节序列。该字节序列可被写入搜索控制点(Search Control Point) 特性以启动搜索操作。类型(Type)字段的值定义如表c

|----------------------|----------------------|----------------------------------|
| 类型值 (Type Value) | 名称 (Name) | 参数说明 (Parameter Description) |
| 0x01 | 曲目名称 (Track Name) | UTF-8字符串 |
| 0x02 | 艺术家名称 (Artist Name) | UTF-8字符串 |
| 0x03 | 专辑名称 (Album Name) | UTF-8字符串 |
| 0x04 | 组名称 (Group Name) | UTF-8字符串 |
| 0x05 | 最早年份 (Earliest Year) | UTF-8字符串 |
| 0x06 | 最晚年份 (Latest Year) | UTF-8字符串 |
| 0x07 | 流派 (Genre) | UTF-8字符串 |
| 0x08 | 仅曲目 (Only Tracks) | 无 |
| 0x09 | 仅组 (Only Groups) | 无 |
| 0x0A-0xFF | 保留 (RFU) | 预留将来使用 |

搜索控制点(Search Control Point) 特性被写入时,服务器应启动搜索操作,并填充当前或新的搜索结果对象。当搜索结果对象完全填充后,若通知功能已启用,服务器应通知客户端设备的搜索结果对象ID(Search Results Object ID) 特性。

写入搜索控制点特性的值是一个由零个或多个搜索控制项组成的序列。每个搜索控制项在逻辑上会生成一组曲目和组。搜索结果对象中包含的曲目和组集合,是满足所有提供的搜索控制项条件的曲目和组。如果向搜索控制点写入零个搜索控制项,则搜索结果由具体实现决定。

例如,要查找1999年的所有曲目,可执行一次包含"仅曲目"条件,并设置"最早年份"为"1999"且"最晚年份"为"1999"的搜索。

如果根据提供的搜索条件未生成任何曲目或组集合,则搜索结果为空,搜索结果对象ID 特性的长度应设为0。

搜索结果的顺序未在本规范中定义。

发送了Search Control Point肯定要有一个ack机制,那么ack就是用notification

搜索控制点(Search Control Point)特性 可通过在客户端特性配置描述符(Client Characteristic Configuration descriptor) 上执行 GATT 写入描述符(Write Characteristic Descriptors) 子过程来配置通知功能。配置完成后,在连接期间可发送该特性的通知。

表3.12展示了搜索控制点通知所需的结构。每次搜索控制点操作码写入后,服务器应向客户端发送搜索控制点通知。如果请求的操作码过程成功完成,则搜索控制点通知的结果码(Result Code) 应设为 "成功(SUCCESS)"。如果请求的操作码过程未能成功完成,结果码宜设为表中的某个值。

|-----------------------|---------------------|----------------------|
| 结果码 (Result Code) | 定义 (Definition) | 说明 (Description) |
| 0x01 | 成功 (SUCCESS) | 搜索请求已接受;搜索已启动。 |
| 0x02 | 失败 (FAILURE) | 搜索请求无效;未启动搜索。 |

搜索结果对象ID(Search Results Object ID)特性 用于访问符合**组对象(Group Object)**类型。该特性通过所包含的OTS(对象传输服务)中的一个组对象来标识搜索结果对象。

若无搜索结果,则该特性的长度应为零。若存在搜索结果,则特性长度为六个字节(即 uint48 类型的大小),且特性值应为 uint48 类型的数值,其范围应符合 OTS 中定义的有效对象ID范围。如存在此值,可在所包含的 OTS 中的对象ID特性 中使用该值,以允许访问搜索结果中的对象。

客户端读取该特性时,搜索结果对象ID特性将返回其关联值。

客户端可通过在客户端特性配置描述符(Client Characteristic Configuration descriptor) 上执行 GATT 写入描述符(Write Characteristic Descriptors) 子过程来配置该特性的通知功能。配置完成后,在连接期间可发送该特性的通知。

当搜索结果对象完全填充后,若通知功能已启用,服务器应向客户端设备发送搜索结果对象ID特性的通知。

22. Content Control ID

内容控制ID(Content Control ID,CCID) 特性。

客户端读取时,内容控制ID特性应返回其关联值。

仅当服务的句柄范围受服务变更影响时,该服务实例中的CCID特性值方可更改。否则,CCID特性值不应改变,并应在跨连接时保持不变。

在MCS的一个实例中,只能存在一个CCID特性实例

相关推荐
墨染倾城殇1 个月前
蓝牙模块低功耗革命:LE Audio多通道音频技术详解(TWS同步/家庭影院/VR音效)
蓝牙模块·低功耗蓝牙模块·le audio
jiang_bluetooth1 年前
Bluetooth LE AUDIO架构概述
架构·蓝牙·ble audio·le audio