« 高速化版 JPEG Library から IDCT を | メイン | Theora の MMX の IDCT その1 »

2007年11月27日

動画再生エンジン開発日誌:: Theora のインラインアセンブラをイントリンシックで

    

Theora では主にIDCT、動き補償、デブロッキングフィルタで MMX が使われている。
一番面倒くさそうな IDCT は後回しにして、一番簡単な動き補償から取り掛かった。
nasm のアセンブラと比べて、gcc のインラインアセンブラは引数の順が逆。
最初は、かなり間違えそうになる。
で、そのまま直していたんだけど、かなり読み辛いのでCのソースと対比しながら、Cのソースをベースにして書き直した。

動き補償が終わったので、次はデブロッキングフィルタ。
同じようにまずはアセンブリのソースを見ながら直す。
で、次にCのソースを見ながら…… と思ったら、処理が明らかに違う。
詳しく見てみると、Cのソースはテーブルを使うようになっているが、MMX 版はテーブルを使わずに直接計算している。
なんてことだ。
仕方ないので、読み辛いアセンブリソースをそのままCにしたソースとコメントを頼りに見やすいように直す。
が、この部分は元々というか、MMX のせいでと言うか読み辛い。
比較命令が使われているせいだ。
a > b に相当する MMX の _mm_cmpgt_pi16 などを実行すると条件が成立するところはすべて 1 に、そうでないところは 0 になる。
で、この結果をマスクとして使って分岐処理を実現する。
つまり、b >= a の時、a を 0 にしたければ次のようになる ( Cでほぼ等価な処理を書いた場合 )。
m = a > b ? 0xFFFF : 0;
a &= m;
MMX ではこうやって書かないといけなかったのか。と知った。
でまあ、足し算とか引き算とかあるわけだけど、その場合は引く値側をマスクしてから引いたりする。
読み辛いことこの上なし。
仕方ないのでコメントで補足というか、仮想コードを併記しておく。

最後に IDCT 。これも同じようにアセンブリのソースをと思ったが長いので、また置換のスクリプトを書くことにした。
で、置換して、そこから直そうとしたが長いので、Cのソースから直接書き起こすことにした。
ただ、大まかな処理ブロックはアセンブリソースに従うようにして。
それで、出来たのだがどうも転置が少ない気がする。
2次元 IDCT では、縦方向と横方向で演算するのだが、MMX には必要な水平演算がない ( 隣どおしのバイトをかけたり足したりができない ) ので、どうしても行列を転置して計算する必要がある。
当然、転置したら元に戻さないと上下反転して-90度回転した ( 対角線で折り返した ) 状態になってしまうので、再度転置する必要がある。
そのため、演算前に転置して、演算後にもう一度転置する必要があるはず。
だけどそれがない。
なぜだろうと思いつつも、IDCT をコンパイルして試してみる。
やはり、絵が変。
なんだろう?
つづく……



投稿者 Takenori : 2007年11月27日 00:17




comments powered by Disqus
Total : Today : Yesterday : なかのひと