从零开始精通RTSP之传输AAC音频流

概述

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包的结构如下。

css 复制代码
+-----------------------------+
| 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++实现,可以参考下面的示例代码。

ini 复制代码
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媒体描述。

ini 复制代码
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毫秒。

💡 如果想阅读最新的文章,或者有技术问题需要交流和沟通,可搜索并关注微信公众号"希望睿智"。

相关推荐
bluebonnet27几秒前
【Rust练习】22.HashMap
开发语言·后端·rust
Iced_Sheep1 小时前
干掉 if else 之策略模式
后端·设计模式
XINGTECODE1 小时前
海盗王集成网关和商城服务端功能golang版
开发语言·后端·golang
程序猿进阶1 小时前
堆外内存泄露排查经历
java·jvm·后端·面试·性能优化·oom·内存泄露
FIN技术铺2 小时前
Spring Boot框架Starter组件整理
java·spring boot·后端
凡人的AI工具箱2 小时前
15分钟学 Go 第 60 天 :综合项目展示 - 构建微服务电商平台(完整示例25000字)
开发语言·后端·微服务·架构·golang
先天牛马圣体2 小时前
如何提升大型AI模型的智能水平
后端
java亮小白19972 小时前
Spring循环依赖如何解决的?
java·后端·spring
2301_811274312 小时前
大数据基于Spring Boot的化妆品推荐系统的设计与实现
大数据·spring boot·后端
草莓base3 小时前
【手写一个spring】spring源码的简单实现--容器启动
java·后端·spring