[轉] H264 Direct預測模式

h.264直接預測

直接預測是B幀上一種獨有的預測方式,其中直接預測又分爲兩種模式: 時域直接模式(temporal direct)、空域直接模式(spatial direct)。html

在分析這兩種模式以前,有一個前提概念須要瞭解:共同位置4x4子宏塊分割塊(co-located 4x4 sub-macroblock partitions),下面簡稱爲co-located。編碼

共同位置4x4子宏塊分割塊,故名思義,該塊大小爲4x4。co-located的主要功能是獲得出該4x4塊的運動向量以及參考幀,以供後面的直接預測作後續處理,若是當前宏塊進行的是直接預測,不管時域或空域,都會用到該co-located,所以須要先求出該4x4co-located的具體位置。spa

 

co-located的定位

1. 定位co-located所在圖像

要求co-located的位置,首先須要知道co-located所在的圖像colPic的位置,colPic能夠肯定在當前圖像的第一個後向參考圖像RefPicList1[ 0 ]內,可是colPic能夠爲幀或場,這取決於當期圖像與參考圖像,是以幀圖像進行編碼,仍是以場圖像進行編碼,或者以互補場對(宏塊級幀場自適應)方式進行編碼。htm

  • 第一項:field_pic_flag表示當前圖像是以幀仍是場方式進行編碼
  • 第二項:表明RefPicList1[0]的編碼方式是幀、場、互補場對(兩個場)
  • 第三項:mb_field_decoding_flag表明當前宏塊對是以幀、場方式進行編碼(前提條件是當前圖像是以幀方式進行編碼,也只有當前圖像選擇了幀編碼,才能選擇宏塊對(宏塊幀場自適應)的編碼方式)
  • 第四項:

    topAbsDiffPOCbottomAbsDiffPOC=|DiffPicOrderCnt(firstRefPicL1Top,CurrPic)|=|DiffPicOrderCnt(firstRefPicL1Bottom,CurrPic)|topAbsDiffPOC=|DiffPicOrderCnt(firstRefPicL1Top,CurrPic)|bottomAbsDiffPOC=|DiffPicOrderCnt(firstRefPicL1Bottom,CurrPic)|blog

    添加這些條件是爲了在採用宏塊級幀場自適編碼方式時,應選擇距離當前圖像最近的頂場或底場做爲col_Pic索引

  • 第五項:col_Pic的取值,firstRefPicL1Top 和firstRefPicL1Bottom 分別爲RefPicList1[ 0 ]中的頂場和底場

注:其實第二項RefPicList1[ 0 ]是一個被動選項,由於它是根據當前圖像的編碼方式是幀、場或宏塊幀場自適應決定的,若是當前圖像是場,那麼RefPicList1[ 0 ]就有多是已解碼的場或者以解碼幀中的一場;若是當前圖像是幀(非MBAFF),那麼RefPicList1[ 0 ]就是幀;若是當前宏塊是幀而且爲MBAFF,那麼RefPicList1[ 0 ]就是一個互補場對(兩個場能夠組成一個幀)隊列

 

2. 獲得co-located在colPic內的位置

實際上,若是獲得了colPic,就能夠經過當前宏塊的16個4x4塊的絕對位置(以4x4塊爲單位相對於圖像左上角(0,0)的絕對位置( opic_block_x,opic_block_y)),獲得co-located在colPic的位置。get

  • 若是當前圖像爲幀,colPic爲場,則co-located爲(opic_block_x,opic_block_y>>1)
  • 若是當前圖像爲場,colPic爲幀,則co-located爲(opic_block_x,opic_block_y<<1)
  • 若是當前圖像與colPic同爲幀或場,則co-located爲(opic_block_x,opic_block_y)

(注:像在jm18.6中,實際計算時,不會出現當前圖像爲場,colPic爲幀的狀況,由於場的參考圖像都會被分爲場後加入參考圖像隊列,因此最終計算時也會先根據當前場的是頂場或底場挑出參考幀中對應的場做爲colPic )it

 

在標準中,先定位co-located所在宏塊mbAddrCol,而後再定位co-located在該宏塊內的地址(xcol,yM)。因爲採用了不一樣於上述的4x4塊定位方法,因此計算方式略複雜,可是獲得的結果是同樣的,最終會定位到同一個co-locatedio

mbAddrCol1mbAddrCol2mbAddrCol3mbAddrCol4mbAddrCol5mbAddrCol6mbAddrCol7=2×PicWidthInMbs×(CurrMbAddr/PicWidthInMbs)+(CurrMbAddr % PicWidthInMbs)+PicWidthInMbs×(yCol/8)=2×CurrMbAddr+(yCol/8)=2×CurrMbAddr+bottom_field_flag=PicWidthInMbs×(CurrMbAddr/(2×PicWidthInMbs))+(CurrMbAddr % PicWidthInMbs)=CurrMbAddr/2=2×(CurrMbAddr/2)+((topAbsDiffPOC<bottomAbsDiffPOC)?0:1)=2×(CurrMbAddr/2)+(yCol/8)mbAddrCol1=2×PicWidthInMbs×(CurrMbAddr/PicWidthInMbs)+(CurrMbAddr % PicWidthInMbs)+PicWidthInMbs×(yCol/8)mbAddrCol2=2×CurrMbAddr+(yCol/8)mbAddrCol3=2×CurrMbAddr+bottom_field_flagmbAddrCol4=PicWidthInMbs×(CurrMbAddr/(2×PicWidthInMbs))+(CurrMbAddr % PicWidthInMbs)mbAddrCol5=CurrMbAddr/2mbAddrCol6=2×(CurrMbAddr/2)+((topAbsDiffPOC<bottomAbsDiffPOC)?0:1)mbAddrCol7=2×(CurrMbAddr/2)+(yCol/8)

 

(FAQ:爲什麼表中沒有FRM與AFRM配對?由於一個sps內只能定義爲FRM或者AFRM(MBAFF),在一個序列內二者是不可能共存的;爲什麼表中能夠有FRM與FLD共存?由於sps能夠定義PAFF(圖像幀場自適應))

 

  • 第一項:PicCodingStruct( CurrPic ),當前圖像的編碼方式
  • 第二項:PicCodingStruct( colPic ),colPic的編碼方式
  • 第三項:mbAddrX,當colPic爲AFRM(宏塊幀場自適應時),該項是用於定位colPic內地址爲mbAddrX的宏塊對,並用該宏塊判斷第五項fieldDecodingFlagX,即該宏塊對是用場編碼仍是幀編碼方式
  • 第四項:mb_field_decoding_flag,若是當前圖像的編碼方式是AFRM,該項用於判斷當前宏塊對是幀編碼仍是場編碼方式
  • 第五項:fieldDecodingFlagX,若是colPic的編碼方式是AFRM,該項用於判斷mbAddrX所在的宏塊對是幀編碼仍是場編碼方式
  • 第六項:mbAddrCol,co-located所在的宏塊在colPic內的地址,(注:涉及到AFRM的圖像都會被當作互補場對來處理,即AFRM幀,而不是colPic)
  • 第七項:yM,co-located相對於其所在宏塊的地址(xCol, yM),單位爲像素,即第一個4x4塊爲(0,0),最後一個爲(12,12),(注:當前4x4塊相對於其所在宏塊的地址爲(xCol,yCol))
  • 第八項:VertMvScale,代表CurrPic與colPic的幀場對應關係

 

另外,爲了減小計算量,還能夠設定direct_8x8_inference_flag等於1,這樣會致使每一個8x8塊共用一個4x4的co-located,共用方式爲一個宏塊的4個8x8塊分別只用該宏塊4個角的4x4塊做爲co-located

 

得到co-located的運動向量與參考幀

  • 若是co-located是幀內預測方式編碼,那麼將沒法得到運動向量與參考幀,mvCol = 0,refIdxCol = -1
  • 若是co-located是幀間預測編碼方式,而且存在前向參考幀,那麼mvCol將是co-located的前向運動向量,refIdxCol是co-located所在的8x8塊中的某一個4x4塊的前向參考索引
  • 若是co-located是幀間預測編碼方式,而且只存在後向參考幀,那麼mvCol將是co-located的後向運動向量,refIdxCol是co-located所在的8x8塊中的某一個4x4塊的後向參考索引

(注:至於如何從8x8塊中選取該4x4塊並沿用其參考索引,標準中並無規定,具體能夠看本文最後的代碼是如何作的)

 

 

時域直接模式(temporal direct)

該模式是基於下圖求出當前4x4塊的先後向mvL0與mvL1,以及前向參考幀List0 reference的索引

已知的變量有:

  1. 後向參考圖像List 1 reference (refPicList1[0])及其索引0
  2. 在計算co-located後獲得的mvCol(mvCol須要根據VertMvScale進行調整,乘或除2),以及參考圖像refColList0[refIdxCol](即List 0 reference)
  3. td與tb爲圖像之間的POC距離,既然List 0 reference、Current B、List 1 reference 已經知道,那麼就容易得出td與tb的值

未知的變量有:

  1. List 0 reference的在當前參考圖像列表中的索引
  2. 先後向運動向量mvL0與mvL1

求解方法:

  1. List 0 reference的索引,該索引是參考圖像列表中圖像List 0 reference所在的最小索引值(這部分因爲jm18.6中對mbaff採用了獨立互補場對參考列表,因此看起來更簡單一點,而標準是從refPicList0參考列表開始,而後結合VertMvScale進行推導,看起來比較繁瑣,但其實獲得的結果是同樣的)。
  2. mvL1 = mvCol/td*(td - tb)
  3. mvL0 = mvCol - mvL1    (忽略mv方向)

因爲這些在標準(8.4.1.2.3)中講的都很是細緻,因此這裏簡要說明一下而已。

 

空域直接模式(spatial direct)

空域模式基於一種假設:當前編碼宏塊與其相鄰宏塊都向着同一個方向運動,你們有着相似的運動向量與參考幀(以下圖)。在這種假設前提上,空域模式主要思想爲採用相鄰塊來對當前宏塊的參考索引以及運動向量進行預測。因爲標準中8.4.1.3有很是詳細的描述,因此在此略過。

可是上述假設也頗有可能不成立,有可能當前宏塊的相鄰塊都是運動的,但當前宏塊是靜止的(以下圖)。好比說當前宏塊是背景的一部分,而相鄰塊則是移動着的前景。這時候就須要判斷當前宏塊是不是運動的,以獲得更準確的空域預測,co-located在這裏就是用來判斷當前宏塊是不是運動宏塊的。若是co-located的mvCol[0]與mvCol[1]能保證在某個範圍以內,則代表當前宏塊爲靜止宏塊,那麼將把當前宏塊的mvL0與mvL1賦值爲0,具體在標準8.4.1.2.2中描述得至關詳細,不做細述。

相關文章
相關標籤/搜索