commit a4ef78b8065d2bef057c68b4e10e62f1401b74ee
Author: wany <13995595726@qq.com>
Date: Sat Nov 22 09:48:37 2025 +0800
init
diff --git a/lib/AbsoluteLayout.jar b/lib/AbsoluteLayout.jar
new file mode 100644
index 0000000..b51cba7
Binary files /dev/null and b/lib/AbsoluteLayout.jar differ
diff --git a/lib/jna.jar b/lib/jna.jar
new file mode 100644
index 0000000..3b8fb4f
Binary files /dev/null and b/lib/jna.jar differ
diff --git a/lib/rt.jar b/lib/rt.jar
new file mode 100644
index 0000000..fc5ef41
Binary files /dev/null and b/lib/rt.jar differ
diff --git a/lib/swing-layout-1.0.3.jar b/lib/swing-layout-1.0.3.jar
new file mode 100644
index 0000000..6e1b43b
Binary files /dev/null and b/lib/swing-layout-1.0.3.jar differ
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..dc6dd1f
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,201 @@
+
+
+ 4.0.0
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.7.1
+
+
+
+ com.whdc
+ tiandy-service
+ 1.0
+ 视频
+
+
+ 8
+ 8
+ UTF-8
+
+
+
+
+
+ ali-maven
+ https://maven.aliyun.com/nexus/content/groups/public
+
+ true
+
+
+ true
+ always
+ fail
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ org.springframework.boot
+ spring-boot-starter-aop
+
+
+ com.baomidou
+ mybatis-plus-boot-starter
+ 3.5.2
+
+
+ org.springframework.boot
+ spring-boot-starter-validation
+ 2.7.1
+
+
+ org.springframework.boot
+ spring-boot-starter-data-redis
+
+
+
+ mysql
+ mysql-connector-java
+ 8.0.16
+
+
+
+
+
+ org.projectlombok
+ lombok
+
+
+
+
+
+ com.alibaba
+ fastjson
+ 1.2.80
+
+
+
+
+
+ com.github.jeffreyning
+ mybatisplus-plus
+ 1.7.0-RELEASE
+
+
+
+
+ com.whdc
+ AbsoluteLayout
+ 1.0
+ ${project.basedir}/lib/AbsoluteLayout.jar
+ system
+
+
+
+ com.whdc
+ jna
+ 1.0
+ ${project.basedir}/lib/jna.jar
+ system
+
+
+
+ com.whdc
+ rt
+ 1.0
+ ${project.basedir}/lib/rt.jar
+ system
+
+
+
+ com.whdc
+ swing-layout
+ 1.0.3
+ ${project.basedir}/lib/swing-layout-1.0.3.jar
+ system
+
+
+
+ com.ruoyi
+ integration-ruoyi
+ 3.8.8
+
+
+ swagger-annotations
+ io.swagger
+
+
+ swagger-annotations
+ io.swagger.core.v3
+
+
+ swagger-models
+ io.swagger
+
+
+ swagger-models
+ io.swagger.core.v3
+
+
+ springfox-swagger-common
+ io.springfox
+
+
+ springfox-swagger-ui
+ io.springfox
+
+
+ springfox-swagger2
+ io.springfox
+
+
+ jsqlparser
+ com.github.jsqlparser
+
+
+ mybatis
+ org.mybatis
+
+
+ mybatis-plus-spring-boot3-starter
+ com.baomidou
+
+
+
+
+ org.locationtech.jts
+ jts-core
+ 1.18.1
+
+
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+ com.whdc.TiandyApplication
+
+
+
+
+ repackage
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/main/java/com/whdc/TiandyApplication.java b/src/main/java/com/whdc/TiandyApplication.java
new file mode 100644
index 0000000..884d68f
--- /dev/null
+++ b/src/main/java/com/whdc/TiandyApplication.java
@@ -0,0 +1,34 @@
+package com.whdc;
+
+import com.github.jeffreyning.mybatisplus.conf.EnableMPP;
+import lombok.extern.slf4j.Slf4j;
+import org.mybatis.spring.annotation.MapperScan;
+import org.springframework.beans.BeansException;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.scheduling.annotation.EnableScheduling;
+import org.springframework.web.servlet.config.annotation.EnableWebMvc;
+
+/**
+ * @author 李赛
+ * @date 2022-06-26 0:17
+ */
+@Slf4j
+@EnableMPP
+@EnableWebMvc
+@EnableScheduling
+@SpringBootApplication
+@MapperScan("com.whdc.mapper")
+public class TiandyApplication {
+ public static void main(String[] args) {
+ try {
+ System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>>> 启动程序 <<<<<<<<<<<<<<<<<<<<<<<<<<<");
+
+ SpringApplication.run(TiandyApplication.class, args);
+ } catch (BeansException e) {
+ e.printStackTrace();
+ log.error(e.getMessage(), e);
+ }
+ }
+
+}
diff --git a/src/main/java/com/whdc/callback/DecodedDataCallback.java b/src/main/java/com/whdc/callback/DecodedDataCallback.java
new file mode 100644
index 0000000..6435fc0
--- /dev/null
+++ b/src/main/java/com/whdc/callback/DecodedDataCallback.java
@@ -0,0 +1,8 @@
+package com.whdc.callback;
+
+
+import com.whdc.dto.FrameInfo;
+
+public interface DecodedDataCallback {
+ void onDecodedDataReceived(int connectId, byte[] data, FrameInfo frameInfo);
+}
\ No newline at end of file
diff --git a/src/main/java/com/whdc/callback/RawFrameCallback.java b/src/main/java/com/whdc/callback/RawFrameCallback.java
new file mode 100644
index 0000000..dc041ea
--- /dev/null
+++ b/src/main/java/com/whdc/callback/RawFrameCallback.java
@@ -0,0 +1,8 @@
+package com.whdc.callback;
+
+
+import com.whdc.dto.RawFrameInfo;
+
+public interface RawFrameCallback {
+ void onRawFrameReceived(int connectId, byte[] data, RawFrameInfo frameInfo);
+}
\ No newline at end of file
diff --git a/src/main/java/com/whdc/controller/VideoController.java b/src/main/java/com/whdc/controller/VideoController.java
new file mode 100644
index 0000000..b24f3c8
--- /dev/null
+++ b/src/main/java/com/whdc/controller/VideoController.java
@@ -0,0 +1,197 @@
+package com.whdc.controller;
+
+import com.whdc.callback.RawFrameCallback;
+import com.whdc.dto.*;
+import com.whdc.service.impl.VideoStreamService;
+import com.whdc.service.impl.VideoSurveillanceService;
+import com.whdc.video.NVSSDK1;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.HashMap;
+import java.util.Map;
+
+@RestController
+@RequestMapping("/api/video")
+@CrossOrigin(origins = "*")
+public class VideoController {
+
+ @Autowired
+ private VideoSurveillanceService videoService;
+
+ @Autowired
+ private VideoStreamService streamService;
+
+ private Integer currentConnectId = -1;
+
+ @PostMapping("/init")
+ public ApiResponse initSDK() {
+ try {
+ videoService.initSDK();
+ return ApiResponse.success("SDK初始化成功");
+ } catch (Exception e) {
+ return ApiResponse.error("SDK初始化失败: " + e.getMessage());
+ }
+ }
+
+ @PostMapping("/login")
+ public ApiResponse login(@RequestBody LoginRequest request) {
+ try {
+ boolean success = videoService.login(
+ request.getIp(),
+ request.getPort(),
+ request.getUsername(),
+ request.getPassword()
+ );
+
+ if (success) {
+ return ApiResponse.success("设备登录成功");
+ } else {
+ return ApiResponse.error("设备登录失败");
+ }
+ } catch (Exception e) {
+ return ApiResponse.error("登录异常: " + e.getMessage());
+ }
+ }
+
+ @PostMapping("/stream/start")
+ public ApiResponse startStream(@RequestBody StartStreamRequest request) {
+ try {
+ int m_iLogonID = request.getM_iServerID();
+ if (m_iLogonID < 0 ) {
+ return ApiResponse.error("请先登录设备");
+ }
+
+ if (request.getChannelNo() < 0) {
+ return ApiResponse.error("通道号参数错误");
+ }
+ if ((request.getStreamType() != 0 && request.getStreamType() != 1)) {
+ return ApiResponse.error("码流类型参数错误 (0-主码流, 1-子码流)");
+ }
+ if (request.getNetMode() < 1) {
+ return ApiResponse.error("网络模式参数错误");
+ }
+
+ // 设置原始流回调
+ videoService.setRawFrameCallback(currentConnectId, new RawFrameCallback() {
+ @Override
+ public void onRawFrameReceived(int connectId, byte[] data, RawFrameInfo frameInfo) {
+ // 只处理视频帧
+ if (frameInfo.getFrameType() == NVSSDK1.VI_FRAME ||
+ frameInfo.getFrameType() == NVSSDK1.VP_FRAME) {
+ streamService.storeFrame(data);
+ }
+ }
+ });
+
+ // 使用默认参数启动视频流:通道0,主码流,TCP模式
+ int connectId = videoService.startRealPlay(request.getChannelNo(), request.getStreamType(),request.getNetMode(),m_iLogonID);
+
+ if (connectId >= 0) {
+ currentConnectId = connectId;
+ return ApiResponse.success("视频流启动成功");
+ } else {
+ return ApiResponse.error("视频流启动失败");
+ }
+ } catch (Exception e) {
+ return ApiResponse.error("启动视频流异常: " + e.getMessage());
+ }
+ }
+
+ @PostMapping("/stream/stop")
+ public ApiResponse stopStream() {
+ try {
+ if (currentConnectId >= 0) {
+ videoService.stopRealPlay(currentConnectId);
+ streamService.cleanup();
+ currentConnectId = -1;
+ return ApiResponse.success("视频流停止成功");
+ } else {
+ return ApiResponse.error("没有活跃的视频流");
+ }
+ } catch (Exception e) {
+ return ApiResponse.error("停止视频流异常: " + e.getMessage());
+ }
+ }
+
+ @PostMapping("/ptz/control")
+ public ApiResponse controlPTZ(@RequestBody PTZControlRequest request) {
+ try {
+ if (!videoService.isLoggedIn()) {
+ return ApiResponse.error("请先登录设备");
+ }
+
+ boolean success = videoService.controlDirection(
+ request.getChannelNo(),
+ request.getDirection(),
+ request.getSpeed()
+ );
+
+ if (success) {
+ String directionText = getDirectionText(request.getDirection());
+ return ApiResponse.success("云台" + directionText + "控制成功");
+ } else {
+ return ApiResponse.error("云台控制失败");
+ }
+ } catch (Exception e) {
+ return ApiResponse.error("云台控制异常: " + e.getMessage());
+ }
+ }
+
+ @PostMapping("/ptz/stop")
+ public ApiResponse stopPTZ(@RequestBody PTZControlRequest request) {
+ try {
+ boolean success = videoService.controlDirection(
+ request.getChannelNo(),
+ NVSSDK1.PROTOCOL_MOVE_STOP,
+ 0
+ );
+
+ if (success) {
+ return ApiResponse.success("云台停止成功");
+ } else {
+ return ApiResponse.error("云台停止失败");
+ }
+ } catch (Exception e) {
+ return ApiResponse.error("云台停止异常: " + e.getMessage());
+ }
+ }
+
+ @PostMapping("/logout")
+ public ApiResponse logout() {
+ try {
+ // 先停止视频流
+ if (currentConnectId >= 0) {
+ videoService.stopRealPlay(currentConnectId);
+ streamService.cleanup();
+ currentConnectId = -1;
+ }
+
+ videoService.logout();
+ return ApiResponse.success("设备注销成功");
+ } catch (Exception e) {
+ return ApiResponse.error("设备注销异常: " + e.getMessage());
+ }
+ }
+
+ @GetMapping("/status")
+ public ApiResponse