【问题标题】:multiple web cams in AMCapAMCap 中的多个网络摄像头
【发布时间】:2010-01-17 04:51:46
【问题描述】:

我在 SDK 中直接显示下构建了 AMCap 示例。它能够处理 2 个或更多网络摄像头,我如何修改程序以让我同时使用它们……比如按下一个显示“开始捕捉”的按钮,并确保所有相机开始捕捉和一个显示“停止”的按钮捕获”以停止所有摄像机。我希望来自不同相机的帧保存在不同的文件中。我是 C++ 新手,任何形式的帮助都将不胜感激!感谢您的宝贵时间!

【问题讨论】:

    标签: c++ sdk directshow


    【解决方案1】:

    使用 GraphEdit 工具。在那里,您可以构建自己的图形,并连接所有视频输入设备。请看http://en.wikipedia.org/wiki/GraphEdit

    【讨论】:

    【解决方案2】:

    如果您刚开始使用 DirectShow 编程,这可能有点困难,但我希望它对您有所帮助,或者为您指明正确的方向。

    M$DN 有一个描述how to select a capture device 的页面。例子有点少,所以我在下面提供了一个简单的实现。

    理论上,您需要枚举CLSID_VideoInputDeviceCategory 中的所有设备,并尝试为类别中的每个有效项目创建渲染图。

    首先,我将向您展示用于迭代类别中设备名称的代码。下面是 3 个静态函数,可用于迭代类别中的设备。将这些函数添加到项目后,您可以通过调用以下函数在视频输入设备类别中列出设备:

    ListDevicesInCategory(CLSID_VideoInputDeviceCategory);
    

    好的,这就是三个函数。 ListDevicesInCategory() 是工作发生的地方。它依赖于另外两个函数,FindDeviceInCategory() 和 CountDevicesInCategory()

    #define RFAIL(x) { HRESULT hr = x; if(FAILED(hr)) {return hr;} }
    
    
    static HRESULT FindDeviceInCategory(IBaseFilter** pSrc, const IID& cls, wstring& wFilterName,int devNum)
    {
        CComPtr<ICreateDevEnum> spDevEnum;
        CComPtr<IEnumMoniker>   spEnum;
        int                     i;
    
        RFAIL( spDevEnum.CoCreateInstance(CLSID_SystemDeviceEnum) );
        RFAIL( spDevEnum->CreateClassEnumerator(cls, &spEnum, 0) );
    
        if(spEnum == 0)
            return E_FAIL;
    
        for(i = 0; i >= 0; i++)
        {
            CComPtr<IMoniker> spiMoniker;
    
            if( spEnum->Next(1, &spiMoniker, 0) != S_OK )           
                return E_FAIL;          
    
            if( devNum == i)
            {
                CComVariant varName;
                CComPtr<IPropertyBag> spiPropBag;
                RFAIL(spiMoniker->BindToStorage(0, 0, IID_IPropertyBag,reinterpret_cast<void**>(&spiPropBag)));
                RFAIL(spiPropBag->Read(L"FriendlyName", &varName, 0));
                RFAIL(spiMoniker->BindToObject(0, 0, IID_IBaseFilter, reinterpret_cast<void**>(pSrc)));
                wFilterName = V_BSTR(&varName);
    
                varName.Clear();
                return S_OK;
            }
        }
    
        return E_FAIL;
    }
    
    static HRESULT CountDevicesInCategory( int *pCount, const IID& categoryClass )
    {
        // pass in a category class like CLSID_VideoInputDeviceCategory, writes the count of the number of filters in that category 
        // available on the local machine
        HRESULT hr = S_OK;
    
        CComPtr<ICreateDevEnum> spIDevEnum;
        CComPtr<IEnumMoniker>   spIEnum;
        CComPtr<IMoniker>       spIMoniker;
    
        hr = CoCreateInstance(CLSID_SystemDeviceEnum, 0, CLSCTX_INPROC_SERVER, IID_ICreateDevEnum, reinterpret_cast<void**>(&spIDevEnum));
        if( ! SUCCEEDED(hr) || hr == S_FALSE )
        {
            *pCount = 0;
            return hr;
        }
    
        hr = spIDevEnum->CreateClassEnumerator( categoryClass, &spIEnum, 0 );
        if( ! SUCCEEDED(hr) || hr == S_FALSE )
        {
            *pCount = 0;
            return hr;
        }
    
        if( spIEnum )
        {
            while( spIEnum->Next(1, &spIMoniker, 0) == S_OK ) 
            { 
                (*pCount) ++; 
                spIMoniker.Detach();
            }       
        }
    
        return S_OK;
    }
    
    static HRESULT ListDevicesInCategory( const GUID & cls )
    {
        CComPtr<IBaseFilter>    spSource;
        wstring *               psNextFilter        = NULL;
        int                     nDeviceNum          = 0;
        int                     nTotalNumDevices    = 0;
        HRESULT                 hr                  = S_OK;
        bool                    bComplete           = false;    
        DeviceNames             CaptureDeviceNames;
    
    
        if( FAILED(CountDevicesInCategory( &nTotalNumDevices, (IID)cls )) )
            bComplete = TRUE;
    
        if( nTotalNumDevices == 0 )
            bComplete = TRUE;
    
    
        while( ! bComplete )
        {   
            psNextFilter = new std::wstring;
    
            hr = FindDeviceInCategory( &spSource, (IID)cls, *psNextFilter, nDeviceNum++ );
    
            if( SUCCEEDED(hr) && spSource  )
            {
                if ( *psNextFilter )
                {
                    wcout << *psNextFilter << endl;
                    delete *psNextFilter;
                    psNextFilter = NULL;
                }
    
                spSource.Release();
                spSource = NULL;
            }
            else
                bComplete = TRUE;
        }           
    
        return S_OK;
    }   
    

    在您感兴趣的类别中识别出一个项目后,您可以使用IGraphBuilder::AddFilter 调用将其添加到图表中。

    要向图表添加过滤器,您首先需要为该过滤器获取 IBaseFilter*。我还有一个功能供您使用。

    定义一个 IBaseFilter 智能指针:

    CComPtr<IBaseFilter> spSource;
    

    附加到过滤器:

    m_spSource.Attach(
                    GetFilter(CLSID_VideoInputDeviceCategory, CComBSTR(L"Osprey-450e Video Device 1A"))
              );
    

    这是最后一个函数 - GetFilter:

    static IBaseFilter * GetFilter( REFCLSID clsidDeviceClass, CComBSTR & sName )
    {   
        HRESULT             hr;
        IBaseFilter *       pRetFilter      = NULL;
        ICreateDevEnum *    pSysDevEnum     = NULL;
        IEnumMoniker *      pEnum           = NULL;
        IMoniker *          pMoniker        = NULL;
        int                 nSameSrcCounter = 0;
    
        hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER, IID_ICreateDevEnum, (void**)&pSysDevEnum);
    
        if( pSysDevEnum )
            hr = pSysDevEnum->CreateClassEnumerator(clsidDeviceClass, &pEnum, 0);
    
        if (hr != S_OK) 
            return NULL;    
    
        USES_CONVERSION;
    
    
        while ( pEnum->Next(1, &pMoniker, NULL) == S_OK )
        {
            IPropertyBag *pPropBag = NULL;
            VARIANT var;
            VariantInit(&var);
    
            pMoniker->BindToStorage(0, 0, IID_IPropertyBag, (void **)&pPropBag);
    
            hr = pPropBag->Read(L"FriendlyName", &var, 0);
            if (SUCCEEDED(hr))
            {
                if(sName == OLE2T(var.bstrVal))
                {           
                    hr = pMoniker->BindToObject(NULL, NULL, IID_IBaseFilter, (void**)&pRetFilter);
                    if (FAILED(hr))                 
                        pRetFilter = NULL;                  
    
                    VariantClear(&var); 
                    pPropBag->Release();
                    pMoniker->Release();
                    break;
                }
            }
    
            VariantClear(&var); 
            pPropBag->Release();
            pMoniker->Release();
        }
    
        pSysDevEnum->Release();
        pEnum->Release();
    
        return pRetFilter;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-10-16
      • 1970-01-01
      • 2018-03-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-07-06
      相关资源
      最近更新 更多