1.初始化相机
cpp
复制代码
#include<Windows.h>
#include<dshow.h> // DirectShow 头文件
#include<iostream>
#pragma comment(lib, "strmiids.lib") // 链接 DirectShow 系统库
struct PTZCam {
IAMCameraControl* pCamCtrl; // IAMCameraControl 是 Windows 系统提供的相机控制接口
PTZCam():
pCamCtrl(nullptr) {}
};
#pragma region 函数声明
bool PTZ_InitCam(PTZCam* cam); // 初始化相机
void PTZ_Release(PTZCam* cam); // 释放相机资源
#pragma endregion
#pragma region 函数实现
bool PTZ_InitCam(PTZCam* cam) {
if (!cam) return false;
// HRESULT 是 Windows API 的返回值类型用来表示 成功 / 失败
// CoInitializeEx 是扩展版的 COM 初始化函数,COM 是 Component Object Model
HRESULT hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
if (FAILED(hr)) return false;
ICreateDevEnum* pDevEnum = nullptr; // 创建"设备扫描器",用来扫描电脑里的摄像头
hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER, IID_ICreateDevEnum,
(void**)&pDevEnum);
if (FAILED(hr))
{
CoUninitialize();
return false;
}
IEnumMoniker* pEnum = nullptr;
// 把扫描到的相机列表存到 pEnum 里
hr = pDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, &pEnum, 0);
if (FAILED(hr) || !pEnum)
{
pDevEnum->Release();
CoUninitialize();
return false;
}
IMoniker* pMoniker = nullptr; // 设备条目指针,相机的"名字/路径/信息包"
if (pEnum->Next(1, &pMoniker, NULL) == S_OK) // 从相机列表里取出第1个相机
{
IBaseFilter* pFilter = nullptr; // 设备过滤器指针,相机的"驱动层接口"
hr = pMoniker->BindToObject(NULL, NULL, IID_IBaseFilter, (void**)&pFilter);
if (SUCCEEDED(hr))
{
// 向相机请求获取 PTZ 遥控器
hr = pFilter->QueryInterface(IID_IAMCameraControl, (void**)&cam->pCamCtrl);
pFilter->Release();
}
pMoniker->Release();
}
pEnum->Release();
pDevEnum->Release();
return cam->pCamCtrl != nullptr;
}
void PTZ_Release(PTZCam* cam) {
if (!cam) return;
if (cam->pCamCtrl) {
cam->pCamCtrl->Release();
cam->pCamCtrl = nullptr;
}
CoUninitialize();
}
#pragma endregion
int main(){
PTZCam cam;
if (!PTZ_InitCam(&cam))
{
std::cout << "Camera init failed!" << std::endl;
system("pause");
PTZ_Release(&cam);
return 1;
}
bool running = true; // 是否正在运行
while (running)
{
}
return 0;
}
2.获取硬件信息并打印
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;
struct PTZCam {
IAMCameraControl* pCamCtrl; // IAMCameraControl 是 Windows 系统提供的相机控制接口
wchar_t camName[256];
long minPan;
long maxPan;
long currPan;
long minTilt;
long maxTilt;
long currTilt;
long minZoom;
long maxZoom;
long currZoom;
bool zoomSupported;
PTZCam():
pCamCtrl(nullptr),
minPan(0),
maxPan(0),
currPan(0),
minTilt(0),
maxTilt(0),
currTilt(0),
minZoom(0),
maxZoom(0),
currZoom(0),
zoomSupported(false)
{
camName[0] = 0;
}
};
#pragma region 函数声明
bool PTZ_InitCam(PTZCam* cam); // 初始化相机
void PTZ_Release(PTZCam* cam); // 释放相机资源
bool PTZ_QueryCapabilities(PTZCam* cam); // 获取硬件信息
#pragma endregion
#pragma region 函数实现
bool PTZ_InitCam(PTZCam* cam) {
if (!cam) return false;
// HRESULT 是 Windows API 的返回值类型用来表示 成功 / 失败
// CoInitializeEx 是扩展版的 COM 初始化函数,COM 是 Component Object Model
HRESULT hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
if (FAILED(hr)) return false;
ICreateDevEnum* pDevEnum = nullptr; // 创建"设备扫描器",用来扫描电脑里的摄像头
hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER, IID_ICreateDevEnum,
(void**)&pDevEnum);
if (FAILED(hr))
{
CoUninitialize();
return false;
}
IEnumMoniker* pEnum = nullptr;
// 把扫描到的相机列表存到 pEnum 里
hr = pDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, &pEnum, 0);
if (FAILED(hr) || !pEnum)
{
pDevEnum->Release();
CoUninitialize();
return false;
}
IMoniker* pMoniker = nullptr; // 设备条目指针,相机的"名字/路径/信息包"
if (pEnum->Next(1, &pMoniker, NULL) == S_OK) // 从相机列表里取出第1个相机
{
// 获取相机名称
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);
pFilter->Release();
}
pMoniker->Release();
}
pEnum->Release();
pDevEnum->Release();
return cam->pCamCtrl != nullptr;
}
void PTZ_Release(PTZCam* cam) {
if (!cam) return;
if (cam->pCamCtrl) {
cam->pCamCtrl->Release();
cam->pCamCtrl = nullptr;
}
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;
}
#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)
{
}
return 0;
}
3.实现PTZ对应功能函数
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;
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;
PTZCam():
pCamCtrl(nullptr),
minPan(0),
maxPan(0),
currPan(0),
minTilt(0),
maxTilt(0),
currTilt(0),
minZoom(0),
maxZoom(0),
currZoom(0),
zoomSupported(false)
{
camName[0] = 0;
}
};
#pragma region 函数声明
bool PTZ_InitCam(PTZCam* cam); // 初始化相机
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
#pragma region 函数实现
bool PTZ_InitCam(PTZCam* cam) {
if (!cam) return false;
// HRESULT 是 Windows API 的返回值类型用来表示 成功 / 失败
// CoInitializeEx 是扩展版的 COM 初始化函数,COM 是 Component Object Model
HRESULT hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
if (FAILED(hr)) return false;
ICreateDevEnum* pDevEnum = nullptr; // 创建"设备扫描器",用来扫描电脑里的摄像头
hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER, IID_ICreateDevEnum,
(void**)&pDevEnum);
if (FAILED(hr))
{
CoUninitialize();
return false;
}
IEnumMoniker* pEnum = nullptr;
// 把扫描到的相机列表存到 pEnum 里
hr = pDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, &pEnum, 0);
if (FAILED(hr) || !pEnum)
{
pDevEnum->Release();
CoUninitialize();
return false;
}
IMoniker* pMoniker = nullptr; // 设备条目指针,相机的"名字/路径/信息包"
if (pEnum->Next(1, &pMoniker, NULL) == S_OK) // 从相机列表里取出第1个相机
{
// 获取相机名称
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);
pFilter->Release();
}
pMoniker->Release();
}
pEnum->Release();
pDevEnum->Release();
return cam->pCamCtrl != nullptr;
}
void PTZ_Release(PTZCam* cam) {
if (!cam) return;
if (cam->pCamCtrl) {
cam->pCamCtrl->Release();
cam->pCamCtrl = nullptr;
}
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->minPan) tiltVal = cam->minPan;
if (tiltVal > cam->maxPan) tiltVal = cam->maxPan;
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 (zoomVal < cam->minPan) zoomVal = cam->minPan;
if (zoomVal > cam->maxPan) zoomVal = cam->maxPan;
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;
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
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)
{
}
return 0;
}
4.监听按键并执行操作
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;
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;
PTZCam():
pCamCtrl(nullptr),
minPan(0),
maxPan(0),
currPan(0),
minTilt(0),
maxTilt(0),
currTilt(0),
minZoom(0),
maxZoom(0),
currZoom(0),
zoomSupported(false)
{
camName[0] = 0;
}
};
#pragma region 函数声明
bool PTZ_InitCam(PTZCam* cam); // 初始化相机
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
#pragma region 函数实现
bool PTZ_InitCam(PTZCam* cam) {
if (!cam) return false;
// HRESULT 是 Windows API 的返回值类型用来表示 成功 / 失败
// CoInitializeEx 是扩展版的 COM 初始化函数,COM 是 Component Object Model
HRESULT hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
if (FAILED(hr)) return false;
ICreateDevEnum* pDevEnum = nullptr; // 创建"设备扫描器",用来扫描电脑里的摄像头
hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER, IID_ICreateDevEnum,
(void**)&pDevEnum);
if (FAILED(hr))
{
CoUninitialize();
return false;
}
IEnumMoniker* pEnum = nullptr;
// 把扫描到的相机列表存到 pEnum 里
hr = pDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, &pEnum, 0);
if (FAILED(hr) || !pEnum)
{
pDevEnum->Release();
CoUninitialize();
return false;
}
IMoniker* pMoniker = nullptr; // 设备条目指针,相机的"名字/路径/信息包"
if (pEnum->Next(1, &pMoniker, NULL) == S_OK) // 从相机列表里取出第1个相机
{
// 获取相机名称
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);
pFilter->Release();
}
pMoniker->Release();
}
pEnum->Release();
pDevEnum->Release();
return cam->pCamCtrl != nullptr;
}
void PTZ_Release(PTZCam* cam) {
if (!cam) return;
if (cam->pCamCtrl) {
cam->pCamCtrl->Release();
cam->pCamCtrl = nullptr;
}
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->minPan) tiltVal = cam->minPan;
if (tiltVal > cam->maxPan) tiltVal = cam->maxPan;
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 (zoomVal < cam->minPan) zoomVal = cam->minPan;
if (zoomVal > cam->maxPan) zoomVal = cam->maxPan;
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
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;
}