0
votes

I'm using DirectShow in order to capture video. I'm attaching the camera to sample grabber and saving the images that I get.

In the following code I have IID_ICaptureGraphBuilder2 connected to the capture device (CLSID_VideoCaptureSources) that is connected to the sample grabber (ISampleGrabber). The graph is connected to IID_IMediaControl. I use IID_IMediaControl Run and Stop. Most of the times the stop gets stuck. There's some kind of deadlock. I tried to add IID_IMediaEvent and m_pEvent->WaitForCompletion(INFINITE, &evCode); but it still doesn't work. Pausing works with no problesm, however upon trying to stop the software is stuck

Building the graph

    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);
2
Can you narrow it down a little bit? Can't see Jack in there...bash.d
I have a graph with Camera, SampleGrabber and MediaControl. In order to Start, Pause and Stop the stream I use Run, Pause and Stop provided but IID_IMediaControl. The Run and the Pause work with no problems, Stop gets stuck.pooh_bear

2 Answers

0
votes

The problem is typical, but it is a guesswork without additional details you need to find out. It is easy to start multithreaded operation, but when it comes to stopping it, one needs to synchronize threads and inaccurate doing this is a typical cause of a deadlock - what you are seeing.

To address this problem you typically attach debugger to the process in question and inspect its call stacks. You will see one thread calling stop and sleeping somewhere deep within the call waiting for something else to happen. It is likely that there is another thread is doing something suspicious as well.

The threads, call stacks and modules on them are suggesting what's wrong and isolating the problem to specific filter or library. More to that, you might want to start reducing your graph temporarily removing filters until you see that the freeze is gone, and you identify the suspicious filter.

0
votes

Sometime it is better to pause graph and wait for state change before stopping the graph. Also note that as per msdn stop will not reset the graph position to the beginning.

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

So to make sure that graph goes to the beginning after stop. I would recommend use SetPosition interface. Below is the small snippet of code I've used for stopping the graph. I assumed that you have valid media control and media seeking interface.

    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);