作者:66
在開始幀間預測代碼分析之前,先把理論部分再理一遍。這部分涉及到的知識點較之前多些,相關的資料與代碼不容易找出匹配的部分,造成作爲新手的我閱讀源代碼反覆好幾次才搞清楚(還沒體驗過上手就明瞭的感覺)。
我把理論部分修改盡力趨同於後面對代碼的解析。
相關的名詞:ME(運動估計)、MC(運動補償)、MV(運動向量,其實就是運動距離加方向,代碼中用Dir表示方向,MV表示距離)、SAD(絕對誤差和)
AMVP(高級運動向量預測)、MVD(預測殘差)、MVP(參考的MV)。
在HEVC中使用了兩種MV預測技術,Merge技術和AMVP技術,兩種技術都用到了空域和時域的MV預測的思想,不同的是,Merge直接拿相近的MV來用,AMVP拿來之後與真正的MV作了比較,編碼MVD。因此,Merge下沒有MVD,AMVP有MVD,這是第一點不同。第二點就是,拿別人的MV來用之前,Merge與AMVP都比較機智,不是每次都抄一個人的MV,它們都拿幾個相鄰PU的MV作爲候選,對比出一個靠譜的拿來用(這不就是作弊嘛,抄抄別人的,不勞而獲),它們的候選數量和選擇順序(這個到後面會明白)不同。
先看Merge。
另外一點要明白的是,他們選出來最優MV後,要用這個MV進行運動估計,就是找相鄰幀上與當前PU最相近的塊,至於怎麼找,之後再說。
Merge:
Merge爲當前PU建立一個MV候選列表,候選數量爲5,遍歷五個MV選取率失真最小的一個作爲最優MV,解碼端同樣地方式建立一個候選列表,傳輸時僅傳輸MV在列表中的索引即可。
①空域 :
圖一、空域候選PU相對位置
當前PU五個方向上的候選PU,遍歷順序爲:A1->B1->B0->A0->B2,候選列表的大小爲5,但HEVC中至多使用其中4個(哪怕五個都存在),並且當其中某一個不可用時,順序用下一個(不夠就補零吧)。
不可用的情況分如下兩種:
圖二、PU的左右、上下劃分
當PU左右劃分而且當前PU位於第二個時A1是不可用的,如果使用了A1的MV,圖中pu與Cpu的mv一致,和不劃分就沒區別了。同樣,PU的上下劃分時第二個的PU是不能使用B1的。
②時域:
類比空域,空域用相鄰塊,則時域用相鄰幀的同位(對應位置)PU的MV來推測當前位置的MV。來看下怎麼推測的。
幀間預測的圖像都要有參考圖像,像B幀參考它之前的圖像,P幀可以參考它之前也可以參考之後。當前幀叫cur,當前幀的參考幀叫cur_ref,當前幀的同位幀叫col,同位幀的參考幀叫col_ref,好像有點亂,我一開始也亂。
圖三、時域MV伸縮
圖中的豎線表示那一幀圖片在時間線上的位置,假設物體勻速運動,那麼從col到col_ref運動時間爲Tcol,從cur到cur_ref的運動時間爲Tcur,物體運動的MV(距離)應該與時間成正比,於是就有:
這樣就能由col(同位)幀推導出當前幀的MV。HEVC中,時域最多提供一個候選MV。
一般在col幀中相對當前PU位置爲右下或中部,如圖:
圖四、候選PU位置
時域colPU首選P1位置,若P1處不可用或不存在時,選P2位置的PU。
空域與時域:
對於B幀,就是需要參考前向幀MV又需要後向幀MV的幀,它有兩個MV列表,list0,list,Merge下爲B幀建立了一個組合列表,將兩個MV列表的候選MV組合到一起,組合方式如下表:
combIdx |
0 |
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
L0CandIdx |
0 |
1 |
0 |
2 |
1 |
2 |
0 |
3 |
1 |
3 |
2 |
3 |
L1CandIdx |
1 |
0 |
2 |
0 |
2 |
1 |
3 |
0 |
3 |
1 |
3 |
2 |
表一、Bslice候選MV組合列表
另外關於B幀在計算MV或像素誤差統計時,HEVC中不是在前後col幀中選其一,而是直接以兩幀像素各以1/2比例疊加成新幀參與計算。這樣做不是太合理,沒有考慮兩幀對當前幀的參考價值,也就是沒按加權(距離當前幀的時間遠近不同,RD的不同等)來疊加成新幀,這個在H.266中提了出來,但因爲代價太大(性能提升不明顯,計算又過於複雜)被否決了。
(本文爲作者原創,未經允許嚴禁轉載)