Hikvision ISUP Client - Complete C development project
|
|
3 日 前 | |
|---|---|---|
| docs | 3 日 前 | |
| include | 3 日 前 | |
| libs | 3 日 前 | |
| scripts | 3 日 前 | |
| src | 3 日 前 | |
| tests | 3 日 前 | |
| .gitignore | 3 日 前 | |
| CHANGELOG.md | 3 日 前 | |
| Makefile | 3 日 前 | |
| README.md | 3 日 前 | |
| config.ini | 3 日 前 |
海康威视 ISUP(Ehome) 协议 C 语言客户端/平台服务端完整开发项目
本项目是一个基于海康威视 ISUP(Ehome) 协议的完整 C 语言开发框架,实现了以下核心功能:
| 组件 | 技术选型 | 说明 |
|---|---|---|
| 编程语言 | C11 | 高性能、底层控制 |
| 操作系统 | Ubuntu 24.04 LTS | 稳定服务器系统 |
| 海康SDK | HCNetSDK (ISUP/Ehome) | 设备注册/流媒体/报警 |
| 流媒体 | ZLMediaKit | RTMP/RTSP/HLS 流媒体服务器 |
| 构建系统 | Make | 简单可靠的构建工具 |
| 版本控制 | Git + Gogs | 自托管代码管理 |
┌─────────────┐ ISUP/TCP ┌──────────────────┐
│ 海康设备 │ ◄──────────────► │ ISUP Client │
│ (摄像头/NVR) │ 注册/流/报警 │ (本程序) │
└─────────────┘ └────────┬─────────┘
│ RTMP/PS流
▼
┌──────────────┐
│ ZLMediaKit │
│ (流媒体服务器) │
└──────┬───────┘
│
┌─────────────────────┼─────────────────────┐
▼ ▼ ▼
┌──────────┐ ┌──────────┐ ┌──────────┐
│ RTMP │ │ HLS │ │ RTSP │
│ 客户端 │ │ 直播 │ │ 拉流 │
└──────────┘ └──────────┘ └──────────┘
本次对完整工程逐文件做了编译级 / 内存安全级 / 逻辑级排查,共修复 9 类 问题,
并在 Ubuntu 24.04 (GCC 14) 下验证 make simulate 零 warning、零 error 通过,
./hikvision-isup-client -test 全链路自测通过、进程干净退出(后台线程全部回收)。
| 编号 | 文件 | 严重级别 | 问题 | 修复 |
|---|---|---|---|---|
| B1 | common.h | 致命(编译失败) | 大量使用 uint8_t 却未包含 <stdint.h> |
增加 #include <stdint.h> |
| B2 | main.c | 致命(编译失败) | cleanup_stream/cleanup_platform 标签重复定义;goto cleanup 指向不存在标签 |
重写为单一 teardown + 各模块 *_ok 状态位逆序清理 |
| B3 | main.c | 致命(运行崩溃) | 心跳/模拟线程创建后从不 join,退出即访问已释放资源;信号处理函数调用 fprintf/localtime 非 async-signal-safe |
线程句柄提为文件作用域并在退出时 join;信号处理仅置 volatile sig_atomic_t 标志,致命信号改回默认行为,改用 sigaction |
| B4 | Makefile | 致命(构建错乱) | BUILD_DIR 在 OBJECTS 之后定义,:= 即时展开使目标路径为空;simulate 宏 HAVE_HIKVISION_SIMULATION 与代码判断的 HAVE_HCNETSDK 不一致;声明了 test 却无规则 |
BUILD_DIR 前移;仿真分支统一宏;补齐 test 目标 |
| B5 | stream.c / playback.c | 高(内存泄漏/失联) | remove_session/remove_playback 先把目标置 NULL 再从头压缩,连带丢弃目标之后的第一个会话 |
改为逐元素搬运、命中者丢弃,不丢元素 |
| B6 | stream.c / playback.c | 高(use-after-free) | free(session) 之后仍读取 session->stream_id/playback_id 打印 |
free 前用局部变量缓存 id |
| B7 | config.h | 中 | pid_file 误声明为 int[],却当字符串使用 |
改为 char[MAX_PATH_SIZE] |
| B8 | utils.c | 中(编译/运行) | 使用 struct stat/stat/mkdir 却未包含 <sys/stat.h> |
增加头文件;补全 ensure_directory |
| B9 | platform.c/stream.c/alarm.c/playback.c | 中(编译失败,GCC14) | NET_E* SDK 函数仅在 platform.c 局部 extern,其它 .c 调用触发隐式声明错误;sleep_milliseconds 无声明 |
新增 include/isup_sdk.h 集中声明,各 .c 统一包含;utils 原型并入 common.h |
| 附带 | main.c/stream.c/playback.c | 低 | PID 写入路径与删除路径不一致(残留);add_unack_alarm/find_session/find_playback/pack_h264_to_ps 定义了却从未调用;模拟线程 fps<=0 除零 |
统一 PID 路径;新增 alarm_ingest/stream_get_session/stream_find_by_channel/playback_get_session 并接入;PS 封装在 stream_send_frame 中实际调用;fps 兜底 |
$ make simulate -> Build complete: hikvision-isup-client (0 warning / 0 error)
$ ./hikvision-isup-client -test ->
===== SELF TEST START =====
[Mock] NET_ECMS_Login ... Device registered: AX5324540
RTMP push thread started: rtmp://127.0.0.1:1935/live/camera1
Playback started/stopped/pause/resume OK
===== SELF TEST PASSED =====
Simulated image thread stopped / Heartbeat thread stopped (线程干净回收)
Hikvision ISUP Client stopped (exit code 0)
sudo apt install build-essential # 需要 GCC 14 + make
make simulate # 无 SDK 的仿真编译(内置 Mock)
make test # 编译 + 全链路自测
make # 有真实 HCNetSDK 时的正式编译(打开 Makefile 中 HCNETSDK_LIBS)
hikvision-isup-client/
├── README.md # 项目说明文档
├── Makefile # 构建配置文件
├── config.ini # 运行配置文件
├── .gitignore # Git忽略规则
├── include/ # 头文件目录
│ ├── common.h # 公共定义与常量
│ ├── config.h # 配置管理
│ ├── platform.h # 平台注册管理
│ ├── stream.h # 视频流管理
│ ├── playback.h # 录像回放管理
│ └── alarm.h # 报警管理
├── src/ # 源代码目录
│ ├── main.c # 主程序入口
│ ├── platform.c # 平台注册实现
│ ├── stream.c # 流媒体管理实现
│ ├── playback.c # 录像回放实现
│ ├── alarm.c # 报警管理实现
│ ├── config.c # 配置管理实现
│ └── utils.c # 工具函数实现
├── libs/ # 第三方库目录
├── scripts/ # 辅助脚本
│ ├── setup.sh # 环境初始化脚本
│ ├── deploy.sh # 部署脚本
│ └── git_sync.sh # Git同步脚本
├── docs/ # 文档目录
├── tests/ # 测试目录
└── logs/ # 日志目录(运行时生成)
# 运行环境初始化脚本
chmod +x scripts/setup.sh
./scripts/setup.sh
手动安装依赖:
sudo apt-get update
sudo apt-get install -y build-essential gcc g++ make cmake git pkg-config libssl-dev \
ffmpeg libavcodec-dev libavformat-dev libavutil-dev libswscale-dev valgrind cppcheck
git clone --depth 1 https://gitee.com/xia-chu/ZLMediaKit
cd ZLMediaKit
git submodule update --init
mkdir build && cd build
cmake ..
make -j4
sudo make install
从海康威视官网下载 HCNetSDK 包,将 Linux 64位版本的文件复制到 libs/ 目录:
libs/
├── libhcnetsdk.so # 主SDK库
├── libHCCommon.so # 公共库
├── libHCWindowsComm.so # 通信库
├── libPlayCtrl.so # 播放库
├── libHCNetSDK.so # 备用SDK库
└── ... # 其他依赖库
# 使用模拟模式编译(无需HCNetSDK,可用于开发和测试)
make simulate
# 默认编译(需要libs目录中有HCNetSDK库文件)
make
# 指定SDK路径
make HCNETSDK_PATH=/opt/hikvision-sdk
# 清理并重新编译
make cleanbuild
# 使用默认配置运行
./hikvision-isup-client
# 指定配置文件
./hikvision-isup-client -c config.ini
# 守护进程模式运行
./hikvision-isup-client -c config.ini -d
# 查看帮助
./hikvision-isup-client -h
# 查看版本
./hikvision-isup-client -v
# 自测模式(完整链路: 注册->推流->回放->报警->登出, 无需真实设备)
./hikvision-isup-client -test
# 一键编译并自测
make test
### 安装到系统
bash sudo make install sudo ./scripts/deploy.sh sudo systemctl enable hikvision-isup-client sudo systemctl start hikvision-isup-client
## 配置说明
### 设备端配置(海康设备Web页面)
按照以下路径配置海康设备:
系统 > 高级配置 > 网络 > 平台接入 > ISUP(原Ehome)
配置参数如下(与项目 config.ini 对应):
| 配置项 | 值 | 说明 |
|--------|-----|------|
| 平台接入方式 | ISUP(原Ehome) | 选择ISUP协议 |
| 启用 | 勾选 | 启用平台接入 |
| 服务器地址 | 117.131.63.98 | 本程序服务器IP |
| 端口 | 7031 | CMS注册端口 |
| 设备ID | AX5324540 | 设备序列号 |
| 注册状态 | 在线 | 确认注册成功 |
| 协议版本 | ISUP5.0 | 协议版本 |
| 加密密钥 | abc12345 | 加密密钥 |
### 程序配置(config.ini)
主要配置项说明:
ini
[CMS]
cms_server_ip=117.131.63.98 # CMS服务器IP(本机IP)
cms_server_port=7031 # CMS监听端口
device_id=AX5324540 # 设备ID
protocol_version=ISUP5.0 # 协议版本
encrypt_key=abc12345 # 加密密钥
[RTMP] rtmp_server=127.0.0.1 # ZLMediaKit服务器地址 rtmp_port=1935 # RTMP端口 rtmp_app_name=live # 应用名称 rtmp_stream_key=camera1 # 流名称
## 核心API说明
### 平台注册流程
c // 1. 初始化CMS库 platform_cms_init();
// 2. 启动CMS监听(接收设备注册) platform_cms_start_listen("0.0.0.0", 7031, device_register_callback, NULL);
// 3. 设备注册(主动向CMS注册) int user_id = platform_device_register("117.131.63.98", 7031,
"AX5324540", "ISUP5.0", "abc12345", NULL);
// 4. 设置自动重连 platform_set_auto_reconnect(user_id, 1, 5);
// 5. 清理 platform_cms_cleanup();
### 录像回放流程
c // 1. 初始化回放模块 playback_init();
// 2. 开启SMS回放监听 stream_start_playback_listen("0.0.0.0", 7660, NULL, NULL);
// 3. 启动回放 PlaybackSession* session = playback_start(
"AX5324540", // 设备ID
1, // 通道号
start_time, // 开始时间
end_time, // 结束时间
1, // 速度(1=正常)
playback_data_cb, // 数据回调
playback_status_cb, // 状态回调
NULL // 用户数据
);
// 4. 停止回放 playback_stop(session);
// 5. 清理 playback_cleanup();
### 报警接入流程
c // 1. 初始化报警模块 alarm_init();
// 2. 启动报警监听 alarm_start_listen("0.0.0.0", 9000,
alarm_data_callback, // 报警数据回调
alarm_process_callback, // 报警处理回调
NULL);
// 3. 清理 alarm_cleanup();
### RTMP推流流程
c // 1. 创建流会话 StreamSession* session = stream_create_session(
"AX5324540", STREAM_TYPE_MAIN, CODEC_TYPE_H264,
1920, 1080, 25, 4096000
);
// 2. 开始推流到ZLMediaKit stream_start_push(session, "rtmp://127.0.0.1:1935/live/camera1",
rtmp_push_callback, NULL);
// 3. 发送视频帧 StreamFrame frame = { .data = frame_data, .data_size = frame_size, ... }; stream_send_frame(session, &frame);
// 4. 停止推流 stream_stop_push(session);
// 5. 销毁会话 stream_destroy_session(session);
## PS流封装说明
本项目实现了H.264/H.265原始码流到MPEG-2 PS(Program Stream)的封装:
### PS流结构
| Pack Header (4-11 bytes) | | Program Stream Map | | PES Packet | | - PES Header | | - PES Payload (NALU) | | ... | | Pack Header | | ... |
### 封装流程
1. 从海康设备接收H.264/H.265原始码流
2. 检测SPS/PPS参数集,如有变化则生成PS系统头和PSMAP
3. 将NALU数据封装为PES包
4. 添加Pack Header
5. 填充到PS_PACKET_SIZE(2048字节)
6. 添加CRC校验
7. 通过RTMP推送到ZLMediaKit
### 在ZLMediaKit中接收
ZLMediaKit 支持直接接收ISUP/Ehome协议的PS流,配置方法:
ini
[rtmp] port=1935
## Git代码管理
### 初始化仓库
bash
chmod +x scripts/git_sync.sh ./scripts/git_sync.sh
### 手动配置
bash
git init git branch -M main
git remote add origin "https://steven_roc:1942ce3d6478f7a572fee3dd4891e49f6c416aad@git.zhonjin.com:40717/steven_roc/hikvision-isup-client.git"
git add -A
git commit -m "Initial commit: Hikvision ISUP Client project"
git push -u origin main
### 日常同步
bash
./scripts/git_sync.sh
git add -A git commit -m "描述本次更新内容" git push
## 日志说明
程序运行日志输出到 `logs/isup_client.log` 文件和控制台。
日志级别:
| 级别 | 说明 |
|------|------|
| DEBUG | 调试信息,详细的内部状态 |
| INFO | 一般信息,关键流程节点 |
| WARN | 警告信息,非致命问题 |
| ERROR | 错误信息,功能异常 |
| FATAL | 致命错误,程序无法继续 |
修改日志级别:编辑 `config.ini` 中的 `log_level` 参数。
## 故障排查
### 常见问题
**1. 设备注册失败**
- 检查海康设备Web页面配置是否正确(服务器地址、端口、设备ID)
- 确认防火墙允许7031端口通信
- 检查加密密钥是否一致
- 查看程序日志中的错误信息
**2. 视频流无法接收**
- 确认设备已注册上线
- 检查SMS端口(默认7660)是否可访问
- 检查HCNetSDK库文件是否正确部署
- 查看日志中的流相关错误信息
**3. RTMP推流失败**
- 确认ZLMediaKit服务正在运行
- 检查rtmp_server和rtmp_port配置
- 使用 `rtmp://server:1935/live/camera1` 测试拉流
- 查看ZLMediaKit日志
**4. 编译错误**
- 运行 `make simulate` 跳过SDK依赖进行开发
- 确认GCC版本 >= 9.0
- 检查 `libs/` 目录中的SDK库文件
### 日志关键字搜索
bash
grep -i "register|login|cms" logs/isup_client.log
grep -i "stream|rtmp|push" logs/isup_client.log
grep -i "alarm" logs/isup_client.log
grep -i "error|fail" logs/isup_client.log ```
本项目为内部开发项目,仅供学习参考使用。