AV1 specification を読む 2018-04-17 (7.7. Set Frame Refs Process)

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

Set Frame Refs では、フレームバッファに格納された参照フレームに自動でラベルを付けます。
（明示的につけることもできます）

ラベルは6種類あり、それぞれ意味合いが異なります。
意味があるとはいっても、使用方法がその意味に縛られる必要はありません。

 * LAST
 * LAST2
 * LAST3
   * 主に直前にデコードされたフレームで、前方参照フレーム（カレントフレームに対して表示順で先行するフレーム）
 * GOLDEN
   * 主に直前のキーフレーム
 * BWDREF
   * 主に後方参照フレーム（カレントフレームに対して表示順として後続するフレーム）
 * ALTREF
 * ALTREF2
   * 主に後方参照フレーム
   * 参照画像として使われるが、表示しない場合もある

ALTREFフレームが特徴的なフレームで、AVC や HEVC には存在しない概念です。
参照には使えるけど表示しない（こともある）ということで、いろいろ面白いことができる気がします。



----

# 7.7. Set Frame Refs Process

>This process is triggered if the function set_frame_refs is called while reading the uncompressed header.

この処理は、uncompressed headerの set_frame_refs() 関数呼び出しで実行します。

>The syntax elements in the ref_frame_idx array are computed based on:
>
> * the syntax elements last_frame_idx and gold_frame_idx,
> * the values stored within the RefOrderHint array (these values represent the least significant bits of the expected output order of the frames).

ref_frame_idx配列の内容を、下記をもとに計算します。

 * last_frame_idx, gold_frame_idx シンタックスエレメント
 * RefOrderHint 配列に格納されている値（フレームの出力順のLSB値を表現）

> The reference buffers used for the LAST_FRAME and GOLDEN_FRAME references are sent explicitly and used to set the corresponding entries of ref_frame_idx as follows (the other entries are initialized to -1 and will be overwritten later in this process):

LAST_FRAME, GOLDEN_FRAME 参照を使う参照バッファは明示的に伝送され、以下のように ref_frame_idx の対応するエントリをセットするために使います（他のエントリは-1に初期化され、この処理の後のほうで上書きします）。

```C++
for ( i = 0; i < REFS_PER_FRAME; i++ )
  ref_frame_idx[ i ] = -1
ref_frame_idx[ LAST_FRAME - LAST_FRAME ] = last_frame_idx
ref_frame_idx[ GOLDEN_FRAME - LAST_FRAME ] = gold_frame_idx
```

>An array usedFrame marking which reference frames have been used is prepared as follows:

どの参照フレームが使われるかを示す配列 usedFrame を以下のように準備します。

```C++
for ( i = 0; i < NUM_REF_FRAMES; i++ )
  usedFrame[ i ] = 0
usedFrame[ last_frame_idx ] = 1
usedFrame[ gold_frame_idx ] = 1
```

>A variable curFrameHint is set equal to 1 << (OrderHintBits - 1).

currFrameHint = 1 << (OrderHintBits-1)

>An array shiftedOrderHints (containing the expected output order shifted such that the current frame has hint equal to curFrameHint) is prepared as follows:

配列 shiftedOrderHints （カレントフレームのヒントが curFrameHint になるようにシフトした期待される出力順）を、以下のように準備します。


```C++
for ( i = 0; i < NUM_REF_FRAMES; i++ )
  shiftedOrderHints[ i ] = curFrameHint + get_relative_dist( RefOrderHint[ i ], OrderHint )
```

>The variable lastOrderHint (representing the expected output order for LAST_FRAME) is set equal to shiftedOrderHints[ last_frame_idx ].
>It is a requirement of bitstream conformance that lastOrderHint is strictly less than curFrameHint.

lastOrderHint = shiftedOrderHints[last_frame_idx] （LAST_FRAME の期待される出力順）

ビットストリーム適合性のためには、厳密に lastOrderHint < curFrameHint でなければなりません。

>The variable goldOrderHint (representing the expected output order for GOLDEN_FRAME) is set equal to shiftedOrderHints[ gold_frame_idx ].
>It is a requirement of bitstream conformance that goldOrderHint is strictly less than curFrameHint.

goldOrderHint = shiftedOrderHints[gold_frame_idx] (GOLDEN_FRAME の期待される出力順)

ビットストリーム適合性には、厳密に goldOrderHint < curFrameHint でなければなりません。

>The ALTREF_FRAME reference is set to be a backward reference to the frame with highest output order as follows:

以下のように、ALTREF_FRAME 参照は、出力順が最も遅い後方参照とします。

```C++
ref = find_latest_backward()
if ( ref >= 0 ) {
  ref_frame_idx[ ALTREF_FRAME - LAST_FRAME ] = ref
  usedFrame[ ref ] = 1
}
```

>where find_latest_backward is defined as:

ここで、find_latest_backward は以下のように定義されます。

```C++
find_latest_backward() {
  ref = -1
  for ( i = 0; i < NUM_REF_FRAMES; i++ ) {
    hint = shiftedOrderHints[ i ]
    if ( !usedFrame[ i ] &&
         hint >= curFrameHint &&
         ( ref < 0 || hint >= latestOrderHint ) ) {
    ref = i
    latestOrderHint = hint
    }
  }
  return ref
}
```

>The BWDREF_FRAME reference is set to be a backward reference to the closest frame as follows:

BWDREF_FRAME 参照を、最も近い後方参照とします。

```C++
ref = find_earliest_backward()
if ( ref >= 0 ) {
  ref_frame_idx[ BWDREF_FRAME - LAST_FRAME ] = ref
  usedFrame[ ref ] = 1
}
```

>where find_earliest_backward is defined as:

ここで、find_earliest_backward は以下のように定義されます。

```C++
find_earliest_backward() {
  ref = -1
  for ( i = 0; i < NUM_REF_FRAMES; i++ ) {
    hint = shiftedOrderHints[ i ]
    if ( !usedFrame[ i ] &&
         hint >= curFrameHint &&
         ( ref < 0 || hint < earliestOrderHint ) ) {
      ref = i
      earliestOrderHint = hint
    }
  }
  return ref
}
```

>The ALTREF2_FRAME reference is set to the next closest backward reference as follows:

ALTREF2_FRAME 参照は、次に近い後方参照フレームとします。

```C++
ref = find_earliest_backward()
if ( ref >= 0 ) {
  ref_frame_idx[ ALTREF2_FRAME - LAST_FRAME ] = ref
  usedFrame[ ref ] = 1
}
```

>The remaining references are set to be forward references in anti-chronological order as follows:

残りの参照は、時系列順とは逆順に前方参照とします。

```C++
for ( i = 0; i < REFS_PER_FRAME - 2; i++ ) {
  refFrame = Ref_Frame_List[ i ]
  if ( ref_frame_idx[ refFrame - LAST_FRAME ] < 0 ) {
    ref = find_latest_forward()
    if ( ref >= 0 ) {
      ref_frame_idx[ refFrame - LAST_FRAME ] = ref
      usedFrame[ ref ] = 1
    }
  }
}
```

>where Ref_Frame_List is specifed as:

ここで、Ref_Frame_List は以下のように規定します。

```C++
Ref_Frame_List[ REFS_PER_FRAME - 2 ] = {
  LAST2_FRAME, LAST3_FRAME, BWDREF_FRAME, ALTREF2_FRAME, ALTREF_FRAME
}
```

>and find_latest_forward is defined as:

find_latest_forward は、以下のように定義されます。

```C++
find_latest_forward() {
  ref = -1
  for ( i = 0; i < NUM_REF_FRAMES; i++ ) {
    hint = shiftedOrderHints[ i ]
    if ( !usedFrame[ i ] &&
         hint < curFrameHint &&
         ( ref < 0 || hint >= latestOrderHint ) ) {
      ref = i
      latestOrderHint = hint
    }
  }
  return ref
}
```

>Finally, any remaining references are set to the reference frame with smallest output order as follows:

最後に、任意の残りの参照を、以下のように出力順の昇順に設定します。

```C++
ref = -1
for ( i = 0; i < NUM_REF_FRAMES; i++ )
  hint = shiftedOrderHints[ i ]
  if ( ref < 0 || hint < earliestOrderHint ) {
    ref = i
    earliestOrderHint = hint
  }
}
for ( i = 0; i < REFS_PER_FRAME; i++ ) {
  if ( ref_frame_idx[ i ] < 0 ) {
    ref_frame_idx[ i ] = ref
  }
}
```

>Note:
>Multiple reference frames can share the same value for OrderHint and care needs to be taken to handle this case consistently. 
>The reference implementation uses an equivalent implementation based on sorting the reference frames based on their expected output order, with ties broken based on the reference buffer index.

注意：
複数の参照フレームが同一の OrderHint 値を持つことができますが、この場合でも正しく取り扱えるように注意が必要です。
リファレンス実装では、参照フレームの期待される出力順を元に等価な実装を使っています。
with ties broken based on the reference buffer index ???