如何读H.264的标准和代码
首先,還是要弄清楚編解碼的流程和 H.264 的關(guān)鍵技術(shù),看白皮書就知道了,另外 H.264 綜述類的文章和別人的學(xué)位論文一般也會講到;
其次,弄清楚代碼的各個函數(shù)實現(xiàn)的功能,這個可以看看 JM 代碼里各個函數(shù)前面的函數(shù)說明;
最后,弄清楚標準各個章節(jié)講的什么內(nèi)容:這里只說重要的。第三章是名詞解釋,第四章是縮略語,第五章是一些計算方式和運算符號的說明,第六章是與 H.264 相關(guān)的一些視頻基礎(chǔ)知識和 H.264 中用到的一些過程推導(dǎo),第七章是 NALU 及其以下語法結(jié)構(gòu)的語法和語義(如果要知道碼流結(jié)構(gòu)就要看這一章了),第八章是詳細說明解碼過程中某一個模塊的功能怎么完成,第九章是熵編碼,附錄 A 是關(guān)于 profile 和 level 的具體規(guī)定,附錄 B 是關(guān)于如何從字節(jié)流中解析 NALU(標準沒有說明如何在 RTP 流中解析 NALU)。
有了上面的基本知識,下面我們結(jié)合對碼流的解析過程來講講怎么讀標準:
1、如果是字節(jié)流的碼流當然就首先要對字節(jié)流進行解析,這就要看附錄 B 了;如果是 RTP 格式的碼流,那首先就要按 RFC3984 來解析了(標準沒有規(guī)定 RTP 格式碼流的解析過程);
2、字節(jié)流解析完后提取出來的就是 NALU 了,對 NALU 的解析就要看 7.3.1 小節(jié)了。第七章中黑色的粗體字都是在碼流中可能出現(xiàn)的語法元素,解碼器的首要任務(wù)就是要對這些語法元素進行解析。對于這些碼流中的語法元素我們要進行解析必須知道三個問題:
(1)、什么時候存在于碼流中?這樣我們才能知道當前解析的是哪個語法元素;
(2)、采用什么樣的熵編碼方式?這樣我們才能知道如何解析;
(3)、含義是什么?這樣我們才知道解析出來之后用來干什么。
三個問題的答案分別是:
(1)、有 if 條件關(guān)聯(lián)的就是可能出現(xiàn)的,沒有 if 條件關(guān)聯(lián)的就是必然出現(xiàn)的。例如,7.3.1 小節(jié)表中的 forbidden_zero_bit 就沒有 if 條件關(guān)聯(lián),所以它必然出現(xiàn)在碼流中;
(2)、每個語法表最后一列都對所在行語法元素的熵編碼方式做了規(guī)定,而最后一列各個符號具體是代表什么編碼方式那就去看 7.2 小節(jié)最后的部分;
(3)、看 7.4 小節(jié)與語法表對應(yīng)的語義部分,例如你查的語法表是 7.3.1,那么該語法表里出現(xiàn)的語法元素的解釋就在 7.4.1 小節(jié)中。
3、NALU 的前面三個語法元素所組成的一個字節(jié)我們稱為 NALU 頭,其余部分(也就是語法表 7.3.1 中的其余部分)我們稱為 NALU 體。對 NALU 體的解析要看 7.3.2 小節(jié)。因為 NALU 有很多種類型,所以要針對 NALU 的不同類型去解析 NALU 體(表 7-1 說明了不同 NALU 對應(yīng)的語法表)。例如,如果當前的 NALU 是 SPS,那么當然就要看 7.3.1 小節(jié);如果當前的 NALU 是 DPA,那么當然就要看 7.3.2.9.1 小節(jié)了;
4、對于屬于 VCL 的 NALU(哪些 NALU 是 VCL NALU 呢?如果你看了 nal_unit_type 的語義,你就應(yīng)該知道),例如表 7-1 中類型為 5 的 NALU,根據(jù)表 7-1 我們知道 NALU 體的語法表是 7.3.2.8。而從 7.3.2.8 我們可以看到,對這種 NALU 的 NALU 體解析實際就是對片級語法進行解析。語法表 7.3.2.8 顯示片級語法解析首先要解析 slice_header()(這種帶括號的表示是另一個語法結(jié)構(gòu)),那么 slice_header() 怎么解析呢?往下看,7.3.3 的所有內(nèi)容都被第一行的 slice_header() 包括在內(nèi),所以 7.3.3 就是對 slice_header() 這個語法層的碼流規(guī)定;
5、按照語法表 7.3.2.8 解析完了 slice_header() 就該解析 slice_data() 了。下面以最常見的 I 幀(CAVLC 熵編碼、非 MBAFF)的解析過程為例簡單描述怎么繼續(xù)讀標準。這時在碼流中出現(xiàn)的第一個 slice_data() 層的語法元素是語法表 7.3.4 中的 macroblock_layer(),也就是說直接到了宏塊層的語法解析,那就要又要看 7.3.5 小節(jié)了;
6、基于我們對編解碼流程的了解,我們知道解碼是一個預(yù)測值加殘差得到重建圖像的過程,那么我們下面的解碼過程就要分成兩步走了:首先,得到預(yù)測值;其次,得到殘差。基于我們對 H.264 關(guān)鍵技術(shù)的了解,我們知道 intra 宏塊(提醒:我們舉的例子是 I 幀,因此解析的是 intra 宏塊)的預(yù)測值是需要使用到預(yù)測模式的,所以我們需要解析語法表 7.3.5 中的 mb_pred(mb_type) 語法層,那么又去看 7.3.5.1 小節(jié)。按照 7.3.5.1 小節(jié)解析出宏塊或塊的預(yù)測方式后我們怎么計算預(yù)測值呢?去看標準 8.3 小節(jié);得到預(yù)測值后我們繼續(xù)按照語法表 7.3.5 解析語法元素直到 residual() 語法層,這就又要去看 7.3.5.3 小節(jié);按照 7.3.5.3 小節(jié)解析出殘差系數(shù)后我們?nèi)绾伟阉€原成真實的殘差呢?去看標準 8.5 小節(jié);
7、預(yù)測值和殘差都有了,加起來就是解碼圖像了。解碼的主要工作到此也算基本完成了。當然,上面的過程中還會用到標準其他章節(jié)的相關(guān)內(nèi)容(例如,8.5 小節(jié)會用到 5.7 小節(jié)中定義的 InverseRasterScan),這就留給大家自己去學(xué)習(xí)了。
上面講了如何讀標準,那么如何讀代碼呢?非常簡單,因為你現(xiàn)在已經(jīng)知道了代碼中各個函數(shù)所實現(xiàn)的功能以及標準各個章節(jié)所涉及的內(nèi)容,那么你就該知道標準某個部分的內(nèi)容與代碼中的哪個函數(shù)對應(yīng),因此對于你想詳細了解實現(xiàn)過程的模塊,對照標準去仔細啃那個函數(shù)吧。對于代碼中不明白的變量或者參數(shù),把程序跑起來,看第 1 個 MB 解碼時候該變量的值是多少,第 23 個 MB 解碼時候該變量的值是多少……多做幾個觀察值,注意不要選擇特殊位置,然后總結(jié)一下規(guī)律,這樣你就自然能分析出該變量的作用和含義了。
以上講的是解碼過程,編碼過程就是解碼的反過程,因此同理。
——天之驕子(firstime)——
2008年8月5日
原文:bbs.chinavideo.org/viewthread.php?tid=4164
總結(jié)
以上是生活随笔為你收集整理的如何读H.264的标准和代码的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Java中多线程并发处理方式
- 下一篇: android中在代码中动态布按钮和画板