フレーム間圧縮を使用するビデオデコーダーにおいて、動き補償 (Motion Compensation) 処理は、 負荷の高いプロセスである。
Theora では、16 x 16, 8 x 8 ブロックの動き補償が行われるため、16 x 16 ブロックでは、 SSE 128 bit レジスターを、8 x 8 ブロックでは、MMX 64 bit レジスターを使用し、 ブロックの1ライン分を一括処理することで、効率を向上させる。
Pentinum 4 以降の x86 Intel プロセッサーでは、64 bit のミスアラインロード (MOVQ) には、 特にペナルティーがない。128 bit のアライメントされていないロード (MOVDQU) には、 ペナルティーが発生する。
NOMV (ゼロベクトル) での 16 x 16 ブロック動き補償では、128 bit のアライメント されたロード (MOVDQA) を使用して、ペナルティーを避けることができる。 0 でないベクトルでは、MOVDQU を使用するが、動き補償ではエンコーダーの動き検索の場合と違い、 一過性のロードであるため、アライメントロードへ最適化する効果は薄いかもしれない。
Theora では、全画素精度の動きベクトルに加えて、半画素精度を動きベクトルを使用する。
この際、ピクセル (画素) の予想値に近傍の2つの画素の平均値を使用する。
P = (A + B) >> 1
SSE が導入された際、PAVGB という平均値を求める命令が追加されたが、この命令では、
P = (A + B + 1) >> 1
という処理が行われるため、規格と相違が生じる。
そこで、切り上げが行われた場合に、補正を行うことで、規格に相当する処理を実現させる。
切り上げが行われる条件は、A, B の最下位ビットのどちらか1つが、1 である場合である。 その時に切り上げられた 1 を減算することで、補正を行う。実際の演算は、以下の通りである。
AVG = (A + B + 1) >> 1 P = AVG - ((A ^ B) & 1)
この場合のステップ数は、4である。
PAVGB 命令を使用しない場合、通常であれば 16 bit へ拡張を行って処理することになるが、 ビット演算のトリックを使用することで、8 bit 処理で平均値を求めることもできる。
説明のためまず 2bit での例を考えると、
A1,A0 は、A の各ビット (0 or 1) B1,B0 は、B の各ビット (0 or 1) P = ((2 * A1 + A0) + (2 * B1 + B0)) >> 1 P = ((2 * A1 + A0) + (2 * B1 + B0)) / 2 P = (A1 + B1) + (A0 + B0) / 2 P = (A1 + B1) * (2**0) + (A0 + B0) * (2**(-1)) ** はべき乗
(A0 + B0) * (2**(-1)) の項を考えると、A0, B0 共に 1 のとき 1 となる。これは、AND 演算に相当する。
(A1 + B1) * (2**0) の項を考えると、A1, B1 共に 1 のとき 2 となる。A1, B1 のどちらかが 1 の とき (XOR) 1 となる。つまり、
P1 = (A1 & B1) << 1) + (A1 ^ B1) P1 = ((A1 & B1) << (1 + 0)) + ((A1 ^ B1) << (1 - 1))
である。
ここで、一般項を考え n ビットの場合を考えると、
Pn = ((An & Bn) << (n + 0)) + ((An ^ Bn) << (n - 1))
と考えることができる。n ビットの演算では、全ての項の和をとることになるので、 結果として、
P = (A & B) + ((A ^ B) >> 1)
と計算することができる。
この場合のステップ数は、4であるが、PackedByte の右シフト命令が存在しないため、 実際にはマスク演算を組み合わせる必要があるので、ステップ数は5となる。
P = (A & B) + (((A ^ B) & 0xfe) >> 1)
[PageInfo]
LastUpdate: 2009-06-19 14:55:40, ModifiedBy: noumiakira
[License]
Creative Commons 2.1 Attribution-ShareAlike
[Permissions]
view:all, edit:members, delete/config:members