New file |
| | |
| | | |
| | | 项目描述 .... |
| | | - 参考网址:https://developer.aliyun.com/article/1199555 |
| | | |
New file |
| | |
| | | <?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 http://maven.apache.org/xsd/maven-4.0.0.xsd"> |
| | | <modelVersion>4.0.0</modelVersion> |
| | | <parent> |
| | | <groupId>org.springframework.boot</groupId> |
| | | <artifactId>spring-boot-starter-parent</artifactId> |
| | | <version>2.4.5</version> |
| | | <relativePath/> <!-- lookup parent from repository --> |
| | | </parent> |
| | | <groupId>com.boying</groupId> |
| | | <artifactId>HkVideo</artifactId> |
| | | <version>1.0-SNAPSHOT</version> |
| | | |
| | | <properties> |
| | | <maven.compiler.source>8</maven.compiler.source> |
| | | <maven.compiler.target>8</maven.compiler.target> |
| | | <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> |
| | | <spring.boot.version>2.2.6.RELEASE</spring.boot.version> |
| | | <spring.boot.admin.version>2.2.2</spring.boot.admin.version> |
| | | <gson.version>2.8.6</gson.version> |
| | | <hutool.version>5.3.2</hutool.version> |
| | | <lombok.version>1.18.12</lombok.version> |
| | | </properties> |
| | | |
| | | <dependencies> |
| | | <dependency> |
| | | <groupId>org.springframework.boot</groupId> |
| | | <artifactId>spring-boot-starter-web</artifactId> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>org.springframework.boot</groupId> |
| | | <artifactId>spring-boot-starter-data-redis</artifactId> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>org.springframework.boot</groupId> |
| | | <artifactId>spring-boot-starter-test</artifactId> |
| | | <scope>test</scope> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>org.springframework</groupId> |
| | | <artifactId>spring-context-support</artifactId> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>com.alibaba</groupId> |
| | | <artifactId>fastjson</artifactId> |
| | | <version>1.2.37</version> |
| | | </dependency> |
| | | <!-- Gson --> |
| | | <dependency> |
| | | <groupId>com.google.code.gson</groupId> |
| | | <artifactId>gson</artifactId> |
| | | <version>${gson.version}</version> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>cn.hutool</groupId> |
| | | <artifactId>hutool-all</artifactId> |
| | | <version>${hutool.version}</version> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>org.projectlombok</groupId> |
| | | <artifactId>lombok</artifactId> |
| | | <version>${lombok.version}</version> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>net.java.jna</groupId> |
| | | <artifactId>jna</artifactId> |
| | | <version>1.0.0</version> |
| | | <scope>system</scope> |
| | | <systemPath>${project.basedir}/lib/jna.jar</systemPath> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>net.java.jna</groupId> |
| | | <artifactId>examples</artifactId> |
| | | <version>1.0.0</version> |
| | | <scope>system</scope> |
| | | <systemPath>${project.basedir}/lib/examples.jar</systemPath> |
| | | </dependency> |
| | | </dependencies> |
| | | <build> |
| | | <plugins> |
| | | <plugin> |
| | | <groupId>org.springframework.boot</groupId> |
| | | <artifactId>spring-boot-maven-plugin</artifactId> |
| | | <configuration> |
| | | <includeSystemScope>true</includeSystemScope> |
| | | <mainClass>com.boying.HkApplication</mainClass> |
| | | </configuration> |
| | | <executions> |
| | | <execution> |
| | | <goals> |
| | | <goal>repackage</goal> |
| | | </goals> |
| | | </execution> |
| | | </executions> |
| | | </plugin> |
| | | </plugins> |
| | | </build> |
| | | |
| | | |
| | | </project> |
New file |
| | |
| | | <?xml version="1.0" encoding="GB2312"?> |
| | | <SdkLocal> |
| | | <SdkLog> |
| | | <logLevel>3</logLevel><!--req, 1-ERROR, 2-DEBUG, 3-INFO--> |
| | | <logDirectory>./SDKLOG/</logDirectory><!--the end of the string must be '/'--> |
| | | <autoDelete>true</autoDelete><!--true: There are less than 10 files in the directory, it will be auto deleted by sdk when the files are more than 10; false: No upper limit to the number of log files--> |
| | | </SdkLog> |
| | | <HeartbeatCfg> |
| | | <Interval>120</Interval> <!-- 心跳时间间隔,单位秒,等于0,使用默认值120s,取值范围为[30, 120] 小于30s,间隔为30s,大于120s,间隔为120s--> |
| | | <Count>1</Count> <!-- 触发异常回调需要心跳交互异常的次数,等于0,使用默认值1次--> |
| | | </HeartbeatCfg> |
| | | </SdkLocal> |
New file |
| | |
| | | The dll in this directory(iconv.dll,libxml2.dll,zlib1.dll,calib.dll)only used in ClientDemo. |
New file |
| | |
| | | package com.boying; |
| | | |
| | | import org.springframework.boot.SpringApplication; |
| | | import org.springframework.boot.autoconfigure.SpringBootApplication; |
| | | import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; |
| | | import org.springframework.context.annotation.Bean; |
| | | import org.springframework.scheduling.annotation.EnableScheduling; |
| | | |
| | | import java.util.concurrent.ArrayBlockingQueue; |
| | | import java.util.concurrent.ThreadPoolExecutor; |
| | | import java.util.concurrent.TimeUnit; |
| | | |
| | | /** |
| | | * @author kdq |
| | | * @version 1.0.0 |
| | | * @ClassName HkApplication.java |
| | | * @Description TODO 参考网址: https://developer.aliyun.com/article/1199555 |
| | | * @createTime 2024年06月25日 09:37:00 |
| | | */ |
| | | @SpringBootApplication(exclude = DataSourceAutoConfiguration.class) |
| | | @EnableScheduling |
| | | public class HkApplication { |
| | | public static void main(String[] args) { |
| | | System.out.println("项目文件夹为:"+System.getProperty("user.dir")); |
| | | SpringApplication.run(HkApplication.class, args); |
| | | } |
| | | |
| | | // //懒行为 创建对象并放到Spring容器中 |
| | | @Bean |
| | | public ThreadPoolExecutor threadPoolExecutor() { |
| | | return new ThreadPoolExecutor(10, |
| | | 20, |
| | | 60L, |
| | | TimeUnit.SECONDS, |
| | | new ArrayBlockingQueue<>(10)); |
| | | } |
| | | |
| | | } |
New file |
| | |
| | | package com.boying.Util; |
| | | |
| | | import com.sun.jna.Platform; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import java.io.File; |
| | | |
| | | @Slf4j |
| | | public class OSUtils { |
| | | // 获取操作平台信息 |
| | | public static String getOsPrefix() { |
| | | String arch = System.getProperty("os.arch").toLowerCase(); |
| | | final String name = System.getProperty("os.name"); |
| | | String osPrefix; |
| | | if (Platform.isWindows()) { |
| | | if ("i386".equals(arch)) { |
| | | arch = "x86"; |
| | | } |
| | | osPrefix = "win32-" + arch; |
| | | } else if (Platform.isLinux()) { |
| | | if ("x86".equals(arch)) { |
| | | arch = "i386"; |
| | | } else if ("x86_64".equals(arch)) { |
| | | arch = "amd64"; |
| | | } |
| | | osPrefix = "linux-" + arch; |
| | | } else { |
| | | osPrefix = name.toLowerCase(); |
| | | if ("x86".equals(arch)) { |
| | | arch = "i386"; |
| | | } |
| | | if ("x86_64".equals(arch)) { |
| | | arch = "amd64"; |
| | | } |
| | | int space = osPrefix.indexOf(" "); |
| | | if (space != -1) { |
| | | osPrefix = osPrefix.substring(0, space); |
| | | } |
| | | osPrefix += "-" + arch; |
| | | } |
| | | return osPrefix; |
| | | } |
| | | public static String getOsName() { |
| | | String osName = ""; |
| | | String osPrefix = getOsPrefix(); |
| | | if (osPrefix.toLowerCase().startsWith("win32-x86") |
| | | || osPrefix.toLowerCase().startsWith("win32-amd64")) { |
| | | osName = "win"; |
| | | } else if (osPrefix.toLowerCase().startsWith("linux-i386") |
| | | || osPrefix.toLowerCase().startsWith("linux-amd64")) { |
| | | osName = "linux"; |
| | | } |
| | | return osName; |
| | | } |
| | | /** |
| | | * 获取库文件 |
| | | * 区分win、linux |
| | | * |
| | | * @return |
| | | */ |
| | | public static String getLoadLibrary() { |
| | | if (isChecking()) { |
| | | return null; |
| | | } |
| | | String userDir = System.getProperty("user.dir"); |
| | | log.info("getLoadLibrary-userDir={}", userDir); |
| | | String loadLibrary = ""; |
| | | String library = ""; |
| | | String osPrefix = getOsPrefix(); |
| | | if (osPrefix.toLowerCase().startsWith("win32-x86")) { |
| | | loadLibrary = System.getProperty("user.dir") + File.separator + "sdk" + File.separator + "hklibwin32" + File.separator; |
| | | library = "HCNetSDK.dll"; |
| | | } else if (osPrefix.toLowerCase().startsWith("win32-amd64")) { |
| | | loadLibrary = System.getProperty("user.dir") + File.separator + "sdk" + File.separator + "hklibwin64" + File.separator; |
| | | library = "HCNetSDK.dll"; |
| | | } else if (osPrefix.toLowerCase().startsWith("linux-i386")) { |
| | | //同 linux-amd64 |
| | | loadLibrary = ""; |
| | | library = "libhcnetsdk.so"; |
| | | } else if (osPrefix.toLowerCase().startsWith("linux-amd64")) { |
| | | //方式一:使用系统默认的加载库路径,在系统的/usr/lib文件中加入你Java工程所需要使用的so文件,然后将HCNetSDKCom文件夹下的组件库也复制到/usr/lib目录,HCNetSDKCom文件夹中的组件库不要随意更换路径。CentOS 64位需拷贝到/usr/lib64下。 |
| | | //针对方式一,前缀就是绝对路径 |
| | | //loadLibrary = "/usr/lib64/lib/hkliblinux64/"; |
| | | //方式二:配置LD_LIBRARY_PATH环境变量加载库文件;配置/etc/ld.so.conf,加上你自己的Java工程所需要的so文件的路径 |
| | | //针对方式二,无需添加前缀,程序会从linux系统的so共享库中查找libhcnetsdk.so |
| | | loadLibrary = ""; |
| | | library = "libhcnetsdk.so"; |
| | | } |
| | | log.info("================= Load library Path :{} ==================", loadLibrary + library); |
| | | return loadLibrary + library; |
| | | } |
| | | |
| | | /** |
| | | * 获取播放库文件 |
| | | * 区分win、linux |
| | | * |
| | | * @return |
| | | */ |
| | | public static String getLoadPlayLibrary() { |
| | | if (isChecking()) { |
| | | return null; |
| | | } |
| | | String userDir = System.getProperty("user.dir"); |
| | | log.info("getPlayLibrary-userDir={}", userDir); |
| | | String loadLibrary = ""; |
| | | String library = ""; |
| | | String osPrefix = getOsPrefix(); |
| | | if (osPrefix.toLowerCase().startsWith("win32-x86")) { |
| | | loadLibrary = System.getProperty("user.dir") + File.separator + "sdk" + File.separator + "hklibwin32" + File.separator; |
| | | library = "PlayCtrl.dll"; |
| | | } else if (osPrefix.toLowerCase().startsWith("win32-amd64")) { |
| | | loadLibrary = System.getProperty("user.dir") + File.separator + "sdk" + File.separator + "hklibwin64" + File.separator; |
| | | library = "PlayCtrl.dll"; |
| | | } else if (osPrefix.toLowerCase().startsWith("linux-i386")) { |
| | | //同 linux-amd64 |
| | | loadLibrary = ""; |
| | | library = "libPlayCtrl.so"; |
| | | } else if (osPrefix.toLowerCase().startsWith("linux-amd64")) { |
| | | //方式一:使用系统默认的加载库路径,在系统的/usr/lib文件中加入你Java工程所需要使用的so文件,然后将HCNetSDKCom文件夹下的组件库也复制到/usr/lib目录,HCNetSDKCom文件夹中的组件库不要随意更换路径。CentOS 64位需拷贝到/usr/lib64下。 |
| | | //针对方式一,前缀就是绝对路径 |
| | | //loadLibrary = "/usr/lib64/lib/hkliblinux64/"; |
| | | //方式二:配置LD_LIBRARY_PATH环境变量加载库文件;配置/etc/ld.so.conf,加上你自己的Java工程所需要的so文件的路径 |
| | | //针对方式二,无需添加前缀,程序会从linux系统的so共享库中查找libhcnetsdk.so |
| | | loadLibrary = ""; |
| | | library = "libPlayCtrl.so"; |
| | | } |
| | | log.info("================= Load PlayLibrary Path :{} ==================", loadLibrary + library); |
| | | return loadLibrary + library; |
| | | } |
| | | private static boolean checking = false; |
| | | public static void setChecking() { |
| | | checking = true; |
| | | } |
| | | public static void clearChecking() { |
| | | checking = false; |
| | | } |
| | | public static boolean isChecking() { |
| | | return checking; |
| | | } |
| | | } |
| | | |
| | | |
New file |
| | |
| | | package com.boying.common; |
| | | |
| | | import com.boying.service.SdkInitService; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.boot.ApplicationArguments; |
| | | import org.springframework.boot.ApplicationRunner; |
| | | import org.springframework.stereotype.Component; |
| | | |
| | | @Component |
| | | public class AppRunner implements ApplicationRunner { |
| | | @Autowired |
| | | private SdkInitService hksdkInitService; |
| | | @Override |
| | | public void run(ApplicationArguments args) throws Exception { |
| | | hksdkInitService.initSdk(); |
| | | } |
| | | } |
| | | |
| | | |
New file |
| | |
| | | package com.boying.common; |
| | | |
| | | public class CommonUtil { |
| | | |
| | | //SDK时间解析 |
| | | public static String parseTime(int time) |
| | | { |
| | | int dwYear=(time>>26)+2000; |
| | | int dwMonth=(time>>22)&15; |
| | | int dwDay=(time>>17)&31; |
| | | int dwHour=(time>>12)&31; |
| | | int dwMinute=(time>>6)&63; |
| | | int dwSecond=(time>>0)&63; |
| | | |
| | | String sTime = String.format("%04d", dwYear) + |
| | | String.format("%02d", dwMonth) + |
| | | String.format("%02d", dwDay) + |
| | | String.format("%02d", dwHour) + |
| | | String.format("%02d", dwMinute) + |
| | | String.format("%02d", dwSecond); |
| | | // System.out.println(sTime); |
| | | return sTime; |
| | | } |
| | | |
| | | |
| | | } |
New file |
| | |
| | | package com.boying.common; |
| | | |
| | | import java.io.BufferedReader; |
| | | import java.io.IOException; |
| | | import java.io.InputStream; |
| | | import java.io.InputStreamReader; |
| | | import java.util.ArrayList; |
| | | import java.util.List; |
| | | |
| | | public class ConvetorUtil { |
| | | private static String ffmpegEXE = "E:\\HK\\ffmpeg-7.0.1-essentials_build\\bin\\ffmpeg.exe"; |
| | | public static void convetor(String videoInputPath, String videoOutPath) throws Exception { |
| | | List<String> command = new ArrayList<String>(); |
| | | command.add(ffmpegEXE); |
| | | command.add("-i"); |
| | | command.add(videoInputPath); |
| | | command.add("-c"); |
| | | command.add("copy"); |
| | | command.add("-an"); |
| | | command.add(videoOutPath); |
| | | ProcessBuilder builder = new ProcessBuilder(command); |
| | | Process process = null; |
| | | try { |
| | | process = builder.start(); |
| | | } catch (IOException e) { |
| | | // TODO Auto-generated catch block |
| | | e.printStackTrace(); |
| | | } |
| | | // 使用这种方式会在瞬间大量消耗CPU和内存等系统资源,所以这里我们需要对流进行处理 |
| | | InputStream errorStream = process.getErrorStream(); |
| | | InputStreamReader inputStreamReader = new InputStreamReader(errorStream); |
| | | BufferedReader br = new BufferedReader(inputStreamReader); |
| | | String line = ""; |
| | | while ((line = br.readLine()) != null) { |
| | | } |
| | | if (br != null) { |
| | | br.close(); |
| | | } |
| | | if (inputStreamReader != null) { |
| | | inputStreamReader.close(); |
| | | } |
| | | if (errorStream != null) { |
| | | errorStream.close(); |
| | | } |
| | | |
| | | } |
| | | } |
New file |
| | |
| | | package com.boying.common; |
| | | |
| | | import com.boying.Util.OSUtils; |
| | | import com.boying.service.HCNetSDK; |
| | | import com.boying.service.SdkInitService; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import java.util.Objects; |
| | | |
| | | @Slf4j |
| | | public class InitSdkTask implements Runnable { |
| | | /** |
| | | * 装配 sdk 所需依赖 |
| | | */ |
| | | static HCNetSDK hCNetSDK = SdkInitService.hcNetSDK; |
| | | |
| | | @Override |
| | | public void run() { |
| | | try { |
| | | if (Objects.equals(OSUtils.getOsName(), "linux")) { |
| | | log.info("InitSdk-is-linux"); |
| | | String userDir = System.getProperty("user.dir"); |
| | | log.info("InitSdk-userDir={}", userDir); |
| | | String osPrefix = OSUtils.getOsPrefix(); |
| | | if (osPrefix.toLowerCase().startsWith("linux-i386")) { |
| | | HCNetSDK.BYTE_ARRAY ptrByteArray1 = new HCNetSDK.BYTE_ARRAY(256); |
| | | HCNetSDK.BYTE_ARRAY ptrByteArray2 = new HCNetSDK.BYTE_ARRAY(256); |
| | | //这里是库的绝对路径,请根据实际情况修改,注意改路径必须有访问权限 |
| | | //linux 下, 库加载参考:OSUtils.getLoadLibrary() |
| | | String strPath1 = System.getProperty("user.dir") + "/hkliblinux32/libcrypto.so.1.1"; |
| | | String strPath2 = System.getProperty("user.dir") + "/hkliblinux32/libssl.so.1.1"; |
| | | System.arraycopy(strPath1.getBytes(), 0, ptrByteArray1.byValue, 0, strPath1.length()); |
| | | ptrByteArray1.write(); |
| | | hCNetSDK.NET_DVR_SetSDKInitCfg(3, ptrByteArray1.getPointer()); |
| | | System.arraycopy(strPath2.getBytes(), 0, ptrByteArray2.byValue, 0, strPath2.length()); |
| | | ptrByteArray2.write(); |
| | | hCNetSDK.NET_DVR_SetSDKInitCfg(4, ptrByteArray2.getPointer()); |
| | | //linux 下, 库加载参考:OSUtils.getLoadLibrary() |
| | | String strPathCom = System.getProperty("user.dir") + "/hkliblinux32/HCNetSDKCom/"; |
| | | HCNetSDK.NET_DVR_LOCAL_SDK_PATH struComPath = new HCNetSDK.NET_DVR_LOCAL_SDK_PATH(); |
| | | System.arraycopy(strPathCom.getBytes(), 0, struComPath.sPath, 0, strPathCom.length()); |
| | | struComPath.write(); |
| | | hCNetSDK.NET_DVR_SetSDKInitCfg(2, struComPath.getPointer()); |
| | | } else if (osPrefix.toLowerCase().startsWith("linux-amd64")) { |
| | | HCNetSDK.BYTE_ARRAY ptrByteArray1 = new HCNetSDK.BYTE_ARRAY(256); |
| | | HCNetSDK.BYTE_ARRAY ptrByteArray2 = new HCNetSDK.BYTE_ARRAY(256); |
| | | //这里是库的绝对路径,请根据实际情况修改,注意改路径必须有访问权限 |
| | | //linux 下, 库加载参考:OSUtils.getLoadLibrary() |
| | | String strPath1 = System.getProperty("user.dir") + "/hkliblinux64/libcrypto.so.1.1"; |
| | | String strPath2 = System.getProperty("user.dir") + "/hkliblinux64/libssl.so.1.1"; |
| | | System.arraycopy(strPath1.getBytes(), 0, ptrByteArray1.byValue, 0, strPath1.length()); |
| | | ptrByteArray1.write(); |
| | | hCNetSDK.NET_DVR_SetSDKInitCfg(3, ptrByteArray1.getPointer()); |
| | | System.arraycopy(strPath2.getBytes(), 0, ptrByteArray2.byValue, 0, strPath2.length()); |
| | | ptrByteArray2.write(); |
| | | hCNetSDK.NET_DVR_SetSDKInitCfg(4, ptrByteArray2.getPointer()); |
| | | String strPathCom = System.getProperty("user.dir") + "/hkliblinux64/HCNetSDKCom/"; |
| | | //linux 下, 库加载参考:OSUtils.getLoadLibrary() |
| | | HCNetSDK.NET_DVR_LOCAL_SDK_PATH struComPath = new HCNetSDK.NET_DVR_LOCAL_SDK_PATH(); |
| | | System.arraycopy(strPathCom.getBytes(), 0, struComPath.sPath, 0, strPathCom.length()); |
| | | struComPath.write(); |
| | | hCNetSDK.NET_DVR_SetSDKInitCfg(2, struComPath.getPointer()); |
| | | } else { |
| | | log.info("osPrefix={}", osPrefix); |
| | | } |
| | | } |
| | | //初始化sdk |
| | | boolean isOk = hCNetSDK.NET_DVR_Init(); |
| | | hCNetSDK.NET_DVR_SetConnectTime(10, 1); |
| | | hCNetSDK.NET_DVR_SetReconnect(100, true); |
| | | if (!isOk) { |
| | | log.error("=================== InitSDK init fail ==================="); |
| | | } else { |
| | | log.info("============== InitSDK init success ===================="); |
| | | } |
| | | } catch (Exception e) { |
| | | log.error("InitSDK-error,e={}", e.getMessage()); |
| | | e.printStackTrace(); |
| | | } |
| | | } |
| | | } |
| | | |
| | | |
New file |
| | |
| | | package com.boying.common; |
| | | |
| | | import com.boying.entity.Dvr; |
| | | import com.boying.service.HCNetSDK; |
| | | import com.boying.service.SdkInitService; |
| | | |
| | | public class LoginSdkUtil { |
| | | private static HCNetSDK hCNetSDK = SdkInitService.hcNetSDK; |
| | | private static Integer login(Dvr dvr){ |
| | | HCNetSDK.NET_DVR_DEVICEINFO_V30 m_strDeviceInfo = new HCNetSDK.NET_DVR_DEVICEINFO_V30(); |
| | | int lUserID = hCNetSDK.NET_DVR_Login_V30(dvr.getDvrip(),(short)dvr.getDvrport(),dvr.getDvrusername(),dvr.getDvrpassword(), m_strDeviceInfo); |
| | | long userID = lUserID; |
| | | if (userID == -1) { |
| | | System.out.println("hksdk(视频)-海康sdk登录失败!"); |
| | | return -1; |
| | | } |
| | | return lUserID; |
| | | } |
| | | } |
New file |
| | |
| | | package com.boying.common; |
| | | |
| | | /** |
| | | * @author jiangxin |
| | | * @create 2022-01-19-16:40 |
| | | */ |
| | | public class osSelect { |
| | | |
| | | public static boolean isLinux() { |
| | | return System.getProperty("os.name").toLowerCase().contains("linux"); |
| | | } |
| | | |
| | | public static boolean isWindows() { |
| | | return System.getProperty("os.name").toLowerCase().contains("windows"); |
| | | } |
| | | } |
New file |
| | |
| | | package com.boying.controller; |
| | | |
| | | import com.alibaba.fastjson.JSON; |
| | | import com.boying.entity.CameraSnapDto; |
| | | import com.boying.entity.VideoRecordDto; |
| | | import lombok.Data; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.data.redis.core.RedisTemplate; |
| | | import org.springframework.web.bind.annotation.GetMapping; |
| | | import org.springframework.web.bind.annotation.RequestMapping; |
| | | import org.springframework.web.bind.annotation.RestController; |
| | | |
| | | import java.text.ParseException; |
| | | import java.text.SimpleDateFormat; |
| | | |
| | | @RestController |
| | | @RequestMapping("/test") |
| | | public class TestController { |
| | | |
| | | @Autowired |
| | | private RedisTemplate redisTemplate; |
| | | |
| | | @GetMapping("/data") |
| | | public void test() throws ParseException { |
| | | // CameraSnapDto dto = new CameraSnapDto(); |
| | | // dto.setChannel(33l); |
| | | // dto.setEqUrl("192.168.0.180"); |
| | | // dto.setEqUser("admin"); |
| | | // dto.setEqPassword("Boying123"); |
| | | // dto.setImgName("test.jpg"); |
| | | // String jsonStr = JSON.toJSONString(dto); |
| | | // redisTemplate.boundListOps("snap:").leftPush(jsonStr); |
| | | SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); |
| | | String start = "2024-07-04 16:05:01"; |
| | | String end = "2024-07-04 16:07:02"; |
| | | VideoRecordDto dto1 = new VideoRecordDto(); |
| | | dto1.setEqPort(33); |
| | | dto1.setDiskUrl("192.168.0.180"); |
| | | dto1.setDiskUser("admin"); |
| | | dto1.setDiskPassword("Boying123"); |
| | | dto1.setVideoName("video.mp4"); |
| | | dto1.setStartTime(sdf.parse(start)); |
| | | dto1.setEndTime(sdf.parse(end)); |
| | | redisTemplate.boundListOps("VIDEO_EQ_KEY:").leftPush(dto1); |
| | | |
| | | } |
| | | |
| | | } |
New file |
| | |
| | | package com.boying.controller; |
| | | |
| | | import com.boying.common.osSelect; |
| | | import com.boying.entity.Dvr; |
| | | import com.boying.service.HCNetSDK; |
| | | import com.sun.jna.Native; |
| | | import com.sun.jna.ptr.IntByReference; |
| | | import org.slf4j.Logger; |
| | | import org.slf4j.LoggerFactory; |
| | | |
| | | import java.io.File; |
| | | import java.text.ParseException; |
| | | import java.text.SimpleDateFormat; |
| | | import java.util.Date; |
| | | import java.util.Timer; |
| | | |
| | | public class VideoDownLoad { |
| | | |
| | | private static Logger logger = LoggerFactory.getLogger(VideoDownLoad.class); |
| | | private static HCNetSDK hcNetSDK = null; |
| | | private int userId;//用户句柄 |
| | | private int loadHandle;//下载句柄 |
| | | private Timer downloadTimer; |
| | | |
| | | /** |
| | | * 动态库加载 |
| | | * |
| | | * @return |
| | | */ |
| | | private static boolean createSDKInstance() { |
| | | if (hcNetSDK == null) { |
| | | synchronized (HCNetSDK.class) { |
| | | String strDllPath = ""; |
| | | try { |
| | | if (osSelect.isWindows()) |
| | | //win系统加载库路径 |
| | | strDllPath = "E:\\HK\\HCNetSDK.dll"; |
| | | |
| | | else if (osSelect.isLinux()) |
| | | //Linux系统加载库路径 |
| | | strDllPath = "E:\\HK\\HCNetSDK.so"; |
| | | hcNetSDK = (HCNetSDK) Native.loadLibrary(strDllPath, HCNetSDK.class); |
| | | } catch (Exception ex) { |
| | | System.out.println("loadLibrary: " + strDllPath + " Error: " + ex.getMessage()); |
| | | return false; |
| | | } |
| | | } |
| | | } |
| | | return true; |
| | | } |
| | | |
| | | /** |
| | | * |
| | | * @param m_sDeviceIP 设备ip地址 |
| | | * @param wPort 端口号,设备网络SDK登录默认端口8000 |
| | | * @param m_sUsername 用户名 |
| | | * @param m_sPassword 密码 |
| | | */ |
| | | public void Login_V40(String m_sDeviceIP,short wPort,String m_sUsername,String m_sPassword) { |
| | | /* 注册 */ |
| | | // 设备登录信息 |
| | | HCNetSDK.NET_DVR_USER_LOGIN_INFO m_strLoginInfo = new HCNetSDK.NET_DVR_USER_LOGIN_INFO(); |
| | | |
| | | // 设备信息 |
| | | HCNetSDK.NET_DVR_DEVICEINFO_V40 m_strDeviceInfo = new HCNetSDK.NET_DVR_DEVICEINFO_V40(); |
| | | m_strLoginInfo.sDeviceAddress = new byte[HCNetSDK.NET_DVR_DEV_ADDRESS_MAX_LEN]; |
| | | System.arraycopy(m_sDeviceIP.getBytes(), 0, m_strLoginInfo.sDeviceAddress, 0, m_sDeviceIP.length()); |
| | | m_strLoginInfo.wPort =wPort ; |
| | | m_strLoginInfo.sUserName = new byte[HCNetSDK.NET_DVR_LOGIN_USERNAME_MAX_LEN]; |
| | | System.arraycopy(m_sUsername.getBytes(), 0, m_strLoginInfo.sUserName, 0, m_sUsername.length()); |
| | | m_strLoginInfo.sPassword = new byte[HCNetSDK.NET_DVR_LOGIN_PASSWD_MAX_LEN]; |
| | | System.arraycopy(m_sPassword.getBytes(), 0, m_strLoginInfo.sPassword, 0, m_sPassword.length()); |
| | | // 是否异步登录:false- 否,true- 是 |
| | | m_strLoginInfo.bUseAsynLogin = false; |
| | | // write()调用后数据才写入到内存中 |
| | | m_strLoginInfo.write(); |
| | | |
| | | userId = hcNetSDK.NET_DVR_Login_V40(m_strLoginInfo, m_strDeviceInfo); |
| | | if (userId == -1) { |
| | | System.out.println("登录失败,错误码为" + hcNetSDK.NET_DVR_GetLastError()); |
| | | return; |
| | | } else { |
| | | System.out.println("登录成功!"); |
| | | |
| | | // read()后,结构体中才有对应的数据 |
| | | m_strDeviceInfo.read(); |
| | | return; |
| | | } |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 按时间下载视频 |
| | | */ |
| | | private boolean downloadVideo(Dvr dvr, Date startTime, Date endTime, String filePath, int channel) { |
| | | if(hcNetSDK == null){ |
| | | if (!createSDKInstance()) { |
| | | System.out.println("Load SDK fail"); |
| | | return false; |
| | | } |
| | | } |
| | | if (userId > -1) { |
| | | //先注销 |
| | | hcNetSDK.NET_DVR_Logout_V30(userId); |
| | | userId = -1; |
| | | } |
| | | boolean initFlag = hcNetSDK.NET_DVR_Init(); |
| | | if (!initFlag) { //返回值为布尔值 fasle初始化失败 |
| | | logger.warn("hksdk(视频)-海康sdk初始化失败!"); |
| | | return false; |
| | | } |
| | | |
| | | //启动SDK写日志 |
| | | hcNetSDK.NET_DVR_SetLogToFile(3, "./sdkLog", false); |
| | | |
| | | HCNetSDK.NET_DVR_DEVICEINFO_V30 m_strDeviceInfo = new HCNetSDK.NET_DVR_DEVICEINFO_V30(); |
| | | userId = hcNetSDK.NET_DVR_Login_V30(dvr.getDvrip(),(short) dvr.getDvrport(), dvr.getDvrusername(), new String(dvr.getDvrpassword()), m_strDeviceInfo); |
| | | logger.info("hksdk(视频)-登录海康录像机信息,状态值:" + hcNetSDK.NET_DVR_GetLastError()); |
| | | long lUserId = userId; |
| | | if (lUserId == -1) { |
| | | logger.warn("hksdk(视频)-海康sdk登录失败!"); |
| | | return false; |
| | | } |
| | | // loadHandle = new NativeLong(-1); |
| | | if (loadHandle == -1) { |
| | | loadHandle = hcNetSDK.NET_DVR_GetFileByTime(userId, channel, getHkTime(startTime), getHkTime(endTime), filePath); |
| | | logger.info("hksdk(视频)-获取播放句柄信息,状态值:" + hcNetSDK.NET_DVR_GetLastError()); |
| | | if (loadHandle >= 0) { |
| | | // 判断文件夹是否存在 |
| | | File files = new File(filePath); |
| | | if(!files.exists()){ |
| | | files.mkdirs(); |
| | | } |
| | | boolean downloadFlag = hcNetSDK.NET_DVR_PlayBackControl(loadHandle, hcNetSDK.NET_DVR_PLAYSTART, 0, null); |
| | | int tmp = -1; |
| | | IntByReference pos = new IntByReference(); |
| | | while (true) { |
| | | boolean backFlag = hcNetSDK.NET_DVR_PlayBackControl(loadHandle, hcNetSDK.NET_DVR_PLAYGETPOS, 0, pos); |
| | | if (!backFlag) {//防止单个线程死循环 |
| | | return downloadFlag; |
| | | } |
| | | int produce = pos.getValue(); |
| | | if ((produce % 10) == 0 && tmp != produce) {//输出进度 |
| | | tmp = produce; |
| | | logger.info("hksdk(视频)-视频下载进度:" + "==" + produce + "%"); |
| | | } |
| | | if (produce == 100) {//下载成功 |
| | | hcNetSDK.NET_DVR_StopGetFile(loadHandle); |
| | | loadHandle=-1; |
| | | hcNetSDK.NET_DVR_Logout(userId);//退出录像机 |
| | | logger.info("hksdk(视频)-退出状态" + hcNetSDK.NET_DVR_GetLastError()); |
| | | hcNetSDK.NET_DVR_Cleanup(); |
| | | |
| | | // Media media = new Media(); |
| | | // media.setDisasterId(disasterId); |
| | | // media.setType(MediaType.VIDEO); |
| | | // media.setCreateDate(new Date()); |
| | | // media.setUploadTime(new Date()); |
| | | // media.setAttachmentName("z" + fileName); |
| | | // media.setIsDeleted(false); |
| | | // media.setUpdate_rhtx(1); |
| | | // media.setFlag("OTHER"); |
| | | // media.setNewsFeedId(0); |
| | | // String http_path = restUrlLocalhost; |
| | | // media.setUrl(http_path + "/urgentlogistic/file/mp4/" + newDate + "/z" +fileName); |
| | | // mediaService.create(media); |
| | | // |
| | | // try { |
| | | // // 视频进行转码 |
| | | // ConvetorUtil.convetor(filePath + fileName,filePath + "z" +fileName); |
| | | // File file = new File(filePath + fileName); |
| | | // // 如果文件路径所对应的文件存在,并且是一个文件,则直接删除 |
| | | // file.delete(); |
| | | // } catch (Exception e) { |
| | | // e.printStackTrace(); |
| | | // } |
| | | |
| | | return true; |
| | | } |
| | | if (produce > 100) {//下载失败 |
| | | hcNetSDK.NET_DVR_StopGetFile(loadHandle); |
| | | loadHandle=-1; |
| | | logger.warn("hksdk(视频)-海康sdk由于网络原因或DVR忙,下载异常终止!错误原因:" + hcNetSDK.NET_DVR_GetLastError()); |
| | | //hcNetSDK.NET_DVR_Logout(userId);//退出录像机 |
| | | //logger.info("hksdk(视频)-退出状态"+hcNetSDK.NET_DVR_GetLastError()); |
| | | return false; |
| | | } |
| | | } |
| | | } else { |
| | | System.out.println("hksdk(视频)-下载失败" + hcNetSDK.NET_DVR_GetLastError()); |
| | | return false; |
| | | } |
| | | } |
| | | return false; |
| | | } |
| | | |
| | | /** |
| | | * 获取海康录像机格式的时间 |
| | | */ |
| | | private HCNetSDK.NET_DVR_TIME getHkTime(Date time) { |
| | | HCNetSDK.NET_DVR_TIME structTime = new HCNetSDK.NET_DVR_TIME(); |
| | | String str = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss").format(time); |
| | | String[] times = str.split("-"); |
| | | structTime.dwYear = Integer.parseInt(times[0]); |
| | | structTime.dwMonth = Integer.parseInt(times[1]); |
| | | structTime.dwDay = Integer.parseInt(times[2]); |
| | | structTime.dwHour = Integer.parseInt(times[3]); |
| | | structTime.dwMinute = Integer.parseInt(times[4]); |
| | | structTime.dwSecond = Integer.parseInt(times[5]); |
| | | return structTime; |
| | | } |
| | | |
| | | public static void main(String[] args) { |
| | | SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss"); |
| | | Date startTime = null; |
| | | Date endTime = null; |
| | | try { |
| | | startTime = sdf.parse("20240625153300"); //开始时间 |
| | | endTime = sdf.parse("20240625153500"); //结束时间 |
| | | } catch (ParseException e) { |
| | | e.printStackTrace(); |
| | | } |
| | | VideoDownLoad test = new VideoDownLoad(); |
| | | Dvr dvr = new Dvr("http://192.168.0.180",8000,"admin","Boying123"); |
| | | int channel = 33;//通道 |
| | | System.out.print(test.downloadVideo(dvr, startTime, endTime, "E:\\HK\\test.mp4", channel)); |
| | | } |
| | | } |
New file |
| | |
| | | package com.boying.entity; |
| | | |
| | | import lombok.Data; |
| | | |
| | | import java.io.Serializable; |
| | | |
| | | @Data |
| | | public class CameraSnapDto implements Serializable { |
| | | private String eqUrl; |
| | | private String eqUser; |
| | | private String eqPassword; |
| | | private String imgName; |
| | | private Long timestamp; |
| | | private int eqPort; |
| | | |
| | | } |
New file |
| | |
| | | package com.boying.entity; |
| | | |
| | | import lombok.Data; |
| | | |
| | | @Data |
| | | public class Dvr { |
| | | // 视频服务器ip地址 |
| | | private String dvrip; |
| | | // 视频服务器端口号 |
| | | private int dvrport; |
| | | // 视频服务器用户名 |
| | | private String dvrusername; |
| | | // 视频服务器密码 |
| | | private String dvrpassword; |
| | | |
| | | public Dvr(String dvrip, int dvrport, String dvrusername, String dvrpassword) { |
| | | this.dvrip = dvrip; |
| | | this.dvrport = dvrport; |
| | | this.dvrusername = dvrusername; |
| | | this.dvrpassword = dvrpassword; |
| | | } |
| | | } |
New file |
| | |
| | | package com.boying.entity; |
| | | |
| | | import lombok.Data; |
| | | |
| | | import java.io.Serializable; |
| | | import java.util.Date; |
| | | |
| | | @Data |
| | | public class VideoRecordDto implements Serializable { |
| | | private String diskUrl; |
| | | private String diskUser; |
| | | private String diskPassword; |
| | | private String videoName; |
| | | private int eqPort; |
| | | private Date startTime; |
| | | private Date endTime; |
| | | } |
New file |
| | |
| | | package com.boying.service; |
| | | |
| | | import com.alibaba.fastjson.JSON; |
| | | import com.boying.entity.CameraSnapDto; |
| | | import com.sun.jna.Pointer; |
| | | import com.sun.jna.ptr.IntByReference; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.beans.factory.annotation.Value; |
| | | import org.springframework.data.redis.core.RedisTemplate; |
| | | import org.springframework.scheduling.annotation.Scheduled; |
| | | import org.springframework.stereotype.Component; |
| | | |
| | | import java.io.File; |
| | | import java.io.FileNotFoundException; |
| | | import java.io.FileOutputStream; |
| | | import java.io.IOException; |
| | | import java.nio.ByteBuffer; |
| | | import java.text.SimpleDateFormat; |
| | | import java.util.Date; |
| | | |
| | | @Component |
| | | public class PicJob { |
| | | |
| | | @Autowired |
| | | private RedisTemplate redisTemplate; |
| | | @Value("${allFilePath.imgPath}") |
| | | private String imgPath; |
| | | private String REDIS_KEY="snap:"; |
| | | private Boolean runFlag = false; |
| | | static HCNetSDK hCNetSDK = SdkInitService.hcNetSDK; |
| | | static PlayCtrl playCtrl = SdkInitService.playCtrl; |
| | | private FRealDataCallBack fRealDataCallBack;//预览回调函数实现 |
| | | private int Count=0; |
| | | int lPlay = -1; //预览句柄 |
| | | int m_lLoadHandle; |
| | | int iPlayBack; //回放句柄 |
| | | int lUserID; |
| | | IntByReference m_lPort= new IntByReference(-1); |
| | | |
| | | @Scheduled(cron = "0/1 * * * * *") |
| | | public void work() throws InterruptedException { |
| | | if(runFlag){ |
| | | return; |
| | | } |
| | | |
| | | CameraSnapDto cameraSnapDto = (CameraSnapDto)redisTemplate.boundListOps(REDIS_KEY).rightPop(); |
| | | if(cameraSnapDto == null){ |
| | | return; |
| | | } |
| | | String loginStatus = (String)redisTemplate.opsForValue().get("Login_Status:"+cameraSnapDto.getEqUrl()); |
| | | if("true".equals(loginStatus)){ |
| | | return; |
| | | } |
| | | if(cameraSnapDto != null){ |
| | | try { |
| | | runFlag = true; |
| | | redisTemplate.opsForValue().set("Login_Status:"+cameraSnapDto.getEqUrl(),"true"); |
| | | HCNetSDK.NET_DVR_DEVICEINFO_V30 m_strDeviceInfo = new HCNetSDK.NET_DVR_DEVICEINFO_V30(); |
| | | lUserID = hCNetSDK.NET_DVR_Login_V30(cameraSnapDto.getEqUrl(),(short)8000,cameraSnapDto.getEqUser(),cameraSnapDto.getEqPassword(), m_strDeviceInfo); |
| | | System.out.println("登录的userid为:"+lUserID); |
| | | long userID = lUserID; |
| | | if (userID == -1) { |
| | | System.out.println("hksdk(视频)-海康sdk登录失败!"+hCNetSDK.NET_DVR_GetLastError()); |
| | | return; |
| | | } |
| | | |
| | | //实时取流 |
| | | realPlay(lUserID,cameraSnapDto.getEqPort()); |
| | | |
| | | getPicbyPlayCtrl(cameraSnapDto.getImgName()); |
| | | |
| | | Thread.sleep(1000); |
| | | //退出程序时调用,每一台设备分别注销 |
| | | // if (hCNetSDK.NET_DVR_Logout(lUserID)) { |
| | | // System.out.println("注销成功"); |
| | | // } |
| | | // |
| | | // //SDK反初始化,释放资源,只需要退出时调用一次 |
| | | // hCNetSDK.NET_DVR_Cleanup(); |
| | | |
| | | }catch (Exception e){ |
| | | runFlag = false; |
| | | }finally { |
| | | runFlag = false; |
| | | redisTemplate.opsForValue().set("Login_Status:"+cameraSnapDto.getEqUrl(),"false"); |
| | | } |
| | | } |
| | | } |
| | | |
| | | public void realPlay(int userID, int iChannelNo) { |
| | | if (userID == -1) { |
| | | System.out.println("请先注册"); |
| | | return; |
| | | } |
| | | HCNetSDK.NET_DVR_PREVIEWINFO strClientInfo = new HCNetSDK.NET_DVR_PREVIEWINFO(); |
| | | strClientInfo.read(); |
| | | strClientInfo.hPlayWnd = 0; //窗口句柄,从回调取流不显示一般设置为空 |
| | | strClientInfo.lChannel = iChannelNo; //通道号 |
| | | strClientInfo.dwStreamType=0; //0-主码流,1-子码流,2-三码流,3-虚拟码流,以此类推 |
| | | strClientInfo.dwLinkMode=0; //连接方式:0- TCP方式,1- UDP方式,2- 多播方式,3- RTP方式,4- RTP/RTSP,5- RTP/HTTP,6- HRUDP(可靠传输) ,7- RTSP/HTTPS,8- NPQ |
| | | strClientInfo.bBlocked=1; |
| | | strClientInfo.byProtoType = 0; |
| | | strClientInfo.write(); |
| | | |
| | | //回调函数定义必须是全局的 |
| | | if (fRealDataCallBack == null) { |
| | | fRealDataCallBack = new FRealDataCallBack(); |
| | | } |
| | | |
| | | //开启预览 |
| | | lPlay = hCNetSDK.NET_DVR_RealPlay_V40(userID, strClientInfo, fRealDataCallBack , null); |
| | | if (lPlay == -1) { |
| | | int iErr = hCNetSDK.NET_DVR_GetLastError(); |
| | | System.out.println("取流失败" + iErr); |
| | | return; |
| | | } |
| | | System.out.println("取流成功"); |
| | | |
| | | //设置裸码流回调函数 |
| | | // if (fPlayescallback==null) |
| | | // { |
| | | // fPlayescallback=new fPlayEScallback(); |
| | | // } |
| | | // boolean setcallback=hCNetSDK.NET_DVR_SetESRealPlayCallBack(lPlay,fPlayescallback,null); |
| | | // if (setcallback==false) |
| | | // { |
| | | // System.out.println("设置裸码流回调失败,错误码:"+hCNetSDK.NET_DVR_GetLastError()); |
| | | // } |
| | | |
| | | //取流解码过程中播放库从解码码流中抓图 |
| | | // getPicbyPlayCtrl(); |
| | | |
| | | /** |
| | | * 预览一段时间;如果要一直取流预览,需要保证程序一直运行 |
| | | */ |
| | | try { |
| | | Thread.sleep(1000); |
| | | } catch (InterruptedException e) { |
| | | // TODO Auto-generated catch block |
| | | e.printStackTrace(); |
| | | } |
| | | |
| | | |
| | | String path = ".\\savevideo.mp4"; |
| | | Boolean bSaveVideo = hCNetSDK.NET_DVR_SaveRealData_V30(lPlay,0x2,path); |
| | | if (bSaveVideo == false) { |
| | | int iErr = hCNetSDK.NET_DVR_GetLastError(); |
| | | System.out.println("NET_DVR_SaveRealData_V30 failed" + iErr); |
| | | return; |
| | | } |
| | | System.out.println("NET_DVR_SaveRealData_V30 suss"); |
| | | |
| | | try { |
| | | Thread.sleep(0); |
| | | } catch (InterruptedException e) { |
| | | // TODO Auto-generated catch block |
| | | e.printStackTrace(); |
| | | } |
| | | |
| | | Boolean bStopSaveVideo = hCNetSDK.NET_DVR_StopSaveRealData(lPlay); |
| | | if (bStopSaveVideo == false) { |
| | | int iErr = hCNetSDK.NET_DVR_GetLastError(); |
| | | System.out.println("NET_DVR_StopSaveRealData failed" + iErr); |
| | | return; |
| | | } |
| | | System.out.println("NET_DVR_StopSaveRealData suss"); |
| | | |
| | | |
| | | if (lPlay>=0) { |
| | | if (hCNetSDK.NET_DVR_StopRealPlay(lPlay)) |
| | | { |
| | | System.out.println("停止预览成功"); |
| | | return; |
| | | } |
| | | } |
| | | } |
| | | |
| | | //播放库抓图 |
| | | public void getPicbyPlayCtrl(String imgName){ |
| | | |
| | | //取流成功后,延时一段时间保证播放库解码开始 |
| | | try { |
| | | Thread.sleep(100); |
| | | } catch (InterruptedException e) { |
| | | e.printStackTrace(); |
| | | } |
| | | IntByReference pWidth = new IntByReference(0); |
| | | IntByReference pHieght = new IntByReference(0); |
| | | boolean bFlag = playCtrl.PlayM4_GetPictureSize(m_lPort.getValue(), pWidth, pHieght); |
| | | if (!bFlag) { |
| | | System.out.println("获取失败:" + playCtrl.PlayM4_GetLastError(m_lPort.getValue())); |
| | | } |
| | | System.out.println(pWidth.getValue()); |
| | | System.out.println(pHieght.getValue()); |
| | | IntByReference RealPicSize = new IntByReference(0); |
| | | int picsize = pWidth.getValue() * pHieght.getValue() * 5; |
| | | HCNetSDK.BYTE_ARRAY picByte = new HCNetSDK.BYTE_ARRAY(picsize); |
| | | picByte.write(); |
| | | Pointer pByte = picByte.getPointer(); |
| | | boolean b_GetPic = playCtrl.PlayM4_GetJPEG(m_lPort.getValue(), pByte, picsize, RealPicSize); |
| | | if (!b_GetPic) { |
| | | System.out.println("抓图失败:" + playCtrl.PlayM4_GetLastError(m_lPort.getValue())); |
| | | } |
| | | picByte.read(); |
| | | SimpleDateFormat sf = new SimpleDateFormat("yyyyMMddHHmmss"); |
| | | String newName = sf.format(new Date()); |
| | | FileOutputStream fout = null; |
| | | try { |
| | | File file = new File(imgPath+imgName); |
| | | if(!file.exists()){ |
| | | file.getParentFile().mkdir(); |
| | | file.createNewFile(); |
| | | } |
| | | fout = new FileOutputStream(file); |
| | | //将字节写入文件 |
| | | long offset = 0; |
| | | ByteBuffer buffers = pByte.getByteBuffer(offset, RealPicSize.getValue()); |
| | | byte[] bytes = new byte[RealPicSize.getValue()]; |
| | | buffers.rewind(); |
| | | buffers.get(bytes); |
| | | fout.write(bytes); |
| | | fout.close(); |
| | | } catch (FileNotFoundException e) { |
| | | // TODO Auto-generated catch block |
| | | e.printStackTrace(); |
| | | } catch (IOException e) { |
| | | // TODO Auto-generated catch block |
| | | e.printStackTrace(); |
| | | } |
| | | System.out.println("抓图成功!"); |
| | | //退出程序时调用,每一台设备分别注销 |
| | | if (hCNetSDK.NET_DVR_Logout(lUserID)) { |
| | | System.out.println("注销成功"); |
| | | } |
| | | |
| | | //SDK反初始化,释放资源,只需要退出时调用一次 |
| | | // hCNetSDK.NET_DVR_Cleanup(); |
| | | return; |
| | | |
| | | } |
| | | |
| | | class FRealDataCallBack implements HCNetSDK.FRealDataCallBack_V30 { |
| | | //预览回调 |
| | | public void invoke(int lRealHandle, int dwDataType, Pointer pBuffer, int dwBufSize, Pointer pUser) { |
| | | if (Count == 100) {//降低打印频率 |
| | | System.out.println("码流数据回调...dwBufSize="+dwBufSize); |
| | | Count = 0; |
| | | } |
| | | Count++; |
| | | //播放库解码 |
| | | switch (dwDataType) { |
| | | case HCNetSDK.NET_DVR_SYSHEAD: //系统头 |
| | | if (!playCtrl.PlayM4_GetPort(m_lPort)) //获取播放库未使用的通道号 |
| | | { |
| | | break; |
| | | } |
| | | if (dwBufSize > 0) { |
| | | if (!playCtrl.PlayM4_SetStreamOpenMode(m_lPort.getValue(), PlayCtrl.STREAME_REALTIME)) //设置实时流播放模式 |
| | | { |
| | | break; |
| | | } |
| | | if (!playCtrl.PlayM4_OpenStream(m_lPort.getValue(), pBuffer, dwBufSize, 1024 * 1024)) //打开流接口 |
| | | { |
| | | break; |
| | | } |
| | | if (!playCtrl.PlayM4_Play(m_lPort.getValue(), null)) //播放开始 |
| | | { |
| | | break; |
| | | } |
| | | |
| | | } |
| | | case HCNetSDK.NET_DVR_STREAMDATA: //码流数据 |
| | | if ((dwBufSize > 0) && (m_lPort.getValue() != -1)) { |
| | | if (!playCtrl.PlayM4_InputData(m_lPort.getValue(), pBuffer, dwBufSize)) //输入流数据 |
| | | { |
| | | break; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | |
| | | } |
New file |
| | |
| | | package com.boying.service; |
| | | |
| | | import com.boying.Util.OSUtils; |
| | | import com.boying.common.InitSdkTask; |
| | | import com.sun.jna.Native; |
| | | import com.sun.jna.Pointer; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.stereotype.Component; |
| | | |
| | | import java.util.concurrent.ThreadPoolExecutor; |
| | | |
| | | @Slf4j |
| | | @Component |
| | | public class SdkInitService { |
| | | public static HCNetSDK hcNetSDK = null; |
| | | public static PlayCtrl playCtrl = null; |
| | | static HCNetSDK.FExceptionCallBack fExceptionCallBack; |
| | | static class FExceptionCallBack_Imp implements HCNetSDK.FExceptionCallBack{ |
| | | @Override |
| | | public void invoke(int dwType, int lUserID, int lHandle, Pointer pUser) { |
| | | System.out.println("异常事件类型"); |
| | | return; |
| | | } |
| | | } |
| | | |
| | | public SdkInitService(){ |
| | | if (hcNetSDK == null){ |
| | | synchronized (HCNetSDK.class){ |
| | | try { |
| | | hcNetSDK = (HCNetSDK) Native.loadLibrary(OSUtils.getLoadLibrary(),HCNetSDK.class); |
| | | } catch (Exception ex) { |
| | | log.error("SdkInitService-init-hCNetSDK-error"); |
| | | } |
| | | } |
| | | } |
| | | if (playCtrl == null){ |
| | | synchronized (HCNetSDK.class){ |
| | | try { |
| | | playCtrl = (PlayCtrl) Native.loadLibrary(OSUtils.getLoadPlayLibrary(), PlayCtrl.class); |
| | | } catch (Exception ex) { |
| | | log.error("PlatCtrlInitService-init-PlatCtrl-error"); |
| | | } |
| | | } |
| | | } |
| | | |
| | | } |
| | | |
| | | @Autowired |
| | | private ThreadPoolExecutor executor; |
| | | public void initSdk() { |
| | | log.info("HKSDKInitService-init-coming"); |
| | | executor.execute(new InitSdkTask()); |
| | | } |
| | | } |
New file |
| | |
| | | package com.boying.service; |
| | | |
| | | import com.boying.entity.VideoRecordDto; |
| | | import com.boying.service.HCNetSDK; |
| | | import com.boying.service.SdkInitService; |
| | | import com.sun.jna.ptr.IntByReference; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.beans.factory.annotation.Value; |
| | | import org.springframework.data.redis.core.RedisTemplate; |
| | | import org.springframework.scheduling.annotation.Scheduled; |
| | | import org.springframework.stereotype.Component; |
| | | |
| | | import java.text.SimpleDateFormat; |
| | | import java.util.ArrayList; |
| | | import java.util.Date; |
| | | import java.util.List; |
| | | import java.util.Timer; |
| | | |
| | | @Component |
| | | public class VideoJob { |
| | | |
| | | @Autowired |
| | | private RedisTemplate redisTemplate; |
| | | @Value("${allFilePath.videoPath}") |
| | | private String videoPath; |
| | | private Boolean runFlag = false; |
| | | private String VIDEO_EQ_KEY="VIDEO_EQ_KEY:"; |
| | | int lUserID; |
| | | int m_lLoadHandle; |
| | | Timer downloadtimer;//下载用定时器 |
| | | private static HCNetSDK hCNetSDK = SdkInitService.hcNetSDK; |
| | | @Scheduled(cron = "0/1 * * * * *") |
| | | public void work() throws InterruptedException { |
| | | if(runFlag){ |
| | | return; |
| | | } |
| | | VideoRecordDto videoRecordDto = (VideoRecordDto) redisTemplate.boundListOps(VIDEO_EQ_KEY).rightPop(); |
| | | if(videoRecordDto == null){ |
| | | return; |
| | | } |
| | | String loginStatus = (String)redisTemplate.opsForValue().get("Login_Status:"+videoRecordDto.getDiskUrl()); |
| | | if("true".equals(loginStatus)){ |
| | | return; |
| | | } |
| | | if(videoRecordDto != null){ |
| | | try { |
| | | runFlag = true; |
| | | redisTemplate.opsForValue().set("Login_Status:"+videoRecordDto.getDiskUrl(),"true"); |
| | | HCNetSDK.NET_DVR_DEVICEINFO_V30 m_strDeviceInfo = new HCNetSDK.NET_DVR_DEVICEINFO_V30(); |
| | | lUserID = hCNetSDK.NET_DVR_Login_V30(videoRecordDto.getDiskUrl(),(short)8000,videoRecordDto.getDiskUser(),videoRecordDto.getDiskPassword(), m_strDeviceInfo); |
| | | long userID = lUserID; |
| | | if (userID == -1) { |
| | | System.out.println("hksdk(视频)-海康sdk登录失败!"); |
| | | return; |
| | | } |
| | | dowmloadRecordByTime(lUserID,videoRecordDto); |
| | | Thread.sleep(0); |
| | | }catch (Exception e){ |
| | | runFlag = false; |
| | | }finally { |
| | | runFlag = false; |
| | | redisTemplate.opsForValue().set("Login_Status:"+videoRecordDto.getDiskUrl(),"false"); |
| | | } |
| | | } |
| | | |
| | | } |
| | | |
| | | //按时间下载录像(不支持转码3GP格式) |
| | | public void dowmloadRecordByTime(int userID,VideoRecordDto dto) |
| | | { |
| | | SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); |
| | | String start = sdf.format(dto.getStartTime()); |
| | | String end = sdf.format(dto.getEndTime()); |
| | | List<Integer> startList = getDateString(start); |
| | | List<Integer> endList = getDateString(end); |
| | | HCNetSDK.NET_DVR_PLAYCOND net_dvr_playcond = new HCNetSDK.NET_DVR_PLAYCOND(); |
| | | net_dvr_playcond.read(); |
| | | net_dvr_playcond.dwChannel=dto.getEqPort(); //通道号 NVR设备路数小于32路的起始通道号从33开始,依次增加 |
| | | //开始时间 |
| | | net_dvr_playcond.struStartTime.dwYear=startList.get(0); |
| | | net_dvr_playcond.struStartTime.dwMonth=startList.get(1); |
| | | net_dvr_playcond.struStartTime.dwDay=startList.get(2); |
| | | net_dvr_playcond.struStartTime.dwHour=startList.get(3); |
| | | net_dvr_playcond.struStartTime.dwMinute=startList.get(4); |
| | | net_dvr_playcond.struStartTime.dwSecond=startList.get(5); |
| | | //停止时间 |
| | | net_dvr_playcond.struStopTime.dwYear=endList.get(0); |
| | | net_dvr_playcond.struStopTime.dwMonth=endList.get(1); |
| | | net_dvr_playcond.struStopTime.dwDay=endList.get(2); |
| | | net_dvr_playcond.struStopTime.dwHour=endList.get(3); |
| | | net_dvr_playcond.struStopTime.dwMinute=endList.get(4); |
| | | net_dvr_playcond.struStopTime.dwSecond=endList.get(5); |
| | | net_dvr_playcond.write(); |
| | | HCNetSDK.NET_DVR_FINDDATA_V40 struFindData = new HCNetSDK.NET_DVR_FINDDATA_V40(); |
| | | struFindData.read(); |
| | | String strFileName = null; |
| | | try { |
| | | strFileName=new String(struFindData.sFileName,"UTF-8").trim(); |
| | | }catch (Exception e){ |
| | | e.printStackTrace(); |
| | | } |
| | | String sFileName = videoPath+dto.getVideoName(); |
| | | System.out.println(sFileName); |
| | | //m_lLoadHandle=hCNetSDK.NET_DVR_GetFileByName(userID,strFileName,sFileName.getBytes()); |
| | | |
| | | m_lLoadHandle = hCNetSDK.NET_DVR_GetFileByTime_V40(userID,sFileName,net_dvr_playcond); |
| | | if (m_lLoadHandle >= 0) |
| | | { |
| | | hCNetSDK.NET_DVR_PlayBackControl(m_lLoadHandle, HCNetSDK.NET_DVR_PLAYSTART, 0, null); |
| | | |
| | | /* IntByReference intP=new IntByReference(5*8*1024); |
| | | IntByReference intInlen=new IntByReference(0); |
| | | boolean b_PlayBack=ClientDemo.hCNetSDK.NET_DVR_PlayBackControl_V40(m_lLoadHandle,24,intP.getPointer(),4,Pointer.NULL,intInlen); |
| | | if (!b_PlayBack) { |
| | | System.out.println("设置下载速度失败,错误码为" + ClientDemo.hCNetSDK.NET_DVR_GetLastError()); |
| | | return; |
| | | }*/ |
| | | Date nowTime = new Date(System.currentTimeMillis()); |
| | | SimpleDateFormat sdFormatter = new SimpleDateFormat("yyyy-MM-dd-hh-mm-ss"); |
| | | System.out.println("开始下载时间:"+sdFormatter.format(nowTime)); |
| | | downloadtimer = new Timer();//新建定时器 |
| | | downloadtimer.schedule(new downloadTask(), 0, 5000);//0秒后开始响应函数 |
| | | } else |
| | | { |
| | | System.out.println("按时间下载失败"); |
| | | System.out.println("laste error " + hCNetSDK.NET_DVR_GetLastError()); |
| | | return; |
| | | } |
| | | } |
| | | |
| | | class downloadTask extends java.util.TimerTask |
| | | { |
| | | //定时器函数 |
| | | @Override |
| | | public void run() |
| | | { |
| | | |
| | | IntByReference nPos = new IntByReference(0); |
| | | hCNetSDK.NET_DVR_PlayBackControl(m_lLoadHandle, HCNetSDK.NET_DVR_PLAYGETPOS, 0, nPos); |
| | | if (nPos.getValue() > 100) |
| | | { |
| | | m_lLoadHandle=-1; |
| | | downloadtimer.cancel(); |
| | | System.out.println( "由于网络原因或DVR忙,下载异常终止!"); |
| | | } |
| | | if (nPos.getValue() == 100) |
| | | { |
| | | Date nowTime = new Date(System.currentTimeMillis()); |
| | | SimpleDateFormat sdFormatter = new SimpleDateFormat("yyyy-MM-dd-hh-mm-ss"); |
| | | System.out.println("结束下载时间:"+sdFormatter.format(nowTime)); |
| | | m_lLoadHandle=-1; |
| | | downloadtimer.cancel(); |
| | | System.out.println("按时间下载结束!"); |
| | | //退出程序时调用,每一台设备分别注销 |
| | | if (hCNetSDK.NET_DVR_Logout(lUserID)) { |
| | | System.out.println("注销成功"); |
| | | } |
| | | // hCNetSDK.NET_DVR_Cleanup(); |
| | | } |
| | | } |
| | | } |
| | | |
| | | static List<Integer> getDateString(String dateString){ |
| | | String[] s = dateString.split(" "); |
| | | List<Integer> list = new ArrayList<>(); |
| | | for (int i = 0; i < s.length; i++) { |
| | | String s1 = s[i]; |
| | | if(i==0){ |
| | | for (String s2 : s1.split("-")) { |
| | | list.add(Integer.parseInt(s2)); |
| | | } |
| | | }else { |
| | | for (String s2 : s1.split(":")) { |
| | | list.add(Integer.parseInt(s2)); |
| | | } |
| | | } |
| | | } |
| | | return list; |
| | | } |
| | | |
| | | public static void main(String[] args) { |
| | | getDateString("2024-07-04 09:37:00"); |
| | | } |
| | | |
| | | } |
New file |
| | |
| | | server: |
| | | port: 8899 |
| | | |
| | | allFilePath: |
| | | imgPath: E:\HK\ClientDemo\Download\img\ |
| | | videoPath: E:\HK\ClientDemo\Download\video\ |
| | | spring: |
| | | redis: |
| | | host: 127.0.0.1 |