0

ビデオをキャプチャするためにDirectShowを使用しています。サンプルグラバーにカメラを取り付けて、取得した画像を保存しています。

次のコードでは、サンプルグラバー(ISampleGrabber)に接続されているキャプチャデバイス(CLSID_VideoCaptureSources)にIID_ICaptureGraphBuilder2接続ています。グラフはIID_IMediaControlに接続されています。IID_IMediaControl RunandStopを使用します。ほとんどの場合、ストップがスタックします。ある種のデッドロックがあります。IID_IMediaEventとm_pEvent->WaitForCompletion(INFINITE、&evCode);を追加しようとしました。しかし、それでも機能しません。一時停止は問題なく機能しますが、ソフトウェアを停止しようとするとスタックします

グラフの作成

    ICaptureGraphBuilder2   *pBuilder;
    IBaseFilter             *pCamera;
    IPin                    *pOutPin;
    IPin                    *pInPin;
    IBaseFilter     *pSampleGrabberFilter;
    IBaseFilter     *pNullRendererFilter;
    ISampleGrabber  *pSampleGrabber;

    HRESULT hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void **)&m_pGraph); 
    hr = CoCreateInstance(CLSID_CaptureGraphBuilder2, NULL, CLSCTX_INPROC_SERVER, IID_ICaptureGraphBuilder2, (LPVOID*)&pBuilder);
    CHECK_HR(hr, L"Can't create Capture Graph Builder");

    hr = pBuilder->SetFiltergraph(m_pGraph);
    CHECK_HR(hr, L"Can't SetFiltergraph");

    pCamera = CreateFilterByName(pCaptureDeviceName, CLSID_VideoCaptureSources);

    WCHAR err[256];
    wsprintf(err, L"Can't add Camera '%s' to graph", pCaptureDeviceName);

    hr = m_pGraph->AddFilter(pCamera , pCaptureDeviceName);
    CHECK_HR(hr, err);


    WCHAR filterName[256];

    pOutPin = GetPinCapture(pCamera, L"Capture", i);
    if (!pOutPin)
        continue;
    IAMStreamConfig *pConfig = NULL;
    hr = pOutPin->QueryInterface(IID_IAMStreamConfig, (void**)&pConfig);
    CHECK_HR(hr, L"Can't get configuration");

    AM_MEDIA_TYPE *pmt = NULL;
    pConfig->GetFormat(&pmt);

    VIDEOINFOHEADER *pFrmt = (VIDEOINFOHEADER *)pmt->pbFormat;
    pFrmt->bmiHeader.biWidth = 1920;
    pFrmt->bmiHeader.biHeight = 1080;

    pConfig->SetFormat(pmt);
    SAFE_RELEASE(pConfig);
    SAFE_RELEASE(pOutPin);

   // Create a sample grabber
    wsprintf(filterName, L"Sample Grabber %d", i);

    // Create a sample grabber
    hr = CoCreateInstance(CLSID_SampleGrabber, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void **)&pSampleGrabberFilter);
    CHECK_HR(hr, L"Unable to create sample grabber filter");

    // Initialize sample grabber

    hr = pSampleGrabberFilter->QueryInterface(IID_ISampleGrabber, (void **)&pSampleGrabber);
    CHECK_HR(hr, L"Unable to get sample grabber");

    hr = pSampleGrabber->SetMediaType(pmt);
    CHECK_HR(hr, L"Unable to set media type");

    hr = pSampleGrabber->SetBufferSamples(false);
    CHECK_HR(hr, L"Unable to set buffer samples!");

    hr = pSampleGrabber->SetOneShot(false);
    CHECK_HR(hr, L"Unable to set one shot!");

    // Add the sample grabber to the graph
    hr = m_pGraph->AddFilter(pSampleGrabberFilter, filterName);
    CHECK_HR(hr, L"Unable to add sample grabber to graph");

    pOutPin = GetPinCapture(pCamera, L"Capture", i);
    pInPin = GetPin(pSampleGrabberFilter, PINDIR_INPUT);
    hr = m_pGraph->ConnectDirect(pOutPin, pInPin, 0);
    CHECK_HR(hr, L"Unable to connect Camera to pSampleGrabberFilter");
    SAFE_RELEASE(pOutPin);
    SAFE_RELEASE(pInPin);

    wsprintf(filterName, L"Null Renderer %d", i);
    // Create a null renderer
    hr = CoCreateInstance(CLSID_NullRenderer, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter,(void **)&pNullRendererFilter);
    CHECK_HR(hr, L"Unable to create null renderer filter");

    hr = m_pGraph->AddFilter(pNullRendererFilter, filterName);
    CHECK_HR(hr, L"Unable to add null renderer to graph");

    pOutPin = GetPin(pSampleGrabberFilter, PINDIR_OUTPUT);
    pInPin = GetPin(pNullRendererFilter, PINDIR_INPUT);

    hr = m_pGraph->ConnectDirect(pOutPin, pInPin, 0);

    SAFE_RELEASE(pOutPin);
    SAFE_RELEASE(pInPin);

    pFrmt = ((VIDEOINFOHEADER *)pmt->pbFormat);

    // Initialize the capture grabber
    m_pCapGrabber[i] = new CapGrabber(i);
    m_pCapGrabber[i]->SetVideoInfoHeader(pFrmt);
    m_pCapGrabber[i]->SetAttachGrabberCB(m_funcAttachGrabber);
    m_pCapGrabber[i]->SetWidth((int)pFrmt->bmiHeader.biWidth);
    m_pCapGrabber[i]->SetHeight((int)pFrmt->bmiHeader.biHeight);

    // Set the capture callback
    hr = pSampleGrabber->SetCallback(m_pCapGrabber[i], 1);

    SAFE_RELEASE(pSampleGrabberFilter);
    SAFE_RELEASE(pSampleGrabber);
    SAFE_RELEASE(pNullRendererFilter);
4

2 に答える 2

0

問題は典型的なものですが、調べる必要がある追加の詳細がない推測です。マルチスレッド操作を開始するのは簡単ですが、それを停止するには、スレッドを同期する必要があり、これを不正確に行うと、デッドロックの典型的な原因になります。

この問題に対処するには、通常、問題のプロセスにデバッガーをアタッチし、その呼び出しスタックを調べます。1 つのスレッドが呼び出しを停止し、呼び出しの奥深くで別の処理が行われるのを待機していることがわかります。別のスレッドも疑わしいことをしている可能性があります。

それらのスレッド、呼び出しスタック、およびモジュールは、何が問題なのかを示唆し、問題を特定のフィルターまたはライブラリに分離しています。さらに、フリーズが解消され、疑わしいフィルターが特定されるまで、フィルターを一時的に削除してグラフの縮小を開始することをお勧めします。

于 2013-02-25T14:26:18.390 に答える
0

グラフを停止する前に、グラフを一時停止して状態の変化を待つ方がよい場合があります。また、msdn stop によると、グラフの位置が先頭にリセットされないことにも注意してください。

http://msdn.microsoft.com/en-us/library/windows/desktop/dd390178(v=vs.85).aspx

したがって、停止後にグラフが最初に移動することを確認します。SetPosition インターフェイスを使用することをお勧めします。以下は、グラフを停止するために使用したコードの小さなスニペットです。有効なメディア コントロールとメディア シーク インターフェイスがあることを前提としています。

    IMediaControl *m_pControl = NULL; 
    IMediaSeeking *m_pMediaSeek = NULL;
    //Assuming that you have valid media control interface and media seeking interface    using QueryInterface

    long long m_pStart = 0;
    m_pControl->Pause();
    m_pControl->GetState(1000, NULL);


    m_pMediaSeek->SetPositions(&m_pStart, AM_SEEKING_AbsolutePositioning, NULL,  AM_SEEKING_NoPositioning);
    m_pControl->Run();
    m_pControl->GetState(1000,NULL);

    m_pControl->Stop();
    m_pControl->GetState(1000,NULL);
于 2013-02-25T16:16:11.663 に答える