AV1 Specofication を読む(パース処理)


AV1 specification 日本語訳

ビットストリームからシンタックス要素(画像をつくるためのパラメータや係数値など)を抽出する方法です。
算術符号化がつかわれています。

まずは、算術符号化を使わない復号方法です。


9. パース処理

9.1 f(n)パース処理

この処理は、シンタックステーブル内のシンタックス要素のデスクリプタが f(n) のときに呼ばれます。

次の n ビットがビットストリームから読まれます。

この処理は以下のように規定されます。

x = 0
for (i=0; i<n; i++)
{
    x = 2*x + read_bit()
}

read_bit() は、ビットストリームkら次のビットを読み、ビットストリームポインタを1進めます。
ビットストリームがバイト列で提供されるならば、最初のビットは最初のバイトのMSBです。

9.2 2値デコーダのパース処理

非圧縮ヘッダとパーティションサイズを除いて、ビットストリーム全体はエントロピー符号化されています。
エントロピーデコーダは「boolean decoder(2値デコーダ)」とも呼ばれ、エントロピーでコード処理を定位するために、init_bool(sz), exit_bool(), read_bool(p) が使われます。

9.2.1 2値デコーダの初期化処理

この処理の入力は、2値デコーダが何バイト読むかを指定する変数 sz です。

この処理は、シンタックス構造内で init_bool(sz) 呼び出しでなされます。

sz<1 になるようなデータをビットストリーム内に含んではなりません。

注意:
init_bool が呼び出されるときは常にビット位置はバイト荒いんされています。なぜなら、非圧縮ヘッダとデータパーティションはバイト単位の長さだからです。

BoolValue = f(8)

BoolRange = 255

BoolMaxBits = 8*sz - 8

9.2.2節で規定される2値デコード処理を、ビットストリームからマーカーシンタックス要素を読むために呼びます。
読んだ値は0でなければなりません。

9.2.2 2値デコード処理

この処理の入力は、2値デコードのための確率を指定する変数 p (0.255) です。

この処理の出力は、デコードされた2値 bool です。

この処理は、シンタックス構造内で read_bool(p) が呼ばれたときになされます。

split = 1 + (((BoolRange-1) * p) >> 8)

Boolrange, BoolValue, bool を以下のように更新します。

  • BoolValue < split ならば、
    • BoolRange = split
    • bool = 0
  • BoolValue >= split ならば、
    • BoolRange -= split
    • boolValue -= split
    • bool = 1

BoolRange<128 ならば、以下を適用します。

  • newBit を以下のように求めます。  * BoolMaxBits>0 なあば、以下の手順を適用します。
    1. newBit = f(1)
    2. BoolMaxBits -= 1
    3. そうではなければ、newBit = 0 とします。しかし、これは発生してはいけません。
  • BoolRange を2倍します
  • BoolValue を以下のように更新します
    • BoolValue = (BoolValue << 1) + newBit

9.2.3 2値デコーダの終了処理

この処理は、シンタックス構造から exit_bool() が呼ばれたときになされます。

パディングシンタックス要素を、f(BoolMaxBits) で読みます。

パディングは0でなければなりません。

フレームの最後の符号化バイトがスーパーフレームマーカーにならないよう、十分なパディングビットが挿入されなければなりません。
バイト b がスーパーフレームマーカーであるのは、(b & 0xE0) == 0xC0 であるときのみです。
つまり、MSB3ビットが 0b110 です。

注意:
パディングは、ビット位置をバイトアラインさせるために必要かつ、ふれーむが スーパーフレームマーカーで終了させないようにするためにも使われます。
ビットストリームがすでにバイトアラインされていれば、パディングは0でも構いません。
8ビット以上パディングしてもかまいません。

9.2.4 read_literal パース処理

この処理は、read_literal(n) が呼ばれてたときになされます。

この処理は以下のように規定されます。

x = 0
for (i=0; i<n; i++)
{
    x = 2*x + read_bool(128)
}

戻り値は x です。