2

C# dll に directshow 機能を実装する作業を行っています。Microsoft が Windows Mobile 6 SDK で提供する C++ ベースの「CameraCapture」の例に基づいて作業を行っています。(このサイトの以前のヘルプのおかげで) 順調に進んでいましたが、C# ランドで directshow イベントをリッスンしようとしているときに、ちょっとした障害に遭遇しました。

dshow イベントをリッスンするためにループするスレッドがあります。ここで定義される手動リセット イベントに基づいて待機します (これは、グラフの初期化の最後に定義されます。グラフが構築され、renderstream が呼び出され、制御ストリームが既にデータフローをブロックしています)。

DshowRequestMan = new ManualResetEvent(false);
MediaEvent = (IMediaEvent)FilterGraph;                
chk(MediaEvent.GetEventHandle(out DshowEventHandle));
DshowRequestMan.Handle = DshowEventHandle; //note: no "SafeHandle" in cf

私がこれで経験している2つの関連する問題があります:

  1. 私の dshow イベント ハンドラー ループが0 のタイムアウトを使用してIMediaEvent.GetEvent()経由でイベントをプルすると、3 回目の反復で「タイムアウトを超えました」という hresult (-2147467260) が返されます。その 3 番目のイベント トリガー (およびその後のエラー) は、C++ の例では発生しません。
  2. 上記のタイムアウトのケースを無視すると、常に 73 イベントでトリガーされます。ループは基本的に一時停止しないため、これによりプロセッサが強制終了されます。

C++ の例でグラフをプレビュー モードで実行すると、2 つの IMediaEvents が取得されます。最初は 13、次に 73 です。その後、実際のキャプチャが開始されるまでトリガーを停止します。私のC#バージョンは13、次に73、次に73をプルしますが、タイムアウトエラーがあります。

つまり、実際に「取得」する dshowevent がないため、タイムアウトが発生するため、DshowRequestMan の 3 回目のトリガーは発生しないようです。

何が間違っているのかわかりません-繰り返しごとに「FreeEventParams()」を呼び出しています...ハンドルプロパティに何かを割り当てているだけなので、ManualResetEventオブジェクトが間違って使用されているのではないかと疑っていますが、同じピンボークされた「WaitForSingleObject」を使用して DshowEventHandle をリッスンすると、問題が発生します... この時点で混乱しています。

どんなアイデアでも大歓迎です。前もって感謝します!

4

3 に答える 3

2

フィルタグラフイベント処理のコードは次のとおりです。

while (!_stopReceivingEvents) {
    IntPtr eventHandle;
    var hr = _mediaEvent.GetEventHandle(out eventHandle);
    DsError.ThrowExceptionForHR(hr);

    //NOTE: Do not close the event handle, because it is used internally by the filter graph
    using (var safeWaitHandle = new SafeWaitHandle(eventHandle, false)) {
        using (var waitHandle = new AutoResetEvent(false) {SafeWaitHandle = safeWaitHandle}) {
            if (WaitHandle.WaitAll(new[] {waitHandle}, 500)) {
                //receive all available events
                do {
                    EventCode eventCode;
                    IntPtr param1;
                    IntPtr param2;
                    hr = _mediaEvent.GetEvent(out eventCode, out param1, out param2, 500);
                    _mediaEvent.FreeEventParams(eventCode, param1, param2);

                    if (hr == 0) {
                        switch (eventCode) {
                            //add handling code here
                        }
                    }
                } while (hr == 0);
            }
        }
    }
}
于 2011-08-10T11:11:47.637 に答える
0

実際の待機コードはどのように見えますか? 問題は、基本的に「イベントをチェックしてすぐに戻る」ことを意味する 0ms を待っている可能性があります。(WAIT_INFINITE を使用したネイティブ呼び出しのように) 待機中にブロックする場合は、System.Threading.Timeout.Infinite (実際には -1) を渡す必要があります。

チェック スレッドを定期的に生成する場合 (これは、無限待機よりもはるかに安全であり、実際にアプリをシャットダウンできるようになります)、待機からの戻りを確認する必要があり、それがタイムアウト (0x80004004) の場合は、戻ってもう一度待ちます。

while(!shutdown)
{
  if(DshowRequestMan.WaitOne(1000))
  {
    // handle the event
  }
}
于 2009-09-09T12:55:42.233 に答える
0

イベントを取得して処理した後、必ずイベントをリセットしていますか?

于 2009-06-30T23:29:29.237 に答える