在我們的日常生活中,比如有緩存電影或者是發送視頻的需求。如果沒有視頻壓縮,一部手機只能存幾分鐘視頻,1TB 硬盤也裝不下幾部電影,用 4G 網絡發一段 1 分鐘視頻,可能需要幾十分鐘(甚至傳不完),在線看視頻更是完全不可能。所以就引入了H264這樣的壓縮技術。這邊文章更注重如何傳輸(NAL)。
如何進行壓縮
空間冗余:一幀圖像中可能會有一片像素是相似的,就可以進行壓縮
時間冗余:幾幀圖像之間會有一些像素部分變化較小,可以進行壓縮
視頻編碼關鍵點
壓縮比:壓縮比越高,視頻文件越小。
算法復雜度:復雜度越高,對設備性能要求越高,但可能帶來更高的壓縮效率或畫質。
還原度:指編碼后的視頻與原始視頻的畫質接近程度。
壓縮比、算法復雜度、還原度并非孤立存在,而是形成 “不可能三角”,三者相互制約
H.264的2大組成部分(NAL VCL)
VCL:負責 “壓縮視頻內容”,通過幀內 / 幀間預測、變換量化等技術,去除視頻中的冗余信息,生成高效壓縮的核心視頻數據。
NAL:負責 “適配網絡傳輸”,將 VCL 生成的壓縮數據打包成符合網絡傳輸規則的單元(加起始碼、頭部信息等),確保數據能在網絡中穩定傳輸和解碼。
H.264編碼相關的一些概念
宏塊(macroblock):宏塊內的像素相似度比較高,前面講到的空間冗余就和這個有關
片(slice):片比宏塊大是組成幀的一部分
幀(frame):一幅圖像
I幀:只進行幀內壓縮,圖像較為完整
B幀:參考前后幀得出當前幀
P幀:只參考前一幀得出當前幀
幀率(fps):單位時間內視頻顯示的畫面幀數
以下是一段H.264的文件進行解析,此處要用到工具winhex和SpecialVH264.exe
由實驗結果可知海思平臺編碼出來的H.264碼流都是一個序列包含:1sps+1pps+1sei+1I幀+若干p幀
對應以上兩個實驗結果繼續詳細的介紹H.264的NAL部分:
序列(sequence):給視頻分段,一個序列就是一個視頻段(每個段都參考一個I幀減小誤差)
分隔符:可以看到轉二進制之后都會用一個00 00 00 01進行分割,在數據段部分有兩個00就會用一個03進行分割,以免數據段和分隔符出現重復
nal_ref_idc:表示該幀數據的重要性,因為網絡傳輸難以避免會出現丟包的情況,定義標志位防止重要的包被丟棄
NALU:分隔符后一位就是NALU,用于標識該幀的類型和其重要性,具體可以參考H264(NAL簡介與I幀判斷)
SPS:規定整個視頻的基礎屬性(比如多大尺寸、每秒多少幀),解碼器先看它才知道怎么 “看懂” 整個視頻。
PPS:針對每幀畫面的編碼方式做具體說明(比如怎么壓縮、怎么去噪),指導解碼器處理單幀數據。
SEI:不是必要的,不直接影響畫面內容,但提供與視頻相關的 “額外信息”(如時間戳、版權聲明、畫質增強提示等),輔助解碼器更好地處理或顯示視頻
如何通過SPS和PPS看到詳細的屬性呢
上面是通過SpecialVH264.exe這個工具查看到的,關于每一項的具體意思可以參考H264碼流中SPS PPS詳解這一篇文章
其中有幾個比較重要的屬性
profile:可以理解為定義了編碼工具的集合,不同的profile,包含了不同的編碼技術
level:主要是對碼流的關鍵參數的取值范圍作了限定,與解碼器的處理能力和存儲能力相關聯
對于profile和level可以看h264中profile和level的含義
pic_width_in_mbs_minus1:用于計算圖像的寬度 frame_width = 16 × (pic_width_in_mbs_minus1 + 1);
pic_height_in_map_units_minus1:用來度量視頻中一幀圖像的高度計算公式和寬度一樣
關于海思平臺H.264的一些知識
p幀的個數等于fps-1;
I幀越大則P幀可以越小,反之I幀越小則P幀會越大,可以理解為參考的越少,自己要做的更多;
I幀的大小取決于圖像本身內容,和壓縮算法的空間壓縮部分;
P幀的大小取決于圖像變化的劇烈程度;
CBR和VBR下P幀的大小策略會不同,CBR時P幀大小基本恒定,VBR時變化會比較劇烈;