From 53f71bb720735595bc29e4ba9ca06f4c5b72773e Mon Sep 17 00:00:00 2001 From: linbo <1034003879@qq.com> Date: Wed, 22 Jul 2026 15:58:40 +0800 Subject: [PATCH] update hikvision camera --- cmvr-es/config/devices/camera/camera.pb.txt | 4 +- cmvr-es/config/manager/device_manager.pb.txt | 4 +- .../include/hikvision_camera.h | 18 ++- .../hikvision_camera/src/hikvision_camera.cpp | 147 +++++++++++------- 4 files changed, 113 insertions(+), 60 deletions(-) diff --git a/cmvr-es/config/devices/camera/camera.pb.txt b/cmvr-es/config/devices/camera/camera.pb.txt index 7aa3d520..54efedd6 100644 --- a/cmvr-es/config/devices/camera/camera.pb.txt +++ b/cmvr-es/config/devices/camera/camera.pb.txt @@ -82,7 +82,7 @@ camera { cameras { id: "hikvision_cam" hikvision { - ip: "192.168.1.64" + ip: "192.168.192.64" port: 8000 username: "admin" password: "okwy1688" @@ -101,7 +101,7 @@ camera { cameras { id: "hikvision_thermal_cam" hikvision { - ip: "192.168.1.65" + ip: "192.168.192.65" port: 8000 username: "admin" password: "okwy1688" diff --git a/cmvr-es/config/manager/device_manager.pb.txt b/cmvr-es/config/manager/device_manager.pb.txt index 37fe6e62..02bcd4db 100644 --- a/cmvr-es/config/manager/device_manager.pb.txt +++ b/cmvr-es/config/manager/device_manager.pb.txt @@ -70,13 +70,13 @@ device_manager { id: "hikvision_cam" type: DEVICE_TYPE_CAMERA config_file: "devices/camera/camera.pb.txt" - enable: false + enable: true } devices { id: "hikvision_thermal_cam" type: DEVICE_TYPE_CAMERA config_file: "devices/camera/camera.pb.txt" - enable: false + enable: true } devices { diff --git a/cmvr-es/devices/camera/hikvision_camera/include/hikvision_camera.h b/cmvr-es/devices/camera/hikvision_camera/include/hikvision_camera.h index 345ef850..0a2dec95 100644 --- a/cmvr-es/devices/camera/hikvision_camera/include/hikvision_camera.h +++ b/cmvr-es/devices/camera/hikvision_camera/include/hikvision_camera.h @@ -4,6 +4,8 @@ #include #include #include +#include +#include #include "common/base/ring_buffer.h" #include "devices/camera/abstract_camera.h" @@ -33,7 +35,11 @@ public: bool startStreaming() override; void stopStreaming() override; - void onStandardData(long real_handle, unsigned int data_type, unsigned char* buffer, unsigned int buffer_size); + void onEsData(unsigned int packet_type, + unsigned char* buffer, + unsigned int buffer_size, + unsigned int width, + unsigned int height); private: bool initSdk_(); @@ -45,7 +51,12 @@ private: void fillIntrinsics_(Rs2Intrinsics& intrinsics) const; void setError_(const std::string& message); std::string sdkError_(const std::string& action) const; - bool isKeyFrame_(const unsigned char* buffer, unsigned int buffer_size) const; + void pushEncodedFrame_(const unsigned char* buffer, + unsigned int buffer_size, + bool is_key_frame, + unsigned int width, + unsigned int height); + void resetStreamState_(); config::HikvisionCameraConfig camera_; std::string ip_; @@ -71,6 +82,9 @@ private: std::string current_video_path_; mutable std::mutex ctrl_mtx_; + std::mutex stream_mtx_; + std::vector es_stream_header_; + bool has_es_stream_header_ = false; int stream_count_ = 0; }; diff --git a/cmvr-es/devices/camera/hikvision_camera/src/hikvision_camera.cpp b/cmvr-es/devices/camera/hikvision_camera/src/hikvision_camera.cpp index 3849fd4d..6129a2c6 100644 --- a/cmvr-es/devices/camera/hikvision_camera/src/hikvision_camera.cpp +++ b/cmvr-es/devices/camera/hikvision_camera/src/hikvision_camera.cpp @@ -1,9 +1,13 @@ #include "../include/hikvision_camera.h" +#include +#include #include #include #include #include +#include +#include #if defined(__linux__) #include @@ -17,6 +21,13 @@ namespace { std::mutex g_sdk_mutex; int g_sdk_ref_count = 0; bool g_sdk_initialized = false; +std::atomic g_ignored_data_type_log_count{0}; +std::atomic g_es_video_log_count{0}; + +constexpr DWORD kHikvisionPacketFileHeader = 0; +constexpr DWORD kHikvisionPacketVideoIFrame = 1; +constexpr DWORD kHikvisionPacketVideoBFrame = 2; +constexpr DWORD kHikvisionPacketVideoPFrame = 3; std::string normalizeSdkPath(std::string path) { @@ -53,14 +64,18 @@ void copyCString(char* dest, size_t dest_size, const std::string& source) std::snprintf(dest, dest_size, "%s", source.c_str()); } -void CALLBACK hikvisionStandardDataCallback( - LONG real_handle, DWORD data_type, BYTE* buffer, DWORD buffer_size, void* user) +void CALLBACK hikvisionEsRealPlayCallback( + LONG, NET_DVR_PACKET_INFO_EX* packet_info, void* user) { auto* camera = static_cast(user); - if (!camera) { + if (!camera || !packet_info) { return; } - camera->onStandardData(real_handle, data_type, buffer, buffer_size); + camera->onEsData(packet_info->dwPacketType, + packet_info->pPacketBuffer, + packet_info->dwPacketSize, + packet_info->wWidth, + packet_info->wHeight); } } // namespace @@ -117,6 +132,7 @@ bool HikvisionCamera::init() stream_frame_buffer_ = std::make_shared>(buffer_size_); stream_frame_buffer_->clear(); + resetStreamState_(); if (!initSdk_()) { return false; @@ -167,6 +183,7 @@ bool HikvisionCamera::stop() } state_.is_streaming = false; stream_count_ = 0; + resetStreamState_(); stopPreview_(); if (user_id_ >= 0) { NET_DVR_Logout(user_id_); @@ -258,13 +275,7 @@ void HikvisionCamera::resumeRecording() void HikvisionCamera::getEncodedFrame(StreamFrameData& frame_data, size_t& index) { - if (!stream_frame_buffer_) { - return; - } - auto frame = stream_frame_buffer_->pop(index); - if (frame.has_value()) { - frame_data = frame.value(); - } + getLatestEncodedFrame(frame_data, index); } bool HikvisionCamera::getLatestEncodedFrame(StreamFrameData& frame_data, size_t& next_index) @@ -299,6 +310,10 @@ bool HikvisionCamera::startStreaming() return false; } + if (stream_count_ == 0 && stream_frame_buffer_) { + stream_frame_buffer_->clear(); + } + state_.is_streaming = true; ++stream_count_; return true; @@ -315,28 +330,86 @@ void HikvisionCamera::stopStreaming() } } -void HikvisionCamera::onStandardData( - long, unsigned int data_type, unsigned char* buffer, unsigned int buffer_size) +void HikvisionCamera::onEsData( + unsigned int packet_type, + unsigned char* buffer, + unsigned int buffer_size, + unsigned int packet_width, + unsigned int packet_height) { - if (data_type != NET_DVR_STD_VIDEODATA || !buffer || buffer_size == 0) { + if (!buffer || buffer_size == 0) { return; } + if (packet_type == kHikvisionPacketFileHeader) { + std::lock_guard lock(stream_mtx_); + if (!has_es_stream_header_) { + es_stream_header_.assign(buffer, buffer + buffer_size); + has_es_stream_header_ = true; + CMVR_LOG(INFO) << "[HikvisionCamera] received ES stream header, size=" << buffer_size; + } + return; + } + + const bool is_video_packet = + packet_type == kHikvisionPacketVideoIFrame || + packet_type == kHikvisionPacketVideoBFrame || + packet_type == kHikvisionPacketVideoPFrame; + if (!is_video_packet) { + const int log_count = g_ignored_data_type_log_count.fetch_add(1); + if (log_count < 10) { + CMVR_LOG(INFO) << "[HikvisionCamera] ignore ES packet_type=" + << packet_type << ", size=" << buffer_size; + } + return; + } + + const int video_log_count = g_es_video_log_count.fetch_add(1); + if (video_log_count < 10) { + CMVR_LOG(INFO) << "[HikvisionCamera] ES video packet_type=" + << packet_type << ", size=" << buffer_size; + } + if (!state_.is_streaming || !stream_frame_buffer_) { return; } + pushEncodedFrame_(buffer, + buffer_size, + packet_type == kHikvisionPacketVideoIFrame, + packet_width, + packet_height); +} + +void HikvisionCamera::pushEncodedFrame_( + const unsigned char* buffer, + unsigned int buffer_size, + bool is_key_frame, + unsigned int packet_width, + unsigned int packet_height) +{ + if (!buffer || buffer_size == 0 || !stream_frame_buffer_) { + return; + } + StreamFrameData frame_data; frame_data.rgbFrame.assign(buffer, buffer + buffer_size); frame_data.codec = codec_; frame_data.fps = fps_; - frame_data.width = width_; - frame_data.height = height_; - frame_data.bKey = isKeyFrame_(buffer, buffer_size); + frame_data.width = packet_width > 0 ? static_cast(packet_width) : width_; + frame_data.height = packet_height > 0 ? static_cast(packet_height) : height_; + frame_data.bKey = is_key_frame; fillIntrinsics_(frame_data.intrinsics); stream_frame_buffer_->push(frame_data); } +void HikvisionCamera::resetStreamState_() +{ + std::lock_guard lock(stream_mtx_); + es_stream_header_.clear(); + has_es_stream_header_ = false; +} + bool HikvisionCamera::initSdk_() { if (sdk_acquired_) { @@ -403,7 +476,7 @@ bool HikvisionCamera::startPreview_() preview_info.dwStreamType = static_cast(stream_type_); preview_info.dwLinkMode = static_cast(link_mode_); preview_info.hPlayWnd = 0; - preview_info.bBlocked = 0; + preview_info.bBlocked = 1; preview_info.dwDisplayBufNum = 1; preview_info.byReconnect = 1; @@ -412,9 +485,8 @@ bool HikvisionCamera::startPreview_() setError_(sdkError_("NET_DVR_RealPlay_V40")); return false; } - if (!NET_DVR_SetStandardDataCallBackEx( - real_handle_, hikvisionStandardDataCallback, this)) { - setError_(sdkError_("NET_DVR_SetStandardDataCallBackEx")); + if (!NET_DVR_SetESRealPlayCallBack(real_handle_, hikvisionEsRealPlayCallback, this)) { + setError_(sdkError_("NET_DVR_SetESRealPlayCallBack")); NET_DVR_StopRealPlay(real_handle_); real_handle_ = -1; return false; @@ -453,37 +525,4 @@ std::string HikvisionCamera::sdkError_(const std::string& action) const return action + " failed, error_code=" + std::to_string(NET_DVR_GetLastError()); } -bool HikvisionCamera::isKeyFrame_(const unsigned char* buffer, unsigned int buffer_size) const -{ - if (!buffer || buffer_size < 5) { - return false; - } - - for (unsigned int i = 0; i + 5 < buffer_size; ++i) { - unsigned int offset = 0; - if (buffer[i] == 0 && buffer[i + 1] == 0 && buffer[i + 2] == 1) { - offset = i + 3; - } else if (i + 4 < buffer_size && buffer[i] == 0 && buffer[i + 1] == 0 && - buffer[i + 2] == 0 && buffer[i + 3] == 1) { - offset = i + 4; - } else { - continue; - } - - const unsigned char nal = buffer[offset]; - if (codec_ == "H265" || codec_ == "h265" || codec_ == "HEVC" || codec_ == "hevc") { - const unsigned char nal_type = (nal >> 1) & 0x3f; - if (nal_type == 19 || nal_type == 20 || nal_type == 32) { - return true; - } - } else { - const unsigned char nal_type = nal & 0x1f; - if (nal_type == 5 || nal_type == 7) { - return true; - } - } - } - return false; -} - } // namespace cmvr::device