背景
在保存aac格式的信息流時必須要對每一幀aac信息流加以頭信息,否則解碼器無法識別aac信息流,這個信息頭就是ADTS信息頭。
代碼
int write_ADTS_header(AVPacket *pkt, AVCodecParameters& codecpar) {
int length = pkt->size + ADTS_HEADER_SIZE;
uint8_t *data1 = new uint8_t[length];
memcpy(data1 + ADTS_HEADER_SIZE, pkt->data, pkt->size);
uint8_t pb[ADTS_HEADER_SIZE] = { 0 };
int sample_index = 0x4;
int channel = codecpar.channels;
switch (codecpar.sample_rate)
{
case 48000:sample_index = 0x3;
break;
case 44100:sample_index = 0x4;
break;
case 32000:sample_index = 0x5;
break;
}
// # 編輯信息頭
pb[0] = 0xff;
pb[1] = 0xf1;
pb[2] = 0x40 | (sample_index << 2) | (channel >> 2);
pb[3] = ((channel & 0x3) << 6) | (length >> 11);
pb[4] = (length >> 3) & 0xff;
pb[5] = ((length << 5) & 0xff) | 0x1f;
pb[6] = 0xfc;
// # end 編輯信息頭
memcpy(data1, &pb, ADTS_HEADER_SIZE);
av_packet_unref(pkt);
pkt->data = data1;
pkt->size = length;
return 0;
}
上面的函數不能直接使用,這個函數是錯誤的,僅供參考
代碼參考數據
以下信息轉載自黃夢軒:AAC的ADTS頭解析
ADTS頭包含了AAC文件的採樣率、通道數、幀數據長度等信息。ADTS頭分爲固定頭信息和可變頭信息兩個部分,固定頭信息在每個幀中的是一樣的,可變頭信息在各個幀中並不是固定值。ADTS頭一般是7個字節((28+28)/ 8)長度,如果需要對數據進行CRC校驗,則會有2個Byte的校驗碼,所以ADTS頭的實際長度是7個字節或9個字節。
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,解碼時忽略
可變頭信息:adts_variable_header()
- 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個採樣及相關數據)。