【问题标题】:How to get a list of video capture devices (web cameras) on windows? (C++)如何在 Windows 上获取视频捕获设备(网络摄像头)的列表? (C++)
【发布时间】:2011-05-16 05:35:45
【问题描述】:

所以我们有一个简单的 C++ win32 控制台应用程序。我们想要的只是打印可用的网络摄像头和其他视频捕获设备的列表。我们想尽可能多地使用 windows api - 没有外部库 - 毕竟 - 我们想要的只是打印出一个列表 - 而不是飞上月球!)怎么做?

我自己的研究: 我找到了这个official msdn sample,但我仍然不知道如何将设备列表输出到屏幕上=((对不起 - 我是 C++ 新手)

...更多研究...

在一个关于主题的最简单的 ms 示例中找到了这个

HRESULT OnInitDialog(HWND hwnd, ChooseDeviceParam *pParam)
{
    HRESULT hr = S_OK;

    HWND hList = GetDlgItem(hwnd, IDC_DEVICE_LIST);

    // Display a list of the devices.

    for (DWORD i = 0; i < pParam->count; i++)
    {
        WCHAR *szFriendlyName = NULL;

        hr = pParam->ppDevices[i]->GetAllocatedString(
            MF_DEVSOURCE_ATTRIBUTE_FRIENDLY_NAME,
            &szFriendlyName,
            NULL
            );

        if (FAILED(hr))
        {
            break;
        }

        int index = ListBox_AddString(hList, szFriendlyName);

        ListBox_SetItemData(hList, index, i);

        CoTaskMemFree(szFriendlyName);
    }

看起来它应该可以完成这项工作,但我不知道如何将其包含到简单的命令行应用程序中以便输出数据...


也来自这个系列:

【问题讨论】:

    标签: c++ visual-studio winapi visual-studio-2010 device


    【解决方案1】:

    这是列出 Windows 机器上连接的网络摄像头的 C++ 代码,无需任何额外的库

    /*  List connected webcams on windows machine
    Build: g++ cameralist.cpp -lstrmiids -lole32 -loleaut32
    microsoft docs https://docs.microsoft.com/en-us/windows/win32/directshow/using-the-system-device-enumerator
    */
    
    #include <windows.h>
    #include <dshow.h>
    
    HRESULT EnumerateDevices(REFGUID category, IEnumMoniker **ppEnum)
    {
        // Create the System Device Enumerator.
    
        HRESULT hr;
        ICreateDevEnum *pDevEnum = NULL;
        hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER,
                              IID_ICreateDevEnum, (void **)&pDevEnum);
    
        if (SUCCEEDED(hr))
        {
            // Create an enumerator for the category.
            hr = pDevEnum->CreateClassEnumerator(category, ppEnum, 0);
            if (hr == S_FALSE)
            {
                hr = VFW_E_NOT_FOUND; // The category is empty. Treat as an error.
            }
            pDevEnum->Release();
        }
        return hr;
    }
    
    void DisplayDeviceInformation(IEnumMoniker *pEnum)
    {
        IMoniker *pMoniker = NULL;
    
        while (pEnum->Next(1, &pMoniker, NULL) == S_OK)
        {
            IPropertyBag *pPropBag;
            HRESULT hr = pMoniker->BindToStorage(0, 0, IID_PPV_ARGS(&pPropBag));
            if (FAILED(hr))
            {
                pMoniker->Release();
                continue;
            }
    
            VARIANT var;
            VariantInit(&var);
    
            // Get description or friendly name.
            hr = pPropBag->Read(L"Description", &var, 0);
            if (FAILED(hr))
            {
                hr = pPropBag->Read(L"FriendlyName", &var, 0);
            }
            if (SUCCEEDED(hr))
            {
                printf("%S\n", var.bstrVal);
                VariantClear(&var);
            }
    
            hr = pPropBag->Write(L"FriendlyName", &var);
       
            hr = pPropBag->Read(L"DevicePath", &var, 0);
            if (SUCCEEDED(hr))
            {
                // The device path is not intended for display.
                printf("Device path: %S\n", var.bstrVal);
                VariantClear(&var);
            }
    
            pPropBag->Release();
            pMoniker->Release();
        }
    }
    
    int main()
    {
        HRESULT hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
        if (SUCCEEDED(hr))
        {
            IEnumMoniker *pEnum;
    
            hr = EnumerateDevices(CLSID_VideoInputDeviceCategory, &pEnum);
            if (SUCCEEDED(hr))
            {
                DisplayDeviceInformation(pEnum);
                pEnum->Release();
            }
    
            CoUninitialize();
        }
        return 0;
    }
    

    【讨论】:

      【解决方案2】:

      从显示的示例中,将以下代码复制到 dev.c 中。然后打开设置了所有 SDK 变量的命令行。在命令行链接到 ole32.lib 和 oleaut32.lib。然后它将显示所有设备。

      cl dev.c ole32.lib oleaut32.lib

      dev.exe 会在命令行给出列表。

      #include <windows.h>
      #include <dshow.h>
      
      #pragma comment(lib, "strmiids")
      
      HRESULT EnumerateDevices(REFGUID category, IEnumMoniker **ppEnum)
      {
          // Create the System Device Enumerator.
          ICreateDevEnum *pDevEnum;
          HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL,  
              CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pDevEnum));
      
          if (SUCCEEDED(hr))
          {
              // Create an enumerator for the category.
              hr = pDevEnum->CreateClassEnumerator(category, ppEnum, 0);
              if (hr == S_FALSE)
              {
                  hr = VFW_E_NOT_FOUND;  // The category is empty. Treat as an error.
              }
              pDevEnum->Release();
          }
          return hr;
      }
      
      
      void DisplayDeviceInformation(IEnumMoniker *pEnum)
      {
          IMoniker *pMoniker = NULL;
      
          while (pEnum->Next(1, &pMoniker, NULL) == S_OK)
          {
              IPropertyBag *pPropBag;
              HRESULT hr = pMoniker->BindToStorage(0, 0, IID_PPV_ARGS(&pPropBag));
              if (FAILED(hr))
              {
                  pMoniker->Release();
                  continue;  
              } 
      
              VARIANT var;
              VariantInit(&var);
      
              // Get description or friendly name.
              hr = pPropBag->Read(L"Description", &var, 0);
              if (FAILED(hr))
              {
                  hr = pPropBag->Read(L"FriendlyName", &var, 0);
              }
              if (SUCCEEDED(hr))
              {
                  printf("%S\n", var.bstrVal);
                  VariantClear(&var); 
              }
      
              hr = pPropBag->Write(L"FriendlyName", &var);
      
              // WaveInID applies only to audio capture devices.
              hr = pPropBag->Read(L"WaveInID", &var, 0);
              if (SUCCEEDED(hr))
              {
                  printf("WaveIn ID: %d\n", var.lVal);
                  VariantClear(&var); 
              }
      
              hr = pPropBag->Read(L"DevicePath", &var, 0);
              if (SUCCEEDED(hr))
              {
                  // The device path is not intended for display.
                  printf("Device path: %S\n", var.bstrVal);
                  VariantClear(&var); 
              }
      
              pPropBag->Release();
              pMoniker->Release();
          }
      }
      
      void main()
      {
          HRESULT hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
          if (SUCCEEDED(hr))
          {
              IEnumMoniker *pEnum;
      
              hr = EnumerateDevices(CLSID_VideoInputDeviceCategory, &pEnum);
              if (SUCCEEDED(hr))
              {
                  DisplayDeviceInformation(pEnum);
                  pEnum->Release();
              }
              hr = EnumerateDevices(CLSID_AudioInputDeviceCategory, &pEnum);
              if (SUCCEEDED(hr))
              {
                  DisplayDeviceInformation(pEnum);
                  pEnum->Release();
              }
              CoUninitialize();
          }
      }
      

      【讨论】:

      • @Naveen,我得到的不是那么友好。 BSTR = 0x0000023ac00eac58 L"\\\\?\\display#int3470#4&2e02b419&0&uid13424#{65e8773d-8f56-11d0-a3b9-00a0c9223196}\\{bf89b5a5-61f7-4127-a279-e187013d ?
      【解决方案3】:

      【讨论】:

      • 它不直接使用win32。我不需要一个库——我只需要一个简单的列表!可能像一个请求一样简单......
      • 我认为你必须使用 directshow/vfw 因为它管理相机 - 我不相信你可以使用 raw win32 访问 directshow 相机
      猜你喜欢
      • 2011-05-30
      • 2011-05-16
      • 2011-05-27
      • 1970-01-01
      • 1970-01-01
      • 2011-06-05
      • 1970-01-01
      • 2012-10-11
      • 1970-01-01
      相关资源
      最近更新 更多