Windows下获取usb视频设备vendor id和product id的4种方法

之前在https://blog.csdn.net/fengbingchun/article/details/103507754 博文中介绍过如何在Linux获取usb视频设备的vendor id和product id,这里介绍在Windows下获取的方式:

1. 打开设备管理器,如下图所示,内置摄像头显示名为”Integrated Webcam”,插入的usb摄像头显示名为”Logitech HD Webcam C310”:

选中其中一个,如”Logitech HD Webcam C310”,点击右键,选中”属性”点击,-->详细信息,-->属性选择”硬件id”,可获取vid和pid值,如下图所示,十六进制vid为”046D”,pid为”081B”:

2. 通过执行ffmpeg获取,执行命令及执行结果如下图所示:

3. 通过Windows的SetupDiGetDeviceInstanceId函数可以获得所有usb设备的vid和vid,测试code如下:

int get_all_usb_devices_vid_pid()
{
	GUID *guidDev = (GUID*)&GUID_DEVCLASS_USB;
	HDEVINFO deviceInfoSet = SetupDiGetClassDevs(guidDev, NULL, NULL, DIGCF_PRESENT | DIGCF_PROFILE);

	CHAR buffer[4000];
	DWORD memberIndex = 0;

	while (true) {
		SP_DEVINFO_DATA deviceInfoData;
		ZeroMemory(&deviceInfoData, sizeof(SP_DEVINFO_DATA));
		deviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
		if (SetupDiEnumDeviceInfo(deviceInfoSet, memberIndex, &deviceInfoData) == FALSE) {
			if (GetLastError() == ERROR_NO_MORE_ITEMS) {
				break;
			}
		}

		DWORD nSize = 0;
		SetupDiGetDeviceInstanceId(deviceInfoSet, &deviceInfoData, buffer, sizeof(buffer), &nSize);
		buffer[nSize] = '\0';
		fprintf(stdout, "%s\n", buffer);

		memberIndex++;
	}

	if (deviceInfoSet) {
		SetupDiDestroyDeviceInfoList(deviceInfoSet);
	}

	return 0;
}

执行结果如下:

4. 提取FFmpeg源码中部分code,测试code如下:

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

int parse_string(const std::string& src, std::string& vid, std::string& pid)
{
	int pos = src.find("vid_");
	if (pos == std::string::npos) return -1;
	vid.assign(src, pos + 4, 4);

	pos = src.find("pid_");
	if (pos == std::string::npos) return -1;
	pid.assign(src, pos + 4, 4);

	return 0;
}

int get_usb_video_devices_vid_pid()
{
	CoInitialize(0);

	ICreateDevEnum *devenum = NULL;
	int r = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, 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 = NULL;
	r = ICreateDevEnum_CreateClassEnumerator(devenum, CLSID_VideoInputDeviceCategory, (IEnumMoniker **)&classenum, 0);
	if (r != S_OK) {
		fprintf(stdout, "fail to ICreateDevEnum_CreateClassEnumerator: %d\n", r);
		return -1;
	}

	IBaseFilter *device_filter = NULL;
	IMoniker *m = NULL;

	while (!device_filter && IEnumMoniker_Next(classenum, 1, &m, NULL) == S_OK) {
		IPropertyBag *bag = NULL;
		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, NULL);
		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);
		fprintf(stdout, "friendly_name: %s\n", friendly_name.get());

		LPMALLOC co_malloc = NULL;
		r = CoGetMalloc(1, &co_malloc);
		if (r != S_OK) {
			fprintf(stdout, "fail to CoGetMalloc: %d\n", r);
			return -1;
		}

		IBindCtx *bind_ctx = NULL;
		r = CreateBindCtx(0, &bind_ctx);
		if (r != S_OK) {
			fprintf(stdout, "fail to CreateBindCtx: %d\n", r);
			return -1;
		}

		LPOLESTR olestr = NULL;
		r = IMoniker_GetDisplayName(m, bind_ctx, NULL, &olestr);
		if (r != S_OK) {
			fprintf(stdout, "fail to IMoniker_GetDisplayName: %d\n", r);
			return -1;
		}

		auto unique_name = dup_wchar_to_utf8(olestr, length);
		/* replace ':' with '_' since we use : to delineate between sources */
		std::for_each(unique_name.get(), unique_name.get() + length, [](char& ch) { if (ch == ':') ch = '_'; });
		fprintf(stdout, "unique_name: %s\n", unique_name.get());
		std::string src(unique_name.get()), vid, pid;
		parse_string(src, vid, pid);
		unsigned int value_vid, value_pid;
		std::istringstream(vid) >> std::hex >> value_vid;
		std::istringstream(pid) >> std::hex >> value_pid;
		fprintf(stdout, "usb device name: %s, vid: %s, value: %d; pid: %s, value: %d\n",
			friendly_name.get(), vid.c_str(), value_vid, pid.c_str(), value_pid);

		if (olestr && co_malloc)
			IMalloc_Free(co_malloc, olestr);
		if (bind_ctx)
			IBindCtx_Release(bind_ctx);
		if (bag)
			IPropertyBag_Release(bag);

		IMoniker_Release(m);
	}

	IEnumMoniker_Release(classenum);

	return 0;
}

执行结果如下:

GitHubhttps://github.com//fengbingchun/OpenCV_Test

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值