feat: 长保持连接,控制端可重启

This commit is contained in:
Mock
2026-04-10 11:10:54 +08:00
parent 08057baf0c
commit adb43efb12
6 changed files with 190 additions and 23 deletions

View File

@@ -50,6 +50,9 @@ class OmniSocketVideoReceiver:
self._latency_samples_ms: deque[float] = deque(maxlen=VIDEO_TIMESTAMP_SAMPLE_SIZE)
self._frames_received = 0
self._last_error = ""
self._reconnect_count = 0
self._ever_connected = False
self._closing = threading.Event()
self._load_backend()
def _load_backend(self) -> None:
@@ -76,7 +79,7 @@ class OmniSocketVideoReceiver:
return
with self._lock:
if self._started:
if self._started or self._closing.is_set():
return
self._started = True
self._thread = threading.Thread(
@@ -167,14 +170,19 @@ class OmniSocketVideoReceiver:
return timestamp_ns, VIDEO_TIMESTAMP_UNIT, VIDEO_TIMESTAMP_ENDIANNESS
def _run(self) -> None:
while True:
while not self._closing.is_set():
try:
session, buffer_bytes = self._connect_session()
self._session = session
self._last_error = ""
with self._lock:
self._session = session
self._last_error = ""
if self._ever_connected:
self._reconnect_count += 1
else:
self._ever_connected = True
buffer = bytearray(buffer_bytes)
while True:
while not self._closing.is_set():
meta = session.recv_into(buffer, timeout_ms=1000)
if meta is None:
continue
@@ -207,15 +215,25 @@ class OmniSocketVideoReceiver:
self._latency_samples_ms.append(latency_ms)
self._frames_received += 1
except Exception as error: # pragma: no cover - runtime integration path
self._last_error = str(error)
time.sleep(2)
if not self._closing.is_set():
session_error = ""
if self._session is not None:
try:
session_error = str(dict(self._session.stats()).get("last_server_error", "") or "")
except Exception:
session_error = ""
self._last_error = session_error or str(error)
time.sleep(2)
finally:
if self._session is not None:
try:
self._session.close()
except Exception:
pass
with self._lock:
self._session = None
if self._closing.is_set():
self._started = False
def get_latest_frame(self) -> bytes | None:
self.ensure_started()
@@ -231,11 +249,11 @@ class OmniSocketVideoReceiver:
with self._lock:
session = self._session
if session is None:
return {"connected": 0}
return {"connected": 0, "registered": 0, "last_server_error": self._last_error}
try:
return dict(session.stats())
except Exception:
return {"connected": 0}
return {"connected": 0, "registered": 0, "last_server_error": self._last_error}
def session_kcp_stats(self) -> dict[str, Any]:
self.ensure_started()
@@ -248,6 +266,7 @@ class OmniSocketVideoReceiver:
config = load_omnisocket_config()
transport_cfg = config.get("transport", {})
video_cfg = config.get("video_receiver", {})
session_stats = self.session_stats()
with self._lock:
has_recent_frame = self._latest_frame is not None and (
time.time() - self._latest_received_at <= OMNISOCKET_FRAME_FRESH_SECONDS
@@ -276,9 +295,12 @@ class OmniSocketVideoReceiver:
"backend_ready": self._session_cls is not None,
"mode": VIDEO_SOURCE_MODE,
"connected": self._session is not None,
"registered": bool(session_stats.get("registered", 0)),
"has_recent_frame": has_recent_frame,
"frames_received": self._frames_received,
"latest_sequence": self._latest_sequence,
"reconnect_count": self._reconnect_count,
"last_server_error": str(session_stats.get("last_server_error", "") or ""),
"last_error": self._last_error,
"config_path": str(OMNISOCKET_CONFIG_PATH),
"server_addr": str(transport_cfg.get("server_addr", "")),
@@ -288,6 +310,19 @@ class OmniSocketVideoReceiver:
"timing": timing_status,
}
def close(self) -> None:
self._closing.set()
with self._lock:
session = self._session
if session is not None:
try:
session.close()
except Exception:
pass
thread = self._thread
if thread is not None and thread.is_alive():
thread.join(timeout=0.5)
class VideoFrameService:
def __init__(self, receiver: OmniSocketVideoReceiver) -> None: