refactor: simplify frame handling by removing stream type management and enhancing validation
All checks were successful
Build Worker Base and Application Images / check-base-changes (push) Successful in 7s
Build Worker Base and Application Images / build-base (push) Has been skipped
Build Worker Base and Application Images / build-docker (push) Successful in 2m55s
Build Worker Base and Application Images / deploy-stack (push) Successful in 12s
All checks were successful
Build Worker Base and Application Images / check-base-changes (push) Successful in 7s
Build Worker Base and Application Images / build-base (push) Has been skipped
Build Worker Base and Application Images / build-docker (push) Successful in 2m55s
Build Worker Base and Application Images / deploy-stack (push) Successful in 12s
This commit is contained in:
parent
dc1db635d0
commit
719d16ae4d
4 changed files with 51 additions and 182 deletions
|
@ -37,7 +37,6 @@ class RTSPReader:
|
|||
self.expected_fps = 6
|
||||
|
||||
# Frame processing parameters
|
||||
self.frame_interval = 1.0 / self.expected_fps # ~167ms for 6fps
|
||||
self.error_recovery_delay = 5.0 # Increased from 2.0 for stability
|
||||
self.max_consecutive_errors = 30 # Increased from 10 to handle network jitter
|
||||
self.stream_timeout = 30.0
|
||||
|
@ -72,7 +71,6 @@ class RTSPReader:
|
|||
frame_count = 0
|
||||
last_log_time = time.time()
|
||||
last_successful_frame_time = time.time()
|
||||
last_frame_time = 0
|
||||
|
||||
while not self.stop_event.is_set():
|
||||
try:
|
||||
|
@ -90,12 +88,7 @@ class RTSPReader:
|
|||
last_successful_frame_time = time.time()
|
||||
continue
|
||||
|
||||
# Rate limiting for 6fps
|
||||
current_time = time.time()
|
||||
if current_time - last_frame_time < self.frame_interval:
|
||||
time.sleep(0.01) # Small sleep to avoid busy waiting
|
||||
continue
|
||||
|
||||
# Read frame immediately without rate limiting for minimum latency
|
||||
ret, frame = self.cap.read()
|
||||
|
||||
if not ret or frame is None:
|
||||
|
@ -118,15 +111,10 @@ class RTSPReader:
|
|||
time.sleep(sleep_time)
|
||||
continue
|
||||
|
||||
# Validate frame dimensions
|
||||
if frame.shape[1] != self.expected_width or frame.shape[0] != self.expected_height:
|
||||
logger.warning(f"Camera {self.camera_id}: Unexpected frame dimensions {frame.shape[1]}x{frame.shape[0]}")
|
||||
# Try to resize if dimensions are wrong
|
||||
if frame.shape[1] > 0 and frame.shape[0] > 0:
|
||||
frame = cv2.resize(frame, (self.expected_width, self.expected_height))
|
||||
else:
|
||||
consecutive_errors += 1
|
||||
continue
|
||||
# Accept any valid frame dimensions - don't force specific resolution
|
||||
if frame.shape[1] <= 0 or frame.shape[0] <= 0:
|
||||
consecutive_errors += 1
|
||||
continue
|
||||
|
||||
# Check for corrupted frames (all black, all white, excessive noise)
|
||||
if self._is_frame_corrupted(frame):
|
||||
|
@ -138,7 +126,6 @@ class RTSPReader:
|
|||
consecutive_errors = 0
|
||||
frame_count += 1
|
||||
last_successful_frame_time = time.time()
|
||||
last_frame_time = current_time
|
||||
|
||||
# Call frame callback
|
||||
if self.frame_callback:
|
||||
|
@ -148,6 +135,7 @@ class RTSPReader:
|
|||
logger.error(f"Camera {self.camera_id}: Frame callback error: {e}")
|
||||
|
||||
# Log progress every 30 seconds
|
||||
current_time = time.time()
|
||||
if current_time - last_log_time >= 30:
|
||||
logger.info(f"Camera {self.camera_id}: {frame_count} frames processed")
|
||||
last_log_time = current_time
|
||||
|
@ -261,14 +249,12 @@ class RTSPReader:
|
|||
logger.error(f"Failed to open stream for camera {self.camera_id}")
|
||||
return False
|
||||
|
||||
# Set capture properties for 1280x720@6fps
|
||||
self.cap.set(cv2.CAP_PROP_FRAME_WIDTH, self.expected_width)
|
||||
self.cap.set(cv2.CAP_PROP_FRAME_HEIGHT, self.expected_height)
|
||||
self.cap.set(cv2.CAP_PROP_FPS, self.expected_fps)
|
||||
# Don't force resolution/fps - let the stream determine its natural specs
|
||||
# The camera will provide whatever resolution/fps it supports
|
||||
|
||||
# Set moderate buffer to handle network jitter while avoiding excessive latency
|
||||
# Buffer of 3 frames provides resilience without major delay
|
||||
self.cap.set(cv2.CAP_PROP_BUFFERSIZE, 3)
|
||||
# Set minimal buffer for lowest latency - single frame buffer
|
||||
# This ensures we always get the most recent frame
|
||||
self.cap.set(cv2.CAP_PROP_BUFFERSIZE, 1)
|
||||
|
||||
# Set FFMPEG options for better H.264 handling
|
||||
self.cap.set(cv2.CAP_PROP_FOURCC, cv2.VideoWriter_fourcc(*'H264'))
|
||||
|
@ -405,15 +391,10 @@ class HTTPSnapshotReader:
|
|||
time.sleep(min(2.0, interval_seconds))
|
||||
continue
|
||||
|
||||
# Validate image dimensions
|
||||
if frame.shape[1] != self.expected_width or frame.shape[0] != self.expected_height:
|
||||
logger.info(f"Camera {self.camera_id}: Snapshot dimensions {frame.shape[1]}x{frame.shape[0]} "
|
||||
f"(expected {self.expected_width}x{self.expected_height})")
|
||||
# Resize if needed (maintaining aspect ratio for high quality)
|
||||
if frame.shape[1] > 0 and frame.shape[0] > 0:
|
||||
# Only resize if significantly different
|
||||
if abs(frame.shape[1] - self.expected_width) > 100:
|
||||
frame = self._resize_maintain_aspect(frame, self.expected_width, self.expected_height)
|
||||
# Accept any valid image dimensions - don't force specific resolution
|
||||
if frame.shape[1] <= 0 or frame.shape[0] <= 0:
|
||||
logger.warning(f"Camera {self.camera_id}: Invalid frame dimensions {frame.shape[1]}x{frame.shape[0]}")
|
||||
continue
|
||||
|
||||
# Reset retry counter on successful fetch
|
||||
retries = 0
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue