前言

监控,相信大家都不陌生。现在的监控技术发展迅速,国内以海康威视为首的智能视频监控提供商也层出不穷。现在,这些提供商都已经提供了相应的SDK以及API接口,能够很好的支撑我们进行摄像机的二次开发工作。相信大家都有接触过这么一个需求:利用手机可以自己进行摄像机的录像控制,然后在规定的时间内停止录制,然后将这个时间段内的视频保存下来。方便客户端的客户进行查看相应时间段的检控视频。这样就避免了视频一直录制,存储空间不足以承受如此之大的压力,而且也可以降低对于实时拉流的带宽要求。

本文关键词

JAVA、大华SDK、视频拉流、自定义拉流时长、录像保存、4G网络摄像机

硬件设备

本次所用到的摄像机是大华的4G网络摄像机,此摄像机支持利用SIM卡进行4G上网

现在不借助大华自带的软件来控制摄像机,自行开发软件来实现手机端访问摄像头进行拉流的触发,摄像头执行相应的程序进行一段时间的拉流,到了预定的时间进行自动保存视频数据到服务器的相应位置。

技术分析

首先,我们要明确的知道要实现这么一个简单的需求要具备哪些知识。
①手机怎么通过网络触发摄像机?
答:摄像头通过手机进行触发使用get请求的方式访问URL,输入设备ID,告诉服务器我要控制那台摄像头,服务器收到请求进行触发。(此技术属于基本的web开发的基本技能实现起来难度不大)
②通过什么样的方式让摄像头执行自己编写的程序?
答:程序运行在服务器上,同时需要让摄像头能够通过固定IP找到这台服务器。
③摄像头怎么找到服务器?
答:摄像头具备一个功能叫做自动注册(相当于第一次在服务器上使用需要创建一样,让服务器知道这个摄像机)主动注册时输入需要摄像头执行相应程序的服务器的固定IP,以及摄像机的端口号(可自定义)设备登录账号和设备登录密码即可完成注册,这个时候形成长连接就可以相互获取信息和传输数据了,服务器也就可以获取到设备的ID,与手机端发送的设备ID对应就可以触发相应的设备进行工作。

技术逻辑图

使用大华的SDK进行二次开发都会有相应的资料,内部也有很多逻辑流程图,这里提取出相关的那一块内容进行展示:

由上图可见,在我们利用手机触发摄像头的时候服务器内程序执行的逻辑是,首先要进行设备的初始化,然后服务器会寻找在记录中是否注册过本台摄像机,是否有此设备的信息,如果没有摄像机的信息需要进行主动注册。这个时候摄像机会执行访问本服务器固定IP的程序进行自动的注册,注册完成后服务器就会收到本台摄像机的设备ID(此时服务器与摄像头已经形成长连接),然后就可以等待客户端利用手机对摄像头进行触发时发出的信号做比对,让对应的摄像头开始工作。最后就是定义录制的时长,和自动保存的功能,完成后会清理内存。

代码实现

前期准备

首先打开我们心爱的idea(我这里使用的是2021 64位版本的)

进入到项目列表的窗口,选择New Project 新建立一个Spring Boot项目

然后,选择Spring Initializr,在右侧的对话框中进行项目名称的修改(我这里名字为CameraTest),然后根据自己的命名习惯将Group、Artifact、Package name名字做修改(这里仅修改了Grop的名称为com.ruoyi),最后注意自己的java的版本号。修改完后点击Next。

创建成功后我们会看到如图所示的界面
src/main/java/com.ruoyi.cameratest/CameraTestApplication
为springboot的启动程序。

然后我们需要修改下自己的maven的文件保存的路径,之后此项目所要用到的外部jar包都会保存在这些文件夹下。
①我们点击File/Settings


②在搜索框内搜索maven会出现如图所示的内容(Maven home path 为当时我们下载maven的源文件文件位置;User settings file首先找到自己的maven安装位置下conf文件下的settings.xml文件;Local repository找到自己maven安装位置下的自己创建的一个用于保存第三方jar包的文件夹)

例如我的maven安装在D:\SoftWares\apache-maven-3.6.1配置如下,完成后点击Apply,点击OK完成设置。

最后我们修改pom.xml文件

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.ruoyi</groupId><artifactId>CameraTest</artifactId><version>0.0.1-SNAPSHOT</version><name>CameraTest</name><description>Demo project for Spring Boot</description><properties><java.version>1.8</java.version><spring-boot.version>2.3.7.RELEASE</spring-boot.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><dependency><groupId>net.java.dev.jna</groupId><artifactId>jna</artifactId><version>5.4.0</version></dependency><dependency><groupId>com.dahua.netsdk</groupId><artifactId>dahua-netsdk-jni</artifactId><version>1.0.0</version></dependency><!--lombok插件--><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.12</version></dependency><!-- Mysql驱动包 --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId></dependency><!-- web --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency></dependencies><dependencyManagement><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-dependencies</artifactId><version>${spring-boot.version}</version><type>pom</type><scope>import</scope></dependency></dependencies></dependencyManagement><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build></project>

这里我们修改了pom.xml文件后需要进行刷新,最后测试一下是否可以成功启动springboot

再来就是进入大华公司的官网找到对应的SDK进行下载

1.消息接收实现类和接口

首先创建如下图所示的文件和类

instructController.java

package com.ruoyi.controller;import com.ruoyi.service.instructService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import java.util.HashMap;
import java.util.Map;@RestController
@RequestMapping("/test")
public class instructController {@Autowiredprivate instructService service;public String VideoPath;public String getVideoPath() {return VideoPath;}public void setVideoPath(String videoPath) {VideoPath = videoPath;}@GetMapping("/ss")public Map<String,Object> SendMessage(PreInfo info){service.SendMessage(info);instructController instr = new instructController();Map<String, Object> result = new HashMap<String, Object>();result.put("videopath", instr.getVideoPath());return result;}}

PreInfo.java

package com.ruoyi.controller;import lombok.Data;@Data
public class PreInfo {private String PreDeviceId;
}

instructService.java

package com.ruoyi.service;import com.ruoyi.controller.PreInfo;public interface instructService {void SendMessage(PreInfo info);
}

ServiceCB.java

package com.ruoyi.demo.frame;import com.ruoyi.controller.PreInfo;
import com.ruoyi.service.instructService;
import org.springframework.stereotype.Component;@Component
public class ServiceCB implements instructService {@Overridepublic void SendMessage(PreInfo info) {System.out.println("成功触发!");}
}

2.主动注册

首先在src/mian/resources文件中将SDK中的dynamic-lib-load.xml文件复制过来,这个文件是为了满足不同平台下需要加载的C动态库

dynamic-lib-load.xml

<?xml version="1.0" encoding="UTF-8" ?>
<dynamic-lib><win64><lib>avnetsdk</lib><lib>dhconfigsdk</lib><lib>dhnetsdk</lib><lib>dhplay</lib><lib>ImageAlg</lib><lib>Infra</lib><lib>IvsDrawer</lib><lib>StreamConvertor</lib><lib>jninetsdk</lib></win64><win32><lib>avnetsdk</lib><lib>dhconfigsdk</lib><lib>dhnetsdk</lib><lib>dhplay</lib><lib>Infra</lib><lib>ImageAlg</lib><lib>StreamConvertor</lib><lib>jninetsdk</lib></win32><linux64><lib>avnetsdk</lib><lib>dhnetsdk</lib><lib>dhconfigsdk</lib><lib>StreamConvertor</lib><lib>jninetsdk</lib></linux64><linux32><lib>avnetsdk</lib><lib>dhconfigsdk</lib><lib>dhnetsdk</lib><lib>StreamConvertor</lib><lib>jninetsdk</lib></linux32><mac64><lib>avnetsdk</lib><lib>dhnetsdk</lib><lib>dhconfigsdk</lib><lib>StreamConvertor</lib></mac64>
</dynamic-lib>

接着在项目目录中新建子文件夹com.ruoyi/lib

打开我们的大华SDK项目在一个新的窗口中,将我们需要的实现类拷贝过来。如下图是大华SDK-java-x64版本的文件目录。

首先我们将SDK中的lib文件中的所有文件全部拷贝到刚建立的lib中。(如果复制过来出现报错,检查import 中的文件路径名称,因为SDK中的项目名称为com.netsdk我们的不是所以需要修改)。后面功能实现类,由于官方的SDK中的实现类功能太多太杂,我做了整理,大家可以复制我整理后的代码。首先我们需要主动注册的实现类AutoRegisterModule.java,登录设备的实现类LoginModule.java,设备的信息类DeviceInfo.java

AutoRegisterModule.java

package com.ruoyi.demo.module;import com.ruoyi.demo.module.LoginModule;
import com.ruoyi.lib.NetSDKLib.LLong;
import com.ruoyi.lib.NetSDKLib.fServiceCallBack;
import com.ruoyi.lib.NetSDKLib;
import com.ruoyi.lib.ToolKits;public class AutoRegisterModule {// 监听服务句柄public static LLong mServerHandler = new LLong(0);// 设备信息public static NetSDKLib.NET_DEVICEINFO_Ex m_stDeviceInfo = new NetSDKLib.NET_DEVICEINFO_Ex();/*** 开启服务** @param address  本地IP地址* @param port     本地端口, 可以任意* @param callback 回调函数*/public static boolean startServer(String address, int port, fServiceCallBack callback) {//调用监听接口实现服务的开启mServerHandler = LoginModule.netsdk.CLIENT_ListenServer(address, port, 1000, callback, null);if (0 == mServerHandler.longValue()) {System.err.println("Failed to start server." + ToolKits.getErrorCodePrint());} else {System.out.printf("Start server, [Server address %s][Server port %d]\n", address, port);}return mServerHandler.longValue() != 0;}/*** 结束服务*/public static boolean stopServer() {boolean bRet = false;if (mServerHandler.longValue() != 0) {bRet = LoginModule.netsdk.CLIENT_StopListenServer(mServerHandler);mServerHandler.setValue(0);System.out.println("Stop server!");}return bRet;}}

LoginModule.java

package com.ruoyi.demo.module;import com.ruoyi.lib.NetSDKLib;
import com.ruoyi.lib.NetSDKLib.LLong;
import com.ruoyi.lib.NetSDKLib.NET_IN_LOGIN_WITH_HIGHLEVEL_SECURITY;
import com.ruoyi.lib.NetSDKLib.NET_OUT_LOGIN_WITH_HIGHLEVEL_SECURITY;
import com.ruoyi.lib.ToolKits;import java.io.File;/*** 登陆接口实现* 主要有 :初始化、登陆、登出功能*/
public class LoginModule {public static NetSDKLib netsdk        = NetSDKLib.NETSDK_INSTANCE;// 设备信息public static NetSDKLib.NET_DEVICEINFO_Ex m_stDeviceInfo = new NetSDKLib.NET_DEVICEINFO_Ex();// 登陆句柄public static LLong m_hLoginHandle = new LLong(0);   private static boolean bInit    = false;private static boolean bLogopen = false;/*** 初始化*/public static boolean init(NetSDKLib.fDisConnect disConnect, NetSDKLib.fHaveReConnect haveReConnect) {   bInit = netsdk.CLIENT_Init(disConnect, null);if(!bInit) {System.out.println("Initialize SDK failed");return false;}//打开日志,可选NetSDKLib.LOG_SET_PRINT_INFO setLog = new NetSDKLib.LOG_SET_PRINT_INFO();File path = new File("./sdklog/");if (!path.exists()) {path.mkdir();}String logPath = path.getAbsoluteFile().getParent() + "\\sdklog\\" + ToolKits.getDate() + ".log";setLog.nPrintStrategy = 0;setLog.bSetFilePath = 1;System.arraycopy(logPath.getBytes(), 0, setLog.szLogFilePath, 0, logPath.getBytes().length);System.out.println(logPath);setLog.bSetPrintStrategy = 1;bLogopen = netsdk.CLIENT_LogOpen(setLog);if(!bLogopen ) {System.err.println("Failed to open NetSDK log");}// 设置断线重连回调接口,设置过断线重连成功回调函数后,当设备出现断线情况,SDK内部会自动进行重连操作// 此操作为可选操作,但建议用户进行设置netsdk.CLIENT_SetAutoReconnect(haveReConnect, null);//设置登录超时时间和尝试次数,可选int waitTime = 5000; //登录请求响应超时时间设置为5Sint tryTimes = 1;    //登录时尝试建立链接1次netsdk.CLIENT_SetConnectTime(waitTime, tryTimes);// 设置更多网络参数,NET_PARAM的nWaittime,nConnectTryNum成员与CLIENT_SetConnectTime // 接口设置的登录设备超时时间和尝试次数意义相同,可选NetSDKLib.NET_PARAM netParam = new NetSDKLib.NET_PARAM();netParam.nConnectTime = 10000;      // 登录时尝试建立链接的超时时间netParam.nGetConnInfoTime = 3000;   // 设置子连接的超时时间netParam.nGetDevInfoTime = 3000;//获取设备信息超时时间,为0默认1000msnetsdk.CLIENT_SetNetworkParam(netParam);    return true;}/*** 清除环境*/public static void cleanup() {if(bLogopen) {netsdk.CLIENT_LogClose();}if(bInit) {netsdk.CLIENT_Cleanup();}}/*** 登录设备*/public static boolean login(String m_strIp, int m_nPort, String m_strUser, String m_strPassword) {    //IntByReference nError = new IntByReference(0);//入参NET_IN_LOGIN_WITH_HIGHLEVEL_SECURITY pstInParam=new NET_IN_LOGIN_WITH_HIGHLEVEL_SECURITY();pstInParam.nPort=m_nPort;pstInParam.szIP=m_strIp.getBytes();pstInParam.szPassword=m_strPassword.getBytes();pstInParam.szUserName=m_strUser.getBytes();//出参NET_OUT_LOGIN_WITH_HIGHLEVEL_SECURITY pstOutParam=new NET_OUT_LOGIN_WITH_HIGHLEVEL_SECURITY();pstOutParam.stuDeviceInfo=m_stDeviceInfo;//m_hLoginHandle = netsdk.CLIENT_LoginEx2(m_strIp, m_nPort, m_strUser, m_strPassword, 0, null, m_stDeviceInfo, nError);        m_hLoginHandle=netsdk.CLIENT_LoginWithHighLevelSecurity(pstInParam, pstOutParam);if(m_hLoginHandle.longValue() == 0) {System.err.printf("Login Device[%s] Port[%d]Failed. %s\n", m_strIp, m_nPort, ToolKits.getErrorCodePrint());} else {System.out.println("Login Success [ " + m_strIp + " ]");}   return m_hLoginHandle.longValue() == 0? false:true;}/*** 登出设备*/public static boolean logout() {if(m_hLoginHandle.longValue() == 0) {return false;}boolean bRet = netsdk.CLIENT_Logout(m_hLoginHandle);if(bRet) {           m_hLoginHandle.setValue(0); }return bRet;}
}

DeviceInfo.java

package com.ruoyi.demo.module;
import com.ruoyi.lib.NetSDKLib;
import com.ruoyi.lib.NetSDKLib.LLong;public class DeviceInfo {private String m_strIp;private int m_nPort;private String m_strUser;private String m_strPassword;private String m_srtId;public DeviceInfo(String m_strIp, int m_nPort, String m_strUser, String m_strPassword) {this.m_strIp = m_strIp; //设备ipthis.m_nPort = m_nPort; //设备端口号this.m_strUser = m_strUser;  //设备登录用户名this.m_strPassword = m_strPassword;  //设备登陆密码}public DeviceInfo() {}//获取设备IDpublic String getM_srtId() {return m_srtId;}//设置设备IDpublic void setM_srtId(String m_srtId) {this.m_srtId = m_srtId;}//获取设备用户名public String getM_strUser() {return m_strUser;}//设置设备用户名public void setM_strUser(String m_strUser) {this.m_strUser = m_strUser;}//获取设备登录密码public String getM_strPassword() {return m_strPassword;}//设置设备登录密码public void setM_strPassword(String m_strPassword) {this.m_strPassword = m_strPassword;}//获取设备IPpublic String getM_strIp() {return m_strIp;}//设置设备IPpublic void setM_strIp(String m_strIp) {this.m_strIp = m_strIp;}//获取设备端口号public int getM_nPort() {return m_nPort;}//设置设备端口号public void setM_nPort(int m_nPort) {this.m_nPort = m_nPort;}public static final NetSDKLib netSdk = NetSDKLib.NETSDK_INSTANCE;//获取登录句柄public LLong getLoginHandle() {return loginHandle;}// 登陆句柄private LLong loginHandle = new LLong(0);}

3.主动注册监听

在编写主动监听实现类之前我们=将内部用到的回调监听的功能都封装成了类这样我们调用起来方便一些

DisConnectCallBack.java(设备断线监听回调用于监听设备的在线状态,如果掉线进行消息回传)

package com.ruoyi.demo.frame;import com.ruoyi.lib.NetSDKLib;
import com.sun.jna.Pointer;/*** 设备断线回调*/public class DisConnectCallBack implements NetSDKLib.fDisConnect {public DisConnectCallBack() {}private static class CallBackHolder {private static DisConnectCallBack instance = new DisConnectCallBack();}public static DisConnectCallBack getInstance() {return CallBackHolder.instance;}public void invoke(NetSDKLib.LLong lLoginID, String pchDVRIP, int nDVRPort, Pointer dwUser) {System.out.printf("Device[%s] Port[%d] DisConnect!\n", pchDVRIP, nDVRPort);}
}

HaveReConnectCallBack.java(设备重连回调,用与监听离线设备重连的状态,将重连成功后的设备信息进行回传)

package com.ruoyi.demo.frame;import com.ruoyi.lib.NetSDKLib;
import com.sun.jna.Pointer;/*** 设备重连回调*/
public class HaveReConnectCallBack implements NetSDKLib.fHaveReConnect {public HaveReConnectCallBack() {}private static class CallBackHolder {private static HaveReConnectCallBack instance = new HaveReConnectCallBack();}public static HaveReConnectCallBack getInstance() {return CallBackHolder.instance;}public void invoke(NetSDKLib.LLong m_hLoginHandle, String pchDVRIP, int nDVRPort, Pointer dwUser) {System.out.printf("ReConnect Device[%s] Port[%d]\n", pchDVRIP, nDVRPort);}
}

CbfRealDataCallBackEx.java(在摄像机工作过程中进行工作状态的监听,将设备数据进行回传)

package com.ruoyi.demo.frame;import com.ruoyi.lib.NetSDKLib;
import com.sun.jna.Pointer;/*** 实时监视数据回调函数--扩展(pBuffer内存由SDK内部申请释放)*/public class CbfRealDataCallBackEx implements NetSDKLib.fRealDataCallBackEx {private static class CallBackHolder {private static CbfRealDataCallBackEx instance = new CbfRealDataCallBackEx();}public static CbfRealDataCallBackEx getInstance() {return CallBackHolder.instance;}@Overridepublic void invoke(NetSDKLib.LLong lRealHandle, int dwDataType, Pointer pBuffer, int dwBufSize, int param, Pointer dwUser) {if (0 != lRealHandle.longValue()) {switch (dwDataType) {case 0:break;case 1://标准视频数据System.out.println("[1]"+"码流大小为" + dwBufSize + "\n" + "码流类型为原始音视频混合数据");break;case 2://yuv 数据System.out.println("[2]"+"码流大小为" + dwBufSize + "\n" + "码流类型为原始音视频混合数据");break;case 3://pcm 音频数据System.out.println("[3]"+"码流大小为" + dwBufSize + "\n" + "码流类型为原始音视频混合数据");break;case 4://原始音频数据System.out.println("[4]"+"码流大小为" + dwBufSize + "\n" + "码流类型为原始音视频混合数据");break;default:break;}}}
}

Run.java(主动注册实现函数,进行主动注册监听)

package com.ruoyi.demo.frame;import com.ruoyi.demo.module.AutoRegisterModule;
import com.ruoyi.demo.module.LoginModule;import javax.swing.*;
import java.net.InetAddress;
import java.net.UnknownHostException;public class Run extends JFrame {// 主动注册监听回调private final ServiceCB servicCallback = new ServiceCB();// 设备断线通知回调private final DisConnectCallBack disConnectCallback = new DisConnectCallBack();/*** 主动注册* @param ServiceAddress 服务器公网IP* @param ServicePort  服务器注册端口默认为9500* */public boolean AutoListen(String ServiceAddress , int ServicePort){//window系统下监听设备返回信息函数,必须增加不增加无法返回注册设备信息pack();//初始化LoginModule.init(disConnectCallback,null);if (ServiceAddress == null){System.out.println("service is null");}if (ServicePort == 0){System.out.println("service port is zero");}//进行主动注册开启服务return(AutoRegisterModule.startServer(ServiceAddress, ServicePort, servicCallback));}/*** 获取本地地址* @return 获取本机ip*/public String getHostAddress() {String address = "";try {InetAddress inetAddress = InetAddress.getLocalHost();address = inetAddress.getHostAddress();} catch (UnknownHostException e) {e.printStackTrace();}return address;}
}

ServiceCB.java(主动监听回调函数)

package com.ruoyi.demo.frame;import com.ruoyi.conversion.CaseMenu;
import com.ruoyi.controller.PreInfo;
import com.ruoyi.conversion.RealPlayByDataTypeDemo;
import com.ruoyi.demo.module.DeviceInfo;
import com.ruoyi.lib.NetSDKLib;
import com.ruoyi.service.instructService;
import com.sun.jna.Pointer;
import org.springframework.stereotype.Component;import java.io.UnsupportedEncodingException;
import java.util.HashSet;
import java.util.Set;/*** 注册服务监听回调*/
@Component
public class ServiceCB implements NetSDKLib.fServiceCallBack,instructService {//设备信息类对象用于获取注册后设备信息DeviceInfo info = new DeviceInfo();/*** 前端发送信息** @param preInfo  前端发送信息*/private static final Set<PreInfo> preInfoSet = new HashSet<>();@Overridepublic int invoke(NetSDKLib.LLong lHandle, String pIp, int wPort,int lCommand, Pointer pParam, int dwParamLen,Pointer dwUserData) {// 将 pParam 转化为序列号byte[] buffer = new byte[dwParamLen];pParam.read(0, buffer, 0, dwParamLen);String deviceId = "";try {deviceId = new String(buffer, "GBK").trim();} catch (UnsupportedEncodingException e) {e.printStackTrace();}System.out.printf("Register Device Info [Device address %s][port %s][DeviceID %s] \n", pIp, wPort, deviceId);switch (lCommand) {case NetSDKLib.EM_LISTEN_TYPE.NET_DVR_DISCONNECT: {  // 验证期间设备断线回调info.setM_strIp("");info.setM_nPort(0);break;}case NetSDKLib.EM_LISTEN_TYPE.NET_DVR_SERIAL_RETURN: { // 设备注册携带序列号info.setM_strIp(pIp);info.setM_nPort(wPort);info.setM_srtId(deviceId);/*** 判断前端是否传输数据* */if (preInfoSet.size() != 0) {//这判断设备id是否相同preInfoSet.forEach(preInfo -> {if (info.getM_srtId().equals(preInfo.getPreDeviceId())) {preInfoSet.remove(preInfo);System.out.println("前端触发ID:" + preInfo.getPreDeviceId());System.out.println("设备当前ID:" + info.getM_srtId());if (preInfo.getPreDeviceId().equals(info.getM_srtId())) {new Thread(() -> {System.out.println("开始录制");info.setM_strUser("自己的大华相机用户名");info.setM_strPassword("自己的大华相机密码");RealPlayByDataTypeDemo demo = new RealPlayByDataTypeDemo();demo.addItem(new CaseMenu.Item(demo, "mp4", "attachFlv"));demo.addItem(new CaseMenu.Item(demo, "stop", "detach"));/*** SDK初始化* @param disConnect 断线回调函数* @param haveReConnect 重连回调函数* */DisConnectCallBack disConnect = new DisConnectCallBack();HaveReConnectCallBack haveReConnect = new HaveReConnectCallBack();demo.init(disConnect, haveReConnect);System.out.println(info.getM_strIp());System.out.println(info.getM_nPort());if (demo.login(info.getM_strIp(), info.getM_nPort(), info.getM_strUser(), info.getM_strPassword(),2,null,info.getM_srtId())) {System.out.println("登录成功");// 登录成功后demo.run(0,info.getM_srtId());try {/*** 视频录制60s* */Thread.sleep(60 * 1000);demo.run(1,null);} catch (InterruptedException e) {e.printStackTrace();}}// 登出设备demo.logout();// 测试结束,释放sdk资源
//                          demo.clean();System.out.println("录制结束");}).start();} else {System.out.println("设备id不一致登录失败!");}}});}break;}default:break;}return lCommand;}@Override//向前端进行摄像机触发成功的消息提醒public void SendMessage(PreInfo info) {preInfoSet.add(info);System.out.println("成功触发!");}}

4.剩余包含的实现类

剩下的实现类均是大华提供的SDK中本身具备的我们只需要复制即可


由于摄像机不再旁边无法进行测试。我会将源文件上传到资源,感兴趣的可自行下载。

注意

主动注册使用了基于window.java的pack()监听函数实现实时监听设备的注册功能;在主动注册中的回调函数为多线程执行模式,每一个新注册的设备都单独运行在一个线程。
所有的业务逻辑需要书写在主动注册的回调函数中作为监听项。
在进行业务操作前必须要使用SDK初始化函数对SDK资源进行初始化,避免产生脏数据。
对于主动注册的登录操作需要使用“高安全的登录”方式,且需要传入设备ID作为参数,才可利用主动注册的登录方式成功登录服务器。
拉流保存的操作可以利用接口“NET_IN_REALPLAY_BY_DATA_TYPE(开始流数据解码)”与“NET_OUT_REALPLAY_BY_DATA_TYPE(停止流数据解码)”两个接口进行视频的录制与解码。(详细可见大华SDK开发文档)
部署服务器的时候需要注意服务器安全规则中的入站安全规则需要将“9500(主动注册端口)”,“Springboot访问端口xxxx”填入入站规则中,才可实现主动注册与远端触发功能。

大华SDK+JAVA+4g网络摄像头进行二次开发相关推荐

  1. 大华SDK java实现车位和违停事件

    写在前面 gitee地址如下: Gitee仓库传送门 大华SDK分语言和操作系统,不同的SDK实现方式不太一样,需要先根据自己的需求进行SDK的选取.比如,很多线上服务是部署在Linux系统的,所以开 ...

  2. 海康、大华、星邦网络摄像头的 RTSP协议 地址与格式

    一.简介 1.RTSP(Real Time Streaming Protocol)是由Real Network和Netscape共同提出的如何有效地在IP网络上传输流媒体数据的应用层协议.RTSP对流 ...

  3. python海康威视网络摄像头_OpenCV:非海康威视大华宇视(其他)网络摄像头IPC 二次开发(Python)获取视频图像...

    # -*- coding: UTF-8 -*- # ! /usr/bin/python import cv2 # 参数 # -------------------------------------- ...

  4. 基于大华SDK的二次开发,用于网络摄像头图像的实时显示和捕获(附源码)

    目录 1. 文章背景 2. 主要模块 2.1 初始化SDK 2.2 登录账号 2.3 捕获图片 2.4 实时显示 2.5 断开时释放 2.6 回调函数 3. 源代码 3.1 头文件 3.2 源文件 1 ...

  5. java对接大华SDK摄像头监控

    java对接大华SDK摄像头监控 SDK对接 java对接大华SDK摄像头监控 前言 获取SDK 配置环境变量 拉取实时监控数据 补充 前言 小编在接到对接大华摄像头实时监控在网页显示直播视频,先是在 ...

  6. 大华 sdk java_[日常总结] 大华SDK基于Java的二次开发实现Restful Api

    最近半个月在对接大华摄像头,要实现摄像头的实时预览.云台控制和截图等功能.在网上找了很多资源也没有找到想要的,所以自己写了工具类.简单陈述一下基于大华的官网SDK实现摄像头的云台控制和抓图.无非就是调 ...

  7. 大华硬盘录像机通过大华SDK接入EasyCVR,为何出现无法在线的情况?

    EasyCVR视频融合云平台开放度高.兼容性强.可支持灵活拓展与第三方集成,目前已经成为安防市场主流的视频能力层服务平台.平台可支持多协议.多类型的设备接入,包括国标GB28181.RTSP/Onvi ...

  8. 视频融合协议安防监控系统EasyCVR支持大华SDK接入设备录像下载流程说明

    上一篇我们讲了EasyCVR视频协议融合平台已经支持了大华SDK协议设备的接入,并且分享了录像回放流程,目前其他私有协议仍在拓展和开发当中.本文我们再分享一下EasyCVR接入大华SDK协议设备后的录 ...

  9. 人脸识别/车牌识别系统安防视频云服务EasyCVR开发支持大华SDK报警上报功能流程说明

    报警上报,即前端设备在检测到事先规定的特殊事件发生时,发送报警到平台端告知平台.平台可以接收到设备上传的外部报警.视频信号丢失报警.遮挡报警和动态检测报警等信息. TSINGSEE青犀视频EasyCV ...

最新文章

  1. 5月“.公司”域名注册总量TOP15:西部数码第四
  2. 不藏私分享五個線上自學平台
  3. OpenGL视点跟踪物体运动
  4. 设计模式C++实现(3)——装饰模式
  5. 计算机桌面老是弹出广告,桌面老是弹出广告怎么办? 爱问知识人
  6. ASP.NET Core快速入门(第6章:ASP.NET Core MVC)--学习笔记
  7. 80端口请求太多超时 php_apmserver 80端口老是被占用问题解决
  8. 1805. 字符串中不同整数的数目
  9. debian7 安装配置
  10. 时光 php,ctphp-php教程-时光划过那刹那-PHP教程--创业的风,吹向了年轻之长藤个人博客网站...
  11. NB50/60 TJ1/TK1 模具 黑苹果保姆级教程整理
  12. SCI论文下载之chrome插件
  13. 深度学习与计算机视觉教程(13) | 目标检测 (SSD,YOLO系列)(CV通关指南·完结)
  14. 520送什么礼物好呢、适合送女友的礼物推荐
  15. 几个网络捕获工具的评价
  16. DISC职业性格测试附完整分析.doc
  17. 网络驱动之net_device结构体
  18. 利用OneDrive网盘建站
  19. 外置USB供电与内置锂电池供电自动切换电路,便携电子设备常用,经典电路必须掌握...
  20. 管理经济学知识点汇总

热门文章

  1. 2020年,微信的基地属性正在悄然转向
  2. c++ struct 中定义函数
  3. ASF网站自带python脚本完成sentinel-1数据自动下载
  4. html如何实现左右布局,前端中的左右布局实现
  5. 怎样与常见的9种人打交道
  6. centos下申请阿里云泛域名证书并自动更新
  7. 无需电脑的多平台推流编码器
  8. 100倍分析性能提升 清华冠军团队用图数据震惊世界
  9. MySql版本号查看命令
  10. 小米手机超越苹果,成欧洲第二;马斯克特斯拉内部邮件:痛恨开会,少讲黑话;Spring 6.0 发布|极客头条...