Просмотр исходного кода

pull from memory if event in progress

Blake Blackshear 4 лет назад
Родитель
Сommit
60207723d1
4 измененных файлов с 34 добавлено и 9 удалено
  1. 4 3
      frigate/app.py
  2. 3 1
      frigate/events.py
  3. 13 0
      frigate/http.py
  4. 14 5
      frigate/object_processing.py

+ 4 - 3
frigate/app.py

@@ -55,8 +55,9 @@ class FrigateApp():
             }
 
     def init_queues(self):
-        # Queue for clip processing
+        # Queues for clip processing
         self.event_queue = mp.Queue()
+        self.event_processed_queue = mp.Queue()
 
         # Queue for cameras to push tracked objects to
         self.detected_frames_queue = mp.Queue(maxsize=len(self.config.cameras.keys())*2)
@@ -89,7 +90,7 @@ class FrigateApp():
 
     def start_detected_frames_processor(self):
         self.detected_frames_processor = TrackedObjectProcessor(self.config, self.mqtt_client, self.config.mqtt.topic_prefix, 
-            self.detected_frames_queue, self.event_queue, self.stop_event)
+            self.detected_frames_queue, self.event_queue, self.event_processed_queue, self.stop_event)
         self.detected_frames_processor.start()
 
     def start_camera_processors(self):
@@ -112,7 +113,7 @@ class FrigateApp():
             logger.info(f"Capture process started for {name}: {capture_process.pid}")
     
     def start_event_processor(self):
-        self.event_processor = EventProcessor(self.config, self.camera_metrics, self.event_queue, self.stop_event)
+        self.event_processor = EventProcessor(self.config, self.camera_metrics, self.event_queue, self.event_processed_queue, self.stop_event)
         self.event_processor.start()
 
     def start_event_cleanup(self):

+ 3 - 1
frigate/events.py

@@ -19,7 +19,7 @@ from peewee import fn
 logger = logging.getLogger(__name__)
 
 class EventProcessor(threading.Thread):
-    def __init__(self, config, camera_processes, event_queue, stop_event):
+    def __init__(self, config, camera_processes, event_queue, event_processed_queue, stop_event):
         threading.Thread.__init__(self)
         self.name = 'event_processor'
         self.config = config
@@ -28,6 +28,7 @@ class EventProcessor(threading.Thread):
         self.camera_processes = camera_processes
         self.cached_clips = {}
         self.event_queue = event_queue
+        self.event_processed_queue = event_processed_queue
         self.events_in_process = {}
         self.stop_event = stop_event
     
@@ -190,6 +191,7 @@ class EventProcessor(threading.Thread):
                         thumbnail=event_data['thumbnail']
                     )
                 del self.events_in_process[event_data['id']]
+                self.event_processed_queue.put((event_data['id'], camera))
 
 class EventCleanup(threading.Thread):
     def __init__(self, config: FrigateConfig, stop_event):

+ 13 - 0
frigate/http.py

@@ -14,6 +14,8 @@ from playhouse.shortcuts import model_to_dict
 
 from frigate.models import Event
 
+logger = logging.getLogger(__name__)
+
 bp = Blueprint('frigate', __name__)
 
 def create_app(frigate_config, database: SqliteDatabase, camera_metrics, detectors, detected_frames_processor):
@@ -79,6 +81,17 @@ def event_snapshot(id):
         response.headers['Content-Type'] = 'image/jpg'
         return response
     except DoesNotExist:
+        # see if the object is currently being tracked
+        try:
+            for camera_state in current_app.detected_frames_processor.camera_states.values():
+                if id in camera_state.tracked_objects:
+                    tracked_obj = camera_state.tracked_objects.get(id)
+                    if not tracked_obj is None:
+                        response = make_response(tracked_obj.get_jpg_bytes())
+                        response.headers['Content-Type'] = 'image/jpg'
+                        return response
+        except:
+            return "Event not found", 404
         return "Event not found", 404
 
 @bp.route('/events')

+ 14 - 5
frigate/object_processing.py

@@ -279,6 +279,9 @@ class CameraState():
         
         return frame_copy
 
+    def finished(self, obj_id):
+        del self.tracked_objects[obj_id]
+
     def on(self, event_type: str, callback: Callable[[Dict], None]):
         self.callbacks[event_type].append(callback)
 
@@ -317,10 +320,10 @@ class CameraState():
         for id in removed_ids:
             # publish events to mqtt
             removed_obj = self.tracked_objects[id]
-            removed_obj.obj_data['end_time'] = frame_time
-            for c in self.callbacks['end']:
-                c(self.name, removed_obj)
-            del self.tracked_objects[id]
+            if not 'end_time' in removed_obj.obj_data:
+                removed_obj.obj_data['end_time'] = frame_time
+                for c in self.callbacks['end']:
+                    c(self.name, removed_obj)
 
         # TODO: can i switch to looking this up and only changing when an event ends?
         #       maybe make an api endpoint that pulls the thumbnail from the file system?
@@ -382,7 +385,7 @@ class CameraState():
             self.previous_frame_id = frame_id
 
 class TrackedObjectProcessor(threading.Thread):
-    def __init__(self, config: FrigateConfig, client, topic_prefix, tracked_objects_queue, event_queue, stop_event):
+    def __init__(self, config: FrigateConfig, client, topic_prefix, tracked_objects_queue, event_queue, event_processed_queue, stop_event):
         threading.Thread.__init__(self)
         self.name = "detected_frames_processor"
         self.config = config
@@ -390,6 +393,7 @@ class TrackedObjectProcessor(threading.Thread):
         self.topic_prefix = topic_prefix
         self.tracked_objects_queue = tracked_objects_queue
         self.event_queue = event_queue
+        self.event_processed_queue = event_processed_queue
         self.stop_event = stop_event
         self.camera_states: Dict[str, CameraState] = {}
         self.frame_manager = SharedMemoryFrameManager()
@@ -480,3 +484,8 @@ class TrackedObjectProcessor(threading.Thread):
                         self.client.publish(f"{self.topic_prefix}/{zone}/{label}", 'ON', retain=False)
                     elif previous_state == True and new_state == False:
                         self.client.publish(f"{self.topic_prefix}/{zone}/{label}", 'OFF', retain=False)
+
+            # cleanup event finished queue
+            while not self.event_processed_queue.empty():
+                event_id, camera = self.event_processed_queue.get()
+                self.camera_states[camera].finished(event_id)