From 6d4089feb7d665a32887e167c42959ce0935748a Mon Sep 17 00:00:00 2001 From: firestarsdog <229254897+firestarsdog@users.noreply.github.com> Date: Sun, 2 Aug 2026 03:24:23 -0400 Subject: [PATCH] Fix desktop raylib replay synchronization --- selfdrive/ui/onroad/cameraview.py | 6 ++++-- selfdrive/ui/tests/test_camera_frame_order.py | 15 +++++++++++++++ 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/selfdrive/ui/onroad/cameraview.py b/selfdrive/ui/onroad/cameraview.py index 624fd1300..38084d1f5 100644 --- a/selfdrive/ui/onroad/cameraview.py +++ b/selfdrive/ui/onroad/cameraview.py @@ -6,7 +6,7 @@ import pyray as rl from msgq.visionipc import VisionIpcClient, VisionStreamType, VisionBuf from openpilot.common.swaglog import cloudlog -from openpilot.system.hardware import TICI +from openpilot.system.hardware import PC, TICI from openpilot.system.ui.lib.application import gui_app from openpilot.system.ui.lib.egl import ( init_egl, is_egl_initialized, finish_gl, create_egl_image, destroy_egl_image, @@ -364,7 +364,9 @@ class CameraView(Widget): f"Dropping inconsistent {self._name} frame: content={content_frame_id}, packet={packet_frame_id}" ) return False - if content_frame_id < self._last_frame_id: + # Device camera frame IDs are monotonic; reject older reusable ring-buffer + # slots there. Desktop replay intentionally lowers IDs when seeking backward. + if not PC and content_frame_id < self._last_frame_id: self._regressive_frame_count += 1 if self._regressive_frame_count == 1 or self._regressive_frame_count % 100 == 0: message = f"Dropping regressive {self._name} frame: content={content_frame_id}, packet={packet_frame_id}, " diff --git a/selfdrive/ui/tests/test_camera_frame_order.py b/selfdrive/ui/tests/test_camera_frame_order.py index 0c4de889c..be64c9c23 100644 --- a/selfdrive/ui/tests/test_camera_frame_order.py +++ b/selfdrive/ui/tests/test_camera_frame_order.py @@ -106,6 +106,7 @@ def test_standalone_camera_reentry_selects_configured_stream(): def test_reused_egl_slot_cannot_move_camera_backwards(monkeypatch): monkeypatch.setattr(big_cameraview.cloudlog, "warning", lambda *_args, **_kwargs: None) + monkeypatch.setattr(big_cameraview, "PC", False) view = _camera_view() displayed = FakeFrame(frame_id=10, idx=0) @@ -122,6 +123,19 @@ def test_reused_egl_slot_cannot_move_camera_backwards(monkeypatch): assert view._regressive_frame_count == 1 +def test_texture_camera_accepts_regressive_replay_frame(monkeypatch): + monkeypatch.setattr(big_cameraview, "PC", True) + view = _camera_view() + + assert view._accept_frame(FakeFrame(frame_id=1140, idx=0), packet_frame_id=1140) + rewind = FakeFrame(frame_id=660, idx=1) + + assert view._accept_frame(rewind, packet_frame_id=660) + assert view.frame is rewind + assert view._last_frame_id == 660 + assert view._regressive_frame_count == 0 + + def test_newer_camera_frame_is_accepted(): view = _camera_view() view._last_frame_id = 30 @@ -150,6 +164,7 @@ def test_shared_camera_has_upstream_shaders_and_driver_enhancement(): def test_shared_camera_falls_back_after_repeated_regressive_frames(monkeypatch): monkeypatch.setattr(big_cameraview.cloudlog, "warning", lambda *_args, **_kwargs: None) + monkeypatch.setattr(big_cameraview, "PC", False) view = _camera_view() view._use_egl = True view.frame = FakeFrame(frame_id=30, idx=0)