从零开始学习音视频编程技术(42) AAC数据解析
时间:2019年11月25日 人气:...



AAC基本格式

AAC音频格式有ADIF和ADTS:

ADIF:Audio Data Interchange Format 音频数据交换格式。这种格式的特征是可以确定的找到这个音频数据的开始,不需进行在音频数据流中间开始的解码,即它的解码必须在明确定义的开始处进行。故这种格式常用在磁盘文件中。

ADTS:Audio Data Transport Stream 音频数据传输流。这种格式的特征是它是一个有同步字的比特流,解码可以在这个流中任何位置开始。它的特征类似于mp3数据流格式。

简单说,ADTS可以在任意帧解码,也就是说它每一帧都有头信息。ADIF只有一个统一的头,所以必须得到所有的数据后解码。且这两种的header的格式也是不同的,目前一般编码后的和抽取出的都是ADTS格式的音频流。

语音系统对实时性要求较高,基本是这样一个流程,采集音频数据,本地编码,数据上传,服务器处理,数据下发,本地解码



一、ADTS格式

1. ADTS(Audio Data Transport Stream)头之于AAC

AAC音频文件的每一帧都由一个ADTS头和AAC ES(AAC音频数据)组成。

ADTS是帧序列,本身具备流特征,在音频流的传输与处理方面更加合适。

ADTS 整体结构

 AAC数据帧

2. ADTS头分析

ADTS头包含了AAC文件的采样率、通道数、帧数据长度等信息。ADTS头分为固定头信息和可变头信息两个部分,固定头信息在每个帧中的是一样的,可变头信息在各个帧中并不是固定值。ADTS头一般是7个字节((28+28)/ 8)长度,如果需要对数据进行CRC校验,则会有2个Byte的校验码,所以ADTS头的实际长度是7个字节或9个字节。

2.1 固定头信息:adts_fixed_header()

ADTS头的固定头信息在每个帧中都是一样的。

adts_fixed_header


  • syncword:帧同步标识一个帧的开始,固定为0xFFF

  • ID:MPEG 标示符。0表示MPEG-4,1表示MPEG-2

  • layer:固定为'00'

  • protection_absent:标识是否进行误码校验。0表示有CRC校验,1表示没有CRC校验

  • profile:标识使用哪个级别的AAC。1: AAC Main  2:AAC LC (Low Complexity)  3:AAC SSR (Scalable Sample Rate) 4:AAC LTP (Long Term Prediction)

  • sampling_frequency_index:标识使用的采样率的下标

  • private_bit:私有位,编码时设置为0,解码时忽略

  • channel_configuration:标识声道数

  • original_copy:编码时设置为0,解码时忽略

  • home:编码时设置为0,解码时忽略


其中sampling_frequency_index如下:

                                             sampling_frequency_index


channel_configuration如下:

channel_configuration


2.2 可变头信息:adts_variable_header()

adts_variable_header.png


  • copyrighted_id_bit:编码时设置为0,解码时忽略

  • copyrighted_id_start:编码时设置为0,解码时忽略

  • aac_frame_length:ADTS帧长度包括ADTS长度和AAC声音数据长度的和。即 aac_frame_length = (protection_absent == 0 ? 9 : 7) + audio_data_length

  • adts_buffer_fullness:固定为0x7FF。表示是码率可变的码流

  • number_of_raw_data_blocks_in_frame:表示当前帧有number_of_raw_data_blocks_in_frame + 1 个原始帧(一个AAC原始帧包含一段时间内1024个采样及相关数据)。



二、LATM格式

LATM 的全称为“Low-overhead MPEG-4 Audio TransportMultiplex”(低开销音频传输复用),
是MPEG-4 AAC制定的一种高效率的码流传输方式,MPEG-2 TS 流也采用LATM 
作为AAC 音频码流的封装格式之 LATM格式也
以帧为单位,主要由AudioSpecificConfig(音频特定配置单元)与音频负载组成。
AudioSpecificConfig 描述了一个LATM 帧的信息,音频负载主要由PayloadLengthInfo(负载长度信息)和PayloadMux(负载净荷)组成
AudioSpecificConfig 信息可以是带内传,也可以是带外传。所谓带内传,就是指每一个LATM 帧,都含有一个AudioSpecificConfig 信息;
而带外传,则每一个LATM帧都不含有AudioSpecificConfig 信息,而通过其他方式把AudioSpecificConfig信息发送到解码端,
由于AudioSpecificConfig 信息一般是不变的,所以只需发送一次即可。由此可见,
AudioSpecificConfig 信息采用带内传输可适应音频编码信息不断变化的情况,
而采用带外传输,可以节省音频传输码率。带内或带外传,由muxconfigPresent 标志位决定。例如流媒体应用中,
muxconfigPresent 可设置为0,这样LATM帧中将不含有AudioSpecificConfig 信息,LATM帧通过RTP包发送出去,
AudioSpecificConfig 可通过SDP文件一次性传送到解码端。

AudioSpecificConfig主要参数

numSubFrames 子帧的数目

numProgram 复用的节目数

numLayer 复用的层数

frameLengthType 负载的帧长度类型,包括固定长度与可变长度

audioObjectType音频对象类型

samplingFrequency采样率

channelConfiguration声道配置


音频负载由若干子帧组成,每个子帧由PayloadLengthInfo和PayloadMux组成
与ADTS帧净荷一样,音频负载主要包含原始帧数据。

AAC打包成TS流通常有两种方式,分别是先打包成ADTS或LATM。ADTS的每一帧都有个帧头,在
每个帧头信息都一样的状况下,会有很大的冗余。LATM格式具有很大的灵活性,每帧的音频配置单元既可以带内传输,
又可以带外传输。正因为如此,LATM不仅适用于流传输还可以用于RTP传输,
RTP传输时,若音频数据配置信息是保持不变,可以
先通过SDP会话先传输StreamMuxConfig(AudioSpecificConfig)信息,
由于LATM流由一个包含了一个或多个音频帧的audioMuxElements(音频复用元素)序列组成。
一个完整或部分完整的audioMuxElement可直接映射到一个RTP负载上。

下面是一个audoMuxEmlemt

AudioMuxElement(muxConfigPresent)
{
    //muxconfigPresent 可设置为0,这样LATM帧中将不含有AudioSpecificConfig 信息,
    //LATM帧通过RTP包发送出去,
    if (muxConfigPresent) 
    {
    useSameStreamMux;
    if (!useSameStreamMux)
    StreamMuxConfig(); 
    
    }
    if (audioMuxVersionA == 0)
    { 
        for (i = 0; i <= numSubFrames; i++)
        { 
        PayloadLengthInfo();
        PayloadMux();
        }
    }
}

可以很简单的把ADTS帧转换为LATM帧,根据ADTS头的信息,生成StreamMuxConfig
将ADTS中的原始帧提取出来,前面加上PayloadLengthInfo做为LATM的音频帧
按照上述格式打包生成AudioMuxElement,作为RTP的负载传输.


本文总结自以下网址:

https://www.jianshu.com/p/b5ca697535bd

https://blog.csdn.net/qingkongyeyue/article/details/77621950


学习音视频技术欢迎访问 http://blog.yundiantech.com  

音视频技术交流讨论欢迎加 QQ群 121376426