2013-02-25 6 views
0

Я использую DirectShow для захвата видео. Я прикрепляю камеру к образцу граббера и сохраняю изображения, которые получаю.IID_IMediaControl застревает при остановке

В следующем коде у меня IID_ICaptureGraphBuilder2 подключен к устройству захвата (CLSID_VideoCaptureSources), который подключен к образцу захвата (ISampleGrabber). График привязан к IID_IMediaControl. Я использую IID_IMediaControl Run и Stop. В большинстве случаев остановка застревает. Там какой-то тупик. Я попытался добавить IID_IMediaEvent и m_pEvent-> WaitForCompletion (INFINITE, & evCode); но он все еще не работает. Приостановка работает без каких-либо problesm, однако при попытке остановить программное обеспечение застрял

Построение графика

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

Можете ли вы немного сузить его? Не вижу Джека там ... –

+0

У меня есть график с Camera, SampleGrabber и MediaControl. Чтобы начать, приостановить и остановить поток, я использую Run, Pause и Stop, но IID_IMediaControl. Работа и пауза работают без проблем, Стоп застревает. –

ответ

0

Проблема типична, но это догадка без дополнительных деталей, которые необходимо выяснить. Легко начать многопоточную работу, но когда дело доходит до ее остановки, нужно синхронизировать потоки и неточно делать это типичная причина тупика - то, что вы видите.

Для решения этой проблемы вы обычно прикрепляете отладчик к рассматриваемому процессу и проверяете его стеки вызовов. Вы увидите, что один поток вызывает остановку и спят где-то в глубине вызова, ожидая чего-то еще. Вероятно, есть и другой поток, который делает что-то подозрительное.

Потоки, стеки вызовов и модули на них указывают на то, что не так, и изолировать проблему от конкретного фильтра или библиотеки. Более того, вы можете начать сокращать график, временно удаляя фильтры, пока не увидите, что замораживание исчезло, и вы идентифицируете подозрительный фильтр.

0

Когда-нибудь лучше приостановить график и дождаться изменения состояния перед остановкой графика. Также обратите внимание, что в соответствии с остановкой msdn не будет сброшено положение графика до начала.

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); 
Смежные вопросы