1

Google で非常に一般的と思われる問題がありますが、解決しませんでした。私のアプリがすべてを閉じようとしているとき、オブジェクトを解放する前に呼び出される最後の関数は IMediaControl::stop です。信号があれば大丈夫です。しかし、シグナルなしでアプリを起動すると (またはアプリの動作中に終了すると)、プログラムは stop() から戻りません。さらに、既にハングしているときにシグナルを提供すると、すべてが正常に戻り、プログラムのハングが解除され、正しく終了します。

これはメインの私のコードの一部です:

hr = connectFilters(pGraph, pCaptureDevice, AUDIO_INPUT_DEVICE_PIN_NAME,
pAnalyzerFilter, SPDIF_ANAL_FILTER_PIN_NAME);
if(SUCCEEDED(hr))
{
    // run the graph
    hr = pControl->Run();
    if(SUCCEEDED(hr))
    {        
        // wait for UI thread to finish
        pFilterObject->WaitForThread();

        // stop the graph and exit
        pControl->Stop();
    }
}

releaseObjects();
return 0;

Google は、いくつかのスレッドが互いに待機していることが原因でデッドロックが発生したことを示唆しています (実際にそうです)。ウィンドウなしでこのアプリに基づいて DLL を実行したため、UI スレッドは問題ではないようですが、問題はまったく同じです。

よろしくお願いします。

日食

編集

ソースと変換の 2 つのフィルターしかありません。プログラムはそれなしで正常に実行されるため、問題は確かに変換フィルターにあります。リリースされていないバッファまたはサンプルがどこかにあるという問題でしょうか? DirectShow がどのように機能するのか正確にはわかりませんが、信号がない場合は何か追加の操作が必要になるのでしょうか?

編集2

Google で、誰かがグラフを停止する前にソース フィルターを停止することでこの問題を解決したことがわかりました。私は同じことをしましたが、それもハングします...これを使用してソースフィルターを取得します。

hr = pFG2->AddSourceFilterForMoniker(pMoniker, pContext, wszName, &pSource);
*ppF = pSource;
(*ppF)->AddRef();

VSデバッガーをアタッチすると、コードを表示できないと表示されるので、MSコードのどこかにあると思います。IMediaSamples を処理する関数にコメントを付けても、ハングします。今、私は何が悪いのかという考えを使い果たしました。また、さまざまな方法でフィルターを停止してグラフから削除しようとしました。

4

1 に答える 1

1

バックグラウンドスレッドからWPFウィンドウまで着信画像を送信しようとしたときに、同じ問題が発生しました。メディアコントロールを停止するか、何かを解放しようとするまで、すべて問題ありませんでした。

問題は、UI スレッドにアクションを取得するためのアクションのディスパッチャー呼び出しにありました。呼び出しを一時的にコメントアウトしたため、ビデオが画面にまったく表示されなくなりましたが、いつでもサンプルグラバーを中断して、まだ実際に実行されていることを確認できました。

スレッド間で画像を手動で分離する必要がありました。ジェネリック関数の何かが参照を保持しているため、com オブジェクト

それを修正するために、ウィンドウにディスパッチャータイマーを作成し、その間隔を 1 ミリ秒に設定し、UI 更新を行う関数へのコールバックを設定し、グラバーで、buffercb イベントでフレームをスタンドアロン変数に保存し、タイマーを有効にしました。 .

これが私が最終的に得たものの簡単な外観です:

    InteropBitmap newbmp;
    DispatcherTimer refreshTimer;
    refreshTimer = new DispatcherTimer(TimeSpan.FromMilliseconds(1), DispatcherPriority.Render, ontimer, this.Dispatcher);
    videoSampleCB.newframearrived += capGrabber_NewFrameArrived;

    void capGrabber_NewFrameArrived(object sender, EventArgs e)
    {
        newbmp = videoSampleCB.newimage;
        refreshTimer.IsEnabled = true;
    }
    void ontimerobject sender, EventArgs e)
    {
        this.BitmapSource = newbmp;
        refreshTimer.IsEnabled = false;
    }
class VideoSampleGrabberCallBack : ISampleGrabberCB  
{
        event eventhandler newframearrived;

        public InteropImage newimage;
        public int BufferCB(double sampleTime, IntPtr buffer, int bufferLen)
        {
             newimage = ...
             newframearrived(this, eventargs.empty);
        }
}
于 2015-10-22T16:07:51.623 に答える