2. AVB核心协议栈:IEEE 802.1AS、802.1Qav、802.1Qat、IEEE 1722
好,咱们直接进入正题。AVB协议栈,说白了就是一套让以太网能“准时”传输音视频的规矩。我当年刚接触时,也被这堆802.1编号搞得头晕。但拆开来看,核心就四个协议,各管一摊。
2.1 IEEE 802.1AS:时间同步——让所有设备用同一个“钟”
音视频传输最怕什么?不同步。你想想看,扬声器比画面慢半秒,这体验谁受得了?802.1AS就是解决这个问题的。
它基于IEEE 1588的精确时间协议(PTP),但做了简化。我习惯叫它“gPTP”(generalized PTP)。为什么简化?因为AVB场景相对固定,不需要1588那么复杂的配置。
核心原理:主从架构,选一个“最佳主时钟”(BMCA),其他设备跟着它对时。
具体怎么对时?我举个例子。主时钟发一个“Sync”报文,里面带上发送时间t1。从设备收到后记下接收时间t2。然后主时钟再发一个“Follow_Up”报文,把t1精确告诉从设备。从设备再发“Delay_Req”,主时钟回“Delay_Resp”。这样来回四次,从设备就能算出自己和主时钟的偏差。
// 时间同步计算简化示例
// 假设:
// t1 = 1000ns (主时钟发送Sync)
// t2 = 1500ns (从时钟接收Sync)
// t3 = 2000ns (从时钟发送Delay_Req)
// t4 = 2500ns (主时钟接收Delay_Req)
// 往返延迟 = (t4 - t1) - (t3 - t2)
// = (2500 - 1000) - (2000 - 1500)
// = 1500 - 500 = 1000ns
// 单向延迟 = 往返延迟 / 2 = 500ns
// 时钟偏差 = t2 - t1 - 单向延迟
// = 1500 - 1000 - 500 = 0ns
我的经验:802.1AS的精度通常在亚微秒级。我在项目中实测过,百兆以太网下能做到±200ns以内。但要注意,交换机的转发延迟必须对称,否则误差会累积。
802.1AS还定义了“时间感知系统”——所有支持gPTP的桥接设备(交换机)都要参与时间同步。这意味着你的交换机也得支持这个协议,不是随便一个傻瓜交换机就能用的。
2.2 IEEE 802.1Qat:流预留协议——给音视频数据“开绿灯”
时间同步好了,数据怎么保证不丢包?这就需要流预留了。802.1Qat,也叫SRP(Stream Reservation Protocol)。
它的思路很简单:在数据发送前,先跟网络“打个招呼”。告诉沿途的交换机:“我要发一路音视频流,需要多少带宽,请给我预留。”
具体流程分两步:
- Talker宣告:发送端广播一个“Talker Advertise”报文,描述流的特征(目的MAC、VLAN ID、最大帧大小、帧间隔等)。
- Listener注册:接收端收到后,回复“Listener Ready”报文。沿途每个交换机都会检查自己是否有足够资源。如果都OK,就建立一条预留路径。
注意:如果某个交换机资源不足,它会回复“Listener Asking Failed”,整个预留就失败了。我曾经遇到过一个坑——交换机内部缓冲区不够,导致预留总是失败,查了半天才发现是硬件限制。
预留成功后,交换机会为这条流维护一个“注册状态”。说白了就是一张表,记录着哪个端口、哪个优先级、多少带宽。
| 字段 | 说明 | 我的建议 |
|---|---|---|
| Stream ID | 唯一标识一条流 | 用MAC+流句柄组合,避免冲突 |
| Destination MAC | 目的MAC地址(通常是组播) | 建议使用AVB保留的组播地址范围 |
| VLAN ID | VLAN标识 | AVB通常用VLAN 2或3 |
| Max Frame Size | 最大帧长度 | 根据音频采样率计算,别留太大余量 |
| Max Interval Frames | 每个时间间隔内的最大帧数 | 这个值影响带宽计算,要算准 |
2.3 IEEE 802.1Qav:转发与排队——保证低延迟的关键
流预留好了,数据怎么转发?802.1Qav就是干这个的。它定义了“时间敏感流”的转发规则。
核心机制是“基于信用的整形”(CBS,Credit-Based Shaper)。我刚开始觉得这名字挺唬人,其实原理不复杂。
每个AVB流都有一个“信用值”。信用值会随时间增加,发送数据时减少。只有当信用值大于等于0时,才能发送数据。这样做的目的是:
- 避免突发:不会一下子把所有数据都发出去,而是平滑地发送
- 保证带宽:信用值的增减速率决定了流的带宽
- 低延迟:高优先级流可以快速获得信用值,优先发送
关键参数:idleSlope(空闲斜率)和sendSlope(发送斜率)。idleSlope决定了信用值增加的速度,也就是流的预留带宽。sendSlope通常是idleSlope的负值。
// CBS整形器伪代码
// 假设:
// idleSlope = 100 Mbps (预留带宽)
// sendSlope = -100 Mbps
// 当前信用值 = 0
// 每收到一个数据帧:
if (信用值 >= 0) {
发送数据帧
信用值 -= 帧大小 * (sendSlope / 链路速率)
} else {
等待,直到信用值 >= 0
}
// 空闲时:
信用值 += idleSlope * 空闲时间
// 信用值上限由 hiCredit 和 loCredit 限制
802.1Qav还定义了8个优先级队列。AVB流通常使用优先级3和4。优先级3用于A类流(延迟要求<2ms),优先级4用于B类流(延迟要求<50ms)。
避坑指南:我曾经在一个项目里发现,某些交换机的CBS实现有bug——信用值计算溢出。后来我加了个保护,定期重置信用值。如果你用商用芯片,一定要确认CBS实现是否完整。
2.4 IEEE 1722:AVB传输协议——把音视频数据“打包”
时间同步了,流预留了,转发规则定了。最后一步:数据怎么封装?这就是IEEE 1722的事。
IEEE 1722定义了AVB数据包的格式。它把音视频数据封装在标准的以太网帧里,加上时间戳等信息。
一个典型的AVB音频包长这样:
// IEEE 1722 AVB音频包结构
// 以太网头 (14字节)
// - 目的MAC: 01:00:5E:xx:xx:xx (组播)
// - 源MAC: 设备MAC
// - EtherType: 0x22F0 (AVB)
//
// AVB头部 (8字节)
// - subtype: 0x00 (音频)
// - stream_id: 8字节 (流标识)
// - avtp_timestamp: 32位 (精确时间戳)
//
// 音频数据 (N字节)
// - 采样数据,格式由stream_format指定
//
// 填充 (如果需要)
// CRC (4字节)
这里最核心的是时间戳。每个音频包都带有一个精确的发送时间,接收端根据这个时间戳来播放。这样即使网络有抖动,播放端也能保持同步。
| 字段 | 长度 | 说明 |
|---|---|---|
| subtype | 8位 | 数据类型:0=音频,1=视频,2=控制 |
| stream_id | 64位 | 全局唯一流标识,通常用MAC+序号 |
| avtp_timestamp | 32位 | 基于gPTP时间的发送时间戳 |
| stream_data | 可变 | 实际的音视频数据 |
注意:IEEE 1722的时间戳是32位的,单位是纳秒。这意味着每4.29秒会溢出一次。实际应用中,接收端需要处理这个溢出,否则播放会断。我一般用“时间戳+序列号”组合来避免这个问题。
IEEE 1722还定义了多种音频格式:
- IEC 61883-6:兼容传统1394音频格式
- AAF:AVB音频格式,更灵活
- CRF:时钟恢复格式,用于同步
我个人推荐用AAF格式。它支持多种采样率(44.1kHz、48kHz、96kHz等)和位深(16位、24位、32位)。而且AAF的包头开销小,带宽利用率高。
小结
这四个协议的关系,我打个比方:
- 802.1AS 是“钟表匠”,让所有设备时间一致
- 802.1Qat 是“交通调度员”,提前规划好路线
- 802.1Qav 是“交警”,保证车流顺畅不堵车
- IEEE 1722 是“快递员”,把货物打包好准时送达
缺了任何一个,AVB都跑不起来。我在项目中见过不少只实现了部分协议的方案,结果要么同步不准,要么丢包严重。所以,如果你要做AVB产品,这四个协议一个都不能少。