Windows下获取视频设备的一种改进实现
生活随笔
收集整理的這篇文章主要介紹了
Windows下获取视频设备的一种改进实现
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
之前在https://blog.csdn.net/fengbingchun/article/details/102806822中介紹過在Windows下獲取視頻設備列表的方法。其實那種實現方法是有缺陷的,當PC機上連接多個視頻設備,并且其中有設備處于啟動運行狀態時,再調用相關接口獲取視頻設備可能會崩潰,因為為了獲取視頻設備列表,它會先以索引0遍歷獲取視頻設備名,然后會執行啟動此設備操作。如果此設備已經被其它應用程序啟動過,則此時就會崩潰。
其實如果僅僅為了獲取視頻設備列表,沒有必要執行啟動設備的操作。以下是測試代碼,無需啟動任何設備即可獲取到所有的視頻設備列表。
此測試代碼調用的是系統C接口,你也可以調整為調用系統的C++接口實現。
#define CINTERFACE
#define COBJMACROS
#include <strmif.h>
#include <Setupapi.h>
#include <uuids.h>
#include <devguid.h>
#include <memory>
#include <algorithm>namespace {std::unique_ptr<char[]> dup_wchar_to_utf8(wchar_t *w, int& len)
{len = WideCharToMultiByte(CP_UTF8, 0, w, -1, 0, 0, 0, 0);std::unique_ptr<char[]> s(new char[len]);WideCharToMultiByte(CP_UTF8, 0, w, -1, s.get(), len, 0, 0);return s;
}} // namespaceint test_get_windows_camera_list()
{CoInitialize(nullptr);ICreateDevEnum *devenum = nullptr;int r = CoCreateInstance(CLSID_SystemDeviceEnum, nullptr, CLSCTX_INPROC_SERVER, IID_ICreateDevEnum, reinterpret_cast<void**>(&devenum));if (r != S_OK) {fprintf(stdout, "fail to CoCreateInstance: %d\n", r);return -1;}IEnumMoniker *classenum = nullptr;r = ICreateDevEnum_CreateClassEnumerator(devenum, CLSID_VideoInputDeviceCategory, (IEnumMoniker **)&classenum, 0);if (r != S_OK) {fprintf(stdout, "fail to ICreateDevEnum_CreateClassEnumerator: %d\n", r);return -1;}IMoniker *m = nullptr;typedef struct devices_info {int index;std::string name;} devices_info;std::vector<devices_info> lists;int device_counter = 0;while (IEnumMoniker_Next(classenum, 1, &m, nullptr) == S_OK) {IPropertyBag *bag = nullptr;VARIANT var;r = IMoniker_BindToStorage(m, 0, 0, IID_IPropertyBag, (void **)&bag);if (r != S_OK) {fprintf(stdout, "fail to IMoniker_BindToStorage: %d\n", r);return -1;}var.vt = VT_BSTR;r = IPropertyBag_Read(bag, L"FriendlyName", &var, nullptr);if (r != S_OK) {fprintf(stdout, "fail to IPropertyBag_Read: %d\n", r);return -1;}int length;auto friendly_name = dup_wchar_to_utf8(var.bstrVal, length);lists.push_back({ device_counter++, friendly_name.get() });if (bag)IPropertyBag_Release(bag);IMoniker_Release(m);}IEnumMoniker_Release(classenum);CoUninitialize();fprintf(stdout, "device lists:\n");std::for_each(lists.cbegin(), lists.cend(), [](const devices_info& info) {fprintf(stdout, " index: %d, name: %s\n", info.index, info.name.c_str());});return 0;
}
執行結果如下:設備索引與設備名并不是固定不變的,再次拔下設備再插上,此時獲得的設備索引和設備名可能與之前不同。
GitHub:https://github.com//fengbingchun/OpenCV_Test
總結
以上是生活随笔為你收集整理的Windows下获取视频设备的一种改进实现的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 模仿视频抓帧实现
- 下一篇: libusb中的热插拔使用举例