从零开始精通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包的结构如下。

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毫秒。

相关推荐
安步当歌29 分钟前
【WebRTC】视频编码链路中各个类的简单分析——VideoStreamEncoder
音视频·webrtc·视频编解码·video-codec
顾北川_野30 分钟前
Android CALL关于电话音频和紧急电话设置和获取
android·音视频
顶呱呱程序34 分钟前
2-143 基于matlab-GUI的脉冲响应不变法实现音频滤波功能
算法·matlab·音视频·matlab-gui·音频滤波·脉冲响应不变法
无所谓จุ๊บ41 分钟前
树莓派开发相关知识十 -小试服务器
服务器·网络·树莓派
道法自然04021 小时前
Ethernet 系列(8)-- 基础学习::ARP
网络·学习·智能路由器
EasyCVR2 小时前
萤石设备视频接入平台EasyCVR多品牌摄像机视频平台海康ehome平台(ISUP)接入EasyCVR不在线如何排查?
运维·服务器·网络·人工智能·ffmpeg·音视频
runing_an_min2 小时前
ffmpeg 视频滤镜:屏蔽边框杂色- fillborders
ffmpeg·音视频·fillborders
明月看潮生3 小时前
青少年编程与数学 02-003 Go语言网络编程 15课题、Go语言URL编程
开发语言·网络·青少年编程·golang·编程与数学
龙哥说跨境3 小时前
如何利用指纹浏览器爬虫绕过Cloudflare的防护?
服务器·网络·python·网络爬虫
懒大王就是我4 小时前
C语言网络编程 -- TCP/iP协议
c语言·网络·tcp/ip