|
|
@@ -18,7 +18,7 @@ from dataclasses import dataclass
|
|
|
|
|
|
from config import PANORAMA_CAMERA, DETECTION_CONFIG
|
|
|
from dahua_sdk import DahuaSDK, PTZCommand
|
|
|
-from video_lock import ff_lock
|
|
|
+from video_lock import safe_read, safe_is_opened
|
|
|
|
|
|
|
|
|
@dataclass
|
|
|
@@ -126,10 +126,22 @@ class PanoramaCamera:
|
|
|
rtsp_url = self.config.get('rtsp_url') or f"rtsp://{self.config['username']}:{self.config['password']}@{self.config['ip']}:{self.config.get('rtsp_port', 554)}/h264/ch{self.config['channel']}/main/av_stream"
|
|
|
|
|
|
try:
|
|
|
+ # 先尝试FFmpeg后端
|
|
|
self.rtsp_cap = cv2.VideoCapture(rtsp_url, cv2.CAP_FFMPEG)
|
|
|
if not self.rtsp_cap.isOpened():
|
|
|
- print(f"无法打开RTSP流: {rtsp_url}")
|
|
|
- return False
|
|
|
+ # FFmpeg失败,尝试GStreamer后端
|
|
|
+ print(f"FFmpeg后端无法打开RTSP流,尝试GStreamer后端...")
|
|
|
+ try:
|
|
|
+ gst_cap = cv2.VideoCapture(rtsp_url, cv2.CAP_GSTREAMER)
|
|
|
+ if gst_cap.isOpened():
|
|
|
+ self.rtsp_cap = gst_cap
|
|
|
+ print(f"使用GStreamer后端打开RTSP流成功")
|
|
|
+ else:
|
|
|
+ print(f"无法打开RTSP流: {rtsp_url}")
|
|
|
+ return False
|
|
|
+ except Exception as ge:
|
|
|
+ print(f"GStreamer后端也不可用: {ge}")
|
|
|
+ return False
|
|
|
|
|
|
self.rtsp_cap.set(cv2.CAP_PROP_BUFFERSIZE, 1)
|
|
|
|
|
|
@@ -161,9 +173,8 @@ class PanoramaCamera:
|
|
|
pass
|
|
|
|
|
|
# RTSP 模式获取帧 (推荐方式)
|
|
|
- if self.rtsp_cap is not None and self.rtsp_cap.isOpened():
|
|
|
- with ff_lock:
|
|
|
- ret, frame = self.rtsp_cap.read()
|
|
|
+ if self.rtsp_cap is not None and safe_is_opened(self.rtsp_cap):
|
|
|
+ ret, frame = safe_read(self.rtsp_cap)
|
|
|
if ret and frame is not None:
|
|
|
with self.frame_lock:
|
|
|
self.current_frame = frame.copy()
|
|
|
@@ -185,7 +196,7 @@ class PanoramaCamera:
|
|
|
self.rtsp_cap = cv2.VideoCapture(rtsp_url, cv2.CAP_FFMPEG)
|
|
|
self.rtsp_cap.set(cv2.CAP_PROP_BUFFERSIZE, 1) # 减少缓冲延迟
|
|
|
|
|
|
- if self.rtsp_cap.isOpened():
|
|
|
+ if safe_is_opened(self.rtsp_cap):
|
|
|
retry_count = 0
|
|
|
continue
|
|
|
except Exception as e:
|
|
|
@@ -234,12 +245,11 @@ class PanoramaCamera:
|
|
|
|
|
|
while self.running:
|
|
|
try:
|
|
|
- if self.rtsp_cap is None or not self.rtsp_cap.isOpened():
|
|
|
+ if self.rtsp_cap is None or not safe_is_opened(self.rtsp_cap):
|
|
|
time.sleep(0.1)
|
|
|
continue
|
|
|
|
|
|
- with ff_lock:
|
|
|
- ret, frame = self.rtsp_cap.read()
|
|
|
+ ret, frame = safe_read(self.rtsp_cap)
|
|
|
if not ret or frame is None:
|
|
|
error_count += 1
|
|
|
if error_count > max_consecutive_errors:
|
|
|
@@ -283,7 +293,7 @@ class PanoramaCamera:
|
|
|
|
|
|
try:
|
|
|
self.rtsp_cap = cv2.VideoCapture(rtsp_url, cv2.CAP_FFMPEG)
|
|
|
- if self.rtsp_cap.isOpened():
|
|
|
+ if safe_is_opened(self.rtsp_cap):
|
|
|
self.rtsp_cap.set(cv2.CAP_PROP_BUFFERSIZE, 1)
|
|
|
print("全景RTSP流重连成功")
|
|
|
else:
|