海康工业相机对接优化视频流
This commit is contained in:
@@ -6,6 +6,9 @@ import org.springframework.stereotype.Service;
|
|||||||
import org.springframework.web.socket.BinaryMessage;
|
import org.springframework.web.socket.BinaryMessage;
|
||||||
import org.springframework.web.socket.WebSocketSession;
|
import org.springframework.web.socket.WebSocketSession;
|
||||||
|
|
||||||
|
import javax.imageio.ImageIO;
|
||||||
|
import java.awt.image.BufferedImage;
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
@@ -24,6 +27,10 @@ public class CameraService {
|
|||||||
private final Map<String, WebSocketSession> webSocketSessions = new ConcurrentHashMap<>();
|
private final Map<String, WebSocketSession> webSocketSessions = new ConcurrentHashMap<>();
|
||||||
// 相机是否正在运行
|
// 相机是否正在运行
|
||||||
private boolean isRunning = false;
|
private boolean isRunning = false;
|
||||||
|
// 帧率控制相关
|
||||||
|
private long lastFrameTime = 0;
|
||||||
|
private final int targetFps = 15; // 目标帧率
|
||||||
|
private final long frameInterval = 1000 / targetFps; // 帧间隔(毫秒)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 初始化相机
|
* 初始化相机
|
||||||
@@ -228,13 +235,33 @@ public class CameraService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
// 帧率控制
|
||||||
|
long currentTime = System.currentTimeMillis();
|
||||||
|
if (currentTime - lastFrameTime < frameInterval) {
|
||||||
|
return; // 跳过当前帧,控制帧率
|
||||||
|
}
|
||||||
|
lastFrameTime = currentTime;
|
||||||
|
|
||||||
// 打印帧信息,以便调试
|
// 打印帧信息,以便调试
|
||||||
printFrameInfo(frameInfo);
|
printFrameInfo(frameInfo);
|
||||||
|
|
||||||
// 对于黑白相机(MV-CE050-30GM),数据是单通道灰度格式
|
// 对于黑白相机(MV-CE050-30GM),数据是单通道灰度格式
|
||||||
// 创建包含图像尺寸信息和原始数据的消息
|
// 将原始灰度数据转换为BufferedImage
|
||||||
|
BufferedImage image = new BufferedImage(frameInfo.width, frameInfo.height, BufferedImage.TYPE_BYTE_GRAY);
|
||||||
|
image.getRaster().setDataElements(0, 0, frameInfo.width, frameInfo.height, bytes);
|
||||||
|
|
||||||
|
// 压缩图像为JPEG格式
|
||||||
|
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||||
|
ImageIO.write(image, "jpeg", baos);
|
||||||
|
byte[] compressedData = baos.toByteArray();
|
||||||
|
baos.close();
|
||||||
|
|
||||||
|
log.debug("Original size: {} bytes, Compressed size: {} bytes, Compression ratio: {:.2f}%",
|
||||||
|
bytes.length, compressedData.length, (1 - (double)compressedData.length / bytes.length) * 100);
|
||||||
|
|
||||||
|
// 创建包含图像尺寸信息和压缩数据的消息
|
||||||
// 消息格式: [width(4 bytes)][height(4 bytes)][image data]
|
// 消息格式: [width(4 bytes)][height(4 bytes)][image data]
|
||||||
byte[] message = new byte[8 + bytes.length];
|
byte[] message = new byte[8 + compressedData.length];
|
||||||
|
|
||||||
// 写入宽度和高度(使用小端序)
|
// 写入宽度和高度(使用小端序)
|
||||||
message[0] = (byte) (frameInfo.width & 0xFF);
|
message[0] = (byte) (frameInfo.width & 0xFF);
|
||||||
@@ -247,8 +274,8 @@ public class CameraService {
|
|||||||
message[6] = (byte) ((frameInfo.height >> 16) & 0xFF);
|
message[6] = (byte) ((frameInfo.height >> 16) & 0xFF);
|
||||||
message[7] = (byte) ((frameInfo.height >> 24) & 0xFF);
|
message[7] = (byte) ((frameInfo.height >> 24) & 0xFF);
|
||||||
|
|
||||||
// 写入原始图像数据
|
// 写入压缩后的图像数据
|
||||||
System.arraycopy(bytes, 0, message, 8, bytes.length);
|
System.arraycopy(compressedData, 0, message, 8, compressedData.length);
|
||||||
|
|
||||||
// 发送图像数据到所有连接的WebSocket客户端
|
// 发送图像数据到所有连接的WebSocket客户端
|
||||||
for (WebSocketSession session : webSocketSessions.values()) {
|
for (WebSocketSession session : webSocketSessions.values()) {
|
||||||
|
|||||||
Reference in New Issue
Block a user