如何通过DirectShow用C++实现多台PTZ相机的控制?

基于"如何通过DirectShow用C++实现PTZ相机的控制?"的脚本,我们来实现一些优化和更新。

1.增加三个函数

PTZ_GetCameraCount() 获取相机的数量

PTZ_GetCameraName(int cameraIndex) 通过相机的索引获取相机的名字

PTZ_InitByIndex(void* handle, int cameraIndex) 通过相机索引获取相机的句柄(实际上是一个结构体 我要把c++文件做成dll导入unity当中 通过类型强转可以实现c++数据和c++++数据的转换)

2.增加了对虚拟相机设备的跳过

3.源代码

cpp 复制代码
#include<Windows.h>
#include<dshow.h> // DirectShow 头文件
#include<iostream>

#pragma comment(lib, "strmiids.lib") // 链接 DirectShow 系统库

// Movement step size
const int  PAN_STEP = 10;
const int  TILT_STEP = 10;
const int  ZOOM_STEP = 10;

// Safety limit: prevent going too low
const long TILT_DOWN_LIMIT = -60;

// Maximum number of cameras we can list
const int MAX_CAMERA_COUNT = 32;

// -----------------------------------------------------------------------------
// Check if camera should be filtered out (skip it)
// Add your own filter keywords here
// -----------------------------------------------------------------------------
inline bool ShouldSkipCamera(const wchar_t* camName) // 内联函数
{
	if (!camName || !camName[0]) return false;

	// Add keywords to skip:
	if (wcsstr(camName, L"Virtual Camera") != nullptr)  return true;
	if (wcsstr(camName, L"STUDIO CAMERA") != nullptr) return true;
	if (wcsstr(camName, L"virtual") != nullptr)        return true;
	if (wcsstr(camName, L"OBS") != nullptr)            return true;

	return false; // Keep this camera
}

struct PTZCam {
	IAMCameraControl* pCamCtrl; // IAMCameraControl 是 Windows 系统提供的相机控制接口

	wchar_t camName[256]; // Windows 系统底层(COM、DirectShow、设备名)全部用 Unicode 宽字符串

	long minPan;
	long maxPan;
	long currPan;
	long minTilt;
	long maxTilt;
	long currTilt;
	long minZoom;
	long maxZoom;
	long currZoom;

	bool zoomSupported;
	bool comInitialized; // 是否由我们初始化了 COM

	PTZCam() :
		pCamCtrl(nullptr),
		minPan(0),
		maxPan(0),
		currPan(0),
		minTilt(0),
		maxTilt(0),
		currTilt(0),
		minZoom(0),
		maxZoom(0),
		currZoom(0),
		zoomSupported(false),
		comInitialized(false)
	{
		camName[0] = 0;
	}
};

#pragma region 原始函数声明(内部用)
bool PTZ_InitCam(PTZCam* cam, int cameraIndex); // 初始化指定索引的相机
void PTZ_Release(PTZCam* cam); // 释放相机资源

bool PTZ_QueryCapabilities(PTZCam* cam); // 获取硬件信息

bool PTZ_SetPan(PTZCam* cam, long panVal);
bool PTZ_SetTilt(PTZCam* cam, long tiltVal);
bool PTZ_SetZoom(PTZCam* cam, long zoomVal);

void PTZ_PanLeft(PTZCam* cam);
void PTZ_PanRight(PTZCam* cam);
void PTZ_TiltUp(PTZCam* cam);
void PTZ_TiltDown(PTZCam* cam);
void PTZ_ZoomIn(PTZCam* cam);
void PTZ_ZoomOut(PTZCam* cam);
#pragma endregion

// DLL export interface for Unity C#
extern "C" {

	__declspec(dllexport) void* PTZ_Create();
	__declspec(dllexport) void PTZ_Destroy(void* handle);

	// === Multiple camera support ===
	__declspec(dllexport) int PTZ_GetCameraCount();
	__declspec(dllexport) const wchar_t* PTZ_GetCameraName(int cameraIndex);
	__declspec(dllexport) bool PTZ_InitByIndex(void* handle, int cameraIndex);

	__declspec(dllexport) bool PTZ_Init(void* handle); // Legacy: initialize first camera (index 0)
	__declspec(dllexport) void PTZ_Release(void* handle);
	__declspec(dllexport) bool PTZ_QueryCapabilities(void* handle);

	__declspec(dllexport) bool PTZ_SetPan(void* handle, long panVal);
	__declspec(dllexport) bool PTZ_SetTilt(void* handle, long tiltVal);
	__declspec(dllexport) bool PTZ_SetZoom(void* handle, long zoomVal);

	__declspec(dllexport) void PTZ_PanLeft(void* handle);
	__declspec(dllexport) void PTZ_PanRight(void* handle);
	__declspec(dllexport) void PTZ_TiltUp(void* handle);
	__declspec(dllexport) void PTZ_TiltDown(void* handle);
	__declspec(dllexport) void PTZ_ZoomIn(void* handle);
	__declspec(dllexport) void PTZ_ZoomOut(void* handle);

	__declspec(dllexport) long PTZ_GetMinPan(void* handle);
	__declspec(dllexport) long PTZ_GetMaxPan(void* handle);
	__declspec(dllexport) long PTZ_GetCurrentPan(void* handle);

	__declspec(dllexport) long PTZ_GetMinTilt(void* handle);
	__declspec(dllexport) long PTZ_GetMaxTilt(void* handle);
	__declspec(dllexport) long PTZ_GetCurrentTilt(void* handle);

	__declspec(dllexport) long PTZ_GetMinZoom(void* handle);
	__declspec(dllexport) long PTZ_GetMaxZoom(void* handle);
	__declspec(dllexport) long PTZ_GetCurrentZoom(void* handle);
	__declspec(dllexport) bool PTZ_IsZoomSupported(void* handle);

} // extern "C"

// DLL 入口
BOOL APIENTRY DllMain(HMODULE hModule, DWORD  ul_reason_for_call, LPVOID lpReserved)
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}

#pragma region 函数实现
bool PTZ_InitCam(PTZCam* cam, int cameraIndex) {
	if (!cam) {
		std::cout << "PTZ_InitCam: cam is null" << std::endl;
		return false;
	}

	if (cameraIndex < 0) {
		std::cout << "PTZ_InitCam: cameraIndex " << cameraIndex << " invalid" << std::endl;
		return false;
	}

	// HRESULT 是 Windows API 的返回值类型用来表示 成功 / 失败
	// CoInitializeEx 是扩展版的 COM 初始化函数,COM 是 Component Object Model
	HRESULT hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
	if (SUCCEEDED(hr)) {
		cam->comInitialized = true; // 是我们初始化的,释放时我们来卸载
	}
	else if (hr == RPC_E_CHANGED_MODE || hr == S_FALSE) {
		// COM 已经被初始化了(Unity 已经初始化了),不用我们管
		cam->comInitialized = false;
	}
	else {
		std::cout << "PTZ_InitCam: CoInitializeEx failed, hr=0x" << std::hex << hr << std::endl;
		return false;
	}

	ICreateDevEnum* pDevEnum = nullptr; // 创建"设备扫描器",用来扫描电脑里的摄像头
	hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER, IID_ICreateDevEnum,
		(void**)&pDevEnum);

	if (FAILED(hr))
	{
		std::cout << "PTZ_InitCam: CoCreateInstance failed, hr=0x" << std::hex << hr << std::endl;
		if (cam->comInitialized) CoUninitialize();
		return false;
	}

	IEnumMoniker* pEnum = nullptr;
	// 把扫描到的相机列表存到 pEnum 里
	hr = pDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, &pEnum, 0);
	if (FAILED(hr) || !pEnum)
	{
		std::cout << "PTZ_InitCam: CreateClassEnumerator failed, hr=0x" << std::hex << hr << std::endl;
		pDevEnum->Release();
		if (cam->comInitialized) CoUninitialize();
		return false;
	}

	IMoniker* pMoniker = nullptr; // 设备条目指针,相机的"名字/路径/信息包"

	// Skip to the requested camera index (also skip filtered cameras)
	int currentValidIndex = 0;
	bool found = false;

	while (pEnum->Next(1, &pMoniker, NULL) == S_OK)
	{
		bool shouldSkip = false;
		IPropertyBag* pPropBag = nullptr;
		HRESULT hrName = pMoniker->BindToStorage(0, 0, IID_IPropertyBag, (void**)&pPropBag);
		if (SUCCEEDED(hrName)) {
			VARIANT var;
			VariantInit(&var);
			hrName = pPropBag->Read(L"FriendlyName", &var, 0);
			if (SUCCEEDED(hrName)) {
				if (ShouldSkipCamera(var.bstrVal)) {
					shouldSkip = true;
				}
				VariantClear(&var);
			}
			pPropBag->Release();
		}

		if (!shouldSkip) {
			if (currentValidIndex == cameraIndex) {
				found = true; // Found target camera
				break;
			}
			currentValidIndex++;
			pMoniker->Release();
			pMoniker = nullptr;
		}
		else {
			pMoniker->Release();
			pMoniker = nullptr;
		}
	}

	if (!found)
	{
		std::cout << "PTZ_InitCam: Camera index " << cameraIndex << " not found after filtering" << std::endl;
		pEnum->Release();
		pDevEnum->Release();
		if (cam->comInitialized) CoUninitialize();
		return false;
	}

	// 获取相机名称
	IPropertyBag* pPropBag = nullptr;
	hr = pMoniker->BindToStorage(0, 0, IID_IPropertyBag, (void**)&pPropBag);
	if (SUCCEEDED(hr))
	{
		VARIANT var;
		VariantInit(&var);
		hr = pPropBag->Read(L"FriendlyName", &var, 0);
		if (SUCCEEDED(hr))
		{
			// 把相机名字存到结构体里
			wcscpy_s(cam->camName, var.bstrVal);
			VariantClear(&var);
		}
		pPropBag->Release();
	}

	IBaseFilter* pFilter = nullptr; // 设备过滤器指针,相机的"驱动层接口"
	hr = pMoniker->BindToObject(NULL, NULL, IID_IBaseFilter, (void**)&pFilter);
	if (SUCCEEDED(hr))
	{
		// 向相机请求获取 PTZ 遥控器
		hr = pFilter->QueryInterface(IID_IAMCameraControl, (void**)&cam->pCamCtrl);
		if (FAILED(hr)) {
			std::cout << "PTZ_InitCam: QueryInterface IAMCameraControl failed, hr=0x" << std::hex << hr << std::endl;
		}
		pFilter->Release();
	}
	else {
		std::cout << "PTZ_InitCam: BindToObject failed, hr=0x" << std::hex << hr << std::endl;
	}
	pMoniker->Release();

	pEnum->Release();
	pDevEnum->Release();

	if (cam->pCamCtrl == nullptr) {
		std::cout << "PTZ_InitCam: pCamCtrl is null - camera does not support PTZ control" << std::endl;
	}

	return cam->pCamCtrl != nullptr;
}
void PTZ_Release(PTZCam* cam) {
	if (!cam) return;

	if (cam->pCamCtrl) {
		cam->pCamCtrl->Release();
		cam->pCamCtrl = nullptr;
	}
	// 只有我们自己初始化的 COM,才需要卸载
	if (cam->comInitialized) {
		CoUninitialize();
	}
}

bool PTZ_QueryCapabilities(PTZCam* cam) {
	if (!cam || !cam->pCamCtrl) return false;

	long stepPan, defPan, flagsPan; // 补足参数
	HRESULT hrPan = cam->pCamCtrl->GetRange(0, &cam->minPan, &cam->maxPan, &stepPan, &defPan, &flagsPan);
	if (FAILED(hrPan)) return false;
	long currValPan, currFlagsPan;
	// 获取Pan当前值 0表示Pan
	cam->pCamCtrl->Get(0, &currValPan, &currFlagsPan);
	cam->currPan = currValPan;
	cam->pCamCtrl->Set(0, cam->currPan, 1); // 0表示Pan 1表示手动控制模式

	long stepTilt, defTilt, flagsTilt;
	HRESULT hrTilt = cam->pCamCtrl->GetRange(1, &cam->minTilt, &cam->maxTilt, &stepTilt, &defTilt, &flagsTilt);
	if (FAILED(hrTilt)) return false;
	long currValTilt, currFlagsTilt;
	cam->pCamCtrl->Get(1, &currValTilt, &currFlagsTilt);
	cam->currTilt = currValTilt;
	cam->pCamCtrl->Set(1, cam->currTilt, 1);// 1表示Tilt 1表示手动控制模式

	long stepZoom, defZoom, flagsZoom;
	HRESULT hrZoom = cam->pCamCtrl->GetRange(3, &cam->minZoom, &cam->maxZoom, &stepZoom, &defZoom, &flagsZoom);
	cam->zoomSupported = SUCCEEDED(hrZoom);
	if (cam->zoomSupported)
	{
		long currValZoom, currFlagsZoom;
		cam->pCamCtrl->Get(3, &currValZoom, &currFlagsZoom);
		cam->currZoom = currValZoom;
		cam->pCamCtrl->Set(3, cam->currZoom, 1);// 3表示Zoom 1表示手动控制模式
	}

	return true;
}

bool PTZ_SetPan(PTZCam* cam, long panVal) {
	if (!cam || !cam->pCamCtrl) return false;

	if (panVal < cam->minPan) panVal = cam->minPan;
	if (panVal > cam->maxPan) panVal = cam->maxPan;
	cam->currPan = panVal;

	HRESULT hr = cam->pCamCtrl->Set(0, panVal, 1);
	return SUCCEEDED(hr);
}
bool PTZ_SetTilt(PTZCam* cam, long tiltVal) {
	if (!cam || !cam->pCamCtrl) return false;

	if (tiltVal < cam->minTilt) tiltVal = cam->minTilt;
	if (tiltVal > cam->maxTilt) tiltVal = cam->maxTilt;
	cam->currTilt = tiltVal;

	HRESULT hr = cam->pCamCtrl->Set(1, tiltVal, 1);
	return SUCCEEDED(hr);
}
bool PTZ_SetZoom(PTZCam* cam, long zoomVal) {
	if (!cam || !cam->pCamCtrl) return false;

	if (!cam->zoomSupported) return false;

	if (zoomVal < cam->minZoom) zoomVal = cam->minZoom;
	if (zoomVal > cam->maxZoom) zoomVal = cam->maxZoom;
	cam->currZoom = zoomVal;

	HRESULT hr = cam->pCamCtrl->Set(3, zoomVal, 1);
	return SUCCEEDED(hr);
}

void PTZ_PanLeft(PTZCam* cam)
{
	if (!cam || !cam->pCamCtrl) return;

	cam->currPan -= PAN_STEP;
	if (cam->currPan < cam->minPan)
		cam->currPan = cam->minPan;

	PTZ_SetPan(cam, cam->currPan);
	std::cout << "← Pan Left  (pan=" << cam->currPan << ")" << std::endl;
}
void PTZ_PanRight(PTZCam* cam)
{
	if (!cam || !cam->pCamCtrl) return;

	cam->currPan += PAN_STEP;
	if (cam->currPan > cam->maxPan)
		cam->currPan = cam->maxPan;

	PTZ_SetPan(cam, cam->currPan);
	std::cout << "→ Pan Right  (pan=" << cam->currPan << ")" << std::endl;
}
void PTZ_TiltUp(PTZCam* cam)
{
	if (!cam || !cam->pCamCtrl) return;

	cam->currTilt += TILT_STEP;
	if (cam->currTilt > cam->maxTilt)
		cam->currTilt = cam->maxTilt;

	PTZ_SetTilt(cam, cam->currTilt);
	std::cout << "↑ Tilt Up   (tilt=" << cam->currTilt << ")" << std::endl;
}
void PTZ_TiltDown(PTZCam* cam)
{
	if (!cam || !cam->pCamCtrl) return;

	cam->currTilt -= TILT_STEP;
	if (cam->currTilt < cam->minTilt)
		cam->currTilt = cam->minTilt;
	if (cam->currTilt < TILT_DOWN_LIMIT) // 限制向下
		cam->currTilt = TILT_DOWN_LIMIT;

	PTZ_SetTilt(cam, cam->currTilt);
	std::cout << "↓ Tilt Down   (tilt=" << cam->currTilt << ")" << std::endl;
}
void PTZ_ZoomIn(PTZCam* cam)
{
	if (!cam || !cam->pCamCtrl || !cam->zoomSupported) return;

	cam->currZoom += ZOOM_STEP;
	if (cam->currZoom > cam->maxZoom)
		cam->currZoom = cam->maxZoom;

	PTZ_SetZoom(cam, cam->currZoom);
	std::cout << "+ Zoom In  (zoom=" << cam->currZoom << ")" << std::endl;
}

void PTZ_ZoomOut(PTZCam* cam)
{
	if (!cam || !cam->pCamCtrl || !cam->zoomSupported) return;

	cam->currZoom -= ZOOM_STEP;
	if (cam->currZoom < cam->minZoom)
		cam->currZoom = cam->minZoom;

	PTZ_SetZoom(cam, cam->currZoom);
	std::cout << "- Zoom Out  (zoom=" << cam->currZoom << ")" << std::endl;
}
#pragma endregion

#pragma region DLL 导出接口实现
extern "C" void* PTZ_Create() {
	return new PTZCam();
}

extern "C" void PTZ_Destroy(void* handle) {
	if (handle) {
		delete (PTZCam*)handle;
	}
}

extern "C" int PTZ_GetCameraCount() {
	// Count how many video input devices are there (filtered)
	HRESULT hr;
	ICreateDevEnum* pDevEnum = nullptr;
	hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER, IID_ICreateDevEnum, (void**)&pDevEnum);
	if (FAILED(hr)) return 0;

	IEnumMoniker* pEnum = nullptr;
	hr = pDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, &pEnum, 0);
	if (FAILED(hr) || !pEnum) {
		pDevEnum->Release();
		return 0;
	}

	int count = 0;
	IMoniker* pMoniker = nullptr;
	while (pEnum->Next(1, &pMoniker, NULL) == S_OK) {
		bool shouldSkip = false;
		IPropertyBag* pPropBag = nullptr;
		hr = pMoniker->BindToStorage(0, 0, IID_IPropertyBag, (void**)&pPropBag);
		if (SUCCEEDED(hr)) {
			VARIANT var;
			VariantInit(&var);
			hr = pPropBag->Read(L"FriendlyName", &var, 0);
			if (SUCCEEDED(hr)) {
				if (ShouldSkipCamera(var.bstrVal)) {
					shouldSkip = true;
				}
				VariantClear(&var);
			}
			pPropBag->Release();
		}
		if (!shouldSkip) {
			count++;
		}
		pMoniker->Release();
	}

	pEnum->Release();
	pDevEnum->Release();
	return count;
}

// -----------------------------------------------------------------------------
// 获取指定索引相机的设备名称 (skips filtered cameras)
// 参数: cameraIndex - 相机索引,从 0 开始
// 返回: 宽字符串指针,C# 用 Marshal.PtrToStringUni() 转成 string
//         失败返回空字符串
// -----------------------------------------------------------------------------
extern "C" const wchar_t* PTZ_GetCameraName(int cameraIndex) {
	// 参数有效性检查
	if (cameraIndex < 0) return L"";

	// 静态缓冲区存储结果,生命周期由DLL维护
	// 单次调用足够存放相机名称,多线程不影响(Unity主线程调用)
	static wchar_t nameBuffer[256];
	nameBuffer[0] = 0;

	HRESULT hr;
	ICreateDevEnum* pDevEnum = nullptr;

	// 创建设备枚举器
	hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER,
		IID_ICreateDevEnum, (void**)&pDevEnum);
	if (FAILED(hr)) return L"";

	IEnumMoniker* pEnum = nullptr;
	// 枚举视频输入设备类别(摄像头)
	hr = pDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, &pEnum, 0);
	if (FAILED(hr) || !pEnum) {
		pDevEnum->Release();
		return L"";
	}

	IMoniker* pMoniker = nullptr;
	bool found = false;
	int currentValidIndex = 0;

	// 遍历所有设备,跳过被过滤的,直到找到目标索引
	while (pEnum->Next(1, &pMoniker, NULL) == S_OK) {
		bool shouldSkip = false;
		IPropertyBag* pPropBag = nullptr;
		hr = pMoniker->BindToStorage(0, 0, IID_IPropertyBag, (void**)&pPropBag);
		if (SUCCEEDED(hr)) {
			VARIANT var;
			VariantInit(&var);
			hr = pPropBag->Read(L"FriendlyName", &var, 0);
			if (SUCCEEDED(hr)) {
				if (ShouldSkipCamera(var.bstrVal)) {
					shouldSkip = true;
				}
				else {
					// Not skipped, check if this is our target
					if (currentValidIndex == cameraIndex) {
						// Found it!
						wcsncpy_s(nameBuffer, 256, var.bstrVal, _TRUNCATE);
						found = true;
					}
					currentValidIndex++;
				}
				VariantClear(&var);
			}
			pPropBag->Release();
		}
		if (!found) {
			pMoniker->Release();
		}
		if (found) break;
	}

	// 释放COM资源
	if (!found && pMoniker) {
		pMoniker->Release();
	}
	pEnum->Release();
	pDevEnum->Release();

	return nameBuffer;
}

extern "C" bool PTZ_InitByIndex(void* handle, int cameraIndex) {
	return PTZ_InitCam((PTZCam*)handle, cameraIndex);
}

extern "C" bool PTZ_Init(void* handle) {
	return PTZ_InitCam((PTZCam*)handle, 0); // Legacy: init first camera (index 0)
}

extern "C" void PTZ_Release(void* handle) {
	PTZ_Release((PTZCam*)handle);
}

extern "C" bool PTZ_QueryCapabilities(void* handle) {
	return PTZ_QueryCapabilities((PTZCam*)handle);
}

extern "C" bool PTZ_SetPan(void* handle, long panVal) {
	return PTZ_SetPan((PTZCam*)handle, panVal);
}

extern "C" bool PTZ_SetTilt(void* handle, long tiltVal) {
	return PTZ_SetTilt((PTZCam*)handle, tiltVal);
}

extern "C" bool PTZ_SetZoom(void* handle, long zoomVal) {
	return PTZ_SetZoom((PTZCam*)handle, zoomVal);
}

extern "C" void PTZ_PanLeft(void* handle) {
	PTZ_PanLeft((PTZCam*)handle);
}

extern "C" void PTZ_PanRight(void* handle) {
	PTZ_PanRight((PTZCam*)handle);
}

extern "C" void PTZ_TiltUp(void* handle) {
	PTZ_TiltUp((PTZCam*)handle);
}

extern "C" void PTZ_TiltDown(void* handle) {
	PTZ_TiltDown((PTZCam*)handle);
}

extern "C" void PTZ_ZoomIn(void* handle) {
	PTZ_ZoomIn((PTZCam*)handle);
}

extern "C" void PTZ_ZoomOut(void* handle) {
	PTZ_ZoomOut((PTZCam*)handle);
}

extern "C" long PTZ_GetMinPan(void* handle) {
	return ((PTZCam*)handle)->minPan;
}

extern "C" long PTZ_GetMaxPan(void* handle) {
	return ((PTZCam*)handle)->maxPan;
}

extern "C" long PTZ_GetCurrentPan(void* handle) {
	return ((PTZCam*)handle)->currPan;
}

extern "C" long PTZ_GetMinTilt(void* handle) {
	return ((PTZCam*)handle)->minTilt;
}

extern "C" long PTZ_GetMaxTilt(void* handle) {
	return ((PTZCam*)handle)->maxTilt;
}

extern "C" long PTZ_GetCurrentTilt(void* handle) {
	return ((PTZCam*)handle)->currTilt;
}

extern "C" long PTZ_GetMinZoom(void* handle) {
	return ((PTZCam*)handle)->minZoom;
}

extern "C" long PTZ_GetMaxZoom(void* handle) {
	return ((PTZCam*)handle)->maxZoom;
}

extern "C" long PTZ_GetCurrentZoom(void* handle) {
	return ((PTZCam*)handle)->currZoom;
}

extern "C" bool PTZ_IsZoomSupported(void* handle) {
	return ((PTZCam*)handle)->zoomSupported;
}
#pragma endregion


//int main() {
//	PTZCam cam;
//
//	if (!PTZ_InitCam(&cam))
//	{
//		std::cout << "Camera init failed!" << std::endl;
//		system("pause");
//		PTZ_Release(&cam);
//		return 1;
//	}
//
//	std::cout << "Camera initialized!" << std::endl;
//	std::wcout << L"Camera Name: " << cam.camName << std::endl << std::endl; // 输出名字
//
//	if (!PTZ_QueryCapabilities(&cam))
//	{
//		std::cout << "ERROR: Failed to get camera capabilities!" << std::endl;
//		system("pause");
//		PTZ_Release(&cam);
//		return 1;
//	}
//
//	// Print capabilities
//	std::cout << "Pan:  range=" << cam.minPan << " ~ " << cam.maxPan << ", current=" << cam.currPan << ", step=" << PAN_STEP << std::endl;
//	std::cout << "Tilt: range=" << cam.minTilt << " ~ " << cam.maxTilt << ", current=" << cam.currTilt << ", step=" << TILT_STEP << std::endl;
//	std::cout << "Tilt down safety limit: " << TILT_DOWN_LIMIT << std::endl;
//	if (cam.zoomSupported)
//	{
//		std::cout << "zoomSupported = true" << std::endl;
//		std::cout << "Zoom: range=" << cam.minZoom << " ~ " << cam.maxZoom << ", current=" << cam.currZoom << ", step=" << ZOOM_STEP << std::endl;
//	}
//	else
//	{
//		std::cout << "WARNING: Zoom not supported by this camera!" << std::endl;
//	}
//	std::cout << std::endl;
//
//	// Print control instructions
//	std::cout << "========== Control Instructions ==========" << std::endl;
//	std::cout << "  W  - Tilt Up" << std::endl;
//	std::cout << "  S  - Tilt Down" << std::endl;
//	std::cout << "  A  - Pan Left" << std::endl;
//	std::cout << "  D  - Pan Right" << std::endl;
//	std::cout << "  Q  - Zoom Out (Wide)" << std::endl;
//	std::cout << "  E  - Zoom In  (Tele)" << std::endl;
//	std::cout << " ESC - Exit" << std::endl << std::endl;
//	std::cout << "Ready..." << std::endl;
//
//	bool running = true; // 是否正在运行
//	while (running)
//	{
//		if (GetAsyncKeyState(VK_ESCAPE) & 0x8000) // 检测【ESC键】是否被按下
//		{
//			running = false;
//		}
//		else if (GetAsyncKeyState('A') & 0x8000)
//		{
//			PTZ_PanLeft(&cam);
//			Sleep(100); // Debounce
//		}
//		else if (GetAsyncKeyState('D') & 0x8000)
//		{
//			PTZ_PanRight(&cam);
//			Sleep(100); // Debounce
//		}
//		else if (GetAsyncKeyState('W') & 0x8000)
//		{
//			PTZ_TiltUp(&cam);
//			Sleep(100); // Debounce
//		}
//		else if (GetAsyncKeyState('S') & 0x8000)
//		{
//			PTZ_TiltDown(&cam);
//			Sleep(100); // Debounce
//		}
//		else if (GetAsyncKeyState('Q') & 0x8000)
//		{
//			PTZ_ZoomOut(&cam);
//			Sleep(100); // Debounce
//		}
//		else if (GetAsyncKeyState('E') & 0x8000)
//		{
//			PTZ_ZoomIn(&cam);
//			Sleep(100); // Debounce
//		}
//
//		Sleep(10);
//	}
//
//	PTZ_Release(&cam);
//
//	return 0;
//}
相关推荐
csbysj20203 小时前
XQuery 添加元素和属性
开发语言
梦游钓鱼3 小时前
c++中单例模式(局部静态变量)
开发语言·c++·单例模式
Smomo^O^3 小时前
基于FreeMarker模板引擎生成Word并导出PDF
java·开发语言
cch89183 小时前
Java vs C语言:编程语言终极对决
java·c语言·开发语言
会编程的土豆3 小时前
【数据结构与算法】堆排序底层原理
数据结构·c++·算法
一只小小的土拨鼠3 小时前
【避坑指南】Qt + MSVC + CUDA 项目链接与发布报错全记录
开发语言·qt
List<String> error_P3 小时前
蓝桥杯3.8模拟赛2-5题
java·开发语言·python
报错小能手3 小时前
ios开发方向——swift并发进阶核心 @MainActor 与 DispatchQueue.main 解析
开发语言·ios·swift
tankeven3 小时前
HJ170 01序列
c++·算法