AV1 specification を読む 2018-04-04 (7.8. Motion Field Estimation Process)

#AV1 specification 日本語訳 (2018-04-04)

モーションフィールドとは、参照フレームの動きベクトル（参照フレームのさらに参照）を使って、カレントフレームの動きを推定したものです。
モーションフィールドの計算手順は大まかに以下のようになります。

 * （各）参照フレームの 8x8 ブロックごとの動きベクトル（参照フレームから、参照フレームの参照フレームを指すベクトル）を、カレントフレームに線形投影します。
  * 投影には、フレームの表示順情報を使います
  * カレントフレームに投影された先が、動きベクトルの根元となります
 * その動きベクトルの根元から、参照フレームの動きベクトルの根元までを、カレントフレーム内の根元のブロックのモーションフィールドMVとします。

イメージとしては、参照フレームに存在する物体が等速直線運動していると仮定して、その物体がカレントフレームのどの位置に存在し、どのように動いているかを推定しています。

動きベクトルの投影は参照フレーム全体からなされますが、カレントブロックへの投影先はフレーム全体を覆うわけではありません。
モーションフィールドは「穴あき」な感じで生成されます。

----

## 7.8. Motion Field Estimation Process

> This process is triggered by a call to motion_field_estimation while reading the uncompressed header.

この処理は、uncompressed_header の motion_field_estimation() の呼び出しで実行します。

> A linear projection model is employed to create a motion field estimation that is able to capture high velocity temporal motion trajectories.
> The motion field is estimated based on the saved motion vectors from the reference frames and the relative frame distances.
> As the frame distances depend on the frame being referenced, a separate motion field is estimated for each reference frame used by the current frame.
> A motion vector (for each reference frame type) is prepared at each location on an 8x8 pixel grid.

時間的に高速な動きの遷移をとらえることができるよう、モーションフィールド推定をするために、線形投影モデルを適用います。
モーションフィールドは、格納された参照フレームのMVと、（カレントフレームから参照フレームへの）相対的なフレーム距離に基づいて推定します。
フレーム距離は参照されるフレームに依存するので、カレントフレームで使うモーションフィールドは、参照フィールドそれぞれ別個に推定されます。
（参照フレームタイプごとに）1つのMVが、8x8グリッド上の各座標について準備されます。

> The variable w8 (representing the width of the motion field in units of 8x8 pixels) is set equal to MiCols >> 1.
> The variable h8 (representing the height of the motion field in units of 8x8 pixels) is set equal to MiRows >> 1.

w8 = MiCols >> 1 （8x8画素単位のモーションフィールドの幅）
h8 = MiRows >> 1 （8x8画素単位のモーションフィールドの高さ）

> As the linear projection can create a field with holes, the motion fields are initialized to an invalid motion vector of -32768, -32768 as follows:

線形投影は穴が開いているフィールドを生成するかもしれないので、モーションフィールドは以下のように無効なMV値 -32768 で初期化しておきます。

```C++
for ( ref = LAST_FRAME; ref <= ALTREF_FRAME; ref++ )
  for ( y = 0; y < h8 ; y++ )
    for ( x = 0; x < w8; x++ )
      for ( j = 0; j < 2; j++ )
        MotionFieldMvs[ ref ][ y ][ x ][ j ] = -1 << 15
```

> The variable lastIdx (representing which reference frame is used for LAST_FRAME) is set equal to ref_frame_idx[ 0 ].
> The variable curGoldOrderHint (representing the expected output order for GOLDEN_FRAME of the current frame) is set equal to OrderHints[ GOLDEN_FRAME ].
> The variable lastAltOrderHint (representing the expected output order for ALTREF_FRAME of LAST_FRAME) is set equal to SavedOrderHints[ lastIdx ][ ALTREF_FRAME ].
> The variable useLast (representing whether to project the motion vectors from LAST_FRAME) is set equal to ( lastAltOrderHint != curGoldOrderHint ).

lastId = ref_frame_idx[0] （どの参照フレームが LAST_FRAME なのか）
curGoldOrderHint = OrderHint[ GOLDEN_FRAME ] （カレントフレームの GOLDEN_FRAME の期待される出力順）
lastAltOrderHint = SavedOrderHints[ lastIdx ][ ALTREF_FRAME ] （LAST_FRAME の ALTREF_FRAME の期待される出力順）
useLast = (lastAltOrderHint != curGoldOrderHint) （LAST_FRANE びMVを射影するかどうか）

> If useLast is equal to 1, the projection process in section 7.8.1 is invoked with src equal to LAST_FRAME, dir equal to 0, offsetSign equal to 1, and refStamp also passed as an input. (The output of this process is discarded.)

useLast==1 ならば、射影処理（7.8.1節）を、src=LAST_FRAME, dir=0, offsetSign=1, refStap を入力として呼び出します。
（処理の出力は破棄します）

> The variable refStamp (that limits how many reference frames have to be projected) is set equal to MFMV_STACK_SIZE - 2.

refStamp = MFMV_STACK_SIZE - 2 （何枚の参照フレームを射影すべきかの制限）

> The variable useBwd is set equal to get_relative_dist( OrderHints[ BWDREF_FRAME ], OrderHint ) > 0.
> 
> If useBwd is equal to 1, the following steps apply:
>
>　* The projection process in section 7.8.1 is invoked with src equal to BWDREF_FRAME, dir equal to 0, and offsetSign equal to 0, and the output assigned to projOutput.
>　* If projOutput is equal to 1, refStamp is set equal to refStamp - 1.

useBwd = get_relative_dist( OrderHints[ BWDREF_FRAME ], OrderHint ) > 0

useBwd==1 ならば以下の手順を適用します。

 * 射影処理（7.8.1節）を、src=BWDREF_FRAME, dir=0, offsetSign=0 を入力として呼び出し、出力を projOutput に割り当てます。
 * projOutput==1 ならば、--refStamp

> The variable useAlt2 is set equal to get_relative_dist( OrderHints[ ALTREF2_FRAME ], OrderHint ) > 0.
>
> If useAlt2 is equal to 1, the following steps apply:
>
>　* The projection process in section 7.8.1 is invoked with src equal to ALTREF2_FRAME, dir equal to 0, and offsetSign equal to 0, and the output assigned to projOutput.
>　* If projOutput is equal to 1, refStamp is set equal to refStamp - 1. 

useAlt2 = get_relative_dist( OrderHints[ ALTREF2_FRAME ], OrderHint ) > 0

useAlt2==1 ならば以下の手順を適用します。

 * 射影処理（7.8.1節）を、src=ALTREF_FRAME, dir=0, offsetSign=0 を入力として呼び出し、出力を projOutput に割り当てます。
 * projOutput==1 ならば、--refStamp


> The variable useAlt is set equal to get_relative_dist( OrderHints[ ALTREF_FRAME ], OrderHint ) > 0.
>
> If useAlt is equal to 1 and (refStamp >= 0), the following steps apply:
>
> 　* The projection process in section 7.8.1 is invoked with src equal to ALTREF_FRAME, dir equal to 0, and offsetSign equal to 0, and the output assigned to projOutput.
> 　* If projOutput is equal to 1, refStamp is set equal to refStamp - 1.

useAlt = get_relative_dist( OrderHints[ ALTREF_FRAME ], OrderHint ) > 0

useBwd==1 ならば以下の手順を適用します。

 * 射影処理（7.8.1節）を、src=ALTREF_FRAME, dir=0, offsetSign=0 を入力として呼び出し、出力を projOutput に割り当てます。
 * projOutput==1 ならば、--refStamp

> If (refStamp >= 0), the projection process in section 7.8.1 is invoked with src equal to LAST2_FRAME, dir equal to 0, and offsetSign equal to 1. (The output of this process is discarded.)

refStaemp>=0 ならば、src=LAST2_FRAME, dir=0, offsetSign=1 を入力として呼び出します（出力は破棄します）。