« ログの出力 | メイン | ソース フィルタの振る舞い »

2005年10月08日

吉里吉里 ムービー拡張日誌2:: WMVの画像が出るようになった

    

比較的似ているフィルタであるプッシュ ソース フィルタ サンプルのソースコードを追うイマイチよくわからない。
と言うより、CSourceStreamによってほとんどの機能が実装されているようだ。
と言うことで、CSourceStreamのソースコードを追うと、CBaseFilter::Pause内でCBaseOutputPin::Activeが呼ばれ、その中で再生を開始しているようだ。
つまり、CBaseFilter::Runが最初に呼ばれると言うわけではないのか。
さらに追うと、CBaseRenderer::Receiveが、ポーズ状態の時にコールされたら、イベントを投げて状態の移行を完了し、CBaseRenderer::GetStateからリターンするようだ。
で、そこからリターンした後に、各フィルタのCBaseFilter::Runが呼ばれているみたい。

で、そのように実装するとIMediaControl::Run()がコールされたしばらく後に、CBaseFilter::Runがコールされるようになった。
そういう風に実装するのか。
これでうまくいくかと思いきや、数フレーム再生された後、アクセス違反が発生する。
あれ? なんだろう?
wmvcore.dll内で発生しているようなので、そちらの問題かと思ったが、ReadFromStreamサンプルを実行してみても発生しないので、やっぱり何かまずいことをやっているようだ。

いろいろと調べるとBufferRendererの不具合だったようだ。
BufferRendererでは、最初に出力の対象となるバッファが設定されていない場合、自分で作る。(吉里吉里の初期化順序では、どうしても最初に設定されている状態にはならない)
そして、アロケーターでメディアサンプルが生成される時、バックバッファに設定されているポインタをメディアサンプルのバッファに設定する。
以降、メディアサンプルのバッファは、SwapBufferによって入れ替えるが、これはレンダリングされた直後に行われる。
問題は、アロケーターのメディアサンプル生成後、出力したいバッファを設定する時に、もともとあったバッファが自分で生成したものであった場合に開放するだけで、新たに設定されたバッファをメディアサンプルへ設定しないことにある。
そのせいで、メディアサンプルのバッファとして設定されるのは、最初にレンダリングされた後になってしまう。
つまり、最初のレンダリング時は開放されたメモリ領域に書き込みを行ってしまっていた。
そこで、出力したいバッファを設定する時に、それがバックバッファであったなら、メディアサンプルのバッファとして設定するようにした。
その後確認したら、問題なく再生できるようになった。
いやー、長かった。
今までBufferRendererの不具合がなぜ顕在化しなかったのかはなぞ。
デコーダーの作りが何か違うのだろうか? と言うか、それ以外考えづらいのだが。

出力したいバッファの設定は、レンダーフィルタの状態が停止か一時停止状態の時のみ行えるようにしておいた方が、より安全になりそうだ。
現在は再生中に出力したいバッファ変更するような使い方はしていないが、念のためにそのように変更した。

次にサウンド部分を作れば、一応WMVの再生が行えるようになる。



投稿者 Takenori : 2005年10月08日 05:23




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