GCCでMMXコードを書いてみた-実践編

## 実際に書いたコードは次の日記にあります



うちのLinuxノートはPC-PJ2-S3。
333MhzのセレロンでP6アーキティクチャでMMXしか使えない。
mplayerを使えば、SDのXvidはぎりぎりながらも満足に再生できるスペックがあるのだが、残念なことにビデオカードのオーバーレイはYUV/YV12の動画データをストレート変換で表示しやがる。


つまり白潰れ黒浮きがちの地味な映像で我慢しなければならない。


いまどきはもちろん7年ほど前あたりからのビデオカードなら、H/W側で適当にTV->PCスケール変換をしてくれるのでPCモニタでも色褪せないビビッドな画面で楽しめるのだが、PJ2搭載のTridentの9525DVDはDVDとかついてる癖にそれができない。
以前からどうにかならんものかと思い、ポストプロセスフィルタの"-vf eq2"で、ブライトネス/コントラスト/サチュレーションなどを調整して誤魔化して我慢していた。


そこにきて最近MMXのコードを書いてみたいという欲求が沸いてきたのと、どうせなら書いたコードは常用したいというその対象として適当だったので、ついコードを改変しTV->PCスケール変換ができるようにしてしまった。


□やったこと
mplayer(mplayer-export-2010-05-09)の、"-vf eq"のソース、"vf_eq.c"を改変。
○できるようになったこと
bt.601の色空間で圧縮されている動画を、YUVフルスケールに変換する。
単にTVスケールで保存されている数値を8bitフルスケールに伸張しているだけです。
後からよく調べたら、bt.601やbt.709というのはRGB<->YUVの変換の式を示しているものであり、YUV(TV)<->YUV(PC"8ビットフルスケール")の変換については一切記述がありません。

×できなくなったこと
・もともとの"-vf eq"の機能、ブライトネス/コントラスト調整が使えません(TV->PC変換後、"-vf eq2"を付け加えて使えば問題ないです)。
□わかっている問題
・横解像度が8ドットの倍数の動画じゃないと高確率で画面が壊れる(YUYV/YV12/I420だとUVプレーンがx, yともに1/2なんで横16ドット)。
・YV12以外未テスト。
□変更内容
MMX対応(MMXがなくても動きます)。
mallocで取得している変換処理バッファの先頭アドレスを、32バイトメモリ境界に合わせた(これだけでフレーム落ち少し減少)。


・感想
変更したコードを適用したmplayerを使った場合、"-vf eq2"で誤魔化していた場合と比較し、フレーム落ちは6割程度に減少しました。
ポストプロセスフィルタなので、ビデオイメージバッファに対するRead-Modify-Writeな実装は変わらないなわけで、無駄なメモリアクセスが発生しています。
つまり、なにもオプションをつけずに再生したときより、速度が低下することは避けられません。
これ以上の速度向上は、libavcodecがビデオイメージバッファに書き込みする直前のレジスタの内容を奪い、TV->PC変換しバッファに書き込もどすようにし、この程度の処理でメモリアクセスが発生しないようにするしかないと思います。


□宿題
・横8ドット以外の動画への対応
・UVプレーンを伸張処理しないことで速度を稼ぐモードをつける(人間の目は輝度に強く反応し..)。
・イメージバッファメモリのプリフェッチ(yライン一本分あらかじめL1キャッシュに突っ込んでおく)
bt.709対応
・PC->TVスケール変換
・オプション記述の変更


プリフェッチは効くのかなぁ(汗。



##肝心の改変したファイルは、少なくとも横方向バグを訂正してから掲載します。
###しかし写真はともかく一般ファイル置けるのかな?hatenaって(汗


## 追記
## プリフェッチだけやってみた。手法としては、ソースのイメージバッファを、処理ループに入る直前に1ライン空読みするだけです。
## うちのマシンではめちゃくちゃ効きました。フレーム落ちだけなら上の状態から2割〜4割削減しました。小躍りしてます。


## 90秒/24fpsの動きの激しいクリップ(いわゆるOPです_no)で、"-vf eq2"で約70〜80ほどフレーム落ちしていたものが17〜26前後になりました。
## EDだと20程だったのが7まで減りました。OP/EDともに、フレーム落ちのうちの4枚は、MP4コンテナに入れたパックドBフレームの関係で必ず一律に捨てられる(落ちる)ので実質フレーム落ちは3まで減少したことになります。
## 普通の本編中はほとんどフレーム落ち無しです。大成功といえるのではないかとおもいます。