From f5d889f364b6d33eee9fc71bba2851fb4863582d Mon Sep 17 00:00:00 2001 From: Nicolas Mowen Date: Tue, 9 Jul 2024 09:15:04 -0600 Subject: [PATCH] Add handler logs when frame is None --- frigate/object_detection.py | 1 + frigate/object_processing.py | 3 +++ frigate/output/birdseye.py | 11 ++++++----- frigate/output/output.py | 1 + frigate/review/maintainer.py | 15 +++++++++++++++ frigate/util/image.py | 20 ++++++++++++++++++-- frigate/video.py | 7 +++++-- 7 files changed, 49 insertions(+), 9 deletions(-) diff --git a/frigate/object_detection.py b/frigate/object_detection.py index 207637ed4..22ff84f89 100644 --- a/frigate/object_detection.py +++ b/frigate/object_detection.py @@ -118,6 +118,7 @@ def run_detector( ) if input_frame is None: + logger.warning(f"Failed to get frame {connection_id} from SHM") continue # detect and send the output diff --git a/frigate/object_processing.py b/frigate/object_processing.py index 4fba022b4..55f6196b6 100644 --- a/frigate/object_processing.py +++ b/frigate/object_processing.py @@ -673,6 +673,9 @@ class CameraState: frame_id, self.camera_config.frame_shape_yuv ) + if current_frame is None: + logger.warning(f"Failed to get frame {frame_id} from SHM") + tracked_objects = self.tracked_objects.copy() current_ids = set(current_detections.keys()) previous_ids = set(tracked_objects.keys()) diff --git a/frigate/output/birdseye.py b/frigate/output/birdseye.py index 6e0e2bc22..0e6218a70 100644 --- a/frigate/output/birdseye.py +++ b/frigate/output/birdseye.py @@ -357,16 +357,17 @@ class BirdsEyeFrameManager: frame = None channel_dims = None else: - try: - frame = self.frame_manager.get( - f"{camera}{frame_time}", self.config.cameras[camera].frame_shape_yuv - ) - except FileNotFoundError: + frame = self.frame_manager.get( + f"{camera}{frame_time}", self.config.cameras[camera].frame_shape_yuv + ) + + if frame is None: # TODO: better frame management would prevent this edge case logger.warning( f"Unable to copy frame {camera}{frame_time} to birdseye." ) return + channel_dims = self.cameras[camera]["channel_dims"] copy_yuv_to_position( diff --git a/frigate/output/output.py b/frigate/output/output.py index 9be50594f..65d1e3323 100644 --- a/frigate/output/output.py +++ b/frigate/output/output.py @@ -99,6 +99,7 @@ def output_frames( frame = frame_manager.get(frame_id, config.cameras[camera].frame_shape_yuv) if frame is None: + logger.warning(f"Failed to get frame {frame_id} from SHM") continue # send camera frame to ffmpeg process if websockets are connected diff --git a/frigate/review/maintainer.py b/frigate/review/maintainer.py index fa2678d9b..11c46262c 100644 --- a/frigate/review/maintainer.py +++ b/frigate/review/maintainer.py @@ -292,6 +292,11 @@ class ReviewSegmentMaintainer(threading.Thread): yuv_frame = self.frame_manager.get( frame_id, camera_config.frame_shape_yuv ) + + if yuv_frame is None: + logger.warning(f"Failed to get frame {frame_id} from SHM") + return + self.update_segment( segment, camera_config, yuv_frame, active_objects, prev_data ) @@ -305,6 +310,11 @@ class ReviewSegmentMaintainer(threading.Thread): yuv_frame = self.frame_manager.get( frame_id, camera_config.frame_shape_yuv ) + + if yuv_frame is None: + logger.warning(f"Failed to get frame {frame_id} from SHM") + return + segment.save_full_frame(camera_config, yuv_frame) self.frame_manager.close(frame_id) self.update_segment(segment, camera_config, None, [], prev_data) @@ -401,6 +411,11 @@ class ReviewSegmentMaintainer(threading.Thread): yuv_frame = self.frame_manager.get( frame_id, camera_config.frame_shape_yuv ) + + if yuv_frame is None: + logger.warning(f"Failed to get frame {frame_id} from SHM") + return + self.active_review_segments[camera].update_frame( camera_config, yuv_frame, active_objects ) diff --git a/frigate/util/image.py b/frigate/util/image.py index a3619193f..5c50cafde 100644 --- a/frigate/util/image.py +++ b/frigate/util/image.py @@ -1,6 +1,7 @@ """Utilities for creating and manipulating image frames.""" import datetime +import inspect import logging import subprocess as sp from abc import ABC, abstractmethod @@ -695,6 +696,7 @@ class SharedMemoryFrameManager(FrameManager): return shm.buf def get(self, name: str, shape) -> Optional[np.ndarray]: + logger.info(f"retrieving {name} from {inspect.stack()[1].filename} {inspect.stack()[1].function}") try: if name in self.shm_store: shm = self.shm_store[name] @@ -703,19 +705,33 @@ class SharedMemoryFrameManager(FrameManager): self.shm_store[name] = shm return np.ndarray(shape, dtype=np.uint8, buffer=shm.buf) except FileNotFoundError: - logger.error(f"Failed to get {name} from SHM") return None def close(self, name: str): + logger.info(f"closing {name}") if name in self.shm_store: self.shm_store[name].close() del self.shm_store[name] def delete(self, name: str): + logger.info(f"deleting expired {name}") if name in self.shm_store: self.shm_store[name].close() - self.shm_store[name].unlink() + + try: + self.shm_store[name].unlink() + except FileNotFoundError: + pass + del self.shm_store[name] + else: + shm = shared_memory.SharedMemory(name=name) + shm.close() + + try: + shm.unlink() + except FileNotFoundError: + pass def create_mask(frame_shape, mask): diff --git a/frigate/video.py b/frigate/video.py index 3397de6e4..97ace7d79 100755 --- a/frigate/video.py +++ b/frigate/video.py @@ -109,7 +109,7 @@ def capture_frames( skipped_eps = EventsPerSecond() skipped_eps.start() - shm_count = max(10, config.detect.fps * 2) + shm_count = max(10, config.detect.fps) shm_frames: list[str] = [] while True: @@ -127,9 +127,11 @@ def capture_frames( if len(shm_frames) > shm_count: expired_frame_name = shm_frames.pop(0) frame_manager.delete(expired_frame_name) - except Exception: + except Exception as e: + logger.error(f"something video bad happened :: {e}") frame_manager.delete(frame_name) + # shutdown has been initiated if stop_event.is_set(): break @@ -149,6 +151,7 @@ def capture_frames( try: # add to the queue frame_queue.put(current_frame.value, False) + frame_manager.close(frame_name) except queue.Full: # if the queue is full, skip this frame skipped_eps.update()