1. 程式人生 > >rtsp 中的H264 編碼+打包+解碼相關知識 ES 、TS ...

rtsp 中的H264 編碼+打包+解碼相關知識 ES 、TS ...

1)ES流(Elementary Stream): 也叫基本碼流,包含視訊、音訊或資料的連續碼流.

2)PES流(Packet Elementary Stream): 也叫打包的基本碼流, 是將基本的碼流ES流根據需要分成長度不等的資料包, 並加上包頭就形成了打包的基本碼流PES流.

3)TS流(Transport Stream): 也叫傳輸流, 是由固定長度為188位元組的包組成, 含有獨立時基的一個或多個program, 一個program又可以包含多個視訊、音訊、和文字資訊的ES流; 每個ES流會有不同的PID標示. 而又為了可以分析這些ES流, TS有一些固定的PID用來間隔傳送program和ES流資訊的表格: PAT和PMT表,(在MPEG-2系統中,由視訊, 音訊的ES流和輔助資料復接生成的用於實際傳輸的標準資訊流稱為MPEG-2傳送流)

封裝 : 就是捆綁打包, 將畫面視訊檔案和音軌檔案打包在一起, 並按照一定規則建立排序和索引, 便於播放器或播放軟體來索引播放. 包括AVI / PS(Program Stream)/ TS(Transport Stream)/ MKV(Matroska)等。

4)I frame :幀內編碼幀又稱intra picture,I幀通常是每個 GOP(MPEG所使用的一種視訊壓縮技術)的第一個幀,經過適度地壓縮,做為隨機訪問的參考點,可以當成圖象。I幀可以看成是一個影象經過壓縮後的產物。

5)P frame:前向預測編碼幀又稱predictive-frame,通過充分將低於影象序列中前面已編碼幀的時間冗餘資訊來壓縮傳輸資料量的編碼影象,也叫預測幀;

6)B frame:雙向預測內插編碼幀又稱bi-directional interpolated predictionframe,既考慮與源影象序列前面已編碼幀,也顧及源影象序列後面已編碼幀之間的時間冗餘資訊來壓縮傳輸資料量的編碼影象,也叫雙向預測幀;

7)PTS:PresentationTime Stamp。PTS主要用於度量解碼後的視訊幀什麼時候被顯示出來;

8)DTS:Decode TimeStamp。DTS主要是標識讀入記憶體中的bit流在什麼時候開始送入解碼器中進行解碼。

在沒有B幀存在的情況下DTS的順序和PTS的順序應該是一樣的。

I frame:自身可以通過視訊解壓演算法解壓成一張單獨的完整的圖片。

P frame:需要參考其前面的一個I frame或者B frame來生成一張完整的圖片。

B frame:則要參考其前一個I或者P幀及其後面的一個P幀來生成一張完整的圖片。

兩個I frame之間形成一個GOP,在x264中同時可以通過引數來設定bf的大小,即:I和p或者兩個P之間B的數量。

通過上述基本可以說明如果有B frame存在的情況下,一個GOP的最後一個frame一定是P.

(10)DTS和PTS的不同:

DTS主要用於視訊的解碼,在解碼階段使用.PTS主要用於視訊的同步和輸出.在display的時候使用.在沒有B frame的情況下.DTS和PTS的輸出順序是一樣的.

下面給出一個GOP為15的例子,其解碼的參照frame及其解碼的順序都在裡面:

如上圖:I frame 的解碼不依賴於任何的其它的幀.而p frame的解碼則依賴於其前面的I frame或者P frame.B frame的解碼則依賴於其前的最近的一個I frame或者P frame及其後的最近的一個P frame.

(11)視訊解碼大致流程如下:

(12)PTS的計算

方法一、根據前後幀的IPB型別,可以得知幀的實際顯示順序,使用前面獲取的sps資訊中的幀率,以及幀計數frame_count即可計算出PTS。此方法需要做幾幀快取(一般快取一個group的長度)。

I P B B I P B B I P B …幀型別 1 2 3 4 5 6 7 8 9 10 11 …第幾幀 1 4 2 3 5 8 6 7 9 12 10…幀顯示順序

一個I幀與下一個I幀之間,是一個group。 從上圖可見,P型別的幀的顯示順序,是排在後面最後一個B幀之後。 所以要獲取第7幀的pts,起碼要知道他下一幀的型別,才能得知他的顯示順序。

第8幀的pts=1000(毫秒)*7(幀顯示順序)*幀率

方法二、每一個slice的資訊裡面,都記錄有pic_order_cnt_lsb,當前幀在這個group中的顯示順序。通過這個pic_order_cnt_lsb,可以直接計算出當前幀的PTS。此方法不需要做幀快取。

計算公式:

pts=1000*(i_frame_counter+ pic_order_cnt_lsb)*(time_scale/num_units_in_tick)

i_frame_counter是最近一次I幀位置的幀序,通過I幀計數+當前group中的幀序,得到幀實際顯示序列位置,乘上幀率,再乘上1000(毫秒)的base_clock(基本時鐘頻率),得到PTS。

I P B B I P B B I P B …幀型別 1 2 3 4 5 6 7 8 9 10 11 …第幾幀 1 4 2 3 5 8 6 7 9 12 10 …幀顯示順序 0 6 2 4 0 6 2 4 0 6 2 … pic_order_cnt_lsb

細心一點可以注意到,在上圖,slice裡面的pic_order_cnt_lsb是以2進行遞增。 通常H264裡面的sps中記錄的幀率,也是實際幀率的2倍time_scale/num_units_in_tick=fps*2

因此,實際的計算公式應該是這樣 pts=1000*(i_frame_counter2+pic_order_cnt_lsb)(time_scale/num_units_in_tick) 或者是 pts=1000*(i_frame_counter+pic_order_cnt_lsb/2)*(time_scale/num_units_in_tick/2)

所以,第11幀的pts應該是這麼計算 1000*(92+2)(time_scale/num_units_in_tick)

RTP打包H264的時間戳,由於H264標準說明是90000/幀率,這裡pts的base_clock都是按照1000(毫秒)計算,如果複用到ts裡,base_clock是90k,所以還應該再乘以90。

pic_order_cnt_lsb:

lsb:least significant bits POC低位

poc:picture oder counter

pic_order_cnt_type:指明瞭POC(Picture Order Count)的編碼方法、POC標識影象的播放順序。