修复问题
This commit is contained in:
@@ -345,7 +345,6 @@ public class MediaTransferFlvByJavacv extends MediaTransfer implements Runnable
|
|||||||
if (enableDetection) initDetectors();
|
if (enableDetection) initDetectors();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("初始化检测模型失败:{}", e.getMessage(), e);
|
log.error("初始化检测模型失败:{}", e.getMessage(), e);
|
||||||
// 模型失败不影响推流,但不禁用检测
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!createGrabber()) return;
|
if (!createGrabber()) return;
|
||||||
@@ -369,15 +368,10 @@ public class MediaTransferFlvByJavacv extends MediaTransfer implements Runnable
|
|||||||
long lastDetectionTime = 0;
|
long lastDetectionTime = 0;
|
||||||
List<Detection> currentDetections = Collections.emptyList(); // 当前显示的检测结果
|
List<Detection> currentDetections = Collections.emptyList(); // 当前显示的检测结果
|
||||||
|
|
||||||
// 检测计数器和性能统计
|
|
||||||
int totalDetections = 0;
|
|
||||||
int successfulDetections = 0;
|
|
||||||
long totalDetectionTime = 0;
|
|
||||||
|
|
||||||
for (; running && grabberStatus && recorderStatus; ) {
|
for (; running && grabberStatus && recorderStatus; ) {
|
||||||
try {
|
try {
|
||||||
if (transferFlag) {
|
if (transferFlag) {
|
||||||
// 仅转复用(未叠框)- 这部分代码保持不变
|
// 仅转复用(未叠框)
|
||||||
long startGrab = System.currentTimeMillis();
|
long startGrab = System.currentTimeMillis();
|
||||||
AVPacket pkt = grabber.grabPacket();
|
AVPacket pkt = grabber.grabPacket();
|
||||||
if ((System.currentTimeMillis() - startGrab) > 5000) {
|
if ((System.currentTimeMillis() - startGrab) > 5000) {
|
||||||
@@ -392,17 +386,9 @@ public class MediaTransferFlvByJavacv extends MediaTransfer implements Runnable
|
|||||||
recorder.recordPacket(pkt);
|
recorder.recordPacket(pkt);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// 转码(可叠框)- 优化这部分以避免栈溢出
|
// 转码(可叠框)
|
||||||
long startGrab = System.currentTimeMillis();
|
long startGrab = System.currentTimeMillis();
|
||||||
Frame frame = null;
|
Frame frame = grabber.grab();
|
||||||
|
|
||||||
try {
|
|
||||||
// 直接获取帧,不进行复杂处理
|
|
||||||
frame = grabber.grab();
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("获取帧异常: {}", e.getMessage());
|
|
||||||
continue; // 跳过这一帧
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((System.currentTimeMillis() - startGrab) > 5000) {
|
if ((System.currentTimeMillis() - startGrab) > 5000) {
|
||||||
log.info("{} 网络异常(转码)", cameraDto.getUrl());
|
log.info("{} 网络异常(转码)", cameraDto.getUrl());
|
||||||
@@ -410,128 +396,96 @@ public class MediaTransferFlvByJavacv extends MediaTransfer implements Runnable
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 如果启用了检测且获取到了有效帧
|
|
||||||
if (frame != null && enableDetection) {
|
if (frame != null && enableDetection) {
|
||||||
// 控制检测频率
|
// 将Frame转换为Mat以进行处理
|
||||||
long currentTime = System.currentTimeMillis();
|
Mat mat = toMat.convert(frame);
|
||||||
boolean shouldDetect = (currentTime - lastDetectionTime >= DETECTION_INTERVAL_MS);
|
|
||||||
|
|
||||||
if (shouldDetect) {
|
if (mat != null && !mat.empty()) {
|
||||||
// 每隔一段时间进行一次检测
|
long currentTime = System.currentTimeMillis();
|
||||||
try {
|
|
||||||
// 安全转换为Mat
|
// 每隔DETECTION_INTERVAL_MS执行一次检测
|
||||||
Mat detectionMat = null;
|
if (currentTime - lastDetectionTime >= DETECTION_INTERVAL_MS) {
|
||||||
try {
|
try {
|
||||||
detectionMat = toMat.convert(frame);
|
log.debug("执行新一轮检测,上次检测时间: {}ms前",
|
||||||
} catch (Exception e) {
|
currentTime - lastDetectionTime);
|
||||||
log.debug("帧转换异常: {}", e.getMessage());
|
|
||||||
continue; // 跳过这一帧
|
// 创建副本进行检测
|
||||||
}
|
Mat detectionMat = new Mat();
|
||||||
|
mat.copyTo(detectionMat);
|
||||||
if (detectionMat != null && !detectionMat.empty()) {
|
|
||||||
// 执行检测
|
// 执行检测
|
||||||
try {
|
currentDetections = detector.detect(detectionMat);
|
||||||
// 打印检测开始信息
|
lastDetectionTime = currentTime;
|
||||||
log.info("===== 开始执行检测 [{}] =====", new java.text.SimpleDateFormat("HH:mm:ss.SSS").format(new java.util.Date()));
|
latestDetections.set(currentDetections);
|
||||||
totalDetections++;
|
|
||||||
|
// 释放检测Mat
|
||||||
// 记录检测开始时间
|
detectionMat.release();
|
||||||
long detectionStartTime = System.currentTimeMillis();
|
|
||||||
|
// 窗口巡检回调
|
||||||
// 执行检测
|
if (windowMode && detectionListener != null &&
|
||||||
currentDetections = detector.detect(detectionMat);
|
currentJobId != null && currentDeviceId != null) {
|
||||||
|
detectionListener.onDetections(currentJobId,
|
||||||
// 计算检测耗时
|
currentDeviceId,
|
||||||
long detectionTime = System.currentTimeMillis() - detectionStartTime;
|
currentDetections,
|
||||||
totalDetectionTime += detectionTime;
|
currentTime);
|
||||||
successfulDetections++;
|
|
||||||
|
|
||||||
// 更新最后检测时间
|
|
||||||
lastDetectionTime = currentTime;
|
|
||||||
latestDetections.set(currentDetections);
|
|
||||||
|
|
||||||
// 打印检测结果
|
|
||||||
StringBuilder detectionInfo = new StringBuilder();
|
|
||||||
detectionInfo.append("\n===== 检测结果 =====\n");
|
|
||||||
detectionInfo.append("检测耗时: ").append(detectionTime).append("ms\n");
|
|
||||||
detectionInfo.append("检测目标数: ").append(currentDetections == null ? 0 : currentDetections.size()).append("\n");
|
|
||||||
|
|
||||||
if (currentDetections != null && !currentDetections.isEmpty()) {
|
|
||||||
detectionInfo.append("检测到的目标:\n");
|
|
||||||
for (int i = 0; i < currentDetections.size(); i++) {
|
|
||||||
Detection det = currentDetections.get(i);
|
|
||||||
detectionInfo.append(" ").append(i+1).append(". ");
|
|
||||||
detectionInfo.append("类型: ").append(det.cls());
|
|
||||||
detectionInfo.append(", 置信度: ").append(String.format("%.2f", det.conf()));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
detectionInfo.append("未检测到目标\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
// 打印检测统计
|
|
||||||
detectionInfo.append("\n检测统计:\n");
|
|
||||||
detectionInfo.append("总检测次数: ").append(totalDetections).append("\n");
|
|
||||||
detectionInfo.append("成功检测次数: ").append(successfulDetections).append("\n");
|
|
||||||
detectionInfo.append("平均检测时间: ").append(successfulDetections > 0 ? (totalDetectionTime / successfulDetections) : 0).append("ms\n");
|
|
||||||
detectionInfo.append("===== 检测结束 =====\n");
|
|
||||||
|
|
||||||
log.info(detectionInfo.toString());
|
|
||||||
|
|
||||||
// 窗口巡检回调
|
|
||||||
if (windowMode && detectionListener != null &&
|
|
||||||
currentJobId != null && currentDeviceId != null) {
|
|
||||||
try {
|
|
||||||
detectionListener.onDetections(currentJobId,
|
|
||||||
currentDeviceId,
|
|
||||||
currentDetections,
|
|
||||||
currentTime);
|
|
||||||
} catch (Exception ignore) {}
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("检测异常: {}", e.getMessage(), e);
|
|
||||||
} finally {
|
|
||||||
// 确保释放Mat
|
|
||||||
try {
|
|
||||||
if (detectionMat != null && !detectionMat.isNull())
|
|
||||||
detectionMat.release();
|
|
||||||
} catch (Exception ignore) {}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log.debug("检测完成,发现 {} 个目标,框将保持3秒",
|
||||||
|
currentDetections == null ? 0 : currentDetections.size());
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.debug("检测异常: {}", e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 每一帧都使用最新的检测结果绘制框
|
||||||
|
// 这样框会保持在原位置,直到下一次检测更新
|
||||||
|
if (currentDetections != null && !currentDetections.isEmpty()) {
|
||||||
|
try {
|
||||||
|
// 在当前帧上绘制检测框
|
||||||
|
Overlay.draw(currentDetections, mat);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.debug("绘制检测框异常: {}", e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 更新"最近叠好框的帧"用于存证
|
||||||
|
updateLatestAnnotated(mat);
|
||||||
|
|
||||||
|
// 统计(仅窗口巡检时)
|
||||||
|
if (windowMode) updateStats(currentDetections);
|
||||||
|
|
||||||
|
// 窗口结束判定
|
||||||
|
if (windowMode && System.currentTimeMillis() >= windowEndMs) {
|
||||||
|
finishWindow();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 将处理后的Mat转换回Frame
|
||||||
|
try {
|
||||||
|
// 创建新的转换器
|
||||||
|
OpenCVFrameConverter.ToMat converter = new OpenCVFrameConverter.ToMat();
|
||||||
|
Frame processedFrame = converter.convert(mat);
|
||||||
|
|
||||||
|
if (processedFrame != null) {
|
||||||
|
// 使用处理后的帧替换原始帧
|
||||||
|
frame = processedFrame;
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("检测流程异常: {}", e.getMessage(), e);
|
log.debug("Mat转Frame异常: {}", e.getMessage());
|
||||||
|
// 如果转换失败,继续使用原始帧
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
// 释放Mat
|
||||||
// 不再尝试将检测结果叠加到当前帧上
|
mat.release();
|
||||||
// 而是在UI层面处理叠加,这样可以避免复杂的帧处理和转换
|
|
||||||
// 或者使用更简单的方式叠加
|
|
||||||
|
|
||||||
// 统计(仅窗口巡检时)
|
|
||||||
if (windowMode) {
|
|
||||||
try {
|
|
||||||
updateStats(currentDetections);
|
|
||||||
} catch (Exception ignore) {}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 窗口结束判定
|
|
||||||
if (windowMode && System.currentTimeMillis() >= windowEndMs) {
|
|
||||||
try {
|
|
||||||
finishWindow();
|
|
||||||
} catch (Exception ignore) {}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 直接使用原始帧,避免复杂的转换
|
// 记录帧
|
||||||
if (frame != null) {
|
if (frame != null) {
|
||||||
try {
|
long now = System.currentTimeMillis();
|
||||||
long now = System.currentTimeMillis();
|
if (startTime == 0) startTime = now;
|
||||||
if (startTime == 0) startTime = now;
|
videoTS = 1000 * (now - startTime);
|
||||||
videoTS = 1000 * (now - startTime);
|
if (videoTS > recorder.getTimestamp()) recorder.setTimestamp(videoTS);
|
||||||
if (videoTS > recorder.getTimestamp()) recorder.setTimestamp(videoTS);
|
recorder.record(frame);
|
||||||
recorder.record(frame);
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("记录帧异常: {}", e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (FrameGrabber.Exception e) {
|
} catch (FrameGrabber.Exception e) {
|
||||||
@@ -546,7 +500,7 @@ public class MediaTransferFlvByJavacv extends MediaTransfer implements Runnable
|
|||||||
log.error("其他异常: {}", e.getMessage());
|
log.error("其他异常: {}", e.getMessage());
|
||||||
// 不要立即退出,尝试继续处理
|
// 不要立即退出,尝试继续处理
|
||||||
try {
|
try {
|
||||||
Thread.sleep(100); // 短暂暂停
|
Thread.sleep(100);
|
||||||
} catch (InterruptedException ie) {
|
} catch (InterruptedException ie) {
|
||||||
Thread.currentThread().interrupt();
|
Thread.currentThread().interrupt();
|
||||||
}
|
}
|
||||||
@@ -568,7 +522,7 @@ public class MediaTransferFlvByJavacv extends MediaTransfer implements Runnable
|
|||||||
safeCloseResources();
|
safeCloseResources();
|
||||||
}
|
}
|
||||||
|
|
||||||
// 将资源关闭逻辑提取到单独的方法,避免嵌套太深
|
// 将资源关闭逻辑提取到单独的方法
|
||||||
private void safeCloseResources() {
|
private void safeCloseResources() {
|
||||||
try {
|
try {
|
||||||
if (detector != null) {
|
if (detector != null) {
|
||||||
|
|||||||
Reference in New Issue
Block a user