mirror of
https://github.com/blakeblackshear/frigate.git
synced 2026-10-07 23:32:48 +03:00
fix birdseye reordering widget in settings
cameras are only sorted while the layout is built, so a config change that reorders them needs a fresh layout even when the active set is unchanged, which is always the case in continuous mode
This commit is contained in:
@@ -1,8 +1,10 @@
|
||||
"""Test camera user and password cleanup."""
|
||||
|
||||
import multiprocessing as mp
|
||||
import unittest
|
||||
|
||||
from frigate.output.birdseye import get_canvas_shape
|
||||
from frigate.config import FrigateConfig
|
||||
from frigate.output.birdseye import BirdsEyeFrameManager, get_canvas_shape
|
||||
|
||||
|
||||
class TestBirdseye(unittest.TestCase):
|
||||
@@ -45,3 +47,70 @@ class TestBirdseye(unittest.TestCase):
|
||||
canvas_width, canvas_height = get_canvas_shape(width, height)
|
||||
assert canvas_width == width # width will be the same
|
||||
assert canvas_height != height
|
||||
|
||||
|
||||
class TestBirdseyeCameraOrder(unittest.TestCase):
|
||||
"""Test that birdseye reacts to camera order changes without a restart."""
|
||||
|
||||
def setUp(self):
|
||||
config = {
|
||||
"mqtt": {"enabled": False},
|
||||
"birdseye": {"enabled": True, "mode": "continuous"},
|
||||
"cameras": {
|
||||
camera: {
|
||||
"ffmpeg": {
|
||||
"inputs": [
|
||||
{"path": "rtsp://10.0.0.1:554/video", "roles": ["detect"]}
|
||||
]
|
||||
},
|
||||
"detect": {"height": 1080, "width": 1920, "fps": 5},
|
||||
}
|
||||
for camera in ("back", "front", "side")
|
||||
},
|
||||
}
|
||||
self.config = FrigateConfig(**config)
|
||||
self.manager = BirdsEyeFrameManager(self.config, mp.Event())
|
||||
|
||||
# mark every camera as continuously active with no frame to draw, which
|
||||
# exercises the layout without needing real yuv frames
|
||||
for camera_data in self.manager.cameras.values():
|
||||
camera_data["current_frame"] = None
|
||||
camera_data["current_frame_time"] = 1.0
|
||||
camera_data["last_active_frame"] = 1.0
|
||||
|
||||
def layout_order(self) -> list[str]:
|
||||
"""Return the cameras in the order the current layout renders them."""
|
||||
return [position[0] for row in self.manager.camera_layout for position in row]
|
||||
|
||||
def test_layout_uses_configured_order(self):
|
||||
"""Test the layout is sorted by order, then by name when tied."""
|
||||
self.config.cameras["side"].birdseye.order = 0
|
||||
self.config.cameras["back"].birdseye.order = 10
|
||||
self.config.cameras["front"].birdseye.order = 20
|
||||
|
||||
self.manager.update_frame()
|
||||
|
||||
assert self.layout_order() == ["side", "back", "front"]
|
||||
|
||||
def test_order_change_rebuilds_layout(self):
|
||||
"""Test a reorder relayouts even though the active cameras are unchanged."""
|
||||
self.manager.update_frame()
|
||||
assert self.layout_order() == ["back", "front", "side"]
|
||||
|
||||
# a stable active set means only an order change can reset the layout,
|
||||
# which is what a settings reorder publishes to this process
|
||||
self.config.cameras["side"].birdseye.order = -10
|
||||
|
||||
_, layout_changed = self.manager.update_frame()
|
||||
|
||||
assert layout_changed
|
||||
assert self.layout_order() == ["side", "back", "front"]
|
||||
|
||||
def test_unchanged_order_keeps_layout(self):
|
||||
"""Test a repeat update with no order change doesn't reset the layout."""
|
||||
self.manager.update_frame()
|
||||
|
||||
_, layout_changed = self.manager.update_frame()
|
||||
|
||||
assert not layout_changed
|
||||
assert self.layout_order() == ["back", "front", "side"]
|
||||
|
||||
Reference in New Issue
Block a user