天天看點

【H264/AVC 句法和語義詳解】(四):通過學習"描述子"實作碼流解析的第一步

本篇隸屬于文集:《H264/AVC 句法和語義詳解》,檢視文集全部文章,請點選文字連結。

想看最新文章,可以直接關注微信公衆号:金架構

在這篇文章中,我們會涉及三個非常重要的問題:

1、如何擷取一條主線和多條輔線,來學習h264解碼器

2、為什麼描述子,是正确打開碼流解析的第一步

3、學習描述子

在前面幾篇中,我們對h264的碼流結構有了初步的了解。但是這還遠遠不夠,因為我們的目标,是通過學習h264的解碼流程,去探索h264裡面的每個知識點。是以在這個時候,讓讀者明白我們現在身處的位置,是一件至關重要的事情。因為隻有這樣,我們才不會局限于某一篇文章,或某一個知識點,而是從全局考慮,為什麼要這樣做。

而且,我希望看我文章的讀者,看完文章後擷取的,不隻是關于音視訊的各個知識點。還有更重要的,那就是思考和自學的能力!在這篇文章結束時,無論新手還是有經驗的同學,都可以從宏觀出發,看出這個系列文章未來十篇的走勢。并且我們還可以共同學習,一起研究。

1. 如何擷取一條學習主線

在快餐文化盛行的今天,很多人都在學習零零碎碎的知識,卻沒有将各個知識點,形成一種互相聯系的知識結構。就比如關于h264,很多人可能知道幀内預測、幀間預測、變換、量化、熵編碼,但如果你問他一個h264編碼器或解碼器該怎麼做,他可能就一頭霧水。

是以這時候一條學習主線就非常重要,這是在你學習過程中,無論遇到什麼困難,都能夠把你拉回到問題本身,并讓你知道現在所處位置的關鍵。

而在h.264裡,這樣的一條學習主線也非常重要,它就是h.264解碼器架構!

1.1 學習主線:H.264解碼器架構
【H264/AVC 句法和語義詳解】(四):通過學習"描述子"實作碼流解析的第一步

H.264解碼器架構

很多人并不會把流程圖當成一回事,其實一個流程圖,有可能是一篇文章、一個系列文章、書中一個章節或一本書的一個核心。

而根據上圖,我們可以制定兩個學習思路:

(1)根據如圖所示流程,從最右側碼流開始,一步步各個擊破,最終學完解碼器各個知識點。

(2)編碼器和解碼器其實隻是步驟相反罷了,一邊學習解碼器各個知識點,一邊反過來思考,編碼過程如何實作。

當然,我們還可以對上述路線進行分段,因為完整的一條學習主線,會包含一段段進階路線。

1.2 學習主線分段

我個人是這樣進行分段的:

【H264/AVC 句法和語義詳解】(四):通過學習"描述子"實作碼流解析的第一步

學習主線分段

這樣分段是有根據的,因為最開始我們手上有的,就是一個字尾為.h264的碼流檔案而已。是以我們首先要做的,就是先把句法元素解析出來。而如圖所示,每一步我們需要學習的技術如下:

(1)h264句法元素的解析:NALU的結構和熵解碼,同時熵解碼又包括指數哥倫布編碼、CAVLC、CABAC。隻要掌握了NALU和熵解碼,我們就可以從碼流中解析出各個句法元素的值。即使我們完全是個小白,也可以按照h264協定完成這步。

(2)資料準備:DCT變換、量化、重排序,和它們相關的句法元素及語義。這個過程是為後面的重建圖像做準備,這時我們已經解析出各個句法元素,實作該過程需要配合各步驟所需要的句法元素。

(3)重建圖像:幀内預測、幀間預測、去塊效應濾波器。這時候碼流資料已經完全解壓縮,就差拿着殘差資料、參考圖像和預測所需的句法元素,預測出預測資料。預測資料經過去塊效應後即可得解碼宏塊,目前圖像的所有宏塊解碼完成,就可以得到重建圖像用于顯示。

是以我們目前所處的位置,即将到達熵解碼階段。

2. 如何擷取多條學習輔線

學習輔線這種事情,相當于知識點的各個擊破,也相當于知識點的聯系和延伸。我們可以一開始就設定多條輔線,而且在學的同時,還可以再設定輔線。就拿h264的解碼學習來說,我們可以設定如下輔線:

(1)h.264 POC的計算

(2)h.264的權重預測

(3)h.264 FMO

(4)h.264參考圖像清單

(5)權重預測

(6)量化

(7)幀内預測

(8)片、宏塊之間的關系

(9)片類型與宏塊類型

(10)NALU

(11)指數哥倫布編碼

(12)熵編碼

(13)YUV顔色空間

(14)殘差

這些問題,可以是各個知識點,也可以是自己問自己的問題,它們的意義,在于在學習主線上,一路設定哨崗,相當于摸着石頭過河。要知道學習新知識的重大突破,就是你得有石頭可摸!

3. 為什麼描述子是正确打開碼流解析的第一步

為了要清楚的解釋這個問題,我們得先知道什麼是描述子?

3.1 什麼是描述子?

還記得在NALU Header的解析中,我們說過,forbidden_zero_bit的值對應1個bit,nal_ref_idc的值對應2個bit,nal_unit_type的值對應5個bit。但是我沒說,我是怎麼知道哪個句法元素的值,對應幾個bit的?或者說,我是怎麼知道,句法元素的值是怎麼計算的?

這就是描述子的作用,比如我們之前計算過的NALU Header的句法元素,它在h.264協定中規定如下:

【H264/AVC 句法和語義詳解】(四):通過學習"描述子"實作碼流解析的第一步

NALU Header句法

右側标紅框的,就是各句法元素對應的描述子,它表示了,這個句法元素的值是如何計算的。其中f(1)、u(2)、u(5)功能一樣,為順序讀取1、2和5個bit位,作為句法元素的值。是以我們才說,forbidden_zero_bit、nal_ref_idc、nal_unit_type的值,分别對應1、2、5個bit。

3.2 描述子種類

那是不是所有的文法元素都是以,連續讀取接下來的n個比特這種模式來計算的呢?不是的,在h.264協定中,規定有如下描述子:

【H264/AVC 句法和語義詳解】(四):通過學習"描述子"實作碼流解析的第一步

h.264協定規定的全部描述子

描述子乍一看很多,其實我們可以把它們分為三類:

(1)連續讀取n(包含b(8))個比特:b(8)、f(n)、i(n)、u(n),其中隻有i(n)為有符号整數,并且幾乎用不到,其他情況則順序從左至右,讀取固定數量的n個bit即可。如上面所講的NALU Header的句法元素

(2)指數哥倫布編碼:ue(v)、me(v)、se(v)、te(v),這四個描述子,都是指數哥倫布編碼。注意到它們使用的變量是v而不是n,它們的值,并不是直接等于讀取固定長度的比特。而是先根據其他句法元素的值,來确定讀取多少比特,然後再将讀取到的比特,進行轉換才能得到所求句法元素的值。

關于它們,我們後面會單獨開幾篇來介紹。

(3)CAVLC、CABAC:ae(v)、ce(v),同指數哥倫布編碼一樣,CAVLC和CABAC也屬于變長編碼,這也是我們需要學習的一大重點。

3.3 利用描述子解析句法元素

是以這時,隻要我們懂得,各個描述子是如何計算的,我們就能根據它們解析出句法元素的值。不過需要注意的是,有時候我們會看到這種情況:

【H264/AVC 句法和語義詳解】(四):通過學習"描述子"實作碼流解析的第一步

句法元素對應兩個描述子的情況

可以看到,在解析宏塊層mb_type的時候,該句法元素對應了兩個描述子,分别為ue(v)和ae(v),并且它們之間用豎線 “|” 分隔開。

H.264協定規定,出現這種情況,得根據另一句法元素entropy_coding_mode_flag 的值來判斷:

如果entropy_coding_mode_flag等于0,則使用左邊的描述子,這時為ue(v)。

如果entropy_coding_mode_flag等于1,則使用右邊的描述子,這時為ae(v)。

3.4 為什麼描述子是正确打開碼流解析的第一步

這個時候,我們就可以來回答最開始這個問題了。

如1.2學習主線分段所說,我們如果要進行碼流解析,第一步則是進行句法元素的解析,而句法元素的解析,又依賴于剛才所講的那幾種描述子。通過剛才的學習我們也知道,學習描述子,其實就相當于學習熵編碼。

是以我們接下來,就從學習描述子開始。

繼續閱讀