1

SDK (PushSourceDesktop) に付属のデスクトップ キャプチャ フィルターを使用しようとしています。私はそれをコンパイルし、実際にデスクトップをキャプチャしてファイルに保存するため、正常に使用しているようです。しかし、完了/終了時にアプリケーションがクラッシュします。

エラーで中断すると、使用可能なソースがないと表示されるだけで、コール スタックの場所は KernelBase.dll!7560280C() です。

誰かが何か問題を認識できるかどうか、またはクラッシュを引き起こす可能性のある露骨に間違ったことをしていないかどうかを確認するために、ここで試してみると思いました。前もって感謝します!

編集:作業コード

int main()
{

HRESULT hr;

hr = CoInitialize(NULL);
{
CComPtr<IBaseFilter> pMux;
CComPtr<IMediaControl> pMC;
CComPtr<IBaseFilter> pFilterr;
CComPtr<IGraphBuilder> pGraph;
CComPtr<ICaptureGraphBuilder2> pBuild;
CComPtr<IUnknown> pUnk;

hr = CoCreateInstance(CLSID_CaptureGraphBuilder2, NULL, CLSCTX_INPROC_SERVER,
    IID_ICaptureGraphBuilder2, (void**)&pBuild);


hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void**)(&pGraph));

hr = pBuild->SetFiltergraph(pGraph);


static CLSID const clsid = {0x4ea6930a, 0x2c8a, 0x4ae6, {0xa5, 0x61, 0x56, 0xe4, 0xb5, 0x4, 0x44, 0x37}}; //Pushsourcedesktop

 hr = CreateObjectFromPath(TEXT("c:\\filters\\PushSource.dll"), clsid, &pUnk);

 pFilterr = pUnk;

if (SUCCEEDED(hr))
{
    HRESULT hr = pGraph->AddFilter(pFilterr, L"Private Filter");
}

hr = pBuild->SetOutputFileName(
    &MEDIASUBTYPE_Avi,  // Specifies AVI for the target file.
    L"C:\\wav\\Example2.avi", // File name.
    (IBaseFilter**)&pMux,              // Receives a pointer to the mux.
    NULL); 


hr = pBuild->RenderStream(
    NULL,//PIN_CATEGORY_CAPTURE,//NULL,//&PIN_CATEGORY_CAPTURE, // Pin category.
    NULL,//&MEDIATYPE_Video,//&MEDIATYPE_Interleaved,//NULL,//&MEDIATYPE_Audio,      // Media type.
    pFilterr,//pSrc,           // Capture filter.
   NULL,//pCompression2, //pCompression,                  // Intermediate filter (optional).
    (IBaseFilter*)pMux);                 // Mux or file sink filter.


    hr = pGraph->QueryInterface(IID_IMediaControl, (void **)&pMC);
    printf("START");  


    pMC->Pause();
    hr = pMC->Run();
    Sleep(4000);
      hr = pMC->Stop();
    printf("END");  

}
CoUninitialize();
return 0;
}
4

1 に答える 1

3

大きな問題は、CoUninitializeすべてのCOMポインタが解放された後にのみ呼び出す必要があることです。スマートテンプレートのように、生のポインタの代わりに生のポインタを使用しているCComPtrので、コードはどちらも読みにくく、間違いを犯してポインタの1つを解放するのを忘れるのは簡単です。CoUninitializeクリーンアップすると、後で一部のCOMオブジェクトがまだ生きているように見え、すぐに問題が発生してアプリがクラッシュします。

COINIT_MULTITHREADEDこれに加えて、あなたがアパートを使う理由はわかりません。トラブルを避けるために、STAスレッドからのフィルターグラフですべてのトップレベルの管理を行う必要があります。ストリーミングスレッドとワーカースレッドはMTAになり、問題ありません。

ATLCComPtrMSDNで詳しく説明されているテンプレートを提供します。DirectShow BaseClassesは、軽量のアナログQzCComPtrを提供します。これは、自分の便宜のために使い始めることをお勧めします。

コードは次のようになります。

CoInitialize(...);
{
  CComPtr<IFooA> pFooA;
  CComPtr<IFooB> pFooB;
  // ...
}
CoUninitialize();

アイデアは、~CComPtrコードがに到達する前にすべてが行われるということCoUninitializeです。

于 2012-06-28T17:02:46.650 に答える