162 lines
4.5 KiB
C++
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#ifndef HIKDEVICE_H
#define HIKDEVICE_H
// 先包含标准库头文件
#include <mutex>
#include <atomic>
#include <vector>
#include <functional>
#include <string>
#include <map>
// 禁用Windows的min/max宏
#ifdef _WIN32
#ifndef NOMINMAX
#define NOMINMAX
#endif
#endif
#include "IHikDevice.h"
// 海康SDK头文件
#ifdef _WIN32
#include "HCNetSDK.h"
#include "plaympeg4.h"
#else
#include "HCNetSDK.h"
#include "LinuxPlayM4.h"
#endif
/**
* @brief 海康相机设备实现类
*
* 封装海康威视HCNetSDK和PlayM4解码库
*/
class CHikDevice : public IHikDevice
{
public:
CHikDevice();
~CHikDevice() override;
// ============ IHikDevice 接口实现 ============
int InitSDK() override;
void CleanupSDK() override;
int Login(const HikDeviceConfig& config) override;
void Logout() override;
bool IsLoggedIn() const override;
int StartPreview() override;
int StartPreviewEx(void* hWnd) override;
void StopPreview() override;
bool IsPreviewing() const override;
EHikDeviceStatus GetStatus() const override;
void SetDecodedFrameCallback(HikDecodedFrameCallback callback, void* pUser) override;
void SetStatusCallback(HikDeviceStatusCallback callback, void* pUser) override;
void SetExceptionCallback(HikExceptionCallback callback, void* pUser) override;
int GetCurrentFrame(unsigned char* pBuffer, int bufferSize, HikFrameInfo& frameInfo) override;
const HikDeviceConfig& GetConfig() const override;
int CaptureToFile(const std::string& filePath, bool isJpeg = true) override;
int PTZControl(int command, bool stop, int speed = 4) override;
int ConfigureOSD(bool showChanName, bool showOsd) override;
private:
// ============ 内部回调函数 ============
/**
* @brief 海康实时数据回调(静态)
*/
static void CALLBACK HikRealDataCallback(LONG lRealHandle, DWORD dwDataType,
BYTE* pBuffer, DWORD dwBufSize, void* pUser);
/**
* @brief PlayM4 解码回调(静态)
* 注意Windows和Linux/ARM的回调签名不同
*/
#ifdef _WIN32
static void CALLBACK PlayM4DecodeCallback(long nPort, char* pBuf, long nSize,
FRAME_INFO* pFrameInfo, long nUser, long nReserved2);
#else
static void CALLBACK PlayM4DecodeCallback(int nPort, char* pBuf, int nSize,
FRAME_INFO* pFrameInfo, void* nUser, int nReserved2);
#endif
/**
* @brief 海康异常回调(静态)
*/
static void CALLBACK HikSDKExceptionCallback(DWORD dwType, LONG lUserID, LONG lHandle, void* pUser);
// ============ 内部方法 ============
/**
* @brief 处理解码后的视频帧
*/
void ProcessDecodedFrame(char* pBuf, long nSize, FRAME_INFO* pFrameInfo);
/**
* @brief 处理异常
*/
void HandleException(DWORD dwType);
/**
* @brief 更新设备状态
*/
void UpdateStatus(EHikDeviceStatus status);
/**
* @brief YV12转RGB32
*/
void ConvertYV12ToRGB32(const unsigned char* yPlane, const unsigned char* uPlane,
const unsigned char* vPlane, unsigned char* rgbData,
int width, int height);
private:
// SDK 初始化状态
std::atomic<bool> m_bSDKInitialized{false};
// 登录相关
LONG m_lUserID = -1;
HikDeviceConfig m_config;
// 预览相关
LONG m_lRealPlayHandle = -1;
std::atomic<bool> m_bPreviewing{false};
// PlayM4 解码相关
LONG m_lPlayM4Port = -1;
std::atomic<bool> m_bPlayM4Playing{false};
// 设备状态
std::atomic<EHikDeviceStatus> m_status{EHikDeviceStatus::Disconnected};
// 当前帧数据
mutable std::mutex m_frameMutex;
std::vector<unsigned char> m_currentFrameData;
HikFrameInfo m_currentFrameInfo;
// 回调函数
HikDecodedFrameCallback m_frameCallback = nullptr;
void* m_pFrameCallbackUser = nullptr;
HikDeviceStatusCallback m_statusCallback = nullptr;
void* m_pStatusCallbackUser = nullptr;
HikExceptionCallback m_exceptionCallback = nullptr;
void* m_pExceptionCallbackUser = nullptr;
// 错误码
mutable int m_lastError = 0;
// 静态成员端口到实例的映射解决64位系统回调指针截断问题
static std::map<long, CHikDevice*> s_portDeviceMap;
static std::mutex s_mapMutex;
};
#endif // HIKDEVICE_H