« Vorbis のデコーダ | メイン | 音側から時間を取得 »

2007年11月19日

動画再生エンジン開発日誌:: Direct 3D を使って描画するように

    

オーバーレイで常に最前面だと扱いづらいのと、画面サイズ以上の動画だとうまく更新されていなかったので、それらに対応するのならと、Direct 3D を使って描画することにした。
ソースコードは VMR を使って描画していたのを原形にして、子ウィンドウを作る部分などをなくして、VMR 依存の部分を書き換えた。
で、動かすと GeForce 8600 では、YV12 フォーマットのテクスチャは作れないようだ。
そうなの? ということは、VMR のはどうなっていたのだろうと確認すると、VMR 側が X8R8G8B8 で要求してそのフォーマットでテクスチャが作られている。
DirectX VA で変換されているんだろうか?
でも、まあそういうことなら X8R8G8B8 でテクスチャを作る。
YV12 から RGB への変換は、ビデオカードがサポートしていれば、単にコピーすれば変換してくれるので、大して気にすることではないはず (
IDirect3D9::CheckDeviceFormatConversion で確認して、IDirect3DDevice9::StretchRect でコピー ) 。

で、結局 YV12 フォーマットのオフスクリーンサーフェイスへデコーダに書き込んでもらい、それを描画前に X8R8G8B8 フォーマットのテクスチャにコピーして、そのテクスチャを板ポリゴンに貼って描画するようにした。
まあ、元々ビデオ画像を表示しつつ何か他のものを描画するために、一度テンポラリのテクスチャにコピーしてから描画しようと考えていたので、結果的には考えていた通りになった。
ただ、出来るのならアロケーターにすぐに戻さず次のフレームまでサンプルを保持することで、そのサンプルをテンポラリとみなしてコピー回数を抑えようと考えていたけど、それは出来ないことになる。
ま、色変換を CPU でやるよりはマシなので仕方ない。

UpdateSurface / UpdateTexture を使って、D3DPOOL_SYSTEMMEM で作ったサーフェイスをビデオメモリ側にコピーすると DMA を使ってコピーされるかもしれないと思って、試そうとしたんだけど、YV12 フォーマットで D3DPOOL_SYSTEMMEM にサーフェイスを作るとサイズがおかしい。
どうも輝度プレーン分しか確保されていない様子。
デコード時の色差プレーンのコピーでメモリのアクセス違反で落ちる。
で、とりあえず高さを1.5倍して無理やり色差の分も確保されるようにして、UpdateSurface してみると色差にごみが入っている。
輝度は正しく入っている様子。
何だろう? ドライバのバグ?それとも、使い方が違うのだろうか?
まあ、なんにせようまくいかないので、とりあえずはこの部分について深く追求しないことにした。
システムメモリのサーフェイスの方がより速く書き込めるので、コピーが DMA なら CPU 負荷を低減できる可能性があるので、後々より高速化するために調べるかもしれないが。

で、オーバーレイから Direct 3D に代えて CPU 負荷を見た感じ、少し増加している気がする。
ちゃんと計ったわけではないので、わからないけど。
ちなみに、オーバーレイを DirectX 2 から DirectX 7 のにしたら少し遅くなった。たぶん、使う構造体などのサイズが大きくなっているのでその辺りかなぁと思ったりするが、詳細はわからない。



投稿者 Takenori : 2007年11月19日 22:23




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