« position/frameプロパティの確認 | メイン | 机上デバッグとコメント整備 »

2004年10月06日

吉里吉里2/KAG3ムービー拡張日誌:: プロセスが残る問題への対処

    

以前、プロセスが残る問題の対処を行ったが、あれで完璧というわけではなかった。
まだ、タイミングによってプロセスが残ってしまうことが判明。
調査すると、DoRenderSample 内でフィルタグラフのIMediaSeeking を使用する箇所で返ってこなくなってしまうようだ。
フィルタグラフはマルチスレッドで動作しており、Stop がコールされても、タイミングによっては、DoRenderSample がコールされてしまうようだ。と言うか、ほとんどの場合、DoRenderSample がコールされてしまう。
そして、その中でフィルタグラフのIMediaSeeking を使うわけだが、すでにdelete中のため、何らかの理由でIMediaSeeking のメソッドがリターンしないようになってしまうようだ。(内部がどのようになっているかわからないので正確な理由は不明。)
そもそも、この時点では単にStopへステートの遷移中なのだから、IMediaSeeking のメソッドぐらい使えても良さそうなものだが、使えない。もしかしたら、デッドロックが発生しているという可能性もある。
レンダーフィルタは下記のようないくつかのクリティカルセクションを使用して動作しているが、それらの取得順序の違いによって・・・ いや、その可能性は低いか。
・m_InterfaceLock フィルタ状態のロック。
・m_RendererLock ストリーミングのロック。
それよりも、フラグの問題かもしれない。レンダーフィルタがもつフィルタは多い。っていうか、内部動作のシーケンス図クレーって感じだ。
BaseClassesはソースが公開されているので、CBaseRenderer などのシーケンス図を書こうと思えば書ける。でも、フィルタグラフのところは不明なので書けない。(もしかしてどこかにあるのかな?)
まあ、結局のところよくわからないのでいろいろと試したが、変なところでフリーズしたりしてうまく行かなかった。
なので、方法を変更することにした。

その方法は次の通り
ストリーミング開始時にコールされるメソッド内でフィルタグラフのIMediaSeeking を使用して、開始フレームを記録する。
レンダリング前にコールされるメソッド内で、自身のフィルタのIMediaSeeking を使用してストリーミングタイムを取得し、記録している開始フレームを加算したものを現在のフレームとみなし、メディアサンプルにメディアタイムとして設定する。もし、自身のIMediaSeeking が使用できない場合は、ストリーミングが開始されてからレンダリングしたフレーム数とドロップしたフレーム数を加算する。ただし、ドロップしたフレーム数はより上位のフィルタでドロップされたものまではわからないので、若干精度が劣る。
そして、DoRenderSample 内でメディアサンプルからメディアタイムを取得し、それを現在のフレームとして使用する。
以上のような処理に変更すると、プロセスが残る問題はなくなった。
ただし、現在のフレーム番号の精度は少し落ちているものと思われる。

この対処でも、完全にこの問題に対処できたとは限らない。
もし、CBaseRenderer::OnStartStreaming が別スレッドコールされてしまうと、同じような問題が発生する可能性がある。しかし、CBaseRenderer::OnStartStreaming を可能な限り追ったところ、CBaseRenderer::Run からコールされているようだ。これが同じスレッドなら・・・
そうだ、GetCurrentThreadId で調べればわかる。
調べるとPlayのコールもととOnStartStreaming のスレッドは異なる。
しかし、OnStartStreaming とレンダリングを行うスレッドも異なった。
結局わからないのか。
でも、フィルタグラフとOnStartStreaming のコール元スレッドが同じ可能性は少し高くなったかも。
もし、スレッドが異なっていたとしても、この問題が発生するのはごくまれだ。(と言っても、起こる可能性があるものは起こってしまうものだけど)
まあ、たぶん同じスレッドでしょう。
他に調べる方法は思い浮かばないし、この問題は解決としておこう。



投稿者 Takenori : 2004年10月06日 03:05




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