1. 程式人生 > >2017.11.1開始學習FFMPEG音視訊編解碼,通過學習雷霄驊文章

2017.11.1開始學習FFMPEG音視訊編解碼,通過學習雷霄驊文章

NAL Header由三部分組成:forbidden_bit,nal_reference_bit(優先順序)2bit,nal_unit_type(型別)5bit。

補充一下NAL_HEADER裡的nal_unit_type一位元組的型別有哪些:

  • 0:未規定                                                                  
  • 1:非IDR影象中不採用資料劃分的片段                (NALU_TYPE_SLICE)
  • 2:非IDR影象中A類資料劃分片段                          (NALU_TYPE_DPA

  • 3:非IDR影象中B類資料劃分片段                          (NALU_TYPE_DPB
  • 4:非IDR影象中C類資料劃分片段                          (NALU_TYPE_DPC
  • 5:IDR影象的片段                                                     (NALU_TYPE_IDR
  • 6:補充增強資訊(SEI)                                          (NALU_TYPE_SEI
  • 7:序列引數集(SPS)                                            (NALU_TYPE_SPS

  • 8:影象引數集(PPS)                                            (NALU_TYPE_PPS)
  • 9:分割符                                                                    (NALU_TYPE_AUD)
  • 10:序列結束符                                                          (NALU_TYPE_EOSEQ
  • 11:流結束符                                                              (NALU_TYPE_EOSTREAM

  • 12:填充資料                                                              (NALU_TYPE_FILL
  • 13:序列引數集擴充套件
  • 14:帶字首的NAL單元
  • 15:子序列引數集
  • 16 – 18:保留
  • 19:不採用資料劃分的輔助編碼影象片段
  • 20:編碼片段擴充套件
  • 21 – 23:保留
  • 24 – 31:未規定
補充一下NAL_HEADER裡的nal_reference_bit有哪些:

            從0到3,3為最高優先順序。

  1. NALU_PRIORITY_DISPOSABLE = 0,  
  2.     NALU_PRIRITY_LOW         = 1,  
  3.     NALU_PRIORITY_HIGH       = 2,  
  4.     NALU_PRIORITY_HIGHEST    = 3
一般一位元組的NAL HEADER :0AABBBBB,常用的NAL HEADER 取值

有:

0x67: SPS 
0x68: PPS 
0x65: IDR   
0x61: non-IDR Slice
0x01: B Slice
0x06: SEI
0x09: AU Delimiter
--------------------------------------------------------------------------------------------------------------------------------------------------------------------

上一階段視訊碼流解析告一段落,上一段的程式主要實現了:從H264視訊原始碼流中提取NALU單元,並簡單的解析NALU首部的欄位,它的型別,程式稍後加上。

下一階段主要學習AAC音訊碼流解析,得到它的基本單元ADTS frame以及簡單解析基本單元ADTS frame首部的欄位。

1.AAC原始碼流是由一個個的ADTS frame組成:

                                         AAC原始碼流:  

                                                                            ADTS frame+ADTS frame+ADTS frame+ADTS frame

2.每個ADTS frame單元之間通過同步字(sync word)進行分隔,同步字為0xFFF,二進位制為:“1111 1111 1111”。

3.AAC碼流解析的步驟就是:先搜尋同步字,分離出ADTS frame單元,再解析ADTS frame首部的各個欄位。

4.對關於音訊碼流的一些基本知識的普及:

                              AAC的英文名稱是:Advenced Audio Coding,高階音訊編碼,是基於MPEG-2的音訊編碼技術。

                              原理:

                                          AAC原始碼流是由一個個的ADTS frame組成,每個ADTS frame之間通過同步字進行分隔,同步字為0xFFF,二進位制為“1111 1111 1111”。

                                          AAC音訊碼流解析的步驟是:首先從碼流中搜索0xFFF,分離出ADTS frame,再解析ADTS frame首部的各個欄位。

                                          ADTS 全稱是:Audio Data Transport Stream,是AAC的一種十分常見的傳輸格式。

                                          可以把ADTS頭看作是AAC的Frame Header:

                                                                                    ADTS_header+AAC ES+ADTS_header+AAC ES+ADTS_header+AAC ES

                                         ADTS頭中有用的資訊:取樣率,聲道數,幀長度。

                                         一般ADTS_Header的頭資訊都是7個位元組,分為兩部分:

                                         adts_fixed_header();

                                        adts_variable_header();

                                      

syncword :同步頭 總是0xFFF, all bits must be 1,代表著一個ADTS幀的開始

ID:MPEG Version: 0 for MPEG-4, 1 for MPEG-2

Layer:always: '00'

profile:表示使用哪個級別的AAC,有些晶片只支援AAC LC 。在MPEG-2 AAC中定義了3種:



sampling_frequency_index:表示使用的取樣率下標,通過這個下標在 Sampling Frequencies[ ]陣列中查詢得知取樣率的值。

There are 13 supported frequencies:

  • 0: 96000 Hz
  • 1: 88200 Hz
  • 2: 64000 Hz
  • 3: 48000 Hz
  • 4: 44100 Hz
  • 5: 32000 Hz
  • 6: 24000 Hz
  • 7: 22050 Hz
  • 8: 16000 Hz
  • 9: 12000 Hz
  • 10: 11025 Hz
  • 11: 8000 Hz
  • 12: 7350 Hz
  • 13: Reserved
  • 14: Reserved
  • 15: frequency is written explictly
channel_configuration: 表示聲道數 
  • 0: Defined in AOT Specifc Config
  • 1: 1 channel: front-center
  • 2: 2 channels: front-left, front-right
  • 3: 3 channels: front-center, front-left, front-right
  • 4: 4 channels: front-center, front-left, front-right, back-center
  • 5: 5 channels: front-center, front-left, front-right, back-left, back-right
  • 6: 6 channels: front-center, front-left, front-right, back-left, back-right, LFE-channel
  • 7: 8 channels: front-center, front-left, front-right, side-left, side-right, back-left, back-right, LFE-channel
  • 8-15: Reserved

frame_length : 一個ADTS幀的長度包括ADTS頭和AAC原始流.

adts_buffer_fullness:0x7FF 說明是位元速率可變的碼流


將AAC ES流打包成ADTS格式,實際上就是在AAC原始流前面加上ADTS頭就行了。

新增ffmpeg新增ADTS頭的程式碼:

  1. int ff_adts_write_frame_header(ADTSContext *ctx,  
  2.                                uint8_t *buf, int size, int pce_size)  
  3. {  
  4.     PutBitContext pb;  
  5.     init_put_bits(&pb, buf, ADTS_HEADER_SIZE);  
  6.     /* adts_fixed_header */  
  7.     put_bits(&pb, 12, 0xfff);   /* syncword */  
  8.     put_bits(&pb, 1, 0);        /* ID */  
  9.     put_bits(&pb, 2, 0);        /* layer */  
  10.     put_bits(&pb, 1, 1);        /* protection_absent */  
  11.     put_bits(&pb, 2, ctx->objecttype); /* profile_objecttype */  
  12.     put_bits(&pb, 4, ctx->sample_rate_index);  
  13.     put_bits(&pb, 1, 0);        /* private_bit */  
  14.     put_bits(&pb, 3, ctx->channel_conf); /* channel_configuration */  
  15.     put_bits(&pb, 1, 0);        /* original_copy */  
  16.     put_bits(&pb, 1, 0);        /* home */  
  17.     /* adts_variable_header */  
  18.     put_bits(&pb, 1, 0);        /* copyright_identification_bit */  
  19.     put_bits(&pb, 1, 0);        /* copyright_identification_start */  
  20.     put_bits(&pb, 13, ADTS_HEADER_SIZE + size + pce_size); /* aac_frame_length */  
  21.     put_bits(&pb, 11, 0x7ff);   /* adts_buffer_fullness */  
  22.     put_bits(&pb, 2, 0);        /* number_of_raw_data_blocks_in_frame */  
  23.     flush_put_bits(&pb);  
  24.     return 0;  

//最近感冒很嚴重,流行感冒,還打了針吃了藥,所以中間間斷了