visual-studio 如何获取 Windows 上的视频捕获设备(网络摄像头)列表?(C++)

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4286223/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-22 12:48:54  来源:igfitidea点击:

How to get a list of video capture devices (web cameras) on windows? (C++)

c++visual-studiowinapivisual-studio-2010device

提问by Rella

So we have a simple C++ win32 console app. All we want is to print list of web cameras and other video capture devices that are avaliable. We want to use windows apis as much as possible - no external libs - after all - all we want is to print out a a list - not to fly onto the moon!) How to do such thing?

所以我们有一个简单的 C++ win32 控制台应用程序。我们想要的只是打印可用的网络摄像机和其他视频捕获设备的列表。我们想尽可能多地使用windows apis - 没有外部libs - 毕竟 - 我们想要的只是打印出aa list - 不要飞上月球!)如何做这样的事情?

My own reserch: I found this official msdn samplebut I still do not get how to output device list onto screen=( (sorry - I am new to C++)

我自己的研究:我找到了这个官方的 msdn 示例,但我仍然不知道如何将设备列表输出到屏幕=((抱歉 - 我是 C++ 新手)

... some more reserch...

......更多的研究......

In one of simpliest ms samples on topic found this

在有关主题的最简单的 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);
    }

looks like it should do the job but I do not get how to include this into simple command line app so to output data...

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



also from this series:

也来自这个系列:

回答by Naveen

From the examples shown, copy the following code into dev.c. Then open the command line with all the SDK variables set. At the command line link to ole32.lib and oleaut32.lib. It will then show you all the devices.

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

cl dev.c ole32.lib oleaut32.lib

cl dev.c ole32.lib oleaut32.lib

dev.exe will give out the list on the command line.

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();
    }
}

回答by Jerry Coffin

This being Microsoft, what could reasonably have been somewhere around 10 lines of code will, thanks to the wonders of COM, end up as a couple hundred linesor so.

这就是微软,由于 COM 的奇迹,本可以合理地大约在 10 行左右的代码最终会变成几百行左右。