AV1 specification を読む 2018-04-17 (7.10.2.4. Block Warp Process)

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

Block Warp Process とは、アフィン変形した参照フレームを切り出して、カレントブロックの予測値とする処理です。
ワープには2種類あります。

 * ローカルワープ
    * シングル予測の場合に選択することができます
    * カレントブロックの周辺の動きベクトルからアフィンパラメータを推定し、参照フレームを変形させます。
 * グローバルワープ
    * フレーム全体のアフィンパラメータ（グローバルモーション）によって、参照フレームを変形させます。

----

#### 7.10.2.4. Block Warp Process

> The inputs to this process are:
> 
>  * a variable useWarp (equal to 1 for local warp, or 2 for global warp),
>  * a variable plane,
>  * a variable refList specifying that the process should predict from RefFrame[ refList ],
>  * variables x and y specifying the location of the top left sample in the CurrFrame[ plane ] array of the region to be predicted,
>  * variables i8 and j8 specifying the offset (in units of 8 samples) relative to the top left sample,
>  * variables w and h giving the width and height of the block in units of samples.

この処理の入力は以下のとおりです。

 * useWarp（1ならばローカルワープ、2ならばグローバルワープ）
 * plane
 * RefFrame[reflist] から予測することを指定する refList
 * 予測すべき CurrFrame[plane] 内の領域の、左上画素の座標 (x, y)
 * その左上画素からの（8画素単位の）オフセットを指定する変数 (i8, j8)
 * 画素単位のブロック幅と高さ (w, h)


> The output from this process is the 2D array named pred containing warped inter > predicted samples.

この処理の出力は、ワープされたインター予測画素を含む二次元配列 pred です。

> The process only updates a section of the pred array.
> The size of the updated section is 8x8 samples, clipped to the size of the block.
> Variables i8 and j8 give the location of the section to update.

この処理は、配列 pred のある部分のみを更新します。
更新する部分は 8x8 画素単位で、ブロックサイズでクリップされます。
変数 i8, j8 は、更新すべき部分の座標です。

> A variable refIdx specifying which reference frame is being used is set equal to ref_frame_idx[ RefFrame[ refList ] - LAST_FRAME ].
> 
> A variable ref specifying the reference frame contents is set equal to FrameStore[ refIdx ].

refIdx = ref_frame_idx[ RefFrame[ refList ] - LAST_FRAME ] （どの参照フレームを使うかを指定する）
ref = FrameStore[ refIdx ] （参照フレームの中身を指定）

> The variables subX and subY are set equal to the subsampling for the current plane as follows:
> 
>  * If plane is equal to 0, subX is set equal to 0 and subY is set equal to 0.
>  * Otherwise, subX is set equal to subsampling_x and subY is set equal to subsampling_y.

subX, subY を、カレントプレーンのサブサンプリングとします。

 * plane==0 ならば、subX=0, subY=0
 * そうでなければ、subX=subsampling_x, subY=subsampling_y

> The variable lastX is set equal to ( (RefUpscaledWidth[ refIdx ] + subX) >> subX) - 1.
> The variable lastY is set equal to ( (RefFrameHeight[ refIdx ] + subY) >> subY) - 1.
> (lastX and lastY specify the coordinates of the bottom right sample of the reference plane.)

lastX = ( (RefUpscaledWidth[ refIdx ] + subX) >> subX) - 1
lastY = ( (RefFrameHeight[ refIdx ] + subY) >> subY) - 1
（lastX, lastY は、参照プレーンの右下画素の座標です）


> The variable srcX is set equal to (x + j8 * 8 + 4) << subX.
> The variable srcY is set equal to (y + i8 * 8 + 4) << subY.
> (srcX and srcY specify a location in the luma plane that will be projected using the warp parameters.)

srcX = (x + j8 * 8 + 4) << subX
srcY = (y + i8 * 8 + 4) << subY
（srcX, srcY は、ワープパラメータを使って射影する輝度プレーンの座標です）

> The array warpParams is specified as follows:
> 
>  * If useWarp is equal to 1, warpParams is set equal to LocalWarpParams.
>  * Otherwise (useWarp is equal to 2), warpParams is set equal to gm_params[ RefFrame[ refList ] ].

配列 warpParams を以下のように適用します。

 * useWarp==1 ならば、warpParams = LocalWarpParams
 * useWarp==2 ならば、warpParams = gm_params[RefFrame[refList]]

> The variable dstX is set equal to warpParams[2] * srcX + warpParams[3] * srcY + warpParams[0].
> The variable dstY is set equal to warpParams[4] * srcX + warpParams[5] * srcY + warpParams[1].
> (dstX and dstY specify the destination location in the luma plane using WARPEDMODEL_PREC_BITS bits of precision).

dstX = warpParams[2] * srcX + warpParams[3] * srcY + warpParams[0]
dstY = warpParams[4] * srcX + warpParams[5] * srcY + warpParams[1]
（dstX, dstY は、WARPMODEL_PERC_BITS 精度の、輝度プレーンの宛先座標です。）

> The setup shear process specified in section 7.10.2.5 is invoked with warpParams as input, and the outputs are assigned to warpValid, alpha, beta, gamma, and delta. (warpValid will always be equal to 1 at this point.)

7.10.2.5節で規定されるsetup shear処理をwarpParamsを入力として呼び出し、出力を warpValid, alpha, beta, gamma, delta に割り当てます。
（この時点で warpValid は常に１です。）

> The sub-sample interpolation is effected via two one-dimensional convolutions. 
> First a horizontal filter is used to build up a temporary array, and then this array is vertically filtered to obtain the final prediction.

画素間補間を、2回の1次元畳み込みで処理します。
最初に水平フィルタで一時配列を構成し、その後垂直フィルタで最終的な予測値を得ます。


> The filtering is applied as follows:
>
> * The array intermediate is specified as follows:

フィルタリングを以下のように適用します。

 * 配列 intermediate を以下のように規定します。

```C++
x4 = dstX >> subX
y4 = dstY >> subY
ix4 = x4 >> WARPEDMODEL_PREC_BITS
sx4 = x4 & ((1 << WARPEDMODEL_PREC_BITS) - 1)
iy4 = y4 >> WARPEDMODEL_PREC_BITS
sy4 = y4 & ((1 << WARPEDMODEL_PREC_BITS) - 1)

for (i1 = -7; i1 < 8; i1++) {
  for (i2 = -4; i2 < 4; i2++) {
    sx = sx4 + alpha * i2 + beta * i1
    offs = Round2(sx, WARPEDDIFF_PREC_BITS) + WARPEDPIXEL_PREC_SHIFTS
    s = 0
    for (i3 = 0; i3 < 8; i3++) {
      s += Warped_Filters[ offs ][ i3 ] *
           ref[ plane ][ Clip3( 0, lastY, iy4 + i1 ) ]
                       [ Clip3( 0, lastX, ix4 + i2 - 3 + i3 ) ]
    }
    intermediate[(i1 + 7)][(i2 + 4)] = Round2(s, InterRound0)
  }
}
```

> * The array pred is specified as follows:

 * 配列 pred を以下のように規定します。

```C++
for (i1 = -4; i1 < Min(4, h - i8 * 8 - 4); i1++) {
  for (i2 = -4; i2 < Min(4, w - j8 * 8 - 4); i2++) {
    sy = sy4 + gamma * i2 + delta * i1
    offs = Round2(sy, WARPEDDIFF_PREC_BITS) + WARPEDPIXEL_PREC_SHIFTS
    s = 0
    for (i3 = 0; i3 < 8; i3++) {
      s += Warped_Filters[offs][i3] * intermediate[(i1 + i3 + 4)][(i2 + 4)]
    }
    pred[ i8 * 8 + i1 + 4 ][ j8 * 8 + i2 + 4 ] = Round2(s, InterRound1)
  }
}
```

> where the constant array Warped_Filters is specified as:

ここで、定数配列 Warped_Filter は以下のように規定されます。

```C++
Warped_Filters[WARPEDPIXEL_PREC_SHIFTS * 3 + 1][8] = {
  ... 略 ...
}
```