Fix birdseye crash when dynamically adding a camera (#18821)

This commit is contained in:
Josh Hawkins
2025-08-16 10:20:33 -05:00
committed by Blake Blackshear
parent 847b03e71b
commit 7c8164aa99
4 changed files with 60 additions and 28 deletions
+48 -25
View File
@@ -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,
+7 -1
View File
@@ -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()