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)。

它的思路很简单:在数据发送前,先跟网络“打个招呼”。告诉沿途的交换机:“我要发一路音视频流,需要多少带宽,请给我预留。”

具体流程分两步:

  1. Talker宣告:发送端广播一个“Talker Advertise”报文,描述流的特征(目的MAC、VLAN ID、最大帧大小、帧间隔等)。
  2. 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产品,这四个协议一个都不能少。