問題背景:
現在主流的封裝格式支持的音視頻編碼標配是H264+AAC,其中像TS、RTP、FLV、MP4都支持音頻的AAC編碼方式。當然,後繼者不乏Opus這種編碼方式,它主要應用在互聯網場景,比如現在谷歌的WebRTC音視頻解決方案就用的Opus,最新發布的Android10支持的音視頻編碼方式就是AV1和Opus,但是AAC目前在廣電,安防,電影院等還是應用最多,Opus目前還不足以威脅到AAC的地位。本篇文章準備講解下AAC的封裝格式ADTS字段含義和解封裝,順便講解下AAC編碼的一些基本情況,如果你只關心解封裝,直接看【AAC的封裝格式】這節即可。
關注公衆號,瞭解更多!
AAC基本概況:
l AAC(Advance Audio Coding):
即高級音頻編碼,出現在1997年,基於MPEG-2的音頻編碼技術,當時被稱爲MPEG-2 AAC,因此把其作爲MPEG-2(MP2)標準的延伸。是由Fraunhofer IIS、杜比實驗室、AT&T、Sony等公司共同開發,目的是取代MP3格式,隨着MPEG-4(MP4)標準在2000年的成型,則爲AAC也叫M4A。
l 和AC3編碼關係:
和AC3關係不大,AC3早於AAC,是由AAC的發起單位杜比實驗室和日本先鋒合作研製的新編碼方式。AAC能輸出AC-3的任何碼率,勝過AC-3,壓縮率更高,但技術上更加複雜。
l AAC背景和發展:
1997年制定了不兼容MPEG-1的音頻標準MPEG-2 NBC即MPEG-2 AAC;
1999年AAC又增加了LTP和PNS工具,形成了MPEG-4 AAC V1;
2002年在MPEG-4 AAC v1增加了SBR和錯誤魯棒性工具,形成了 HE-AAC;
2004年MPEG-4在HE-AAC引入了PS模塊,提升降碼率性能,形成了EAAC+;
對於1999年、2002年、2004年增加了SBR和PS等編碼技術的統稱爲MPEG-4 AAC;
備註:上面這些SBR PS等縮寫就是音頻的編碼算法代名詞,網上比較多,感興趣的可以進一步自行搜索。1. SBR技術即Spectral Band Replication(頻段複製)音樂的主要頻譜集中在低頻段,高頻段幅度很小,但很重要,決定了音質。如果對整個頻段編碼,若是爲了保護高頻就會造成低頻段編碼過細以致文件巨大;若是保存了低頻的主要成分而失去高頻成分就會喪失音質。SBR把頻譜切割開來,低頻單獨編碼保存主要成分,高頻單獨放大編碼保存音質,“統籌兼顧”了,在減少文件大小的情況下還保存了音質,完美的化解這一矛盾。
2. PS指“parametric stereo”(參數立體聲)。原來的立體聲文件文件大小是一個聲道的兩倍。但是兩個聲道的聲音存在某種相似性,根據香農信息熵編碼定理,相關性應該被去掉才能減小文件大小。所以PS技術存儲了一個聲道的全部信息,然後,花很少的字節用參數描述另一個聲道和它不同的地方。
l AAC編碼技術參數:
採樣率範圍:8KHz-96KHz 範圍比較廣,就是一秒在模擬信號上進行多少次採樣;
碼率:8kbps-576kbps,支持範圍比較寬,在壓縮比和質量上都能考慮到;
聲道:最多支持48個主聲道,16個低頻聲道,聲音細節更豐富,音樂場景也用的多;
採樣精度:就是一個採樣點需要在計算機表示佔用的字節數,一般用2字節16bit表示;
l AAC編碼的主要規格:
根據不同的編碼技術,AAC的編碼分爲九種規格,這和H264的編碼規格大同小異。
1. MPEG-2 AAC LC低複雜度規格(Low Complexity)編碼方式比較簡單,沒有增益控制,但是提高了編碼效率,在中等碼率的編碼效率和音質方面,都能找到平衡點。
2. MPEG-2 AAC Main 主規格
3. MPEG-2 AAC SSR 可變採樣率規格(Scaleable Sample Rate)
4. MPEG-4 AAC LC 低複雜度規格(Low Complexity)
5. MPEG-4 AAC Main 主規格--包含了除增益控制之外的全部功能,音質最好
6. MPEG-4 AAC SSR 可變採樣率規格(Scaleable Sample Rate)
7. MPEG-4 AAC LTP 長時期預測規格(Long Term Prediction)
8. MPEG-4 AAC LD 低延遲預測規格(Low Delay)
9. MPEG-4 AAC HE 高效率規格(High Efficency)--這種規格適合用於低碼率編碼,有Nero-ACC編碼器支持,是一種成熟的商用編碼器。
目前使用最多的就是LC和HE(適合降低碼率),流行的Nero AAC編碼程序支持LC、HE、HEv2三種規格的,而且編碼後的AAC音頻,規格都顯示LC。其中HE就是在AAC(LC)編碼技術上增加SBR技術,HEv2就是AAC(LC)上技術上不僅僅增加了SBR技術,同時也增加了PS技術。
所以一般的商業音頻編碼器只支持部分編碼規格,這也是我們選擇編碼器的重要考慮因素之一,因爲不同的編碼規格支持的音頻採樣率,碼率都不一樣,背後採用的編碼技術和算法複雜度也不一樣。
l AAC編碼方式特點:
1. AAC高壓縮比的音頻編碼方式,比G7xx、MP3、AC3系列的壓縮比都高,並且質量和CD差不多,但是和比較新的Opus還是差點,不過Opus目前還未充分普及;
2. AAC也採用了變換編碼算法,採用了更高的濾波器組,這是壓縮高的原因;
3. AAC爲了提高壓縮比,還採用了噪聲重整,反向自適應預測,聯合立體聲和量化霍夫曼編碼算法等新技術;
4. AAC支持了更多的採樣率和比特率,支持了1-48個音軌和多達15個低頻音軌,具有多種語言兼容能力;
5. AAC支持了更寬的聲音頻率範圍,從8KHz-96KHz,遠寬於MP3的16KHz-48KHz範圍;
6. AAC特殊的算法可以保有聲音頻率甚高和甚低頻率。聲音細節更豐富更清晰更接近原聲;
7. AAC採用了優化算法,導致解碼端簡單,降低了解碼端的處理複雜度;
AAC的封裝格式:
n AAC封裝類型:
1. ADIF:Audio Data Interchange Format音頻數據交換格式,這種格式一般應用在將音頻通過寫文件方式存儲在磁盤裏,不能進行隨機訪問,不允許在文件中間開始進行解碼。只有拿到整個文件時才能開始進行渲染播放,這種暫時還沒用到,不是這篇文章的重點。
2. ADTS:Audio Data Transport Stream 音頻數據傳輸流。這種格式的特徵是用同步字節進行將AAC音頻截斷,然後可以允許客戶端在任何地方進行解碼播放,適合網絡傳輸場景。這也是本文介紹的封裝格式重點。
ADTS的格式如下:
n AAC封裝頭字段:
ADIF的格式:
adif_sequence
adif_header + byte_alignment + raw_data_stream
adif_header + byte_alignment + raw_data_block......+ raw_data_block
ADIF Header頭信息如下:
ADTS的格式:
adts_sequence
adts_frame + adts_frame + ...... + adts_frame
adts_fixed_header + adts_variable_header + error_check + raw_data_block + error_check
ADTS header 的固定頭和可變頭信息:
固定頭意思就是一旦音頻文件形成,所有幀的信息頭字段意義都是一樣的,但是可變頭說的是每個幀這裏面字段都有不一樣的地方,不要理解爲可有可無的意思。
ADTS幀頭各個字段和含義:
序號 |
域 |
長度bits |
說明 |
解釋 |
1 |
Syncword |
12 |
all bits must be 1 |
總是0xFFF,代表一個ADTS幀的開始,作爲分界符,用於同步每幀起始位置。 |
2 |
ID即MPEG version |
1 |
0 for MPEG-4, 1 for MPEG-2 |
一般用0,因爲都是屬於MPEG的規範。 |
3 |
Layer |
2 |
always 0 |
總是00 |
4 |
Protection Absent |
1 |
set to 1 if there is no CRC and 0 if there is CRC |
這裏代表是否有CRC檢驗字段,1代表沒有,0代表有。 |
5 |
Profile |
2 |
the MPEG-4 Audio Object Type minus 1 |
代表使用哪個級別和規範的AAC,其中01代表Low Complexity(LC),其中profile等於Audio Object Type的值減1,其中所有Audio Object Type值在下面所示。 |
6 |
Sampling Frequency Index |
4 |
MPEG-4 Sampling Frequency Index (15 is forbidden) |
採樣率下標,由於AAC的採樣率範圍是8KHz-96KHz,所以具體用那個,這個字段決定。 |
7 |
Private Bit |
1 |
set to 0 when encoding, ignore when decoding |
一般默認0即可 |
8 |
Channel Configuration |
3 |
MPEG-4 Channel Configuration (in the case of 0, the channel configuration is sent via an inband PCE) |
通道配置即聲道數,一般2表示立體聲雙聲道。具體取值範圍參考下表。 |
9 |
Originality copy |
1 |
set to 0 when encoding, ignore when decoding |
一般默認0即可 |
10 |
Home |
1 |
set to 0 when encoding, ignore when decoding |
一般默認0即可 |
11 |
Copyrighted identification bit |
1 |
set to 0 when encoding, ignore when decoding |
一般默認0即可 |
12 |
Copyrighted identification Start |
1 |
set to 0 when encoding, ignore when decoding |
一般默認0即可 |
13 |
Aac Frame Length |
13 |
this value must include 7 or 9 bytes of header length: FrameLength = (ProtectionAbsent == 1 ? 7 : 9) + size(AACFrame) |
一個ADTS幀的長度包括ADTS頭和AAC原始流。用AAC原始流長度+7或者9。 當proection_ansent = 0 則+9 proection_ansent = 1 則+7 |
14 |
ADTS Buffer Fullness |
11 |
buffer fullness |
0x7FF 說明是碼率可變的碼流。 0x000代表是固定碼率的碼流。 |
15 |
Number of AAC Frames |
2 |
number of AAC frames (RDBs) in ADTS frame minus 1, for maximum compatibility always use 1 AAC frame per ADTS frame |
ADTS幀中有number_of_raw_data_blocks_in_frame + 1個AAC原始幀。 所以說number_of_raw_data_blocks_in_frame == 0 表示說ADTS幀中有一個AAC數據塊。 (一個AAC原始幀包含一段時間內1024個採樣及相關數據) |
16 |
CRC |
16 |
CRC if protection absent is 0 |
校驗字段,爲可選字段。 |
ADTS各個字段的取值範圍:
1. Profile 取值:
Object Type ID |
Aduio Object Type |
備註 |
1 |
AAC Main |
|
2 |
AAC LC |
最常用 |
3 |
AAC LTR |
|
4 |
SBR |
|
5 |
AAC scalable |
2. Sampling Frequency Index採樣率取值
Sampling frequency index |
value |
備註 |
0x0 即0000 |
96000 |
DVD-Audio、一些 LPCM DVD 音軌、Blu-ray Disc(藍光盤)音軌、和 HD-DVD (高清晰度 DVD)音軌所用所用採樣率 |
0x1 即0001 |
88000 |
|
0x2 即0010 |
64000 |
|
0x03即0011 |
48000 |
miniDV、數字電視、DVD、DAT、電影和專業音頻所用的數字聲音所用採樣率 |
0x04即0100 |
44100 |
音頻 CD, 也常用於 MPEG-1 音頻(VCD, SVCD, MP3)所用採樣率 |
0x05即0101 |
32000 |
|
0x06即0110 |
24000 |
|
0x07即0111 |
22000 |
|
0x08即1000 |
16000 |
|
0x09即1001 |
12000 |
|
0x0a即1010 |
11025 |
|
0x0b即1011 |
8000 |
電話所用採樣率, 對於人的說話已經足夠 |
0x0c即1100 |
7350 |
|
0x0d即1101 |
reserver |
|
0x0e即1110 |
reserve |
|
0x0f即1111 |
escape value |
3. Channel Configuration通道數取值
value |
number of channels |
Audio syntactic list in order received |
tips |
0 |
- |
- |
關於這些字段看下面raw_data_block基本碼流組件說明
|
1 |
1 |
single_channel_element |
1 |
2 |
2 |
channel_pair_element() |
2 |
3 |
3 |
single_channel_element() channel_pair_element() |
1+2 |
4 |
4 |
single_channel_element() channel_pair_element() single_channel_element()
|
1+2+1 |
5 |
5 |
single_channel_element() channel_pair_element()
channel_pair_element()
|
1+2+2 |
6 |
5+1 |
single_channel_element() channel_pair_element() channel_pair_element() lfe_channel_element() |
1+2+2+1 |
7 |
7+1 |
single_channel_element() channel_pair_element() channel_pair_element() channel_pair_element()
lfe_channel_element() |
1+2+2+2+1 |
8-15 |
- |
- |
保留 |
ADTS的raw_data_block基本碼流組件,頭部有3位標誌位id_syn_ele,指示六種不同類型的元素:
id_syn_ele |
數據流 |
含義 |
註釋 |
ID_SCE(0x0) |
single_channel_element() |
單通道元素基本上只由一個ICS組成。一個原始數據塊最可能由16個SCE組成。 |
核心算法區 |
ID_CPE(0x1) |
channel_pair_element() |
由兩個可能共享邊信息的ICS和一些聯合立體聲編碼信息組成。一個原始數據塊最多可能由16個SCE組成。 |
核心算法區 |
ID_CCE(0x2) |
coupling_channel_element() |
藕合通道元素。代表一個塊的多通道聯合立體聲信息或者多語種程序的對話信息。
|
核心算法區 |
ID_LFE(0x3) |
lfe_channel_element() |
低頻元素。包含了一個加強低採樣頻率的通道。 |
核心算法區 |
ID_DSE(0x4) |
data_stream_element() |
數據流元素,包含了一些並不屬於音頻的附加信息。 |
擴展流或者用戶數據,非核心算法區 |
ID_PCE(0x5) |
program_config_element() |
程序配置元素。包含了聲道的配置信息。它可能出現在ADIF 頭部信息中。
|
擴展流或者用戶數據,非核心算法區 |
ID_FIL(0x6) |
fill_element() |
填充元素。包含了一些擴展信息。如SBR,動態範圍控制信息等。 |
擴展流或者用戶數據,非核心算法區 |
實例分析:
用MediaInfo工具可以查看AAC音頻的基本信息
AAC Audio ES Viewer工具可以詳細分析每一個字節
分析各個字段含義
待分析數據:
固定頭十六進制可變頭十六進制
FF F1 4C 8 0 42 E0 00
固定頭二進制可變頭二進制
1111 1111 1111 0001 0100 1100 1000 0000 0100 0010 1110 0000 0000 0000
固定頭字段含義
syncword :
十六進制:0x0FFF (12 bits) 分界符
二進制:1111 1111 1111
ID:
十進制0 (1 bit) 0 代表MPEG4的AAC
二進制0 (1 bit) 0
layer :
十進制0 (2 bits) 固定填充00,默認
二進制0 0
protection_absent:
十進制1 (1 bit),決定了頭的長度,目前7字節
二進制:1
profile :
十進制:1 [Low Complexity profile (LC)] (2 bits)
二進制:01
sampling_frequency_index:
十進制:3 [48000 Hz] (4 bits)
二進制:0011
private_bit
十進制: 0 (1 bit)
二級制:0
channel_configuration
十進制: : 2 [2 - LF RF] (3 bits)
二級制:10
original/copy
十進制: 0 (1 bit),默認
二進制:0
home:
十進制:0 (1 bit),默認
二進制:0
可變頭信息
copyright_identification_bit:
十進制:0 (1 bit),默認
二進制:0
copyright_identification_start :
十進制:0 (1 bit),默認
二進制:0
frame_length:
十進制:535 (13 bits) 長度,包括頭和實際裸流數據535-7=528
二級制:00 0100 0010 111
adts_buffer_fullness:
十進制:0 (11 bits)
二進制:0 0000 0000 00 代表是固定碼率0x000,可變碼率是0x7FF
number_of_raw_data_blocks_in_frame:
十進制:0 (2 bits),代表後面的實際幀數0+1個AAC幀
二級制:00
AAC幀的裸流
raw_data_block()
核心代碼參考:
我們在開發中經常遇到這塊就是AAC封裝格式的解析,需要拿到裸流進行播放和提取裏面的相應字段,或者將裸流打包爲ADTS然後封裝到TS、MP4、FLV中進行打包發送傳輸。下面的代碼通過讀取一個文件流,獲取裏面的ADTS信息和音頻幀。
1. 先定義ADTS頭的結構體
2. 讀取文件流的第一個ADTS音頻幀的頭部數據,並解析裏面的長度;
3. 再根據長度讀取裏面的音頻裸數據;
4. 不斷循環即可完成頭部數據的解析和其裸數據的讀取;
總結:
這篇文章初步講解了AAC音頻編碼的基礎知識,同時引出了AAC裸數據打包音頻幀的兩種方式,其實ADTS給出了用工具分析的實例和進行解封裝的示意代碼,對平時AAC打包FLV、MP4、TS等封裝格式打下基礎。
今天就說這麼多,祝您中秋快樂,工作順利!
往期回顧文章:
個人轉載內容至朋友圈和羣聊天,無需特別申請版權許可。
記得右下角點“在看”,還可以把訂閱號加星標,這樣防止遺漏哦!