Search code examples
c++videodirectshowvideo-capture

Failed to get IAMStreamConfig interface


I could capture the image from webcam and save it as bitmap by using sampleGrabber. And I know I could use the IAMStreamConfig interface to GetFormat and SetFormat the video resolution. My question is, I using FindInterface() to get IAMStreamConfig* but always failed.Is it because I place it in a wrong place or something else I didn't notice. I placed it before RenderStream. Here are some code below, thanks for your patient and help!

INT USBDeviceApp::GetInterfaces()
{
    HRESULT hr;

    hr = CoCreateInstance (CLSID_FilterGraph, NULL, CLSCTX_INPROC,
        IID_IGraphBuilder, (void **) &pGraphBuilder);
    if (FAILED(hr))
        return hr;

    hr = CoCreateInstance (CLSID_CaptureGraphBuilder2 , NULL, CLSCTX_INPROC,
              IID_ICaptureGraphBuilder2, (void **) &pCaptureGraphBuilder2);
    if (FAILED(hr))
        return hr;

    hr = pGraphBuilder->QueryInterface(IID_IMediaControl,(LPVOID *)
                                       &pMediaControl);
    if (FAILED(hr))
        return hr;


    hr = pGraphBuilder->QueryInterface(IID_IVideoWindow, (LPVOID *) 
                                       &pVideoWindow);
    if(FAILED(hr))
    {
        return hr;
    }
    hr = pGraphBuilder->QueryInterface(IID_IMediaEvent,(LPVOID *) 
                                      &pMediaEvent);
    if(FAILED(hr))
    {
        return hr;
    }
// ------------------------
// Create the Sample Grabber.
    hr = CoCreateInstance(CLSID_SampleGrabber, NULL, CLSCTX_INPROC_SERVER,
         IID_IBaseFilter, (void**)&pGrabberF);
    if (FAILED(hr))
    {
        return hr;
    }

      hr = pGrabberF->QueryInterface(IID_ISampleGrabber,
                                (void**)&pSampleGrabber);
      if(FAILED(hr))
      {
        AfxMessageBox(_T("Error SampleGrabber QueryInterface"));
      }


    return 1;
}

INT USBDeviceApp::InitMonikers()
{
    HRESULT hr;
    ULONG cFetched;

    ICreateDevEnum *pCreateDevEnum;     
    hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, 
         CLSCTX_INPROC_SERVER, IID_ICreateDevEnum, (void**)&pCreateDevEnum);
    if (FAILED(hr))
    {
        return hr;
    }

    IEnumMoniker *pEnumMoniker; 

    hr = pCreateDevEnum->
    CreateClassEnumerator(CLSID_VideoInputDeviceCategory,&pEnumMoniker, 0);
    if (FAILED(hr) || !pEnumMoniker)
    {
        return -1;
    }

    hr = pEnumMoniker->Next(1, &pMonikerVideo, &cFetched);
    if (S_OK == hr)
    {
        hr = pMonikerVideo->BindToObject(0,0,IID_IBaseFilter, 
                                        (void**)&pVideoCaptureFilter);
        if (FAILED(hr))
        {
            return hr;
        }
    }
    pEnumMoniker->Release();

    return 1;
}

INT USBDeviceApp::CaptureVideo()
{
    HRESULT hr = CoInitialize(NULL);

    hr = GetInterfaces();
    if (FAILED(hr))
    {
        AfxMessageBox(_T("Failed to get video interfaces!"));
        return hr;
    }

    hr = pCaptureGraphBuilder2->SetFiltergraph(pGraphBuilder);
    if (FAILED(hr))
    {
        AfxMessageBox(_T("Failed to attach the filter graph to the capture graph!"));
        return hr;
    }
    //IAMStreamConfig *pConfig
    hr = pCaptureGraphBuilder2->FindInterface(&PIN_CATEGORY_PREVIEW,
                                      &MEDIATYPE_Video,
                                      pVideoCaptureFilter,IID_IAMStreamConfig, (void **)&pConfig);
    if (FAILED(hr))
    {
         AfxMessageBox(_T("Couldn't initialize IAMStreamConfig!"));
    }
    else
    {////
        int iCount = 0,iSize = 0;
        hr = pConfig->GetNumberOfCapabilities(&iCount,&iSize);
        if(iSize == sizeof(VIDEO_STREAM_CONFIG_CAPS))
        {
            for(int iFormat = 0;iFormat < iCount;iFormat++)
            {
                VIDEO_STREAM_CONFIG_CAPS scc;
                AM_MEDIA_TYPE *pmtConfig;
                hr = pConfig->GetStreamCaps(iFormat, &pmtConfig, (BYTE*)&scc);
                if(hr)
                {
                    if((pmtConfig->majortype == MEDIATYPE_Video) &&
                        (pmtConfig->subtype == MEDIASUBTYPE_RGB24) &&
                        (pmtConfig->formattype == FORMAT_VideoInfo) &&
                        (pmtConfig->cbFormat >= sizeof (VIDEOINFOHEADER)) &&
                        (pmtConfig->pbFormat != NULL))
                    {
                        VIDEOINFOHEADER *pVih = (VIDEOINFOHEADER*)pmtConfig->pbFormat;
                        pVih->bmiHeader.biWidth = 1280;
                        pVih->bmiHeader.biHeight = 720;
                        pVih->bmiHeader.biSizeImage = DIBSIZE(pVih->bmiHeader);
                        hr = pConfig->SetFormat(pmtConfi);
                    }

                    DeleteMediaType(pmtConfig);
                }
            }
        }
    }////

    hr = InitMonikers();
    if(FAILED(hr))
    {
    return hr;
    }
    hr = pGraphBuilder->AddFilter(pVideoCaptureFilter, L"Video Capture");
    if (FAILED(hr))
    {
        pVideoCaptureFilter->Release();
        return hr;
    }

    AM_MEDIA_TYPE mt;
    ZeroMemory(&mt, sizeof(AM_MEDIA_TYPE));
    mt.majortype = MEDIATYPE_Video;
    mt.subtype = MEDIASUBTYPE_RGB24;
    hr = pSampleGrabber->SetMediaType(&mt);

    hr = pSampleGrabber->SetOneShot(FALSE);
    hr = pSampleGrabber->SetBufferSamples(TRUE);

    hr = pGraphBuilder->AddFilter(pGrabberF, L"Sample Grabber");
    if (FAILED(hr))
    {
         return hr;
    }

    hr = pCaptureGraphBuilder2->RenderStream(&PIN_CATEGORY_PREVIEW, &MEDIATYPE_Video, pVideoCaptureFilter, pGrabberF, 0 );
    if (FAILED(hr))
    {
        pVideoCaptureFilter->Release();
        return hr;
    }

    hr = pSampleGrabber->GetConnectedMediaType( &mt );
    if(FAILED( hr ))
    {
        return -1; 
    }
    VIDEOINFOHEADER * vih = (VIDEOINFOHEADER*) mt.pbFormat;

    pVih = (VIDEOINFOHEADER*) mt.pbFormat;

    CSampleGrabberCB *CB  = new CSampleGrabberCB() ;

    if(!FAILED( hr ))
    {
        CB->Width  = vih->bmiHeader.biWidth;
        CB->Height = vih->bmiHeader.biHeight;
        FreeMediaType( mt );
    }
    hr = pSampleGrabber->SetCallback( CB, 1 );

    pVideoCaptureFilter->Release();

    this->SetUpVideoWindow();
    hr = pMediaControl->Run();
    if (FAILED(hr))
    {
        return hr;
    }

    return hr;
}

hr = pCaptureGraphBuilder2->FindInterface() always failed to get the IAMStreamConfig interface, I really don't know why. Can someone help me, thanks so much!


Solution

  • Your API call below

    pCaptureGraphBuilder2->FindInterface(&PIN_CATEGORY_PREVIEW,
       &MEDIATYPE_Video,
       pVideoCaptureFilter,IID_IAMStreamConfig, (void **) &pConfig);
    

    applies several restrictions to the search, including pin category: you are looking for a preview pin. For example, the graph below features three video capture devices and none of them has the dedicated preview pin: preview pin is optional.

    enter image description here

    You need to take this into account and either relax the search criteria or I would rather suggest that you locate the pin of your interest directly on the capture filter. Then you will set it and and connect it with downstream peer filters. FindInterface is powerful but it also adds chances to get into confusion.