fix: use nvdec

This commit is contained in:
ziesorx 2025-09-25 22:16:19 +07:00
parent f9a67935d6
commit b919a1ebe2
5 changed files with 328 additions and 19 deletions

View file

@ -166,28 +166,83 @@ class RTSPReader:
logger.info(f"RTSP reader thread ended for camera {self.camera_id}")
def _initialize_capture(self) -> bool:
"""Initialize video capture with optimized settings for 1280x720@6fps."""
"""Initialize video capture with hardware acceleration (NVDEC) for 1280x720@6fps."""
try:
# Release previous capture if exists
if self.cap:
self.cap.release()
time.sleep(0.5)
logger.info(f"Initializing capture for camera {self.camera_id}")
logger.info(f"Initializing capture for camera {self.camera_id} with hardware acceleration")
hw_accel_success = False
# Create capture with FFMPEG backend and TCP transport for reliability
# Use TCP instead of UDP to prevent packet loss
rtsp_url_tcp = self.rtsp_url.replace('rtsp://', 'rtsp://')
if '?' in rtsp_url_tcp:
rtsp_url_tcp += '&tcp'
else:
rtsp_url_tcp += '?tcp'
# Method 1: Try GStreamer with NVDEC (most efficient on NVIDIA GPUs)
if not hw_accel_success:
try:
# Build GStreamer pipeline for NVIDIA hardware decoding
gst_pipeline = (
f"rtspsrc location={self.rtsp_url} protocols=tcp latency=100 ! "
"rtph264depay ! h264parse ! "
"nvv4l2decoder ! " # NVIDIA hardware decoder
"nvvideoconvert ! " # NVIDIA hardware color conversion
"video/x-raw,format=BGRx,width=1280,height=720 ! "
"videoconvert ! "
"video/x-raw,format=BGR ! "
"appsink max-buffers=1 drop=true sync=false"
)
logger.info(f"Attempting GStreamer NVDEC pipeline for camera {self.camera_id}")
self.cap = cv2.VideoCapture(gst_pipeline, cv2.CAP_GSTREAMER)
# Alternative: Set environment variable for RTSP transport
import os
os.environ['OPENCV_FFMPEG_CAPTURE_OPTIONS'] = 'rtsp_transport;tcp'
if self.cap.isOpened():
hw_accel_success = True
logger.info(f"Camera {self.camera_id}: Successfully using GStreamer with NVDEC hardware acceleration")
except Exception as e:
logger.debug(f"Camera {self.camera_id}: GStreamer NVDEC not available: {e}")
self.cap = cv2.VideoCapture(self.rtsp_url, cv2.CAP_FFMPEG)
# Method 2: Try FFMPEG with NVIDIA CUVID hardware decoder
if not hw_accel_success:
try:
import os
# Set FFMPEG to use NVIDIA CUVID decoder
os.environ['OPENCV_FFMPEG_CAPTURE_OPTIONS'] = 'video_codec;h264_cuvid|rtsp_transport;tcp|hwaccel;cuda'
logger.info(f"Attempting FFMPEG with h264_cuvid for camera {self.camera_id}")
self.cap = cv2.VideoCapture(self.rtsp_url, cv2.CAP_FFMPEG)
if self.cap.isOpened():
hw_accel_success = True
logger.info(f"Camera {self.camera_id}: Using FFMPEG with CUVID hardware acceleration")
except Exception as e:
logger.debug(f"Camera {self.camera_id}: FFMPEG CUVID not available: {e}")
# Method 3: Try VAAPI hardware acceleration (for Intel/AMD GPUs)
if not hw_accel_success:
try:
gst_pipeline = (
f"rtspsrc location={self.rtsp_url} protocols=tcp latency=100 ! "
"rtph264depay ! h264parse ! "
"vaapih264dec ! " # VAAPI hardware decoder
"vaapipostproc ! "
"video/x-raw,format=BGRx,width=1280,height=720 ! "
"videoconvert ! "
"video/x-raw,format=BGR ! "
"appsink max-buffers=1 drop=true sync=false"
)
logger.info(f"Attempting GStreamer VAAPI pipeline for camera {self.camera_id}")
self.cap = cv2.VideoCapture(gst_pipeline, cv2.CAP_GSTREAMER)
if self.cap.isOpened():
hw_accel_success = True
logger.info(f"Camera {self.camera_id}: Successfully using GStreamer with VAAPI hardware acceleration")
except Exception as e:
logger.debug(f"Camera {self.camera_id}: GStreamer VAAPI not available: {e}")
# Fallback: Standard FFMPEG with software decoding
if not hw_accel_success:
logger.warning(f"Camera {self.camera_id}: Hardware acceleration not available, falling back to software decoding")
import os
os.environ['OPENCV_FFMPEG_CAPTURE_OPTIONS'] = 'rtsp_transport;tcp'
self.cap = cv2.VideoCapture(self.rtsp_url, cv2.CAP_FFMPEG)
if not self.cap.isOpened():
logger.error(f"Failed to open stream for camera {self.camera_id}")