Admit onboard camera preview only after its acquisition producer is ready

This commit is contained in:
DCCONSTRUCTIONS
2026-09-07 16:44:38 +03:00
parent fa8ac760a1
commit 9e03404f23
5 changed files with 65 additions and 12 deletions
@@ -970,7 +970,9 @@ class XgridsK1CameraGateway:
)
return self.snapshot()
def open_delivery(self, generation: int) -> CameraProcessLease:
def open_delivery(
self, generation: int, *, require_recording: bool = False
) -> CameraProcessLease:
with self._lifecycle_lock:
with self._lock:
self._require_open_locked()
@@ -978,6 +980,8 @@ class XgridsK1CameraGateway:
raise ValueError("camera preview generation не активно")
producer = self._producer
recording_active = self._recording_root is not None
if require_recording and (not recording_active or producer is None):
raise RuntimeError("camera acquisition producer is not ready")
if producer is None:
# An acquisition owns its producer lifecycle. Once an epoch is
# sealed, a disposable browser reconnect must not resurrect the
+17 -4
View File
@@ -133,8 +133,23 @@ class NodeMediaPeers:
while identifier in self.items and time.monotonic() < deadline:
state = self.camera.snapshot()
delivery = state.get("delivery") or {}
if state.get("generation") is not None and delivery.get("media_type"):
lease = await asyncio.to_thread(self.camera.open_delivery, state["generation"])
recording = state.get("recording") or {}
if recording.get("source_end_expected"):
break
if (state.get("generation") is not None and delivery.get("media_type")
and recording.get("active") is True
and recording.get("producer_alive") is True
and recording.get("media_ready") is True
and recording.get("active_epoch") == state["generation"]):
try:
lease = await asyncio.to_thread(
self.camera.open_delivery, state["generation"], require_recording=True
)
except (ValueError, RuntimeError):
# The acquisition owner may replace an epoch between this
# snapshot and lease admission. Observe its next ready epoch.
await asyncio.sleep(0.25)
continue
try:
channel.send(json.dumps({
"type": "camera-ready", "mime": delivery["media_type"],
@@ -143,8 +158,6 @@ class NodeMediaPeers:
self.camera.release_delivery(lease, client_closed=True)
raise
return lease
if state.get("phase") == "error":
break
await asyncio.sleep(0.25)
return None