|
@@ -1,41 +1,32 @@
|
|
|
package com.persagy.cameractl.service.windows;
|
|
|
|
|
|
-import java.io.File;
|
|
|
-import java.io.FileOutputStream;
|
|
|
-import java.util.HashMap;
|
|
|
-import java.util.Map;
|
|
|
-import java.util.concurrent.CountDownLatch;
|
|
|
-
|
|
|
+import com.persagy.cameractl.common.VideoExportProcessContext;
|
|
|
import com.persagy.cameractl.conf.AllStaticConfig;
|
|
|
-import com.persagy.cameractl.utils.Camera;
|
|
|
-import com.persagy.cameractl.utils.DateUtil;
|
|
|
-import com.persagy.cameractl.utils.EnumTools;
|
|
|
-import com.persagy.cameractl.utils.JsonTools;
|
|
|
-import com.persagy.cameractl.utils.OtherTools;
|
|
|
-import com.persagy.cameractl.utils.ResultClass;
|
|
|
-import com.persagy.cameractl.utils.StringTools;
|
|
|
+import com.persagy.cameractl.utils.*;
|
|
|
+import com.persagy.nvr.EndPlayCallBackClass;
|
|
|
import com.sun.jna.Memory;
|
|
|
import com.sun.jna.Pointer;
|
|
|
import com.sun.jna.platform.win32.WinDef;
|
|
|
-import com.sun.jna.platform.win32.WinDef.CHARByReference;
|
|
|
-import com.sun.jna.platform.win32.WinDef.DWORD;
|
|
|
-import com.sun.jna.platform.win32.WinDef.DWORDByReference;
|
|
|
-import com.sun.jna.platform.win32.WinDef.UINT;
|
|
|
-import com.sun.jna.platform.win32.WinDef.UINTByReference;
|
|
|
-
|
|
|
+import com.sun.jna.platform.win32.WinDef.*;
|
|
|
import lombok.extern.slf4j.Slf4j;
|
|
|
+import org.apache.commons.lang.StringUtils;
|
|
|
import sun.misc.BASE64Encoder;
|
|
|
|
|
|
+import java.io.File;
|
|
|
+import java.io.FileOutputStream;
|
|
|
+import java.util.HashMap;
|
|
|
+import java.util.Map;
|
|
|
+
|
|
|
@Slf4j
|
|
|
@SuppressWarnings("restriction")
|
|
|
public class ZhaosMainWindows {
|
|
|
-
|
|
|
+
|
|
|
// 默认连接超时时间,单位:毫秒
|
|
|
int wait_time = 5000;
|
|
|
|
|
|
// 摄像头对象
|
|
|
Camera _camera;
|
|
|
-
|
|
|
+
|
|
|
// 登录句柄
|
|
|
DWORD loginHandler;
|
|
|
|
|
@@ -83,19 +74,19 @@ public class ZhaosMainWindows {
|
|
|
|
|
|
/**
|
|
|
* 登录
|
|
|
- *
|
|
|
+ *
|
|
|
* @return
|
|
|
* @date 2021年9月28日 上午10:32:05
|
|
|
*/
|
|
|
private String login() {
|
|
|
try {
|
|
|
- Map<String, String> userinfoMap = new HashMap<String, String>();
|
|
|
+ Map<String, String> userinfoMap = new HashMap<>();
|
|
|
String userNameBase64 = new BASE64Encoder().encode(_camera.userName.getBytes());
|
|
|
String passwordBase64 = new BASE64Encoder().encode(_camera.password.getBytes());
|
|
|
userinfoMap.put("user_name", userNameBase64);
|
|
|
userinfoMap.put("password", passwordBase64);
|
|
|
|
|
|
- Map<String, Object> loginInfoMap = new HashMap<String, Object>();
|
|
|
+ Map<String, Object> loginInfoMap = new HashMap<>();
|
|
|
loginInfoMap.put("user_info", userinfoMap);
|
|
|
loginInfoMap.put("strNvrIp", _camera.cameraIp);
|
|
|
loginInfoMap.put("nNvrPort", _camera.cameraPort);
|
|
@@ -130,7 +121,7 @@ public class ZhaosMainWindows {
|
|
|
|
|
|
// 登录
|
|
|
String loginResult = this.login();
|
|
|
- if (loginResult != "true") {
|
|
|
+ if (!"true".equals(loginResult)) {
|
|
|
return this.executeErr(false, loginResult, "登录失败");
|
|
|
}
|
|
|
|
|
@@ -138,7 +129,7 @@ public class ZhaosMainWindows {
|
|
|
resultClass.name = true;
|
|
|
return resultClass;
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
/**
|
|
|
* 获得控制编码
|
|
|
*/
|
|
@@ -165,8 +156,8 @@ public class ZhaosMainWindows {
|
|
|
if (controlResult != 0) {
|
|
|
return String.valueOf(controlResult);
|
|
|
}
|
|
|
- // 休眠1秒,即让云台执行1秒后再进行停止
|
|
|
- Thread.sleep(1000);
|
|
|
+ // 休眠,即让云台执行后再进行停止
|
|
|
+ Thread.sleep(200);
|
|
|
// 再执行停止命令
|
|
|
reqPtzControlMap.put("value", 0);
|
|
|
String reqPtzControlStr2 = JsonTools.obj2Str(reqPtzControlMap);
|
|
@@ -174,7 +165,7 @@ public class ZhaosMainWindows {
|
|
|
// byte[] reqPtzControlBytes2 = reqPtzControlStr2.getBytes();
|
|
|
int controlResult2 = AllStaticConfig.vskClient.JsonSdk_PtzControl(this.loginHandler, reqPtzControlStr2);
|
|
|
if (controlResult2 != 0) {
|
|
|
- return String.valueOf("控制停止时失败:" + controlResult2);
|
|
|
+ return "控制停止时失败:" + controlResult2;
|
|
|
}
|
|
|
|
|
|
return "true";
|
|
@@ -187,65 +178,44 @@ public class ZhaosMainWindows {
|
|
|
/**
|
|
|
* 视频回放
|
|
|
*/
|
|
|
- private String startPlayBack() {
|
|
|
+ private String startPlayBack(WinDef.LPVOID pUser, EndPlayCallBackClass endPlayCallBackClass,
|
|
|
+ VideoExportProcessContext context) {
|
|
|
try {
|
|
|
- Map<String, String> userinfoMap = new HashMap<String, String>();
|
|
|
- String userNameBase64 = new BASE64Encoder().encode(_camera.userName.getBytes());
|
|
|
- String passwordBase64 = new BASE64Encoder().encode(_camera.password.getBytes());
|
|
|
- userinfoMap.put("user_name", userNameBase64);
|
|
|
- userinfoMap.put("password", passwordBase64);
|
|
|
-
|
|
|
// 公元1970年1月1日0时0分0 秒算起至今的UTC时间所经过的秒数。
|
|
|
- long startTimeSeconds = new DateUtil(_camera.startDateStr).getSecondsStart1970UTC();
|
|
|
- long endTimeSeconds = new DateUtil(_camera.endDateStr).getSecondsStart1970UTC();
|
|
|
+ long startTimeSeconds = new DateUtil(_camera.startDateStr).getSecondsStart1970UTC8();
|
|
|
+ long endTimeSeconds = new DateUtil(_camera.endDateStr).getSecondsStart1970UTC8();
|
|
|
|
|
|
- Map<String, Object> playbackStreamTimeMap = new HashMap<String, Object>();
|
|
|
+ Map<String, Object> playbackStreamTimeMap = new HashMap<>();
|
|
|
playbackStreamTimeMap.put("chid", _camera.channel - 1);
|
|
|
- playbackStreamTimeMap.put("stream_type", 0);
|
|
|
+ playbackStreamTimeMap.put("stream_type", _camera.streamType);
|
|
|
playbackStreamTimeMap.put("start_time", startTimeSeconds);
|
|
|
playbackStreamTimeMap.put("end_time", endTimeSeconds);
|
|
|
- playbackStreamTimeMap.put("user_info", userinfoMap);
|
|
|
|
|
|
String pInfoStr = JsonTools.obj2Str(playbackStreamTimeMap);
|
|
|
- // byte[] pInfo = pInfoStr.getBytes();
|
|
|
-
|
|
|
- // int pUserValue = 2;
|
|
|
- // pUserValue.getpo
|
|
|
- String pUserValue = StringTools.getUUID();
|
|
|
- Pointer pUserPointer = new Memory(40);
|
|
|
- pUserPointer.setString(0, pUserValue);
|
|
|
- WinDef.LPVOID pUser = new WinDef.LPVOID(pUserPointer);
|
|
|
-
|
|
|
-// ULONGLONG pTotalSizeLong = new ULONGLONG(1);
|
|
|
-// ULONGLONGByReference pTotalSize = new ULONGLONGByReference(pTotalSizeLong);
|
|
|
-
|
|
|
- // DWORD playBackIdDWORD = new DWORD(Native.getNativeSize(DWORD.class));
|
|
|
-// DWORD playBackIdDWORD = new DWORD(96);
|
|
|
-// WinDef.DWORDByReference pnPlaybackID = new WinDef.DWORDByReference(playBackIdDWORD);
|
|
|
|
|
|
- // Pointer pnPlaybackID = new Memory(20);
|
|
|
-
|
|
|
- // if (_camera.isUseCustomCall == 1) {
|
|
|
- //
|
|
|
- // }
|
|
|
-
|
|
|
- log.error("-----------即将调用JsonSdk_PlayBackStartByTime,串:" + pInfoStr);
|
|
|
- log.error("loginHandler:" + loginHandler.intValue());
|
|
|
- log.error("startTimeSeconds:" + startTimeSeconds + ",endTimeSeconds:" + endTimeSeconds);
|
|
|
+ log.info("-----------即将调用JsonSdk_PlayBackStartByTime,串:" + pInfoStr);
|
|
|
+ log.info("loginHandler:" + loginHandler.intValue());
|
|
|
+ log.info("startTimeSeconds:" + startTimeSeconds + ",endTimeSeconds:" + endTimeSeconds);
|
|
|
// 发送根据时间进行回放的指令
|
|
|
- // int playBackResult =
|
|
|
- // AllStaticConfig.vskClient.JsonSdk_PlayBackStartByTime(loginHandler, pInfoStr,
|
|
|
- // new DataPlayCallBackClass(), new EndPlayCallBackClass(), null, pUser,
|
|
|
- // pTotalSize, pnPlaybackID);
|
|
|
+ WinDef.DWORDLONG pTotalSize = new WinDef.DWORDLONG();
|
|
|
+ WinDef.DWORDByReference pnDownID = new WinDef.DWORDByReference(new WinDef.DWORD(0));
|
|
|
+ context.startTransmission();
|
|
|
+
|
|
|
int playBackResult = AllStaticConfig.vskClient.JsonSdk_PlayBackStartByTime(loginHandler, pInfoStr,
|
|
|
- AllStaticConfig.dataPlayCallBackClass, AllStaticConfig.endPlayCallBackClass, null, pUser, null,
|
|
|
- null);
|
|
|
+ AllStaticConfig.dataPlayCallBackClass, endPlayCallBackClass, null, pUser,
|
|
|
+ pTotalSize, pnDownID);
|
|
|
+
|
|
|
+// WinDef.DWORDByReference pTotalSize = new WinDef.DWORDByReference();
|
|
|
+// WinDef.DWORDByReference pnDownID = new WinDef.DWORDByReference(new WinDef.DWORD(0));
|
|
|
+// int playBackResult = AllStaticConfig.vskClient.JsonSdk_DownloadStartByTime(loginHandler, pInfoStr,
|
|
|
+// AllStaticConfig.dataPlayCallBackClass, AllStaticConfig.endPlayCallBackClass, "c:/persagy-camera/persagy-camera/download.h264",
|
|
|
+// pUser, 0, pTotalSize, pnDownID);
|
|
|
|
|
|
if (playBackResult != 0) {
|
|
|
+ context.endTransmission();
|
|
|
return String.valueOf(playBackResult);
|
|
|
}
|
|
|
-// long pnPlaybackIdValue = pnPlaybackID.getValue().longValue();
|
|
|
- AllStaticConfig.playBackMp4State = 0;
|
|
|
+
|
|
|
return "true";
|
|
|
} catch (Exception e) {
|
|
|
log.error("调用回放时异常:", e);
|
|
@@ -257,8 +227,8 @@ public class ZhaosMainWindows {
|
|
|
private String searchLog() {
|
|
|
try {
|
|
|
// 公元1970年1月1日0时0分0 秒算起至今的UTC时间所经过的秒数。
|
|
|
- long startTimeMillSeconds = new DateUtil(_camera.startDateStr).getSecondsStart1970UTC();
|
|
|
- long endTimeMillSeconds = new DateUtil(_camera.endDateStr).getSecondsStart1970UTC();
|
|
|
+ long startTimeMillSeconds = new DateUtil(_camera.startDateStr).getSecondsStart1970UTC8();
|
|
|
+ long endTimeMillSeconds = new DateUtil(_camera.endDateStr).getSecondsStart1970UTC8();
|
|
|
|
|
|
Map<String, Object> sysLogMap = new HashMap<String, Object>();
|
|
|
sysLogMap.put("log_type", 1);
|
|
@@ -330,7 +300,7 @@ public class ZhaosMainWindows {
|
|
|
return initResultClass;
|
|
|
|
|
|
String controlResult = onPtzDirctCtrl();
|
|
|
- if (controlResult != "true") {
|
|
|
+ if (!"true".equals(controlResult)) {
|
|
|
return this.executeErr(true, controlResult, "控制指令调用失败");
|
|
|
}
|
|
|
return this.executeSuccess(null);
|
|
@@ -339,65 +309,63 @@ public class ZhaosMainWindows {
|
|
|
/**
|
|
|
* 回放入口 synchronized关键字即把方法改为同步,两个线程同时调用该方法时,上一个线程执行完后下一个线程才会执行
|
|
|
*/
|
|
|
- public synchronized ResultClass playBackMain() {
|
|
|
- try {
|
|
|
- ResultClass returnResult = new ResultClass();
|
|
|
- AllStaticConfig.playBackFilePath = OtherTools.getVideoFilePath();
|
|
|
- if (AllStaticConfig.playBackFilePath.equals("")) {
|
|
|
- returnResult.name = false;
|
|
|
- returnResult.reason = "回放文件名称生成失败";
|
|
|
- return returnResult;
|
|
|
- }
|
|
|
+ public ResultClass playBackMain() {
|
|
|
+ ResultClass returnResult = new ResultClass();
|
|
|
+ String playBackFilePath = OtherTools.getVideoFilePath();
|
|
|
+ if (StringUtils.isEmpty(playBackFilePath)) {
|
|
|
+ returnResult.name = false;
|
|
|
+ returnResult.reason = "回放文件名称生成失败";
|
|
|
+ return returnResult;
|
|
|
+ }
|
|
|
|
|
|
- File mp4File = new File(AllStaticConfig.playBackFilePath);
|
|
|
- AllStaticConfig.playBackFileName = mp4File.getName();
|
|
|
+ File mp4File = new File(playBackFilePath);
|
|
|
+ String playBackFileName = mp4File.getName();
|
|
|
|
|
|
- String errPrefixStr = "回放失败";
|
|
|
- // 初始化
|
|
|
- ResultClass initResultClass = initAndLogin();
|
|
|
- if (!initResultClass.name)
|
|
|
- return initResultClass;
|
|
|
+ String tempPlayBackFilePath = playBackFilePath + ".tmp";
|
|
|
+ String token = OtherTools.getMp4NamePrefix(playBackFileName);
|
|
|
|
|
|
+ String errPrefixStr = "回放失败";
|
|
|
+ // 初始化
|
|
|
+ ResultClass initResultClass = initAndLogin();
|
|
|
+ if (!initResultClass.name)
|
|
|
+ return initResultClass;
|
|
|
+
|
|
|
+ String pUserValue = StringTools.getUUID();
|
|
|
+ Pointer pUserPointer = new Memory(40);
|
|
|
+ pUserPointer.setString(0, pUserValue);
|
|
|
+ WinDef.LPVOID pUser = new WinDef.LPVOID(pUserPointer);
|
|
|
+
|
|
|
+ VideoExportProcessContext context = new VideoExportProcessContext(
|
|
|
+ pUserPointer, playBackFilePath, tempPlayBackFilePath);
|
|
|
+
|
|
|
+ // 保证在当前流程中不被GC回收掉
|
|
|
+ EndPlayCallBackClass endPlayCallBackClass = new EndPlayCallBackClass(context);
|
|
|
+
|
|
|
+ try {
|
|
|
// 回放开始
|
|
|
- String playBackResult = this.startPlayBack();
|
|
|
- if (playBackResult != "true")
|
|
|
+ String playBackResult = this.startPlayBack(pUser, endPlayCallBackClass, context);
|
|
|
+ if (!"true".equals(playBackResult))
|
|
|
return this.executeErr(true, playBackResult, "执行回放时失败");
|
|
|
|
|
|
- final CountDownLatch latch = new CountDownLatch(1);// 使用java并发库concurrent
|
|
|
- new Thread(new Runnable() {
|
|
|
- public void run() {
|
|
|
- // 生成中
|
|
|
- while (AllStaticConfig.playBackMp4State == 0) {
|
|
|
- try {
|
|
|
- Thread.sleep(1);
|
|
|
- } catch (Exception e) {
|
|
|
- }
|
|
|
- }
|
|
|
- latch.countDown();// 让latch中的数值减一
|
|
|
-
|
|
|
- }
|
|
|
- }).start();
|
|
|
- try {
|
|
|
- latch.await();// 阻塞当前线程直到latch中数值为零才执行
|
|
|
- // 生成成功
|
|
|
- if (AllStaticConfig.playBackMp4State == 1) {
|
|
|
- log.info("正在拼接正常url");
|
|
|
- String token = OtherTools.getMp4NamePrefix(AllStaticConfig.playBackFileName);
|
|
|
- String url = OtherTools.playMp4RootUrl + token;
|
|
|
- Map<String, String> dataMap = new HashMap<String, String>();
|
|
|
- dataMap.put("url", url);
|
|
|
- log.info("即将正常返回url");
|
|
|
- return this.executeSuccess(dataMap);
|
|
|
+ // 生成成功
|
|
|
+ if (context.await()) {
|
|
|
+ if (!context.hasData()) {
|
|
|
+ return this.executeErr(true, "无可回放内容", errPrefixStr);
|
|
|
}
|
|
|
- log.info("errPrefixStr:" + errPrefixStr);
|
|
|
- return this.executeErr(true, "视频文件生成失败", errPrefixStr);
|
|
|
- } catch (Exception e) {
|
|
|
- log.error("回放异常:", e);
|
|
|
- return this.executeErr(true, "等待MP4生成异常", errPrefixStr);
|
|
|
+
|
|
|
+ String url = OtherTools.playMp4RootUrl + token;
|
|
|
+ Map<String, String> dataMap = new HashMap<>();
|
|
|
+ dataMap.put("url", url);
|
|
|
+ return this.executeSuccess(dataMap);
|
|
|
}
|
|
|
+
|
|
|
+ log.info("errPrefixStr:" + errPrefixStr);
|
|
|
+ return this.executeErr(true, "视频文件生成失败", errPrefixStr);
|
|
|
} catch (Exception e) {
|
|
|
- log.error("回放入口异常:", e);
|
|
|
- return this.executeErr(true, "回放入口异常", "");
|
|
|
+ log.error("回放异常:", e);
|
|
|
+ return this.executeErr(true, "视频文件生成异常", errPrefixStr);
|
|
|
+ } finally {
|
|
|
+ context.clean();
|
|
|
}
|
|
|
|
|
|
};
|