2017年10月3日 星期二

3+1 H.264 基礎

https://goo.gl/nsHhUc
https://www.ptt.cc/bbs/C_and_CPP/M.1332759347.A.4D0.html
來源 : 工研院


  • H264基本

1. 前言


且H.264/AVC也首次將視訊編碼層(Video Coding Layer,VCL)與網路提取層(Network Abstraction Layer,NAL)的概念涵蓋進來,H.264/AVC根據使用的編碼工具種類來提供三種編碼規模(Profile),如表1所示分別為Baseline Profile、Main Profile、Extension Profile,而相對應的影片尺寸與位元率等級由Level 1至Level 5.1,涵蓋小畫面與高解析度畫面的應用範圍。Baseline Profile主要是著眼於低位元率的應用(例如:影像通訊),而且其運算複雜度低,所以也適合應用於個人隨身的多媒體撥放機;Main Profile因為有支援交錯式影片(interlaced content)的編碼,所以適合應用於HDTV數位電視廣播,而且非常容易整合在傳統的MPEG-2 Transport/Program Stream上來傳送H.264/AVC位元流;Extension Profile是對於IP-TV或是MOD (Multimedia On Demand)等應用,使用包含高抗錯性編碼工具(error resilient tools).


  • 總結: 

1 .Baseline Profile :  只使用 I-Frame 與 P-Frame 的 CAVLC 編碼
CAVLC (Context-Adaptive Variable-Length Coding) 上下文自適應可變長度編碼
(簡單說:p 為前一張的動態資訊圖,非完整圖片)

2.Main  Profile:
相較於Baseline類型,加入交錯式(interlaced)影像(B-Frame)、及CABAC等工具.

3. High  Profile:
High類型提高Main類型使用位階的上限,放寬採用8×8的DCT轉換,並提供較好的量化步階調整模式。High類型已經逐漸取代Main類型.

公司只用過base.


[H264 Encoder]



2. 網路提取層 (Network Abstraction Layer,NAL)

亦即以NAL封包為單位的方式來做為VCL編解碼的運算單位,這樣傳輸層拿到NAL封包之後不需要再進行切割,只需附加該傳輸協定的檔頭資訊(adding header only)就可以交由底層傳送出去,如圖1所示,可以將NAL當成是一個專作封裝(packaging)的模組,用來將VCL壓縮過的bitstream(NAL unit stream)封裝成適當大小的封包單位(NAL-unit),並在NAL-unit Header中的NAL-unit Type欄位記載此封包的型式,每種型式分別對應到VCL中不同的編解碼工具。





一個完整的H.264/AVC bitstream是由多個NAL-units所組成的,所以此bitstream也稱之為NAL unit stream,一個NAL unit stream內可以包含多個壓縮視訊序列(coded video sequence)一個單獨的(coded video sequence)代表一部視訊影片,而壓縮視訊序列又是由多個access units所組成,當接收端收到一個access unit後,可以完整地解碼成單張的畫面,而每個壓縮視訊序列的第一個access unit必須為Instantaneous Decoding Refresh (IDR) access unit,IDR access unit的內容全是採用intra-prediction編碼,所以自己本身即可完全解碼,不用參考其他access unit的資料。access unit亦是由多個NAL-units所組成,標準中總共規範12種的NAL-unit型式,這些可以進一步分類成VCL NAL-unit及non-VCL NAL-unit,所謂的VCL NAL-unit純粹是壓縮影像的內容,而所謂的non-VCL NAL-unit則有兩種:Parameter Sets與Supplemental Enhancement Information (SEI),SEI可以存放影片簡介、版權宣告、使用者自行定義的資料…等;Parameter Sets主要是描述整個壓縮視訊序列的參數,例如:長寬比例、影像顯現的時間點(timestamp)、相關解碼所需的參數…等,以往像MPEG-2/-4都把這些資訊放在一般的packet header,所以很容易隨著packet loss而消失,現在H.264/AVC將這些資訊獨立出來成為特殊的parameter set,可以採用所謂的out-of-band的方式來傳送,以便將out-of-band channel用最高層級的通道編碼(channel coding)保護機制,來保證傳輸的正確性





3. 視訊編碼層 (Video Coding Layer,VCL)


如圖1所示,H.264/AVC的視訊編碼機制是以圖塊(block-based)為基礎單元,也就是說先將整張影像分割成許多矩形的小區域,稱之為巨圖塊(macroblock,MB),再將這些巨圖塊進行編碼,先使用畫面內預測(intra-prediction)與畫面間預測(inter-prediction)技術,以去除影像之間的相似性來得到所謂的差餘影像(residual),再將差餘影像施以空間轉換(transform)與量化(quantize)來去除視覺冗餘,最後視訊編碼層會輸出編碼過的位元流(bitstream),之後再包裝成網路提取層的單元封包(NAL-unit),經由網路傳送到遠端或儲存在儲存媒體中。
H.264/AVC允許視訊影片以frame或是以filed的方式來進行編碼,兩者可以共存,而frame可以是progress或是interlace形式,對同一段影片來說也可使用兩者來混合編碼,這個特性與MPEG-2相同。而在影像色彩格式的支援上,H.264/AVC第一版的標準只支援YCrCb 4:2:0 (又稱YUV420)取樣的方式,而在增修的第二版標準中增加4:2:2與4:4:4取樣格式,通常這些格式會被數位電影或HDTV影片所採用。



3.1 H.264/AVC影像格式階層架構
H.264/AVC的階層架構由小到大依序是sub-block、block、macroblock(MB)、slice、slice group、frame/field-picture、sequence。


對一個採用4:2:0取樣的MB而言,它是由16x16點的Luma與相對應的2個8x8點Chroma來組成,而在H.264/AVC的規範中,MB可再分割成多個16x8、8x16、8x8、8x4、4x8、4x4格式的sub-blocks。所謂的slice是許多MB的集合,而一張影像是由許多slice所組成(圖3),slice為H.264/AVC格式中的最小可解碼單位(self-decodable unit),也就是說一個slice單靠本身的壓縮資料就能解碼,而不必依靠其他slice,這樣的好處是當傳送到遠端時,每接收完一筆slice的壓縮資料就能馬上解碼,不用等待整張的資料接收完後才能開始,而且萬一傳送的過程中發生資料遺失或錯誤,也只是影響該筆slice,不會對其他slice有所影響,但跟MPEG-2的slice不同處在於它允許slice的範圍可以超過一行MB,也就是說H.264/AVC允許整張影像只由單一個slice組成。H.264/AVC的slice架構還有一項特性稱為Flexible Macroblock Ordering (FMO),也就是說組成slice的MB可以不必侷限於循序掃描(raster scan)的排列方式,例如:圖3最右側的排法就非常適用於多個前景(foreground) slice groups與一個獨自的背景(background) slice group,好處是對不同的slice group可以用不同品質的壓縮參數,例如:對於前景物件通常是人眼較感興趣的區域,可以用較小的壓縮率來維持較好的品質。

3.2 Slice的編碼模式

H.264/AVC的slice依照編碼的類型可以分成下列種類:(1) I-slice:(2) P-slice:(3) B-slice: 與P-slice類.
H.264/AVC另外增加兩種特殊slice類型:(1) SP-slice: 即所謂的Switching P slice,為P-slice的一種特殊類型,用來串接兩個不同bitrate的bitstream;(2) SI-slice: 即所謂的Switching I slice,為I-slice的一種特殊類型,除了用來串接兩個不同content的bitstream外,也可用來執行隨機存取(random access)來達到網路VCR的功能。
這兩種特殊的slice主要是為了讓相同content但不同bitrate的bitstream可以較平順地串接,對同一個視訊內容的影片來說,server會預先存放不同bitrate的壓縮影片,而當頻寬改變時,server就會送出適合當時頻寬位元率的影片,傳統的做法是需要等到適當的時間點來傳送新的I-slice (容量較P-slice大上許多),但因為頻寬變小導致需要較多的時間來傳送I-slice,如此會讓client端的影像有所延遲,使用SP-slice會很容易來達成.





--------------------------------------------------------------------------

由下圖得知NAL Unit 組成 Access Unit 組成 RTP Packet(coded video sequence?)

[RTP Packet]

NAL Unit
一張會動畫面被H.264分成需多NALU(NAL Unit)
每個NAL Unit如下圖, 圖片來源: Exploring H.264. Part 2: H.264 Bitstream format

[NAL Structure]



  • Single NAL Unit Packet
nal unit type為1-23的padload格式如下 (即在rtp padload第12byte開始)[Single NAL Unit Packet]

nal header
ex. 0x67 (0110 0111)
b[0]: forbidden_zero_bit = 0,
b[1-2]: nal_ref_idc = 3,
b[3-7]: nal_unit_type = 7


根據RFC3984以RTP 封裝H.264 raw data來作video streaming.

1.H.264 raw data
以00 00 01 或 00 00 00 01作為開頭(Start Code),接著是8 bit NALU 
NALU的format


#define NALU_TYPE_SLICE 1( P-Frame?)
#define NALU_TYPE_IDR 5 (I-frame)
#define NALU_TYPE_SEI 6
#define NALU_TYPE_SPS 7
#define NALU_TYPE_PPS 8

正常的H264 NALU順序:
SPS(NAL type = 0x07) -> PPS(0x8) -> I-Frame(0X5), P-Frame(0x1)
把[SPS,PPS,IDR(即IFRAME)]當成一個Frame送到decoder


p.s. RTP?NALU定義?
我們header of rtp header?

參考來源:
https://erwinchang.github.io/2017/03/14/h264/
深入淺出

2020/01/16 新增 知呼(來源)

*1 frame 可以有1~多個slice. (每個slice可放於NAL包中)

*公司中使用 I frame , P frame(依賴於I frame) ; (沒用B frame)(依賴於I,P,B frame 前後倒快轉用)

網絡抽象層單元類型 (NALU)

NALU header 由1byte組成;  F ( forbidden_zero_bit)(1bit) ,NRI ( nal_ref_idc)(2 bit), type ( nal_unit_type)(5bit)=>用於區分SPS(0x67) ;PPS(0x68);IDR_SLICE(0x65);SLICE(0x41)

forbidden_​​zero_bit. 在 H.264 規範中規定了這一位必須為 0.
nal_ref_idc. 取 00 ~ 11, 似乎指示這個 NALU 的重要性. 00表示NALU解碼器可以丟棄.


+---------------+
|0|1|2|3|4|5|6|7|
+-+-+-+-+-+-+-+-+
|F|NRI| Type  |
+---------------+

如果一個H.264的NALU是這樣的:

[00 00 00 01 67 42 A0 1E 23 56 0E 2F ...]

這是一個序列參數集 NAL 單元. [00 00 00 01] 是四個字節的開始碼, 0x67 是 NALU header, 0x42 開始的數據是 NALU 內容.

封裝成 RTP 包將如下:

[ RTP Header ] [ 67 42 A0 1E 23 56 0E 2F ]

即只要去掉 4 個字節的開始碼就可以了.



  • 2017 11/15=> ffmpeg會破圖

可用Elecard解析frame

已前攝影機有 I-720p  or  I-1080p
所以I,P frame 來可能為 intersect(交錯送)

海思decode 分為frame mode & stream mode

正常frame mode I , p , p , p.....這樣收frame
所以餵進去decode 沒問題

但是stream(intersect) mode可能是I(半張),I(half),p(half#1),p(half#1),p(half#2),p(half#2)..... 
半張,半張,或一部分一部分 分開送
所以收入會破圖, 以前頻寬不夠,所以採此做法


1 則留言:

  1. 大師您好

    我只想對 mp4檔輸出 I frame P frame 和 B frame,
    請問 ffmpeg的命令要如何下?

    敬祝 吉祥如意

    回覆刪除