天天看點

流媒體-H264協定-編碼-x264學習-相關概念x264編譯及檔案解析(一)

  1. 流媒體-H264協定-編碼-x264學習-相關概念x264編譯及檔案解析(一)
  2. 流媒體-H264協定-編碼-x264學習-主要結構體(二)
  3. 流媒體-H264協定-編碼-x264學習-主要函數(三)
  4. 流媒體-H264協定-編碼-x264學習-C++11多線程實作編碼(四)

文章目錄

    • 一、ffmpeg相關指令
    • 二、windows10編譯x264
      • x264源碼下載下傳
      • msys2下載下傳
        • 最常用的pacman指令
        • MSYS2的源配置
        • 安裝依賴
      • 編譯
      • poxports工具下載下傳
      • vc的lib工具生成lib庫
    • 三、概念
      • H.264/AVC
      • 白平衡
      • 指數哥倫布碼編碼
      • 幀内編碼
      • 基于波形的一系列視訊編碼标準
      • 基于内容的編碼
        • 預測編碼
        • 幀内預測 intra
          • 4x4亮度塊預測模式
          • 16x16亮度塊預測模式
      • 幀間預測 inter
        • 運動估計搜尋算法
          • 運動矢量
          • 運動補償
      • 變換編碼
      • 熵編碼
      • 序列參數集 Sequence Paramater Set(SPS)
      • 圖像參數集Picture Paramater Set(PPS)
      • 參數圖像
      • 片(條帶) Slice
      • IDR幀(Instantaneous Decoding Refresh)即時解碼重新整理
      • H.264 的功能分層:VCL和NAL
        • NAL 單元
      • vui(Video Usability Information Guide) 視訊可用性資訊
      • YUV 編碼類型
      • 碼率
        • 碼率類型
        • 碼率控制類型
      • 量化參數(QP,Quantizer Parameter)
      • x264參數preset、tune、profile和level
    • 四、srs3.0中source.200kbps.768x320.flv轉h264視訊二進制檔案解析
      • h264碼流NAL單元分割
      • NAL頭部:一位元組[詳情ITU-T H.264建議書 7.4語義]
      • NAL有校負載
        • EBSP:擴充位元組序列載荷(Extended Byte String Payload)
        • RBSP:原始位元組序列載荷(Raw Byte Sequence Payload)
        • SODB:資料位元組流 (String Of Data Bits)
        • 解析SEI資訊
        • 解析SPS
        • 解析PPS
        • 解析Slice
    • 主要參考文獻

一、ffmpeg相關指令

ffmpeg 常用指令彙總

//從mp4封裝格式中抽取h264 碼流
ffmpeg -i test.mp4 -codec copy -bsf: h264_mp4toannexb -f h264 out.264
//抽取音頻
ffmpeg -i test.mp4 -vn -acodec copy  out.aac
//生成原生的yuv資料
ffmpeg -i test.mp4 -pix_fmt yuv420p -vcodec rawvideo -an out.yuv
           

二、windows10編譯x264

x264源碼下載下傳

x264源碼下載下傳,需要翻牆下載下傳。

msys2下載下傳

msys2官網,需要翻牆下載下傳。

Minimal GNU(POSIX)system on Windows,是一個小型的GNU環境,包括基本的bash,make等等。提供了一個易于使用的環境,用于建構,安裝和運作本機Windows軟體,與Cygwin大緻功能相當即在windows平台上提供運作的類UNIX模拟環境。

最常用的pacman指令

pacman -Syu: 更新系統及所有已經安裝的軟體。
pacman -S 軟體名: 安裝軟體。也可以同時安裝多個包,隻需以空格分隔包名即可。
pacman -Rs 軟體名: 删除軟體,同時删除本機上隻有該軟體依賴的軟體。
pacman -Ru 軟體名: 删除軟體,同時删除不再被任何軟體所需要的依賴。
pacman -Ssq 關鍵字: 在倉庫中搜尋含關鍵字的軟體包,并用簡潔方式顯示。
pacman -Qs 關鍵字: 搜尋已安裝的軟體包。
pacman -Qi 軟體名: 檢視某個軟體包資訊,顯示軟體簡介,構架,依賴,大小等詳細資訊。
pacman -Sg: 列出軟體倉庫上所有的軟體包組。
pacman -Sg 軟體包組: 檢視某軟體包組所包含的所有軟體包。
pacman -Sc:清理未安裝的封包件,封包件位于 /var/cache/pacman/pkg/ 目錄。
pacman -Scc:清理所有的緩存檔案。
           

MSYS2的源配置

MSYS2配置清華鏡像修改msys2安裝目錄下的\etc\pacman.d檔案夾裡面的3個mirrorlist.*檔案,依樣畫葫蘆把鏡像添加再更新即可。

//編輯 /etc/pacman.d/mirrorlist.mingw32 ,在檔案開頭添加:
Server = https://mirrors.tuna.tsinghua.edu.cn/msys2/mingw/i686

//編輯 /etc/pacman.d/mirrorlist.mingw64 ,在檔案開頭添加:
Server = https://mirrors.tuna.tsinghua.edu.cn/msys2/mingw/x86_64

//編輯 /etc/pacman.d/mirrorlist.msys ,在檔案開頭添加:
Server = https://mirrors.tuna.tsinghua.edu.cn/msys2/msys/$arch

//然後執行 pacman -Sy 重新整理軟體包資料即可。
           

安裝依賴

pacman -S mingw-w64-x86_64-gcc yasm make nasm //安裝mingw-w64-x86_64-gcc yasm make nasm
           

編譯

打開MSYS2 MinGW 64-bit,進入到x264源碼所在路徑,x86_64-w64-mingw32編譯windows環境目标檔案,執行:

#  ./configure --host=x86_64-w64-mingw32 --enable-shared --enable-static --prefix=/usr/local/x264
platform:       X86_64
byte order:     little-endian
system:         WINDOWS
cli:            yes
libx264:        internal
shared:         yes
static:         yes
bashcompletion: no
asm:            yes
interlaced:     yes
avs:            avisynth
lavf:           no
ffms:           no
mp4:            no
gpl:            yes
thread:         win32
opencl:         yes
filters:        crop select_every
lto:            no
debug:          no
gprof:          no
strip:          no
PIC:            yes
bit depth:      all
chroma format:  all

You can run 'make' or 'make fprofiled' now.
           

編譯安裝

make && make install
           

檢視生成檔案

cd /usr/local/x264
# ls -R
.:
bin  include  lib
./bin:
libx264-161.dll  x264.exe
./include:
x264.h  x264_config.h
./lib:
libx264.a  libx264.dll.a  pkgconfig
./lib/pkgconfig:
x264.pc
           

poxports工具下載下傳

windows下使用此工具利用dll動态庫生成lib靜态庫

.\pexports.exe .\libx264-161.dll > .\libx264-161.def //使用pexports工具生成libx264-161.def
           

vc的lib工具生成lib庫

lib可執行檔案在Microsoft Visual Studio\2017\Professional\VC\Tools\MSVC\14.16.27023\bin\Hostx64\x64目錄下:

.\lib.exe /machine:x64 /def:libx264-161.def //在目前目錄下生成libx264-161.lib
           

三、概念

H.264/AVC

MPEG( Moving Picture Experts Group)和 VCEG( Video Coding Experts Group)已經聯合開發了一個比早期研發的MPEG和H.263性能更好的視訊壓縮編碼标準,這就是被命名為 AVC( Advanced Video Coding)的,也被稱為ITU-TH.264建議和MPEG-4的第10部分的标準,在這裡,就簡稱它為 H.264/AVC 或 H.264。

白平衡

  1. 白平衡其基本概念是“不管在任何光源下,都能将白色物體還原為白色”衡,在不同的光線下,由于圖像傳感器輸出的不平衡性,造成其輸出的彩色失真:或者圖像偏藍,或者偏紅,對在特定光源下拍攝時出現的偏色現象,通過加強對應的補色來進行補償。
  2. 涉及到另一個重要的概念:色溫。所謂色溫,簡而言之,就是定量地以開爾文溫度表示色彩,色溫是指絕對黑體從絕對零度(-273℃)開始加溫後所呈現的顔色。某一種色光比其它色光的色溫高時,說明該色光比其它色光偏藍,反之則偏紅;同樣,當一種色光比其它色光偏藍時說明該色光的色溫偏高,反之偏低。
  3. 白平衡就是針對不同色溫條件下,通過調整錄影機内部的色彩電路使拍攝出來的影像抵消偏色,更接近人眼的視覺習慣。白平衡可以簡單地了解為在任意色溫條件下,錄影機鏡頭所拍攝的标準白色經過電路的調整,使之成像後仍然為白色。
  4. 作用:1、糾正色溫,還原拍主體的色彩,使在不同光源條件下拍攝的畫面同人眼觀看的畫面色彩相近。2、通過控制色溫,可以獲得色彩效果迥異的照片

指數哥倫布碼編碼

[參考:指數哥倫布編碼]

幀内編碼

基于波形的一系列視訊編碼标準

基于内容的編碼

預測編碼

幀内預測 intra

[參考:幀内預測]

對于一幅圖像,相鄰的兩個像素的亮度和色度值之間經常是比較接近的,也就是顔色是逐漸變化的,不會一下子突變成完全不一樣的顔色。而進行視訊編碼,目的就是利用這個相關性,來進行壓縮。幀内預測是利用視訊空間域的相關性,使用同一幀圖像内鄰近已編碼像素預測目前的像素,以達到有效去除視訊時域備援的目的。

4x4亮度塊預測模式

9種方式

16x16亮度塊預測模式

4種方式

幀間預測 inter

幀間預測主要包括運動估計(運動搜尋方法、運動估計準則、亞像素插值和運動矢量估計)和運動補償

運動估計搜尋算法

[參考:運動估計搜尋算法]

運動矢量
運動補償

變換編碼

熵編碼

序列參數集 Sequence Paramater Set(SPS)

[參考:序列參數集]

SPS中儲存了一組編碼視訊序列(Coded video sequence)的全局參數。所謂的編碼視訊序列即原始視訊的一幀一幀的像素資料經過編碼之後的結構組成的序列。而每一幀的編碼後資料所依賴的參數儲存于圖像參數集中。

一個SPS和PPS的NAL Unit通常位于整個碼流的起始位置。但在某些特殊情況下,在碼流中間也可能出現這兩種結構,主要原因可能為:

  1. 解碼器需要在碼流中間開始解碼;
  2. 編碼器在編碼的過程中改變了碼流的參數(如圖像分辨率等);

圖像參數集Picture Paramater Set(PPS)

[參考:圖像參數解析]

通常情況下,PPS類似于SPS,在H.264的裸碼流中單獨儲存在一個NAL Unit中,隻是PPS NAL Unit的nal_unit_type值為8;而在封裝格式中,PPS通常與SPS一起,儲存在視訊檔案的檔案頭中。

參數圖像

為了提高預測精度,H.264編碼器可從一組前面或後面已編碼圖像中選出一個或兩個與目前最比對的圖像作為幀間編碼間的參數圖像,這樣一來,複雜度大為增加,但多次比較的結果,使比對後的預測精度顯著改進。 H.264 中最多可從 15個參數圖像中進行選擇,選出最佳的比對圖像。

片(條帶) Slice

[參考:片 Slice]

  1. 一個視訊圖像可編碼成一個或更多個片,每片包含整數個宏塊( MB),即每片至少一個 MB,最多時每片包含整個圖像的宏塊。總之,一幅圖像中每片的宏塊數不一定固定。
  2. 設片的目的是為了限制誤碼的擴散和傳輸,應使編碼片互相間是獨立的。某片的預測不能以其它片中的宏塊為參考圖像,這樣某一片中的預測誤差才不會傳播到其它片中去。
  3. 編碼片共有 5 種不同類型,除已講過的 I 片、 P 片、 B 片外,還有 SP 片和 SI 片。其中 SP(切換P)是用于不同編碼流之間的切換;它包含P和/或I宏塊。它是擴充檔次中必須具有的切換,它包含了一種特殊類型的編碼宏塊,叫做SI宏塊,SI也是擴充檔次中的必備功能。在I slice中隻包含I宏塊,不能包含P或B宏塊;在P和B slice中,除了相應的P和B類型宏塊之外,還可以包含I類型宏塊

IDR幀(Instantaneous Decoding Refresh)即時解碼重新整理

I 和 IDR 幀都是使用幀内預測的。它們都是同一個東西而已,在編碼和解碼中為了友善,要首個 I 幀和其他 I 幀差別開,是以才把第一個首個I幀叫IDR,這樣就友善控制編碼和解碼流程。IDR幀的作用是立刻重新整理,使錯誤不緻傳播,從IDR幀開始,重新算一個新的序列開始編碼。++GOP(Group of picture)關鍵幀的周期,也就是兩個IDR幀之間的距離++。

舉個例子,在一段視訊中,存在以下幀:I P B P B P B B P I P B…

如果這段視訊應用了多重參照幀,那麼藍色的P幀在參照他前面的I幀(紅色)的同時,還可能會參照 I 幀之前的 P (綠色),由于I幀前後的場景可能會有很大的反差甚至根本不同,是以此時 P 幀參考I幀之前的幀不但會沒有意義,反而會造成很多問題。是以一種新型的幀被引入,那就是 IDR 幀。如果這段視訊應用了多重參考幀的同時采用了IDR幀,那麼幀的順序就會變成這樣:I P B P B P B B P IDR P B…

由于 IDR 幀禁止後面的幀向自己前面的幀參照,是以這回那個藍色的 P 幀就不會參照綠色的 P 幀了

H.264 的功能分層:VCL和NAL

視訊編碼層( VCL)和網絡提取層( NAL, Network Abstraction Layer)。VCL資料即編碼處理的輸出,它表示被壓縮編碼後的視訊資料序列。在VCL資料傳輸或存儲之前,這些編碼的 VCL 資料,先被映射或封裝進 NAL 單元中

NAL 單元

[參考:H.264/AVC視訊編解碼技術詳解 六、H.264的NAL解析]

vui(Video Usability Information Guide) 視訊可用性資訊

X264算法參數二(VUI參數配置)

YUV 編碼類型

色度抽樣(4:2:0)到底是什麼意思 顔色是由亮度(Luminance或Luma)和色度(chromaticity)共同表示的,色度是不包括亮度在内的顔色的性質,它反映的是顔色的色調和飽和度(指色彩的鮮豔程度,也稱作純度).如何了解 YUV

碼率

碼率就是資料傳輸時機關時間傳送的資料位數,一般我們用的機關是kbps即千位每秒。也就是取樣率(并不等同與采樣率,采樣率的機關是Hz,表示每秒采樣的次數),機關時間内取樣率越大,精度就越高,處理出來的檔案就越接近原始檔案。

碼率類型

  • VBR(Variable Bitrate)動态比特率 也就是沒有固定的比特率,壓縮軟體在壓縮時根據音頻資料即時确定使用什麼比特率,這是以品質為前提兼顧檔案大小的方式,推薦編碼模式;
  • ABR(Average Bitrate)平均比特率 是VBR的一種插值參數。LAME針對CBR不佳的檔案體積比和VBR生成檔案大小不定的特點獨創了這種編碼模式。ABR在指定的檔案大小内,以每50幀(30幀約1秒)為一段,低頻和不敏感頻率使用相對低的流量,高頻和大動态表現時使用高流量,可以做為VBR和CBR的一種折衷選擇。
  • CBR(Constant Bitrate),常數比特率 指檔案從頭到尾都是一種位速率。相對于VBR和ABR來講,它壓縮出來的檔案體積很大,而且音質相對于VBR和ABR不會有明顯的提高。

碼率控制類型

[參考:X264碼率控制總結1——ABR,CQP,CRF]

X264顯式支援的一趟碼率控制方法有:ABR, CQP, CRF. 預設方法是CRF。這三種方式的優先級是ABR > CQP > CRF。圖像編解碼:CRF(品質/碼率控制)和QP

  • ABR:恒定平均目标碼率。想要選擇這種碼率控制方法,必須先設定bitrate
  • CQP:恒定QP. 無預設值
  • CRF:恒定Rate Factor (碼率系數)預設值23

量化參數(QP,Quantizer Parameter)

[參考:H264量化參數QP]

量化參數,反映了空間細節壓縮情況。值越小,量化越精細,圖像品質越高,産生的碼流也越長。如QP小,大部分的細節都會被保留;QP增大,一些細節丢失,碼率降低,但圖像失真加強和品質下降。量化參數QP是量化步長Qstep的序号,QP取最小值0時,表示量化最精細;相反,QP取最大值51時,表示量化是最粗糙的。

x264參數preset、tune、profile和level

  1. preset是編碼速度

從最快到最慢。無特殊要求選fast即可,編碼加快,意味着資訊丢失越嚴重,輸出圖像品質越差。

/****************************************************************************
 * Advanced parameter handling functions
 ****************************************************************************/

/* 這些功能充分展示了x264的preset-tune-profile系統的全部功能,便于調整大量内部參數
 *
 * 為了複制x264CLI的選項處理,必須按以下順序調用這些函數:
 * 1) x264_param_default_preset
 * 2) Custom user options (via param_parse or directly assigned variables)
 * 3) x264_param_apply_fastfirstpass
 * 4) x264_param_apply_profile
 *
 * 另外, 如果 preset 被設定為 "placebo"或者--slow-firstpass則x264CLI不執行第三步 
/* x264_param_default_preset:
 *      The same as x264_param_default, but also use the passed preset and tune
 *      to modify the default settings.
 *      (either can be NULL, which implies no preset or no tune, respectively)
 *
 *      Currently available presets are, ordered from fastest to slowest: */
static const char * const x264_preset_names[] = { "ultrafast", "superfast", "veryfast", "faster", "fast",
                                                "medium", "slow", "slower", "veryslow", "placebo", 0 };
           

預設值也可以按數字索引,如x264_param_default_preset(&param, “3”, … ),ultrafast 對應 “0” placebo對應 “9”,當然,如果在兩者之間添加新的預設值,這種映射可能會發生變化,但始終是從最快到最慢排序的

警告:這些預設的速度會急劇增加,Ultrafast是placebo的100倍

  1. tune是編碼品質和畫面細節相關的參數

tune是x264中重要性僅次于preset的選項,它是視覺優化的參數,tune可以了解為視訊偏好(或者視訊類型),tune不是一個單一的參數,而是由一組參數構成。

static const char * const x264_tune_names[] = { "film", "animation", "grain", "stillimage",
                                            "psnr", "ssim", "fastdecode", "zerolatency", 0 };
           
  • film:電影類型,對視訊的品質非常嚴格時使用該選項
  • animation:卡通片,壓縮的視訊是卡通片時使用該選項
  • grain:顆粒物很重,該選項适用于顆粒感很重的視訊
  • stillimage:靜态圖像,該選項主要用于靜止畫面比較多的視訊
  • psnr:提高psnr,該選項編碼出來的視訊psnr比較高
  • ssim:提高ssim,該選項編碼出來的視訊ssim比較高
  • fastdecode:快速解碼,該選項有利于快速解碼
  • zerolatency:零延遲,該選項主要用于視訊直播
  1. profile是限制條件

H.264有四種畫質級别,分别是baseline, extended, main, high

static const char * const x264_profile_names[] = { "baseline", "main", "high", "high10", "high422", "high444", 0 };
           
  • Baseline Profile:基本畫質。支援I/P 幀,隻支援無交錯(Progressive)和CAVLC;
  • Extended profile:進階畫質。支援I/P/B/SP/SI 幀,隻支援無交錯(Progressive)和CAVLC;(用的少)
  • Main profile:主流畫質。提供I/P/B 幀,支援無交錯(Progressive)和交錯(Interlaced), 也支援CAVLC 和CABAC 的支援;
  • High profile:進階畫質。在main Profile 的基礎上增加了8x8内部預測、自定義量化、 無損視訊編碼和更多的YUV 格式;

H.264 Baseline profile、Extended profile和Main profile都是針對8位樣本資料、4:2:0格式(YUV)的視訊序列。在相同配置情況下,High profile(HP)可以比Main profile(MP)降低10%的碼率。 根據應用領域的不同,Baseline profile多應用于實時通信領域,Main profile多應用于流媒體領域,High profile則多應用于廣電和存儲領域。

4. level:level_idc屬性:參考H264編碼profile & level控制

  • 在給定的profile下,level通常與解碼器的處理能力和記憶體容量相對應。每一個檔次設定不同的參數(如取樣速率、圖像尺寸、編碼比特率等),得到對應的編解碼器性能的不同level
  • Description: Set bitstream Level IDC. 預設為 21,設定為 0 表示終止
  • 注:與ProfileIDC類似,LevelIDC在編碼過程中設定了一定的限制,如支援的分辨率、最大引用數、幀速率等,見H.264/AVC附錄A
Options: Options: description
10 1 (supports only QCIF format and below with 380160 samples/sec)
11 1.1 (CIF and below. 768000 samples/sec)
12 1.2 (CIF and below. 1536000 samples/sec)
13 1.3 (CIF and below. 3041280 samples/sec)
20 2 (CIF and below. 3041280 samples/sec)
21 2.1 (Supports HHR formats. Enables Interlace support. 5068800 samples/sec)
22 2.2 (Supports SD/4CIF formats. Enables Interlace support. 5184000 samples/sec)
30 3 (Supports SD/4CIF formats. Enables Interlace support. 10368000 samples/sec)
31 3.1 (Supports 720p HD format. Enables Interlace support. 27648000 samples/sec)
32 3.2 (Supports SXGA format. Enables Interlace support. 55296000 samples/sec)
40 4 (Supports 2Kx1K format. Enables Interlace support. 62914560 samples/sec)
41 4.1 (Supports 2Kx1K format. Enables Interlace support. 62914560 samples/sec)
42 4.2 (Supports 2Kx1K format. Frame coding only. 125829120 samples/sec)
50 5 (Supports 3672x1536 format. Frame coding only. 150994944 samples/sec)
51 5.1 (Supports 4096x2304 format. Frame coding only. 251658240 samples/sec)
  1. 參數設定函數
/****************************************************************************
 * Basic parameter handling functions
 ****************************************************************************/
/* x264_param_default:
 *      fill x264_param_t with default values and do CPU detection */
X264_API void x264_param_default( x264_param_t * );

/*      多個 tunings 可以被使用通過 ",./-+"分隔符分割,
 *      多個 psy tunings 不能被使用.
 *      film, animation, grain, stillimage, psnr, and ssim 屬于 psy tunings.
 *
 *      returns 0 on success, negative on failure (e.g. invalid preset/tune name). */
X264_API int x264_param_default_preset( x264_param_t *, const char *preset, const char *tune );

/*      (can be NULL, in which case the function will do nothing)
 *
 *      不保證設定的profile被使用:如果 "High" 被設定已經 Baseline-compatible,流将會保持baseline.
 *      簡而言之,它不會增加設定,隻會降低設定
 *
 *      returns 0 on success, negative on failure (e.g. invalid profile name). */
X264_API int x264_param_apply_profile( x264_param_t *, const char *profile );
           

四、srs3.0中source.200kbps.768x320.flv轉h264視訊二進制檔案解析

h264碼流NAL單元分割

實際的H264資料幀中,往往幀前面帶有00 00 00 01 或 00 00 01分隔符

NAL頭部:一位元組[詳情ITU-T H.264建議書 7.4語義]

H264資料幀分割之後的下一個位元組就是NALU類型,将其轉為二進制資料後,解讀順序為從左往右算:

  1. 第1位禁止位,值為1表示文法出錯,應設定為0
  2. 第2~3位為參考級别
  • 主要表示NAL的優先級。當該值為正時,表示目前NAL Unit中包含了SPS、PPS和作為參考幀的Slice等重要資料
  1. 第4~8為是nal單元類型
  • 包括VCL層和非VCL層的多種資料類型。
  1. 常見的nal_unit_type取值有:
  • 1表示非IDR幀編碼條帶
  • 2表示編碼條帶資料分割塊 A
  • 3表示編碼條帶資料分割塊 B
  • 4表示編碼條帶資料分割塊 C
  • 5表示IDR幀
  • 6表示輔助性增強資訊(SEI)
  • 7表示SPS
  • 8表示PPS

NAL有校負載

EBSP:擴充位元組序列載荷(Extended Byte String Payload)

等同于NAL Body的資料本身。在EBSP中包含了一個特殊的位元組0x03,表示防止競争校驗位元組:

emulation_prevention_three_byte:設定該值的目的是為了防止NAL Body内部出現于NAL Unit起始碼0x 00 00 01或0x 00 00 00 01沖突。

當内部的連續4位元組資料出現了下列情況時:

0x 00 00 00
0x 00 00 01
0x 00 00 02
0x 00 00 03
           

在兩個0位元組之後會插入值為3的一個位元組,形成下列情況:

0x 00 00 03 00
0x 00 00 03 01
0x 00 00 03 02
0x 00 00 03 03
           

在進行解析時需要将附加的03位元組去掉,得到RBSP資料。

RBSP:原始位元組序列載荷(Raw Byte Sequence Payload)

相當于NAL Body去掉emulation_prevention_three_byte之後的資料,是對原始的文法元素碼流進一步處理後産生的資料。相比于原始的文法元素碼流,RBSP在末尾添加了rbsp_trailing_bits()部分,其主要目的是位元組對齊。每個rbsp_trailing_bits()包括一個1bit和若幹個0bit,0bit的個數不定,以實作位元組的對齊。

SODB:資料位元組流 (String Of Data Bits)

表示H.264的文法元素編碼完成後的實際的原始二進制碼流。SODB通常不能保證位元組對齊

解析SEI資訊

解析一位元組NAL頭得到類型為6,即附加增強資訊

06-->0 00 00110  //類型6:附加增強資訊(SEI),圖像的額外資訊
           

根據[ITU-T H.264建議書 7文法和語義7.3.2.++3++]進行解析負載類型和負載長度:

sei_message( ) 
{ 
    payloadType = 0
    while( next_bits( 8 ) == 0xFF )  //第一個FF之前的位元組組合數為payloadType
    {
        ff_byte /* equal to 0xFF */ 
        payloadType += 255
    }
    last_payload_type_byte // 8位
    payloadType += last_payload_type_byte
    payloadSize = 0
    while( next_bits( 8 ) = = 0xFF ) 
    {
        ff_byte /* equal to 0xFF */ 
        payloadSize += 255
    }
    last_payload_size_byte 
    payloadSize += last_payload_size_byte
    sei_payload( payloadType, payloadSize ) 
}
           

0x05 FF FF AC

得出負載類型和負載長度

  1. 負載類型:

    0x05

    –>5;
  2. 負載長度

    FF FF AC

    –>682 (FF + FF + AC = 2AA)

根據[++ITU-T H.264建議書 輔助增強資訊 D.1 SEI在和文法++]解析負載資料:

User_data_unregistered( payloadSize ) 
{ 
    uuid_iso_iec_11578 // u(128) 16位元組編号
    for( i = 16; i < payloadSize; I++ )
    user_data_payload_byte //
}
           

16個位元組uuid,uuid_iso_iec_11578 應有一個由 UUID 指定的值,依照 ISO/IEC 11578:1996 附件 A 的規程:

00000000                              dc 45 e9 bd e6 d9 48  |..........E....H|
00000010  b7 96 2c d8 20 d9 23 ee  ef                       |..,. .#..
           

剩餘682-16 = 662位元組資料,其文法和語義由 UUID 生成器指明:

00000000                                                    |                |
00000010                              78 32 36 34 20 2d 20  |         x264 - |
00000020  63 6f 72 65 20 31 33 38  20 2d 20 48 2e 32 36 34  |core 138 - H.264|
00000030  2f 4d 50 45 47 2d 34 20  41 56 43 20 63 6f 64 65  |/MPEG-4 AVC code|
00000040  63 20 2d 20 43 6f 70 79  6c 65 66 74 20 32 30 30  |c - Copyleft 200|
00000050  33 2d 32 30 31 33 20 2d  20 68 74 74 70 3a 2f 2f  |3-2013 - http://|
00000060  77 77 77 2e 76 69 64 65  6f 6c 61 6e 2e 6f 72 67  |www.videolan.org|
00000070  2f 78 32 36 34 2e 68 74  6d 6c 20 2d 20 6f 70 74  |/x264.html - opt|
00000080  69 6f 6e 73 3a 20 63 61  62 61 63 3d 31 20 72 65  |ions: cabac=1 re|
00000090  66 3d 33 20 64 65 62 6c  6f 63 6b 3d 31 3a 30 3a  |f=3 deblock=1:0:|
000000a0  30 20 61 6e 61 6c 79 73  65 3d 30 78 33 3a 30 78  |0 analyse=0x3:0x|
000000b0  31 33 33 20 6d 65 3d 68  65 78 20 73 75 62 6d 65  |133 me=hex subme|
000000c0  3d 37 20 70 73 79 3d 31  20 70 73 79 5f 72 64 3d  |=7 psy=1 psy_rd=|
000000d0  31 2e 30 30 3a 30 2e 30  30 20 6d 69 78 65 64 5f  |1.00:0.00 mixed_|
000000e0  72 65 66 3d 31 20 6d 65  5f 72 61 6e 67 65 3d 31  |ref=1 me_range=1|
000000f0  36 20 63 68 72 6f 6d 61  5f 6d 65 3d 31 20 74 72  |6 chroma_me=1 tr|
00000100  65 6c 6c 69 73 3d 31 20  38 78 38 64 63 74 3d 31  |ellis=1 8x8dct=1|
00000110  20 63 71 6d 3d 30 20 64  65 61 64 7a 6f 6e 65 3d  | cqm=0 deadzone=|
00000120  32 31 2c 31 31 20 66 61  73 74 5f 70 73 6b 69 70  |21,11 fast_pskip|
00000130  3d 31 20 63 68 72 6f 6d  61 5f 71 70 5f 6f 66 66  |=1 chroma_qp_off|
00000140  73 65 74 3d 2d 32 20 74  68 72 65 61 64 73 3d 38  |set=-2 threads=8|
00000150  20 6c 6f 6f 6b 61 68 65  61 64 5f 74 68 72 65 61  | lookahead_threa|
00000160  64 73 3d 31 20 73 6c 69  63 65 64 5f 74 68 72 65  |ds=1 sliced_thre|
00000170  61 64 73 3d 30 20 6e 72  3d 30 20 64 65 63 69 6d  |ads=0 nr=0 decim|
00000180  61 74 65 3d 31 20 69 6e  74 65 72 6c 61 63 65 64  |ate=1 interlaced|
00000190  3d 30 20 62 6c 75 72 61  79 5f 63 6f 6d 70 61 74  |=0 bluray_compat|
000001a0  3d 30 20 63 6f 6e 73 74  72 61 69 6e 65 64 5f 69  |=0 constrained_i|
000001b0  6e 74 72 61 3d 30 20 62  66 72 61 6d 65 73 3d 33  |ntra=0 bframes=3|
000001c0  20 62 5f 70 79 72 61 6d  69 64 3d 32 20 62 5f 61  | b_pyramid=2 b_a|
000001d0  64 61 70 74 3d 31 20 62  5f 62 69 61 73 3d 30 20  |dapt=1 b_bias=0 |
000001e0  64 69 72 65 63 74 3d 31  20 77 65 69 67 68 74 62  |direct=1 weightb|
000001f0  3d 31 20 6f 70 65 6e 5f  67 6f 70 3d 30 20 77 65  |=1 open_gop=0 we|
00000200  69 67 68 74 70 3d 32 20  6b 65 79 69 6e 74 3d 32  |ightp=2 keyint=2|
00000210  35 30 20 6b 65 79 69 6e  74 5f 6d 69 6e 3d 32 35  |50 keyint_min=25|
00000220  20 73 63 65 6e 65 63 75  74 3d 34 30 20 69 6e 74  | scenecut=40 int|
00000230  72 61 5f 72 65 66 72 65  73 68 3d 30 20 72 63 5f  |ra_refresh=0 rc_|
00000240  6c 6f 6f 6b 61 68 65 61  64 3d 34 30 20 72 63 3d  |lookahead=40 rc=|
00000250  61 62 72 20 6d 62 74 72  65 65 3d 31 20 62 69 74  |abr mbtree=1 bit|
00000260  72 61 74 65 3d 32 30 36  20 72 61 74 65 74 6f 6c  |rate=206 ratetol|
00000270  3d 31 2e 30 20 71 63 6f  6d 70 3d 30 2e 36 30 20  |=1.0 qcomp=0.60 |
00000280  71 70 6d 69 6e 3d 31 30  20 71 70 6d 61 78 3d 35  |qpmin=10 qpmax=5|
00000290  31 20 71 70 73 74 65 70  3d 34 20 69 70 5f 72 61  |1 qpstep=4 ip_ra|
000002a0  74 69 6f 3d 31 2e 34 31  20 61 71 3d 31 3a 31 2e  |tio=1.41 aq=1:1.|
000002b0  30 30 00 
           

結尾比特即rbsp trailing bits,在user_data_unregistered()裡面都是按位元組寫入的,是以此時的NAL unit結尾寫入的位元組一定是0x80.

解析SPS

[ITU-T H.264建議書 7.3.2 原始位元組序列載荷和RBSP尾比特文法]

[參考:H264碼流中SPS PPS詳解]

在H.264标準協定中規定類型7表示該NAL Unit内儲存的資料為Sequence Paramater Set。在H.264的各種文法元素中,SPS中的資訊至關重要。如果其中的資料丢失或出現錯誤,那麼解碼過程很可能會失敗。

NAL頭部一位元組為:0x67

0x67 ---> 0 11 00111:禁止位為0;優先級為3;NAL類型為7--序列參數集
           

在H.264的SPS中:

  1. 第一個位元組:profile_idc表示畫質級别–>0x64:100;
  2. 第二位元組:constraint_set0_flag ~ constraint_set3_flag,reserved_zero_4bits –>0x00
  3. 第三位元組:level_idc表示目前碼流的Level–>0x20
  4. 無符号指數哥倫布碼編碼的文法元素:seq_parameter_set_id表示目前的序列參數集的id。通過該id值,圖像參數集pps可以引用其代表的sps中的參數,該值的取值範圍為[0,31]–>0xAC
  5. 如下:
H.264
    NAL unit header or first byte of the payload
        0... .... = F bit: No bit errors or other syntax violations
        .11. .... = Nal_ref_idc (NRI): 3
        ...0 0111 = Type: NAL unit - Sequence parameter set (7)
    H264 NAL Unit Payload
        0110 0100 = Profile_idc: High profile (100)
        0... .... = Constraint_set0_flag: 0
        .0.. .... = Constraint_set1_flag: 0
        ..0. .... = Constraint_set2_flag: 0
        ...0 .... = Constraint_set3_flag: 0
        .... 0... = Constraint_set4_flag: 0
        .... .0.. = Constraint_set5_flag: 0
        .... ..00 = Reserved_zero_2bits: 0
        0010 0000 = Level_id: 32 [Level 3.2 20 Mb/s]
        1... .... = seq_parameter_set_id: 0   //用于識别圖像參數集所指的序列參數集, [0-31]
        .010 .... = chroma_format_id: 1    //與亮度取樣對應的色度取樣
        .... 1... = bit_depth_luma_minus8: 0
        .... .1.. = bit_depth_chroma_minus8: 0
        .... ..0. = qpprime_y_zero_transform_bypass_flag: 0
        .... ...0 = seq_scaling_matrix_present_flag: 0
        1... .... = log2_max_frame_num_minus4: 0   //此參數計算得出MaxFrameNum的值
        .1.. .... = pic_order_cnt_type: 0   //解碼圖像順序的計數方法 [0-2]
        ..01 1... = log2_max_pic_order_cnt_lsb_minus4: 2
        .... .001  01.. .... = num_ref_frames: 4
        ..0. .... = gaps_in_frame_num_value_allowed_flag: 0
        ...0 0000  1100 00.. = pic_width_in_mbs_minus1: 47  //以宏塊為單元的每個解碼圖像的寬度
        .... ..00  0010 100. = pic_height_in_map_units_minus1: 19
        .... ...1 = frame_mbs_only_flag: 1 //等于 0 表示編碼視訊序列的編碼圖像可能是編碼場或編碼幀
                                           //1 表示編碼視訊序列的每個編碼圖像都是一個僅包含幀宏塊的編碼幀
        1... .... = direct_8x8_inference_flag: 1
        .0.. .... = frame_cropping_flag: 0
        ..1. .... = vui_parameters_present_flag: 1
        ...1 .... = aspect_ratio_info_present_flag: 1
        .... 0000  0001 .... = aspect_ratio_idc: 1
        .... 0... = overscan_info_present_flag: 0
        .... .0.. = video_signal_type_present_flag: 0
        .... ..0. = chroma_loc_info_present_flag: 0
        .... ...1 = timing_info_present_flag: 1
        0000 0000  0000 0000  0000 0000  0000 0001 = num_units_in_tick: 1
        0000 0000  0000 0000  0000 0000  0011 0010 = time_scale: 50
        0... .... = fixed_frame_rate_flag: 0
        .0.. .... = nal_hrd_parameters_present_flag: 0
        ..0. .... = vcl_hrd_parameters_present_flag: 0
        ...0 .... = pic_struct_present_flag: 0
        .... 1... = bitstream_restriction_flag: 1
        .... .1.. = motion_vectors_over_pic_boundaries_flag: 1
        .... ..1. = max_bytes_per_pic_denom: 0
        .... ...1 = max_bits_per_mb_denom: 0
        0001 100. = max_mv_length_horizontal: 11
        .... ...0  0011 00.. = log2_max_mv_length_vertical: 11
        .... ..01  1... .... = num_reorder_frames: 2
        .001 01.. = max_dec_frame_buffering: 4
        .... ..1. = rbsp_stop_bit: 1
        .... ...0 = rbsp_trailing_bits: 0
           

解析PPS

NAL頭部一位元組為:0x68

0x68 ---> 0 11 01000:禁止位為0;優先級為3;NAL類型為8--圖像參數集
           

在H.264的PPS中,解析過程看建議書:…

H.264
    NAL unit header or first byte of the payload
        0... .... = F bit: No bit errors or other syntax violations
        .11. .... = Nal_ref_idc (NRI): 3
        ...0 1000 = Type: NAL unit - Picture parameter set (8)
    H264 NAL Unit Payload
        1... .... = pic_parameter_set_id: 0 //辨別在條帶頭中提到的圖像參數集 [0-255]
        .1.. .... = seq_parameter_set_id: 0 //指活動的序列參數集
        ..1. .... = entropy_coding_mode_flag: 1 //用于選取文法元素的熵編碼方式
        ...0 .... = pic_order_present_flag: 0
        .... 1... = num_slice_groups_minus1: 0 //加 1 表示一個圖像中的條帶組數
        .... .011 = num_ref_idx_l0_active_minus1: 2
        1... .... = num_ref_idx_l1_active_minus1: 0
        .1.. .... = weighted_pred_flag: 1
        ..10 .... = weighted_bipred_idc: 2
        .... 1... = pic_init_qp_minus26: 0
        .... .1.. = pic_init_qs_minus26: 0
        .... ..00  101. .... = chroma_qp_index_offset(se(v)): -2
        ...1 .... = deblocking_filter_control_present_flag: 1
        .... 0... = constrained_intra_pred_flag: 0
        .... .0.. = redundant_pic_cnt_present_flag: 0
        .... ..1. = transform_8x8_mode_flag: 1
        .... ...0 = pic_scaling_matrix_present_flag: 0
        0010 1... = second_chroma_qp_index_offset(se(v)): -2
        .... .1.. = rbsp_stop_bit: 1
        .... ..00 = rbsp_trailing_bits: 0
           

解析Slice

片(條帶類型):

slice_type  slice_type 的名稱
    0           P (P 條帶)
    1           B (B 條帶)
    2           I (I 條帶)
    3           SP (SP 條帶)
    4           SI (SI 條帶)
    5           P (P 條帶)
    6           B (B 條帶)
    7           I (I 條帶)
    8           SP (SP 條帶)
    9           SI (SI 條帶)
           

解析資料示例:

001a0498h: 00 00 00 01 41 9B B4 4B E1 08 43 C8 CD 14 78 10 | óÌ.».g‹ßž]©à7.ɏ|
001a04a8h: 20 4A 05 31 42 40 22 BF E4 02 56 2C 4B EC 4A D5 | -=*ä+.§x.å...G.|
...
           

NAL頭部一位元組為:0x41

0x41 ---> 0 10 00001:禁止位為0;優先級為2;NAL類型為1--一個非 IDR 圖像的編碼條帶
           

slice頭部,具體檢視建議書7.3.3 條帶頭文法,例:

slice_header( ) {

    first_mb_in_slice  //2  ue(v):無符号指數哥倫布邊貿
    slice_type  //2 ue(v)
    pic_parameter_set_id  // 2 ue(v)
    frame_num // 2 u(v)

    if( !frame_mbs_only_flag ) { //在sps中為1,跳過
        field_pic_flag  //u(1)-->一位元組
        if( field_pic_flag )
            bottom_field_flag
    }
    if( nal_unit_type == 5 )
        idr_pic_id
    if( pic_order_cnt_type = = 0 ) 
    {
        pic_order_cnt_lsb
        if( pic_order_present_flag && !field_pic_flag )
            delta_pic_order_cnt_bottom
    }
    ...
    if( slice_type = = P | | slice_type = = SP | | slice_type = = B ) //P條帶
    {
        num_ref_idx_active_override_flag   //u(1)
        if( num_ref_idx_active_override_flag ) 
        {
            num_ref_idx_l0_active_minus1
            if( slice_type = = B )
                num_ref_idx_l1_active_minus1
        }
    }
    
}
...
           

9B B4

改成二進制數:

1001 1011 1011 0100

解碼過程:

1 00110 1 1 1 011 010 0

1、擷取二進制序列開頭連續的N個0
2、讀取之後的N+1位的值,假設為X
3、X-1擷取解碼後的值
           

得到:

first_mb_in_slice = 0;
slice_type = 5;
pic_parameter_set_id = 0;
frame_num = 0;
    frame_mbs_only_flag = 1
        field_pic_flag = 0;
        
  ...
           

主要參考文獻

  1. [ITU-T H.264建議書]
  2. ffmpeg 常用指令彙總
  3. 指數哥倫布編碼
  4. H264碼流中SPS PPS詳解
  5. H.264/AVC視訊編解碼技術詳解

繼續閱讀