mirror of
https://github.com/blakeblackshear/frigate.git
synced 2026-05-01 19:17:41 +03:00
Start processes dynamically when needed
This commit is contained in:
parent
f5b3f9ae87
commit
c7b4d7791b
@ -9,6 +9,7 @@ from multiprocessing.synchronize import Event as MpEvent
|
|||||||
|
|
||||||
from frigate.camera import CameraMetrics, PTZMetrics
|
from frigate.camera import CameraMetrics, PTZMetrics
|
||||||
from frigate.config import FrigateConfig
|
from frigate.config import FrigateConfig
|
||||||
|
from frigate.config.camera import CameraConfig
|
||||||
from frigate.config.updater import GlobalConfigUpdateEnum, GlobalConfigUpdateSubscriber
|
from frigate.config.updater import GlobalConfigUpdateEnum, GlobalConfigUpdateSubscriber
|
||||||
from frigate.const import SHM_FRAMES_VAR
|
from frigate.const import SHM_FRAMES_VAR
|
||||||
from frigate.models import Regions
|
from frigate.models import Regions
|
||||||
@ -49,6 +50,7 @@ class CameraMaintainer(threading.Thread):
|
|||||||
GlobalConfigUpdateEnum.remove_camera,
|
GlobalConfigUpdateEnum.remove_camera,
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
self.shm_count = self.__calculate_shm_frame_count()
|
||||||
|
|
||||||
def __init_historical_regions(self) -> None:
|
def __init_historical_regions(self) -> None:
|
||||||
# delete region grids for removed or renamed cameras
|
# delete region grids for removed or renamed cameras
|
||||||
@ -77,13 +79,23 @@ class CameraMaintainer(threading.Thread):
|
|||||||
cam_total_frame_size = 0.0
|
cam_total_frame_size = 0.0
|
||||||
|
|
||||||
for camera in self.config.cameras.values():
|
for camera in self.config.cameras.values():
|
||||||
if camera.enabled and camera.detect.width and camera.detect.height:
|
if (
|
||||||
|
camera.enabled_in_config
|
||||||
|
and camera.detect.width
|
||||||
|
and camera.detect.height
|
||||||
|
):
|
||||||
cam_total_frame_size += round(
|
cam_total_frame_size += round(
|
||||||
(camera.detect.width * camera.detect.height * 1.5 + 270480)
|
(camera.detect.width * camera.detect.height * 1.5 + 270480)
|
||||||
/ 1048576,
|
/ 1048576,
|
||||||
1,
|
1,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# leave room for 2 cameras that are added dynamically, if a user wants to add more cameras they may need to increase the SHM size and restart after adding them.
|
||||||
|
cam_total_frame_size += 2 * round(
|
||||||
|
(camera.detect.width * camera.detect.height * 1.5 + 270480) / 1048576,
|
||||||
|
1,
|
||||||
|
)
|
||||||
|
|
||||||
if cam_total_frame_size == 0.0:
|
if cam_total_frame_size == 0.0:
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
@ -103,17 +115,17 @@ class CameraMaintainer(threading.Thread):
|
|||||||
|
|
||||||
return shm_frame_count
|
return shm_frame_count
|
||||||
|
|
||||||
def __start_camera_processors(self) -> None:
|
def __start_camera_processor(self, name: str, config: CameraConfig) -> None:
|
||||||
for name, config in self.config.cameras.items():
|
config = self.config.cameras[name]
|
||||||
if not self.config.cameras[name].enabled_in_config:
|
if not config.enabled_in_config:
|
||||||
logger.info(f"Camera processor not started for disabled camera {name}")
|
logger.info(f"Camera processor not started for disabled camera {name}")
|
||||||
continue
|
return
|
||||||
|
|
||||||
camera_process = FrigateProcess(
|
camera_process = FrigateProcess(
|
||||||
target=track_camera,
|
target=track_camera,
|
||||||
name=f"camera_processor:{name}",
|
name=f"camera_processor:{name}",
|
||||||
args=(
|
args=(
|
||||||
name,
|
config.name,
|
||||||
config,
|
config,
|
||||||
self.config.model,
|
self.config.model,
|
||||||
self.config.model.merged_labelmap,
|
self.config.model.merged_labelmap,
|
||||||
@ -126,27 +138,24 @@ class CameraMaintainer(threading.Thread):
|
|||||||
),
|
),
|
||||||
daemon=True,
|
daemon=True,
|
||||||
)
|
)
|
||||||
self.camera_metrics[name].process = camera_process
|
self.camera_metrics[config.name].process = camera_process
|
||||||
camera_process.start()
|
camera_process.start()
|
||||||
logger.info(f"Camera processor started for {name}: {camera_process.pid}")
|
logger.info(f"Camera processor started for {config.name}: {camera_process.pid}")
|
||||||
|
|
||||||
def __start_camera_capture(self) -> None:
|
def __start_camera_capture(self, name: str, config: CameraConfig) -> None:
|
||||||
shm_frame_count = self.__calculate_shm_frame_count()
|
|
||||||
|
|
||||||
for name, config in self.config.cameras.items():
|
|
||||||
if not self.config.cameras[name].enabled_in_config:
|
if not self.config.cameras[name].enabled_in_config:
|
||||||
logger.info(f"Capture process not started for disabled camera {name}")
|
logger.info(f"Capture process not started for disabled camera {name}")
|
||||||
continue
|
return
|
||||||
|
|
||||||
# pre-create shms
|
# pre-create shms
|
||||||
for i in range(shm_frame_count):
|
for i in range(self.shm_count):
|
||||||
frame_size = config.frame_shape_yuv[0] * config.frame_shape_yuv[1]
|
frame_size = config.frame_shape_yuv[0] * config.frame_shape_yuv[1]
|
||||||
self.frame_manager.create(f"{config.name}_frame{i}", frame_size)
|
self.frame_manager.create(f"{config.name}_frame{i}", frame_size)
|
||||||
|
|
||||||
capture_process = FrigateProcess(
|
capture_process = FrigateProcess(
|
||||||
target=capture_camera,
|
target=capture_camera,
|
||||||
name=f"camera_capture:{name}",
|
name=f"camera_capture:{name}",
|
||||||
args=(config, shm_frame_count, self.camera_metrics[name]),
|
args=(config, self.shm_count, self.camera_metrics[name]),
|
||||||
)
|
)
|
||||||
capture_process.daemon = True
|
capture_process.daemon = True
|
||||||
self.camera_metrics[name].capture_process = capture_process
|
self.camera_metrics[name].capture_process = capture_process
|
||||||
@ -174,19 +183,21 @@ class CameraMaintainer(threading.Thread):
|
|||||||
self.__init_historical_regions()
|
self.__init_historical_regions()
|
||||||
|
|
||||||
# start camera processes
|
# start camera processes
|
||||||
self.__start_camera_processors()
|
for camera, config in self.config.cameras.items():
|
||||||
self.__start_camera_capture()
|
self.__start_camera_processor(camera, config)
|
||||||
|
self.__start_camera_capture(camera, config)
|
||||||
|
|
||||||
while not self.stop_event.wait(1):
|
while not self.stop_event.wait(1):
|
||||||
updates = self.update_subscriber.check_for_updates()
|
updates = self.update_subscriber.check_for_updates()
|
||||||
|
|
||||||
for update_type, update_payload in updates:
|
for update_type, update_config in updates:
|
||||||
if update_type == GlobalConfigUpdateEnum.add_camera:
|
if update_type == GlobalConfigUpdateEnum.add_camera:
|
||||||
pass
|
self.__start_camera_processor(update_config.name, update_config)
|
||||||
|
self.__start_camera_capture(update_config.name, update_config)
|
||||||
elif update_type == GlobalConfigUpdateEnum.debug_camera:
|
elif update_type == GlobalConfigUpdateEnum.debug_camera:
|
||||||
pass
|
pass
|
||||||
elif update_type == GlobalConfigUpdateEnum.remove_camera:
|
elif update_type == GlobalConfigUpdateEnum.remove_camera:
|
||||||
camera = update_payload.get("camera")
|
camera = update_config.name
|
||||||
|
|
||||||
if camera:
|
if camera:
|
||||||
self.__stop_camera_capture_process(camera)
|
self.__stop_camera_capture_process(camera)
|
||||||
|
|||||||
@ -5,6 +5,7 @@ from enum import Enum
|
|||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
from frigate.comms.config_updater import ConfigPublisher, ConfigSubscriber
|
from frigate.comms.config_updater import ConfigPublisher, ConfigSubscriber
|
||||||
|
from frigate.config.camera import CameraConfig
|
||||||
|
|
||||||
|
|
||||||
class GlobalConfigUpdateEnum(str, Enum):
|
class GlobalConfigUpdateEnum(str, Enum):
|
||||||
@ -46,21 +47,21 @@ class GlobalConfigUpdateSubscriber:
|
|||||||
exact=False,
|
exact=False,
|
||||||
)
|
)
|
||||||
|
|
||||||
def check_for_updates(self) -> list[tuple[GlobalConfigUpdateEnum, Any]]:
|
def check_for_updates(self) -> list[tuple[GlobalConfigUpdateEnum, CameraConfig]]:
|
||||||
updated_topics: list[tuple[GlobalConfigUpdateEnum, Any]] = []
|
updated_topics: list[tuple[GlobalConfigUpdateEnum, CameraConfig]] = []
|
||||||
|
|
||||||
# get all updates available
|
# get all updates available
|
||||||
while True:
|
while True:
|
||||||
update_topic, payload = self.subscriber.check_for_update()
|
update_topic, update_config = self.subscriber.check_for_update()
|
||||||
|
|
||||||
if update_topic is None or payload is None:
|
if update_topic is None or update_config is None:
|
||||||
break
|
break
|
||||||
|
|
||||||
_, raw_type = update_topic.split("/")
|
_, raw_type = update_topic.split("/")
|
||||||
update_type = GlobalConfigUpdateEnum[raw_type]
|
update_type = GlobalConfigUpdateEnum[raw_type]
|
||||||
|
|
||||||
if update_type in self.topics:
|
if update_type in self.topics:
|
||||||
updated_topics.append((update_type, payload))
|
updated_topics.append((update_type, update_config))
|
||||||
|
|
||||||
return updated_topics
|
return updated_topics
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user