mirror of
https://github.com/blakeblackshear/frigate.git
synced 2025-07-30 13:48:07 +02:00
Fix birdseye crash when dynamically adding a camera (#18821)
This commit is contained in:
parent
20dac9d05e
commit
55c6008ff0
@ -423,6 +423,7 @@ class FrigateApp:
|
||||
self.camera_metrics,
|
||||
self.ptz_metrics,
|
||||
self.stop_event,
|
||||
self.metrics_manager,
|
||||
)
|
||||
self.camera_maintainer.start()
|
||||
|
||||
|
@ -6,7 +6,7 @@ import os
|
||||
import shutil
|
||||
import threading
|
||||
from multiprocessing import Queue
|
||||
from multiprocessing.managers import DictProxy
|
||||
from multiprocessing.managers import DictProxy, SyncManager
|
||||
from multiprocessing.synchronize import Event as MpEvent
|
||||
|
||||
from frigate.camera import CameraMetrics, PTZMetrics
|
||||
@ -35,6 +35,7 @@ class CameraMaintainer(threading.Thread):
|
||||
camera_metrics: DictProxy,
|
||||
ptz_metrics: dict[str, PTZMetrics],
|
||||
stop_event: MpEvent,
|
||||
metrics_manager: SyncManager,
|
||||
):
|
||||
super().__init__(name="camera_processor")
|
||||
self.config = config
|
||||
@ -56,6 +57,7 @@ class CameraMaintainer(threading.Thread):
|
||||
self.shm_count = self.__calculate_shm_frame_count()
|
||||
self.camera_processes: dict[str, mp.Process] = {}
|
||||
self.capture_processes: dict[str, mp.Process] = {}
|
||||
self.metrics_manager = metrics_manager
|
||||
|
||||
def __init_historical_regions(self) -> None:
|
||||
# delete region grids for removed or renamed cameras
|
||||
@ -128,7 +130,7 @@ class CameraMaintainer(threading.Thread):
|
||||
return
|
||||
|
||||
if runtime:
|
||||
self.camera_metrics[name] = CameraMetrics()
|
||||
self.camera_metrics[name] = CameraMetrics(self.metrics_manager)
|
||||
self.ptz_metrics[name] = PTZMetrics(autotracker_enabled=False)
|
||||
self.region_grids[name] = get_camera_regions_grid(
|
||||
name,
|
||||
|
@ -319,35 +319,48 @@ class BirdsEyeFrameManager:
|
||||
self.frame[:] = self.blank_frame
|
||||
|
||||
self.cameras = {}
|
||||
for camera, settings in self.config.cameras.items():
|
||||
# precalculate the coordinates for all the channels
|
||||
y, u1, u2, v1, v2 = get_yuv_crop(
|
||||
settings.frame_shape_yuv,
|
||||
(
|
||||
0,
|
||||
0,
|
||||
settings.frame_shape[1],
|
||||
settings.frame_shape[0],
|
||||
),
|
||||
)
|
||||
self.cameras[camera] = {
|
||||
"dimensions": [settings.detect.width, settings.detect.height],
|
||||
"last_active_frame": 0.0,
|
||||
"current_frame": 0.0,
|
||||
"layout_frame": 0.0,
|
||||
"channel_dims": {
|
||||
"y": y,
|
||||
"u1": u1,
|
||||
"u2": u2,
|
||||
"v1": v1,
|
||||
"v2": v2,
|
||||
},
|
||||
}
|
||||
for camera in self.config.cameras.keys():
|
||||
self.add_camera(camera)
|
||||
|
||||
self.camera_layout = []
|
||||
self.active_cameras = set()
|
||||
self.last_output_time = 0.0
|
||||
|
||||
def add_camera(self, cam: str):
|
||||
"""Add a camera to self.cameras with the correct structure."""
|
||||
settings = self.config.cameras[cam]
|
||||
# precalculate the coordinates for all the channels
|
||||
y, u1, u2, v1, v2 = get_yuv_crop(
|
||||
settings.frame_shape_yuv,
|
||||
(
|
||||
0,
|
||||
0,
|
||||
settings.frame_shape[1],
|
||||
settings.frame_shape[0],
|
||||
),
|
||||
)
|
||||
self.cameras[cam] = {
|
||||
"dimensions": [
|
||||
settings.detect.width,
|
||||
settings.detect.height,
|
||||
],
|
||||
"last_active_frame": 0.0,
|
||||
"current_frame": 0.0,
|
||||
"layout_frame": 0.0,
|
||||
"channel_dims": {
|
||||
"y": y,
|
||||
"u1": u1,
|
||||
"u2": u2,
|
||||
"v1": v1,
|
||||
"v2": v2,
|
||||
},
|
||||
}
|
||||
|
||||
def remove_camera(self, cam: str):
|
||||
"""Remove a camera from self.cameras."""
|
||||
if cam in self.cameras:
|
||||
del self.cameras[cam]
|
||||
|
||||
def clear_frame(self):
|
||||
logger.debug("Clearing the birdseye frame")
|
||||
self.frame[:] = self.blank_frame
|
||||
@ -774,7 +787,7 @@ class Birdseye:
|
||||
self.broadcaster = BroadcastThread(
|
||||
"birdseye", self.converter, websocket_server, stop_event
|
||||
)
|
||||
self.birdseye_manager = BirdsEyeFrameManager(config, stop_event)
|
||||
self.birdseye_manager = BirdsEyeFrameManager(self.config, stop_event)
|
||||
self.frame_manager = SharedMemoryFrameManager()
|
||||
self.stop_event = stop_event
|
||||
self.requestor = InterProcessRequestor()
|
||||
@ -804,6 +817,16 @@ class Birdseye:
|
||||
self.birdseye_manager.clear_frame()
|
||||
self.__send_new_frame()
|
||||
|
||||
def add_camera(self, camera: str) -> None:
|
||||
"""Add a camera to the birdseye manager."""
|
||||
self.birdseye_manager.add_camera(camera)
|
||||
logger.debug(f"Added camera {camera} to birdseye")
|
||||
|
||||
def remove_camera(self, camera: str) -> None:
|
||||
"""Remove a camera from the birdseye manager."""
|
||||
self.birdseye_manager.remove_camera(camera)
|
||||
logger.debug(f"Removed camera {camera} from birdseye")
|
||||
|
||||
def write_data(
|
||||
self,
|
||||
camera: str,
|
||||
|
@ -133,7 +133,7 @@ class OutputProcess(FrigateProcess):
|
||||
# check if there is an updated config
|
||||
updates = config_subscriber.check_for_updates()
|
||||
|
||||
if "add" in updates:
|
||||
if CameraConfigUpdateEnum.add in updates:
|
||||
for camera in updates["add"]:
|
||||
jsmpeg_cameras[camera] = JsmpegCamera(
|
||||
cam_config, self.stop_event, websocket_server
|
||||
@ -141,6 +141,12 @@ class OutputProcess(FrigateProcess):
|
||||
preview_recorders[camera] = PreviewRecorder(cam_config)
|
||||
preview_write_times[camera] = 0
|
||||
|
||||
if (
|
||||
self.config.birdseye.enabled
|
||||
and self.config.cameras[camera].birdseye.enabled
|
||||
):
|
||||
birdseye.add_camera(camera)
|
||||
|
||||
(topic, data) = detection_subscriber.check_for_update(timeout=1)
|
||||
now = datetime.datetime.now().timestamp()
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user