RTP 之 AAC 封包和解包

根据课程视频整理:

  • 161--5 RTP之AAC封包和解包1-软件框架分析.mp4
  • 162--5 RTP之AAC封包和解包2-原理和源码解析.mp4

目标:讲清楚 AAC/ADTS、RTP payload、AU Header、时间戳计算、软件框架以及打包/解包流程。

1. 基础概念

AAC 是音频编码格式。开发中常见的 AAC 文件通常带 ADTS 头,每个 ADTS frame 由:

ADTS Header + AAC Raw Data

组成。

RTP 发送 AAC 时,通常不把 ADTS Header 原封不动地塞进 RTP payload,而是提取 AAC raw data,并按 RFC 3640 的方式添加 AU Header 信息。AU 是 Access Unit,可以理解为一个音频访问单元,通常对应一帧 AAC 音频数据。

AAC RTP 软件入口与调试环境

2. 软件框架

课程的 AAC 部分先从软件框架入手,整体路径可以概括为:

读取 AAC 文件
解析 ADTS Header
拿到一帧 AAC raw data
调用 RTP AAC 打包函数
构造 RTP header
构造 AU headers
拷贝 AAC raw data
通过 socket 发送
接收端解析 RTP payload
恢复 AAC frame

AAC RTP 软件框架

代码里通常会拆成几类函数:

读取 AAC 帧的代码路径

3. ADTS Header

ADTS Header 里保存了 AAC 帧的描述信息,常见字段包括:

字段含义
syncword同步头,通常是 0xFFF
profileAAC profile,例如 AAC LC
sampling_frequency_index采样率索引
channel_configuration声道配置
aac_frame_lengthADTS header + AAC raw data 的总长度

读取 AAC 文件时,先通过 ADTS Header 得到当前帧长度,然后读出完整 frame。RTP 打包时通常要跳过 ADTS Header,只发送 AAC raw data。

aac_raw_len = aac_frame_length - adts_header_len

4. AAC RTP Payload 格式

常见 AAC over RTP payload 可以分成三段:

RTP Header | AU-headers-length | AU-header | AAC Raw Data

其中 RTP Header 是标准 RTP 头;AU-headers-lengthAU-header 用来描述后面 AAC raw data 的长度等信息。

AAC RTP 打包流程概览

课程重点讲的字段:

AU-headers-length:2 字节,单位是 bit
AU-header:通常 2 字节,其中 13 bit 表示 AU-size
AAC Raw Data:真正的 AAC 音频负载

如果一个 RTP 包只承载一个 AAC AU,常见做法是:

AU-headers-length = 16
AU-header         = 当前 AAC raw data 长度 << 3

因为 AU-header 长度是 16 bit,其中高 13 bit 是 AU-size,低 3 bit 可理解为 AU-Index 或相关索引位。

AU-headers-length 与 AU-header

5. AU Header 构造

假设 AAC raw data 长度是 len,AU Header 常见构造方式:

payload[0] = 0x00;
payload[1] = 0x10;              // AU-headers-length = 16 bits
payload[2] = (len & 0x1fe0) >> 5;
payload[3] = (len & 0x1f) << 3;
memcpy(payload + 4, aac_raw_data, len);

对应结构:

payload[0..1]  AU-headers-length
payload[2..3]  AU-header
payload[4..]   AAC raw data

AAC AU Header 构造代码

这里最容易混淆的是单位:AU-headers-length 的单位是 bit,不是字节。一个 AU-header 如果占 2 字节,也就是 16 bit,所以值写 0x0010

6. Timestamp 计算

AAC RTP timestamp 使用音频采样率作为时钟。例如采样率是 44100Hz,一个 AAC LC frame 通常包含 1024 个采样点,那么每发送一帧 AAC,timestamp 增量通常是:

1024

这和 H.264 视频常用 90000Hz 时钟不同。视频 timestamp 常按帧率计算,而 AAC timestamp 通常按每帧采样点数推进。

AAC timestamp 和采样率

常见例子:

sample rate = 44100
one AAC frame = 1024 samples
RTP timestamp increment = 1024

如果音频是 48000Hz,timestamp 时钟就是 48000Hz,但 AAC LC 一帧仍通常推进 1024 个采样点。

AAC timestamp 示例

7. AAC RTP 发送流程

发送端可以按这个流程写:

打开 AAC 文件
while 读取一帧 ADTS:
    解析 ADTS Header
    计算 AAC raw data 偏移和长度
    填 RTP Header
    填 AU-headers-length
    填 AU-header
    拷贝 AAC raw data
    发送 RTP 包
    sequence number += 1
    timestamp += 1024

AAC RTP 打包代码

RTP Header 里需要关注:

字段AAC 中的用法
Payload Type动态类型常见为 96,也要和 SDP 对上
Sequence Number每发送一个 RTP 包加 1
Timestamp每个 AAC frame 按采样点推进,常见加 1024
SSRC同一路音频流保持一致
Marker音频里通常不像视频那样强依赖一帧结束标记

8. AAC RTP 解包流程

接收端解析 RTP payload:

跳过 RTP Header
读取 AU-headers-length
根据 AU-headers-length 计算 AU-header 字节数
读取 AU-header,得到 AU-size
按 AU-size 取出 AAC raw data
需要写回 .aac 文件时,重新补 ADTS Header
交给解码器时,按解码器要求决定是否补 ADTS Header

AAC RTP 解包代码

如果要把 RTP 解出的数据保存成可播放的 .aac 文件,一般要重新写 ADTS Header:

ADTS Header | AAC Raw Data
ADTS Header | AAC Raw Data
ADTS Header | AAC Raw Data
...

如果直接送给某些解码器,则可能只需要 raw data,具体取决于解码器输入格式。

9. SDP 中的 AAC 配置

RTSP 的 DESCRIBE 响应里,SDP 会告诉客户端音频流的参数。AAC 常见字段包括:

m=audio ... RTP/AVP 96
a=rtpmap:96 MPEG4-GENERIC/44100/2
a=fmtp:96 ...

其中:

RTSP/SDP 中的 AAC 配置

客户端必须让 SDP 参数和实际 RTP payload 对上,否则可能出现能收到包但无法解码的问题。

10. 调试要点

调试 AAC over RTP 时按下面检查:

最后可以这样记:

AAC over RTP:ADTS 负责文件帧描述,RTP 发送 raw data;payload 前面加 AU Header 说明 raw data 长度。

评论

...

正在读取评论。