#ifndef HIKDEVICE_H #define HIKDEVICE_H // 先包含标准库头文件 #include #include #include #include #include #include // 禁用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 m_bSDKInitialized{false}; // 登录相关 LONG m_lUserID = -1; HikDeviceConfig m_config; // 预览相关 LONG m_lRealPlayHandle = -1; std::atomic m_bPreviewing{false}; // PlayM4 解码相关 LONG m_lPlayM4Port = -1; std::atomic m_bPlayM4Playing{false}; // 设备状态 std::atomic m_status{EHikDeviceStatus::Disconnected}; // 当前帧数据 mutable std::mutex m_frameMutex; std::vector 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 s_portDeviceMap; static std::mutex s_mapMutex; }; #endif // HIKDEVICE_H