概述
AAC,英文全称为Advanced Audio Coding,是一种高效的有损音频压缩格式,由MPEG-4标准定义。相比传统的MP3,AAC在相同比特率下能提供更好的音质,尤其在低比特率场景下优势明显。AAC支持多种采样率、声道数和编码工具,比如:LC(Low Complexity)、HE-AAC(High-Efficiency AAC)、HE-AAC v2(增强型高效率AAC)等,可适应不同应用场景的需求。
AAC ADTS
AAC ADTS是指AAC数据在传输或存储时,采用的封装格式。ADTS为AAC编码的音频数据提供了一个标准化的容器,使得非实时流媒体环境(比如:文件系统、HTTP下载等)也能方便地处理和识别AAC数据。ADTS头部结构详细描述了封装AAC音频数据的ADTS帧的前导部分,它包含了必要的信息以供解码器正确识别、解析和解码AAC音频数据。在实际应用中,ADTS头部通常为7个字节,不包含CRC校验。当需要增加数据完整性检查时,可以选择添加2个字节的CRC校验,此时头部总长度为9个字节。ADTS头部包含以下字段。
syncword:同步字,固定为0xFFF,占12位,用于识别ADTS帧的起始位置。
ID:固定为0,占1位,表明是MPEG-4格式的音频数据。
layer:固定为0,占2位,无特定含义,在MPEG-1/2 Layer III中用于区分层信息,但在AAC中未使用。
protection absent:占1位,表示是否包含CRC校验。1表示没有CRC校验(通常情况),0表示存在CRC校验。
profile:占2位,表示AAC编码的Profile,如0表示AAC Main Profile,1表示AAC Low Complexity (LC),2表示AAC Scalable Sample Rate (SSR),3保留。
sampling freq:占4位,采样率索引,指示音频的采样频率。比如:0表示96 kHz,1表示88.2 kHz,2表示64 kHz,3表示48 kHz,4表示44.1 kHz,5表示32 kHz,6表示24 kHz,7表示22.05 kHz,8表示16 kHz,9表示12 kHz,10表示11.025 kHz,11表示8 kHz,12至15保留。
private bit:占1位,保留位,通常为0。
channel config:占3位,表示声道数配置。比如:0表示单声道,1表示立体声,2至7表示多声道模式。
original/copy:占1位,原版/复制标志,通常为0,表示原版。
home:占1位,保留位,通常为0。
emphasis:占2位,强调模式,通常为0,表示无强调。
frame length:占13位,表示当前ADTS帧的总长度(不包括syncword和CRC,如果有),单位为字节。
adts buffer fullness:占11位,解码器缓冲区状态信息,用于解码器的缓冲管理。
number of raw data blocks:占2位,原始数据块数量,通常为00,表示只有一个数据块。
optional CRC:可选,占16位。如果protection absent字段为0,则ADTS头后会跟随一个16-bit的CRC校验码,用于检测ADTS头的完整性。
封装方法
RTP封装AAC音频数据时,需要遵循一定的规则和步骤,以确保音频数据能够被正确地传输和解码。与H264、H265的封装方法相比,AAC的封装方法相对比较简单。AAC音频帧一般比较小,只用一个RTP包便可以承载。因此,可以直接将AAC音频数据放入一个RTP包的Payload中。注意:AAC音频数据不包括ADTS头。此时,RTP包的结构如下。
html
+-----------------------------+
| RTP Header (12 Byte) |
| AAC Header (4 Byte) |
| AAC Data ... |
+-----------------------------+
可以看到,在12字节的RTP Header后,还有4字节的AAC Header,最后才是AAC音频数据。AAC Header的第一个字节固定为0x00,第二个字节固定为0x10。第三、四个字节保存AAC Data的大小,最多只能保存13位。第三个字节保存数据大小的高8位,第四个字节的高5位保存数据大小的低5位。如果用C/C++实现,可以参考下面的示例代码。
cpp
rtpPacket->payload[0] = 0x00;
rtpPacket->payload[1] = 0x10;
// 取aacDataLen的高8位
rtpPacket->payload[2] = (aacDataLen & 0x1FE0) >> 5;
// 取aacDataLen的低5位
rtpPacket->payload[3] = (aacDataLen & 0x1F) << 3;
AAC的SDP
在使用裸AAC(Raw AAC)格式时,SDP媒体描述应反映这种封装方式,以便接收端能够正确识别、配置解码器并处理音频流。下面,给出了一个针对裸AAC格式的典型SDP媒体描述。
cpp
v=0
o=- 1595963774959070000 1 IN IP4 192.0.2.1
s=Example Session
t=0 0
m=audio 49250 RTP/AVP 96
c=IN IP4 192.0.2.1
a=rtpmap:96 MPEG4-GENERIC/44100/2
a=fmtp:96 streamtype=5;profile-level-id=1;mode=AAC-hbr;sizelength=13;indexlength=3;indexdeltalength=3;
a=ptime:1024
a=maxptime:6144
a=control:trackID=1
m=行中,audio表明这是一个音频媒体流;49250是传输此音频流所使用的端口号;RTP/AVP表示使用RTP进行传输,且使用AVP作为默认的RTP特性集;96是RTP负载类型,用于标识封装在RTP包内的AAC数据。这个值必须与接收端协商一致,以便接收端能够识别出AAC音频。
a=rtpmap行定义了负载类型(PT=96)对应的编码格式和参数。MPEG4-GENERIC表示使用MPEG-4 Generic编码格式封装数据,对于裸AAC而言,这是合适的标识符。44100表示采样率为44.1 kHz,2表示双声道(立体声)。
a=fmtp行提供了负载类型(PT=96)的附加参数。streamtype=5指定为音频流(MPEG-4 Object Type Indication)。profile-level-id=1用于指定AAC编码的Profile和Level,但实际值需参照AAC标准或具体实现。mode=AAC-hbr表示使用AAC High Bit Rate(HBR)模式。sizelength=13;indexlength=3;indexdeltalength=3为AAC音频配置信息的长度,具体值根据实际AAC配置而定。
a=ptime行表示建议的解码器缓冲区处理的最短有效载荷时间(取样点数或毫秒),在此例中为1024个采样点。对于44.1 kHz采样率,相当于约23.2毫秒。
a=maxptime行设置了接收端解码器缓冲区应能处理的最大有效载荷时间(取样点数或毫秒),防止过大的包导致缓冲溢出,在此例中为6144个采样点。对于44.1 kHz采样率,约为143毫秒。