本人由於最近在讀取h264檔案的時候,遇到如何讀取完整一幀資料的問題,通過使用elecard stream analyzer工具,以及結合《新一代視頻壓縮編碼通訊協定--H264/AVC》(第二版)書,並在網上尋找總結如下:
首先NAL句法,標題句法以及nal_unit_type語義必須知道:
以上兩圖截自《新一代視頻壓縮編碼通訊協定--H264/AVC》(第二版)
簡單的區分幀的方法就是讀取檔案的時候與0x00 0x00 0x00 0x01比較,如果相等認為是一個片,再讀取一個位元組就對應表6.1的forbidden_zero_bit(1bit),nal_ref_idc(2bit),nal_unit_type(5bit),nal_unit_type值根據表6.20可以確定該框架類型,對於7,8是沒有first_mb_in_slice,可以一直讀到下一個0x00 0x00 0x00 0x01這之間的資料都是參數集資料。對於1,5都是有first_mb_in_slice並且每一幀第一片的first_mb_in_slice都是0,這對於分成多片的一幀資料的擷取是很有用的。
下面是指數哥倫布碼的解析:來自http://blog.csdn.net/simongyley/article/details/8517817
解析k階指數哥倫布碼時,首先從位元流的當前位置開始尋找第一個非零位元,並將找到的零位元個數記為leadingZeroBits,然後根據leadingZeroBits計算CodeNum。用虛擬碼描述如下:
first_mb_in_slice是需要對h264通過ExpGolomb編碼過的一串2進位數進行ExpGolomb解碼得到,通過在網上多方尋找並結合h264的檔案分析,終於找到了計算方法,現在跟大家分享一下,有不對的地方歡迎指正。
I幀情況:
如下圖所示:
88 80 = 1000 1000 1000 0000 假設階數為0,那麼leadingZeroBits=0, CodeNum(first_mb_in_slice) = 1-1+0=0
06 62 = 0000 0110 0110 0010 假設階數為0,那麼LeadingZeroBits=5, CodeNum(first_mb_in_slice)=2EXP(5)-2EXP(0)+10011(2進位)=32-1+19=50
p幀情況:
如下圖所示:
9A 00 = 1001 1010 0000 0000 假設階數為0,那麼leadingZeroBits=0, CodeNum(first_mb_in_slice) = 1-1+0=0
03 29 = 0000 0011 0010 1001 假設階數為0,那麼LeadingZeroBits=6, CodeNum(first_mb_in_slice)=2EXP(6)-2EXP(0)+100101(2進位)=64-1+37=100
其實對於0階而言,最簡單的方法就是判斷該位元組第一個bit是否為1,如果是1,CodeNum(first_mb_in_slice),肯定為0,就是一幀的第一片。
原理解說完畢,希望對大家有所協助。具體計算first_mb_in_slice的代碼網上應該比較多,也可以參考ffmpeg的。