直接預測是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的位置,首先須要知道co-located所在的圖像colPic的位置,colPic能夠肯定在當前圖像的第一個後向參考圖像RefPicList1[ 0 ]內,可是colPic能夠爲幀或場,這取決於當期圖像與參考圖像,是以幀圖像進行編碼,仍是以場圖像進行編碼,或者以互補場對(宏塊級幀場自適應)方式進行編碼。htm
topAbsDiffPOCbottomAbsDiffPOC=|DiffPicOrderCnt(firstRefPicL1Top,CurrPic)|=|DiffPicOrderCnt(firstRefPicL1Bottom,CurrPic)|topAbsDiffPOC=|DiffPicOrderCnt(firstRefPicL1Top,CurrPic)|bottomAbsDiffPOC=|DiffPicOrderCnt(firstRefPicL1Bottom,CurrPic)|blog
添加這些條件是爲了在採用宏塊級幀場自適編碼方式時,應選擇距離當前圖像最近的頂場或底場做爲col_Pic索引
注:其實第二項RefPicList1[ 0 ]是一個被動選項,由於它是根據當前圖像的編碼方式是幀、場或宏塊幀場自適應決定的,若是當前圖像是場,那麼RefPicList1[ 0 ]就有多是已解碼的場或者以解碼幀中的一場;若是當前圖像是幀(非MBAFF),那麼RefPicList1[ 0 ]就是幀;若是當前宏塊是幀而且爲MBAFF,那麼RefPicList1[ 0 ]就是一個互補場對(兩個場能夠組成一個幀)隊列
實際上,若是獲得了colPic,就能夠經過當前宏塊的16個4x4塊的絕對位置(以4x4塊爲單位相對於圖像左上角(0,0)的絕對位置( opic_block_x,opic_block_y)),獲得co-located在colPic的位置。get
(注:像在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(圖像幀場自適應))
另外,爲了減小計算量,還能夠設定direct_8x8_inference_flag等於1,這樣會致使每一個8x8塊共用一個4x4的co-located,共用方式爲一個宏塊的4個8x8塊分別只用該宏塊4個角的4x4塊做爲co-located
(注:至於如何從8x8塊中選取該4x4塊並沿用其參考索引,標準中並無規定,具體能夠看本文最後的代碼是如何作的)
該模式是基於下圖求出當前4x4塊的先後向mvL0與mvL1,以及前向參考幀List0 reference的索引
已知的變量有:
未知的變量有:
求解方法:
因爲這些在標準(8.4.1.2.3)中講的都很是細緻,因此這裏簡要說明一下而已。
空域模式基於一種假設:當前編碼宏塊與其相鄰宏塊都向着同一個方向運動,你們有着相似的運動向量與參考幀(以下圖)。在這種假設前提上,空域模式主要思想爲採用相鄰塊來對當前宏塊的參考索引以及運動向量進行預測。因爲標準中8.4.1.3有很是詳細的描述,因此在此略過。
可是上述假設也頗有可能不成立,有可能當前宏塊的相鄰塊都是運動的,但當前宏塊是靜止的(以下圖)。好比說當前宏塊是背景的一部分,而相鄰塊則是移動着的前景。這時候就須要判斷當前宏塊是不是運動的,以獲得更準確的空域預測,co-located在這裏就是用來判斷當前宏塊是不是運動宏塊的。若是co-located的mvCol[0]與mvCol[1]能保證在某個範圍以內,則代表當前宏塊爲靜止宏塊,那麼將把當前宏塊的mvL0與mvL1賦值爲0,具體在標準8.4.1.2.2中描述得至關詳細,不做細述。