使用Java调用海康威视SDK实现摄像头预览超详细教程

一、环境准备

1. 硬件要求

  • 海康威视网络摄像头(如DS-2CD2系列)
  • 支持Java开发的计算机
  • 网络连接设备(确保摄像头与计算机在同一网络)
图片[1]_使用Java调用海康威视SDK实现摄像头预览超详细教程_知途无界

2. 软件准备

  • JDK 1.8或更高版本
  • IDE(Eclipse/IntelliJ IDEA)
  • 海康威视SDK开发包(HCNetSDK)

3. SDK下载与配置

  1. 访问海康威视开放平台下载最新SDK
  2. 解压后得到以下关键文件:
    • HCNetSDK.jar(Java开发包)
    • hcnetsdk.dll(Windows平台动态库)
    • libhcnetsdk.so(Linux平台动态库)

二、项目配置

1. 创建Java项目

mvn archetype:generate -DgroupId=com.hikvision -DartifactId=camera-preview -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false

2. 添加SDK依赖

HCNetSDK.jar添加到项目依赖中:

<!-- pom.xml -->
<dependencies>
    <dependency>
        <groupId>com.hikvision</groupId>
        <artifactId>HCNetSDK</artifactId>
        <version>1.0</version>
        <scope>system</scope>
        <systemPath>${project.basedir}/lib/HCNetSDK.jar</systemPath>
    </dependency>
</dependencies>

3. 配置动态库路径

将动态库文件放在项目lib目录下,并设置系统属性:

// 在程序启动时加载
static {
    String os = System.getProperty("os.name").toLowerCase();
    if (os.contains("win")) {
        System.loadLibrary("hcnetsdk");
        System.loadLibrary("PlayCtrl");
    } else if (os.contains("linux")) {
        System.loadLibrary("hcnetsdk");
    }
}

三、初始化SDK

1. SDK初始化

import com.sun.jna.Native;
import com.sun.jna.Pointer;
import com.hikvision.HCNetSDK;

public class HikvisionCamera {
    private HCNetSDK hcNetSDK;
    private HCNetSDK.NET_DVR_DEVICEINFO_V30 deviceInfo;
    private int userId = -1;
    
    public boolean initSDK() {
        hcNetSDK = HCNetSDK.INSTANCE;
        boolean initSuc = hcNetSDK.NET_DVR_Init();
        if (!initSuc) {
            System.err.println("初始化失败,错误码:" + hcNetSDK.NET_DVR_GetLastError());
            return false;
        }
        
        // 设置连接超时和重连时间
        hcNetSDK.NET_DVR_SetConnectTime(3000, 3);
        hcNetSDK.NET_DVR_SetReconnect(10000, true);
        
        return true;
    }
}

2. 登录设备

public boolean login(String ip, int port, String username, String password) {
    HCNetSDK.NET_DVR_USER_LOGIN_INFO loginInfo = new HCNetSDK.NET_DVR_USER_LOGIN_INFO();
    loginInfo.sDeviceAddress = ip.getBytes();
    loginInfo.wPort = (short) port;
    loginInfo.sUserName = username.getBytes();
    loginInfo.sPassword = password.getBytes();
    loginInfo.bUseAsynLogin = false;
    
    deviceInfo = new HCNetSDK.NET_DVR_DEVICEINFO_V30();
    
    userId = hcNetSDK.NET_DVR_Login_V30(loginInfo, deviceInfo);
    if (userId < 0) {
        System.err.println("登录失败,错误码:" + hcNetSDK.NET_DVR_GetLastError());
        return false;
    }
    return true;
}

四、实现摄像头预览

1. 预览参数配置

public class PreviewParam {
    public static final int PREVIEW_CHANNEL = 1; // 通道号
    public static final int STREAM_TYPE = 0;     // 0-主码流,1-子码流
    public static final int LINK_MODE = 0;      // 0-TCP,1-UDP
    public static final int SHOW_MODE = 1;       // 0-直接显示,1-回调显示
}

2. 创建预览窗口

import com.sun.jna.Native;
import com.sun.jna.examples.win32.W32API;
import com.sun.jna.examples.win32.GDI32;
import com.sun.jna.examples.win32.User32;

public class PreviewWindow {
    private W32API.HWND hwnd;
    private int width = 800;
    private int height = 600;
    
    public void createWindow() {
        // Windows平台创建预览窗口
        String className = "HikvisionPreview";
        String windowName = "摄像头预览";
        
        User32.WNDCLASSEX wc = new User32.WNDCLASSEX();
        wc.hInstance = User32.INSTANCE.GetModuleHandle(null);
        wc.lpfnWndProc = new User32.WNDPROC() {
            public int callback(W32API.HWND hWnd, int uMsg, 
                W32API.WPARAM wParam, W32API.LPARAM lParam) {
                return User32.INSTANCE.DefWindowProc(hWnd, uMsg, wParam, lParam);
            }
        };
        wc.lpszClassName = className;
        User32.INSTANCE.RegisterClassEx(wc);
        
        hwnd = User32.INSTANCE.CreateWindowEx(
            0, className, windowName,
            User32.WS_OVERLAPPEDWINDOW,
            User32.CW_USEDEFAULT, User32.CW_USEDEFAULT,
            width, height,
            null, null, wc.hInstance, null);
        
        User32.INSTANCE.ShowWindow(hwnd, User32.SW_SHOW);
        User32.INSTANCE.UpdateWindow(hwnd);
    }
    
    public W32API.HWND getHwnd() {
        return hwnd;
    }
}

3. 启动实时预览

private int previewHandle = -1;

public boolean startPreview(PreviewWindow previewWindow) {
    HCNetSDK.NET_DVR_PREVIEWINFO previewInfo = new HCNetSDK.NET_DVR_PREVIEWINFO();
    previewInfo.lChannel = PreviewParam.PREVIEW_CHANNEL;
    previewInfo.dwStreamType = PreviewParam.STREAM_TYPE;
    previewInfo.dwLinkMode = PreviewParam.LINK_MODE;
    previewInfo.hPlayWnd = previewWindow.getHwnd();
    previewInfo.bBlocked = 1;
    
    previewHandle = hcNetSDK.NET_DVR_RealPlay_V40(userId, previewInfo, null, null);
    if (previewHandle < 0) {
        System.err.println("预览失败,错误码:" + hcNetSDK.NET_DVR_GetLastError());
        return false;
    }
    return true;
}

4. 回调函数实现(可选)

// 实现回调接口
public class PreviewCallback implements HCNetSDK.FRealDataCallBack_V30 {
    @Override
    public void invoke(int lRealHandle, int dwDataType, 
        Pointer pBuffer, int dwBufSize, Pointer pUser) {
        
        // 处理视频流数据
        switch (dwDataType) {
            case HCNetSDK.NET_DVR_SYSHEAD:
                System.out.println("收到系统头数据");
                break;
            case HCNetSDK.NET_DVR_STREAMDATA:
                System.out.println("收到视频流数据,大小:" + dwBufSize);
                break;
            case HCNetSDK.NET_DVR_AUDIOSTREAMDATA:
                System.out.println("收到音频流数据");
                break;
        }
    }
}

// 设置回调
public void setCallback() {
    HCNetSDK.FRealDataCallBack_V30 callback = new PreviewCallback();
    hcNetSDK.NET_DVR_SetRealDataCallBack_V30(previewHandle, callback, 0);
}

五、完整示例代码

public class HikvisionCameraDemo {
    public static void main(String[] args) {
        HikvisionCamera camera = new HikvisionCamera();
        
        // 1. 初始化SDK
        if (!camera.initSDK()) {
            return;
        }
        
        // 2. 登录设备
        String ip = "192.168.1.64";
        int port = 8000;
        String username = "admin";
        String password = "hik12345";
        
        if (!camera.login(ip, port, username, password)) {
            camera.cleanup();
            return;
        }
        
        // 3. 创建预览窗口
        PreviewWindow previewWindow = new PreviewWindow();
        previewWindow.createWindow();
        
        // 4. 开始预览
        if (!camera.startPreview(previewWindow)) {
            camera.cleanup();
            return;
        }
        
        // 5. 设置回调(可选)
        camera.setCallback();
        
        // 保持程序运行
        try {
            Thread.sleep(30000); // 预览30秒
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        
        // 6. 释放资源
        camera.cleanup();
    }
}

六、资源释放与错误处理

1. 停止预览

public void stopPreview() {
    if (previewHandle >= 0) {
        hcNetSDK.NET_DVR_StopRealPlay(previewHandle);
        previewHandle = -1;
    }
}

2. 注销登录

public void logout() {
    if (userId >= 0) {
        hcNetSDK.NET_DVR_Logout(userId);
        userId = -1;
    }
}

3. 清理SDK

public void cleanup() {
    stopPreview();
    logout();
    
    if (hcNetSDK != null) {
        hcNetSDK.NET_DVR_Cleanup();
    }
}

4. 错误处理

public static String getErrorMsg(int errorCode) {
    switch (errorCode) {
        case HCNetSDK.NET_DVR_NOERROR: return "没有错误";
        case HCNetSDK.NET_DVR_PASSWORD_ERROR: return "用户名或密码错误";
        case HCNetSDK.NET_DVR_NOENOUGHPRI: return "权限不足";
        case HCNetSDK.NET_DVR_NOINIT: return "SDK未初始化";
        case HCNetSDK.NET_DVR_CHANNEL_ERROR: return "通道号错误";
        // 更多错误码处理...
        default: return "未知错误:" + errorCode;
    }
}

七、常见问题解决方案

1. SDK初始化失败

  • 问题​:NET_DVR_Init返回false
  • 解决方案​:
    • 检查动态库路径是否正确
    • 确保动态库文件与程序架构匹配(32/64位)
    • 以管理员权限运行程序

2. 登录失败

  • 问题​:NET_DVR_Login_V30返回-1
  • 解决方案​:
    • 检查IP、端口、用户名和密码
    • 确认摄像头网络连接正常
    • 检查防火墙设置,确保8000端口开放

3. 预览无图像

  • 问题​:预览窗口黑屏
  • 解决方案​:
    • 确认通道号是否正确
    • 检查摄像头是否启用主码流
    • 尝试切换TCP/UDP模式

4. 内存泄漏

  • 问题​:长时间运行后内存占用过高
  • 解决方案​:
    • 确保每次调用NET_DVR_Init后都有对应的NET_DVR_Cleanup
    • 及时释放预览句柄和用户ID
    • 避免频繁创建/销毁窗口

八、高级功能扩展

1. 云台控制

public boolean ptzControl(int command, int speed) {
    if (userId < 0) return false;
    
    boolean result = hcNetSDK.NET_DVR_PTZControl_Other(
        userId, PreviewParam.PREVIEW_CHANNEL, command, 0, speed);
    
    if (!result) {
        System.err.println("云台控制失败:" + getErrorMsg(hcNetSDK.NET_DVR_GetLastError()));
    }
    return result;
}

// 使用示例
camera.ptzControl(HCNetSDK.TILT_UP, 3); // 向上转动,速度3

2. 抓图功能

public boolean capturePicture(String savePath) {
    if (previewHandle < 0) return false;
    
    boolean result = hcNetSDK.NET_DVR_CapturePicture(
        previewHandle, savePath.getBytes());
    
    if (!result) {
        System.err.println("抓图失败:" + getErrorMsg(hcNetSDK.NET_DVR_GetLastError()));
    }
    return result;
}

3. 录像功能

public boolean startRecord(String savePath) {
    if (previewHandle < 0) return false;
    
    boolean result = hcNetSDK.NET_DVR_SaveRealData(
        previewHandle, savePath.getBytes());
    
    if (!result) {
        System.err.println("开始录像失败:" + getErrorMsg(hcNetSDK.NET_DVR_GetLastError()));
    }
    return result;
}

public boolean stopRecord() {
    if (previewHandle < 0) return false;
    
    boolean result = hcNetSDK.NET_DVR_StopSaveRealData(previewHandle);
    
    if (!result) {
        System.err.println("停止录像失败:" + getErrorMsg(hcNetSDK.NET_DVR_GetLastError()));
    }
    return result;
}

九、跨平台注意事项

1. Linux平台差异

  • 动态库文件为libhcnetsdk.so
  • 不需要创建Windows窗口句柄
  • 使用X11或Qt等图形库创建预览窗口

2. MacOS支持

  • 海康官方未提供Mac版SDK
  • 可通过虚拟机或Docker运行Windows/Linux环境
  • 考虑使用FFmpeg进行二次开发

十、性能优化建议

  1. 多线程处理​:将预览和业务逻辑分离到不同线程
  2. 缓冲区管理​:合理设置回调缓冲区大小
  3. 硬件加速​:启用DirectShow或OpenGL渲染
  4. 资源复用​:避免频繁登录/注销设备

通过本教程,您应该已经掌握了使用Java调用海康威视SDK实现摄像头预览的核心技术。实际开发中,请根据具体需求调整参数和处理逻辑,并参考海康威视官方文档获取最新API信息。

© 版权声明
THE END
喜欢就点个赞,支持一下吧!
点赞21 分享
评论 抢沙发
头像
欢迎您留下评论!
提交
头像

昵称

取消
昵称表情代码图片

    暂无评论内容