使用Java语言从海康SDK取流并提取H264裸流存入队列

本文将介绍如何使用Java语言调用海康SDK,从海康摄像机获取视频流,并从中提取H264裸流,存入到队列中进行后续处理。

实现步骤

  1. 导入海康SDK相关的jar包,例如hkjvmsdk.jarhkplayctrl.jar等。

  2. 初始化SDK,包括设备登录、获取通道号等。

  3. 创建播放器对象,并设置播放器的回调函数,用于接收海康SDK传来的视频数据。

  4. 在回调函数中,判断数据类型是否为H264格式,如果是,则将数据存入队列中。

  5. 在主程序中,循环从队列中取出数据进行处理,例如保存到文件中。

代码示例

import com.sun.jna.NativeLong;
import com.sun.jna.Pointer;
import com.sun.jna.ptr.NativeLongByReference;
import com.sun.jna.ptr.PointerByReference;
import com.sun.jna.win32.StdCallLibrary;

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;

public class HKSdkDemo {

    // 海康SDK相关接口
    public interface HCNetSDK extends StdCallLibrary {
        boolean NET_DVR_Init();

        boolean NET_DVR_Cleanup();

        boolean NET_DVR_SetConnectTime(int dwWaitTime, int dwTryTimes);

        boolean NET_DVR_SetReconnect(int dwInterval, boolean bEnableRecon);

        NativeLong NET_DVR_Login_V30(String sDVRIP, short wDVRPort, String sUserName, String sPassword,
                                     HCNetSDK.NET_DVR_DEVICEINFO_V30 lpDeviceInfo);

        boolean NET_DVR_Logout(NativeLong lUserID);

        NativeLong NET_DVR_RealPlay_V40(NativeLong lUserID,
                                        HCNetSDK.NET_DVR_PREVIEWINFO lpPreviewInfo,
                                        HCNetSDK.REALDATACALLBACK_V30 fRealDataCallBack_V30,
                                        Pointer pUser);

        boolean NET_DVR_StopRealPlay(NativeLong lRealHandle);

        boolean NET_DVR_MakeKeyFrame(NativeLong lUserID, NativeLong lChannel);

        boolean NET_DVR_SetStandardDataCallBack(NativeLong lRealHandle,
                                                 HCNetSDK.STANDARDDATACALLBACK fStdDataCallback,
                                                 Pointer pUserData);

        interface REALDATACALLBACK_V30 extends StdCallCallback {
            void invoke(NativeLong lRealHandle, int dwDataType, Pointer pBuffer, int dwBufSize, Pointer pUser);
        }

        interface STANDARDDATACALLBACK extends StdCallCallback {
            void invoke(NativeLong lRealHandle, int dwDataType, Pointer pBuffer, int dwBufSize, Pointer pUser);
        }

        class NET_DVR_DEVICEINFO_V30 extends Structure {
            byte[] sSerialNumber = new byte[48];
            byte byAlarmInPortNum;
            byte byAlarmOutPortNum;
            byte byDiskNum;
            byte byDVRType;
            byte byChanNum;
            byte byStartChan;
            byte byAudioChanNum;
            byte byIPChanNum;
            byte[] byRes1 = new byte[24];
            Pointer struDeviceV30 = null;
            byte[] byRes2 = new byte[128];
        }

        class NET_DVR_PREVIEWINFO extends Structure {
            public NativeLong lChannel;
            public int dwStreamType;
            public int dwLinkMode;
            public Pointer hPlayWnd;
            public boolean bBlocked;
            public boolean bPassbackRecord;
            public byte byPreviewMode;
            public byte[] byRes = new byte[255];
        }
    }

    private static class HkSdkManager {
        private HCNetSDK hcNetSDK;
        private NativeLong lUserID;
        private BlockingQueue<byte[]> queue;

        public HkSdkManager(String ip, short port, String username, String password, int channelNum) {
            hcNetSDK = HCNetSDK.INSTANCE;
            queue = new LinkedBlockingQueue<>();

            // 初始化sdk
            hcNetSDK.NET_DVR_Init();
            hcNetSDK.NET_DVR_SetConnectTime(3000, 1);
            hcNetSDK.NET_DVR_SetReconnect(10000, true);

            // 登录设备
            HCNetSDK.NET_DVR_DEVICEINFO_V30 deviceInfo = new HCNetSDK.NET_DVR_DEVICEINFO_V30();
            lUserID = hcNetSDK.NET_DVR_Login_V30(ip, port, username, password, deviceInfo);

            // 创建播放器对象
            HCNetSDK.NET_DVR_PREVIEWINFO previewInfo = new HCNetSDK.NET_DVR_PREVIEWINFO();
            previewInfo.lChannel = new NativeLong(channelNum);
            previewInfo.dwStreamType = 0;
            previewInfo.dwLinkMode = 0;
            previewInfo.hPlayWnd = null;
            previewInfo.bBlocked = true;
            previewInfo.bPassbackRecord = false;
            previewInfo.byPreviewMode = 0;

            NativeLongByReference lRealHandle = new NativeLongByReference();
            lRealHandle.setValue(new NativeLong(-1));
            HCNetSDK.REALDATACALLBACK_V30 realDataCallback = new HCNetSDK.REALDATACALLBACK_V30() {
                @Override
                public void invoke(NativeLong lRealHandle, int dwDataType, Pointer pBuffer, int dwBufSize, Pointer pUser) {
                    // 判断数据类型是否为H264格式
                    if (dwDataType == 1) {
                        byte[] data = pBuffer.getByteArray(0, dwBufSize);
                        queue.offer(data); // 存入队列
                    }
                }
            };
            hcNetSDK.NET_DVR_RealPlay_V40(lUserID, previewInfo, realDataCallback, null);

            // 设置播放器的标准数据回调函数
            HCNetSDK.STANDARDDATACALLBACK stdDataCallback = new HCNetSDK.STANDARDDATACALLBACK() {
                @Override
                public void invoke(NativeLong lRealHandle, int dwDataType, Pointer pBuffer, int dwBufSize, Pointer pUser) {

                }
            };
            hcNetSDK.NET_DVR_SetStandardDataCallBack(lRealHandle.getValue(), stdDataCallback, null);
        }

        public byte[] takeData() throws InterruptedException {
            return queue.take();
        }

        public void release() {
            // 停止播放器
            hcNetSDK.NET_DVR_StopRealPlay(lUserID);

            // 登出设备
            hcNetSDK.NET_DVR_Logout(lUserID);

            // 释放sdk资源
            hcNetSDK.NET_DVR_Cleanup();
        }
    }

    public static void main(String[] args) {
        String ip = "192.168.1.1";
        short port = 8000;
        String username = "admin";
        String password = "admin123";
        int channelNum = 1;

        HkSdkManager hkSdkManager = new HkSdkManager(ip, port, username, password, channelNum);
        try {
            while (true) {
                byte[] data = hkSdkManager.takeData(); // 从队列中取出数据
                // 处理数据,例如保存到文件中
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            hkSdkManager.release();
        }
    }
}

代码说明

  1. HCNetSDK接口: 该接口定义了与海康SDK交互的函数,例如设备登录、获取视频流、停止播放等。

  2. HkSdkManager: 该类封装了海康SDK的调用逻辑,包括设备登录、获取视频流、提取H264裸流并存入队列等操作。

  3. REALDATACALLBACK_V30: 该回调函数用于接收海康SDK传来的视频数据,并判断数据类型是否为H264格式,如果是则将数据存入队列中。

  4. STANDARDDATACALLBACK: 该回调函数用于接收海康SDK传来的标准数据,例如时间戳、报警信息等。

  5. takeData: 该方法从队列中取出H264裸流数据。

  6. release: 该方法用于释放海康SDK资源,包括停止播放器、登出设备等。

注意事项

  1. 请确保已安装海康SDK,并配置好环境变量。

  2. 请确保已获取设备的IP地址、端口号、用户名和密码。

  3. 请确保已配置正确的通道号。

  4. 请根据实际需求修改代码中的数据处理逻辑。

总结

本文介绍了如何使用Java语言调用海康SDK,从海康摄像机获取视频流,并从中提取H264裸流,存入到队列中进行后续处理。文章包含详细的步骤、代码示例和相关说明,帮助开发者快速上手海康SDK开发。

海康SDK取流提取H264裸流并存入队列的Java实现

原文地址: https://www.cveoy.top/t/topic/n0W6 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录