AAC的ADTS標頭檔案資訊介紹
阿新 • • 發佈:2019-02-17
ADTS是Audio Data Transport Stream的簡稱。
博文轉自:http://blog.csdn.net/jay100500/article/details/52955232 是AAC音訊檔案常見的傳輸格式。 有的時候當你編碼AAC裸流的時候,會遇到寫出來的AAC檔案並不能在PC和手機上播放,很大的可能就是AAC檔案的每一幀裡缺少了ADTS頭資訊檔案的包裝拼接。只需要加入標頭檔案ADTS即可。一個AAC原始資料塊長度是可變的,對原始幀加上ADTS頭進行ADTS的封裝,就形成了ADTS幀。 下面分析下ADTS標頭檔案結構和資訊: AAC音訊檔案的每一幀由ADTS Header和AAC Audio Data組成。大家可以用AAC Audio ES Viewer工具來檢視AAC的ADTS Header。
每一幀的ADTS的標頭檔案都包含了音訊的取樣率,聲道,幀長度等資訊,這樣解碼器才能解析讀取。
一般情況下ADTS的頭資訊都是7個位元組,分為2部分:
adts_fixed_header();
adts_variable_header();
先來看:adts_fixed_header();- syncword :總是0xFFF,
代表一個ADTS幀的開始, 用於同步.
解碼器可通過0xFFF確定每個ADTS的開始位置.
因為它的存在,解碼可以在這個流中任何位置開始, 即可以在任意幀解碼。 - ID
- Layer:always: '00'
- protection_absent:Warning, set to 1 if there is no CRC and 0 if there is CRC
- profile:表示使用哪個級別的AAC,如01 Low Complexity(LC) -- AAC LC
profile的值等於 Audio Object Type的值減1.
profile = MPEG-4 Audio Object Type - 1 - sampling_frequency_index:取樣率的下標
- channel_configuration:
- aac_frame_length:一個ADTS幀的長度包括ADTS頭和AAC原始流。frame length, this value must include 7 or 9 bytes of header length:
aac_frame_length = (protection_absent == 1 ? 7 : 9) + size(AACFrame)
protection_absent=0時, header length=9bytes
protection_absent=1時, header length=7bytes - adts_buffer_fullness:0x7FF 說明是位元速率可變的碼流。
- number_of_raw_data_blocks_in_frame:表示ADTS幀中有number_of_raw_data_blocks_in_frame +
1個AAC原始幀。
所以說number_of_raw_data_blocks_in_frame == 0 表示說ADTS幀中有一個AAC資料塊。
(一個AAC原始幀包含一段時間內1024個取樣及相關資料)
這裡給出JAVA和Android裡的給AAC新增ADTS標頭檔案的部分方法程式碼,針對ByteBuffer。
- /**
- * 新增ADTS頭
- *
- * @param packet
- * @param packetLen
- */
- privatevoid addADTStoPacket(byte[] packet, int packetLen) {
- int profile = 2; // AAC LC
- int freqIdx = 4; // 44.1KHz
- int chanCfg = 2; // CPE
- // fill in ADTS data
- packet[0] = (byte) 0xFF;
- packet[1] = (byte) 0xF9;
- packet[2] = (byte) (((profile - 1) << 6) + (freqIdx << 2) + (chanCfg >> 2));
- packet[3] = (byte) (((chanCfg & 3) << 6) + (packetLen >> 11));
- packet[4] = (byte) ((packetLen & 0x7FF) >> 3);
- packet[5] = (byte) (((packetLen & 7) << 5) + 0x1F);
- packet[6] = (byte) 0xFC;
- }
這裡是呼叫:(可根據自己需求,這裡的AudioBufFrame是我們自己專案裡的類,其實就是個ByteBuffer封裝的類)
- AudioBufFrame audioBufFrame = (AudioBufFrame) o;
- int outBufferSize = audioBufFrame.buf.limit() + 7;
- byte[] aacBytes = newbyte[outBufferSize];
- try {
- if (!write) {
- fout = new FileOutputStream(MyConfiguration.VIDEO_PATH + "/audio.aac");
- write = true;
- }
- addADTStoPacket(aacBytes, outBufferSize);
- audioBufFrame.buf.get(aacBytes, 7, audioBufFrame.buf.limit());
- fout.write(aacBytes);
- } catch (IOException e) {
- e.printStackTrace();
- }
- int ff_adts_write_frame_header(ADTSContext *ctx,
- uint8_t *buf, int size, int pce_size)
- {
- PutBitContext pb;
- init_put_bits(&pb, buf, ADTS_HEADER_SIZE);
- /* adts_fixed_header */
- put_bits(&pb, 12, 0xfff); /* syncword */
- put_bits(&pb, 1, 0); /* ID */
- put_bits(&pb, 2, 0); /* layer */
- put_bits(&pb, 1, 1); /* protection_absent */
- put_bits(&pb, 2, ctx->objecttype); /* profile_objecttype */
- put_bits(&pb, 4, ctx->sample_rate_index);
- put_bits(&pb, 1, 0); /* private_bit */
- put_bits(&pb, 3, ctx->channel_conf); /* channel_configuration */
- put_bits(&pb, 1, 0); /* original_copy */
- put_bits(&pb, 1, 0); /* home */
- /* adts_variable_header */
- put_bits(&pb, 1, 0); /* copyright_identification_bit */
- put_bits(&pb, 1, 0); /* copyright_identification_start */
- put_bits(&pb, 13, ADTS_HEADER_SIZE + size + pce_size); /* aac_frame_length */
- put_bits(&pb, 11, 0x7ff); /* adts_buffer_fullness */
- put_bits(&pb, 2, 0); /* number_of_raw_data_blocks_in_frame */
- flush_put_bits(&pb);
- return0;
- }