【问题标题】:Failed to get IAMStreamConfig interface获取IAMStreamConfig接口失败
【发布时间】:2025-12-28 02:30:07
【问题描述】:

我可以使用 sampleGrabber 从网络摄像头捕获图像并将其保存为位图。而且我知道我可以使用 IAMStreamConfig 接口来 GetFormat 和 SetFormat 视频分辨率。我的问题是,我使用 FindInterface() 来获取 IAMStreamConfig* 但总是失败。是因为我把它放在了错误的地方还是我没有注意到的其他东西。我把它放在 RenderStream 之前。下面是一些代码,感谢您的耐心和帮助!

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() 总是获取不到IAMStreamConfig接口,真不知道为什么。谁能帮帮我,非常感谢!

【问题讨论】:

    标签: c++ video directshow video-capture


    【解决方案1】:

    您的 API 调用如下

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

    对搜索应用若干限制,包括 pin 类别:您正在寻找预览 pin。例如,下图包含三个视频捕获设备,它们都没有专用的预览引脚:预览引脚是可选的。

    您需要考虑到这一点,要么放宽搜索条件,要么我建议您直接在捕获过滤器上找到您感兴趣的图钉。然后您将设置它并将其与下游对等过滤器连接。 FindInterface 很强大,但也增加了混乱的机会。

    【讨论】:

    • 我厌倦了找到源过滤器输出引脚并使用 QueryInterface 获取 IAMStreamConfig 接口,终于可以工作了。谢谢罗曼!