AV1 specification を読む 2018-04-17 (7.10.2.3. Block Inter Prediction Process)

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

Block Inter Prediction Process では、参照フレームから動きベクトルで指定された座標の画素ブロックを切り出して、カレントブロックの予測値とする処理です。
動きベクトルは 1/8 画素精度（小数部3ビット）なので、最大8タップの補間フィルタを使って、小数座標の画素値を計算します。

この補間処理は、カレントフレームと参照フレームの解像度比によるスケーリング処理も兼ねています。
このため、補間する小数精度は4bit（1/16画素単位;16位相）となっています。


----

#### 7.10.2.3. Block Inter Prediction Process

>The inputs to this process are:
>
> * a variable plane,
> * a variable refIdx specifying which reference frame is being used (or -1 for intra block copy),
> * variables x and y giving the block location with in units of 1/1024 th of a sample,
> * variables xStep and yStep giving the step size in units of 1/1024 th of a sample,
> * variables w and h giving the width and height of the block in units of samples,
> * variables candRow and candCol specifying the location (in units of 4x4 blocks) of the motion vector information to be used.

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

 * plane
 * どの参照フレームを使うか指定する refIdx （-1 ならばイントラブロックコピー）
 * 1/1024 画素単位のブロック座標 (x, y)
 * 1/1024 画素単位のステップサイズ (xStep, yStep)
 * 1画素単位のブロック幅と高さ (w, h)
 * 使用する動きベクトル情報を指定する（4x4ブロック単位の）座標 (candRow, candCol)

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

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

> A variable ref specifying the reference frame contents is set as follows:
>
> * If refIdx is equal to -1, ref is set equal to CurrFrame.
> * Otherwise (refIdx is greater than or equal to 0), ref is set equal to FrameStore[ refIdx ].

参照フレームを指定する変数 ref の内容は以下のように設定します。

 * refIdx==-1 ならば、ref = CurrFrame
 * refIdx>=0 ならば、、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 intermediateHeight specifying the height required for the intermediate array is set equal to (((h - 1) * yStep + (1 << SCALE_SUBPEL_BITS) - 1) >> SCALE_SUBPEL_BITS) + 8.

中間配列の高さを指定する変数
intermediateHeight = (((h - 1) * yStep + (1 << SCALE_SUBPEL_BITS) - 1) >> SCALE_SUBPEL_BITS) + 8.

> 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.
> The fractional parts of the motionv vectors determine the filtering process. 
> If the fractional part is zero, then the filtering is equivalent to a straight sample copy.

画素間補間は2回の1次元畳み込みでなされます。
最初の水平フィルタでテンポラリ配列を構成し、この配列に垂直フィルタすることで最終的な予測になります。
動きベクトルの小数部分でフィルタ処理が決まります。
小数部分がゼロならば、このフィルタリングは単なるコピーと等価です。

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

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

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

```C++
interpFilter = InterpFilters[ candRow ][ candCol ][ 1 ]
if ( w <= 4 ) {
  if (interpFilter == EIGHTTAP || interpFilter == EIGHTTAP_SHARP) {
    interpFilter = 4
  } else if (interpFilter == EIGHTTAP_SMOOTH) {
    interpFilter = 5
  }
}

for ( r = 0; r < intermediateHeight; r++ ) {
  for ( c = 0; c < w; c++ ) {
    s = 0
    p = x + xStep * c
    for ( t = 0; t < 8; t++ )
      s += Subpel_Filters[ interpFilter ][ (p >> 6) & SUBPEL_MASK ][ t ] *
           ref[ plane ] [ Clip3( 0, lastY, (y >> 10) + r - 3 ) ]
                        [ Clip3( 0, lastX, (p >> 10) + t - 3 ) ]
    intermediate[ r ][ c ] = Round2(s, InterRound0)
  }
}
```

> * The array pred is specified as follows:

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

```C++
interpFilter = InterpFilters[ candRow ][ candCol ][ 0 ]
if ( h <= 4 ) {
  if (interpFilter == EIGHTTAP || interpFilter == EIGHTTAP_SHARP) {
    interpFilter = 4
  } else if (interpFilter == EIGHTTAP_SMOOTH) {
    interpFilter = 5
  }
}
for ( r = 0; r < h; r++ ) {
  for ( c = 0; c < w; c++ ) {
    s = 0
    p = (y & 1023) + yStep * r
    for ( t = 0; t < 8; t++ )
      s += Subpel_Filters[ interpFilter ][ (p >> 6) & SUBPEL_MASK ][ t ] *
           intermediate[ (p >> 10) + t ][ c ]
    pred[ r ][ c ] = Round2(s, InterRound1)
  }
}
```

> where the constant array Subpel_Filters is specified as:

ここで、定数配列 SubPe_Filters を以下のように規定します。

> Note: All the values in Subpel_Filters are even. 
> The last two filter types are used for small blocks and only have four filter taps.
> The filter at index 4 has a four tap version of the EIGHTTAP filter.
> The filter at index 5 has a four tap version of the EIGHTAP_SMOOTH filter.

注意：
Subpel_Filters のすべての値は偶数です。
最後の2つのフィルタタイプは小さなブロックに適用するタイプで、4タップしかありません。
index=4 のフィルタは、EIGHTTAP フィルタの4タップ版です。
index=5 のフィルタは、EIGHTTAP_SMOOTH フィルタの4タップ版です。

SubPel_Filters[フィルタタイプ][位相][タップ]

| フィルタタイプ(index) | 名称 |
|:----:|:---:|:---:|
|0|EIGHTTAP |
|1|EIGHTTAP_SMOOTH |
|2|EIGHTTAP_SHARP |
|3|BILINEAR |
|4|EIGHTTAP の4タップ版 |
|5|SMOOTH の4タップ版 |

```C++
Subpel_Filters[ 6 ][ 16 ][ 8 ] = {
  {
    { 0, 0, 0, 128, 0, 0, 0, 0 },
    { 0, 2, -6, 126, 8, -2, 0, 0 },
    { 0, 2, -10, 122, 18, -4, 0, 0 },
    { 0, 2, -12, 116, 28, -8, 2, 0 },
    { 0, 2, -14, 110, 38, -10, 2, 0 },
    { 0, 2, -14, 102, 48, -12, 2, 0 },
    { 0, 2, -16, 94, 58, -12, 2, 0 },
    { 0, 2, -14, 84, 66, -12, 2, 0 },
    { 0, 2, -14, 76, 76, -14, 2, 0 },
    { 0, 2, -12, 66, 84, -14, 2, 0 },
    { 0, 2, -12, 58, 94, -16, 2, 0 },
    { 0, 2, -12, 48, 102, -14, 2, 0 },
    { 0, 2, -10, 38, 110, -14, 2, 0 },
    { 0, 2, -8, 28, 116, -12, 2, 0 },
    { 0, 0, -4, 18, 122, -10, 2, 0 },
    { 0, 0, -2, 8, 126, -6, 2, 0 }
  },
  {
    { 0, 0, 0, 128, 0, 0, 0, 0 },
    { 0, 2, 28, 62, 34, 2, 0, 0 },
    { 0, 0, 26, 62, 36, 4, 0, 0 },
    { 0, 0, 22, 62, 40, 4, 0, 0 },
    { 0, 0, 20, 60, 42, 6, 0, 0 },
    { 0, 0, 18, 58, 44, 8, 0, 0 },
    { 0, 0, 16, 56, 46, 10, 0, 0 },
    { 0, -2, 16, 54, 48, 12, 0, 0 },
    { 0, -2, 14, 52, 52, 14, -2, 0 },
    { 0, 0, 12, 48, 54, 16, -2, 0 },
    { 0, 0, 10, 46, 56, 16, 0, 0 },
    { 0, 0, 8, 44, 58, 18, 0, 0 },
    { 0, 0, 6, 42, 60, 20, 0, 0 },
    { 0, 0, 4, 40, 62, 22, 0, 0 },
    { 0, 0, 4, 36, 62, 26, 0, 0 },
    { 0, 0, 2, 34, 62, 28, 2, 0 }
  },
  {
    { 0, 0, 0, 128, 0, 0, 0, 0 },
    { -2, 2, -6, 126, 8, -2, 2, 0 },
    { -2, 6, -12, 124, 16, -6, 4, -2 },
    { -2, 8, -18, 120, 26, -10, 6, -2 },
    { -4, 10, -22, 116, 38, -14, 6, -2 },
    { -4, 10, -22, 108, 48, -18, 8, -2 },
    { -4, 10, -24, 100, 60, -20, 8, -2 },
    { -4, 10, -24, 90, 70, -22, 10, -2 },
    { -4, 12, -24, 80, 80, -24, 12, -4 },
    { -2, 10, -22, 70, 90, -24, 10, -4 },
    { -2, 8, -20, 60, 100, -24, 10, -4 },
    { -2, 8, -18, 48, 108, -22, 10, -4 },
    { -2, 6, -14, 38, 116, -22, 10, -4 },
    { -2, 6, -10, 26, 120, -18, 8, -2 },
    { -2, 4, -6, 16, 124, -12, 6, -2 },
    { 0, 2, -2, 8, 126, -6, 2, -2 }
  },
  {
    { 0, 0, 0, 128, 0, 0, 0, 0 },
    { 0, 0, 0, 120, 8, 0, 0, 0 },
    { 0, 0, 0, 112, 16, 0, 0, 0 },
    { 0, 0, 0, 104, 24, 0, 0, 0 },
    { 0, 0, 0, 96, 32, 0, 0, 0 },
    { 0, 0, 0, 88, 40, 0, 0, 0 },
    { 0, 0, 0, 80, 48, 0, 0, 0 },
    { 0, 0, 0, 72, 56, 0, 0, 0 },
    { 0, 0, 0, 64, 64, 0, 0, 0 },
    { 0, 0, 0, 56, 72, 0, 0, 0 },
    { 0, 0, 0, 48, 80, 0, 0, 0 },
    { 0, 0, 0, 40, 88, 0, 0, 0 },
    { 0, 0, 0, 32, 96, 0, 0, 0 },
    { 0, 0, 0, 24, 104, 0, 0, 0 },
    { 0, 0, 0, 16, 112, 0, 0, 0 },
    { 0, 0, 0, 8, 120, 0, 0, 0 }
  },
  {
    { 0, 0, 0, 128, 0, 0, 0, 0 },
    { 0, 0, -4, 126, 8, -2, 0, 0 },
    { 0, 0, -8, 122, 18, -4, 0, 0 },
    { 0, 0, -10, 116, 28, -6, 0, 0 },
    { 0, 0, -12, 110, 38, -8, 0, 0 },
    { 0, 0, -12, 102, 48, -10, 0, 0 },
    { 0, 0, -14, 94, 58, -10, 0, 0 },
    { 0, 0, -12, 84, 66, -10, 0, 0 },
    { 0, 0, -12, 76, 76, -12, 0, 0 },
    { 0, 0, -10, 66, 84, -12, 0, 0 },
    { 0, 0, -10, 58, 94, -14, 0, 0 },
    { 0, 0, -10, 48, 102, -12, 0, 0 },
    { 0, 0, -8, 38, 110, -12, 0, 0 },
    { 0, 0, -6, 28, 116, -10, 0, 0 },
    { 0, 0, -4, 18, 122, -8, 0, 0 },
    { 0, 0, -2, 8, 126, -4, 0, 0 }
  },
  {
    { 0, 0, 0, 128, 0, 0, 0, 0 },
    { 0, 0, 30, 62, 34, 2, 0, 0 },
    { 0, 0, 26, 62, 36, 4, 0, 0 },
    { 0, 0, 22, 62, 40, 4, 0, 0 },
    { 0, 0, 20, 60, 42, 6, 0, 0 },
    { 0, 0, 18, 58, 44, 8, 0, 0 },
    { 0, 0, 16, 56, 46, 10, 0, 0 },
    { 0, 0, 14, 54, 48, 12, 0, 0 },
    { 0, 0, 12, 52, 52, 12, 0, 0 },
    { 0, 0, 12, 48, 54, 14, 0, 0 },
    { 0, 0, 10, 46, 56, 16, 0, 0 },
    { 0, 0, 8, 44, 58, 18, 0, 0 },
    { 0, 0, 6, 42, 60, 20, 0, 0 },
    { 0, 0, 4, 40, 62, 22, 0, 0 },
    { 0, 0, 4, 36, 62, 26, 0, 0 },
    { 0, 0, 2, 34, 62, 30, 0, 0 }
  }
}
```