_VideoRelay
Bounded video delivery for one (client, display) pair.
The fan-out offers every encoded chunk synchronously and never awaits a socket; each relay's own task drains its backlog. One slow client can therefore neither pace the other clients nor back frames up into the shared pipeline or its socket transport (whose freed burst peaks the allocator retains, ratcheting RSS): past its byte budget (~ VIDEO_RELAY_BUDGET_SECONDS of stream at the configured bitrate) it drops its backlog and skips ahead to the next keyframe, the standard broadcast-video contract. Keyframes are exempt from the budget (part of one is useless), so the true bound is budget plus one keyframe burst.
H.264 chain safety is tracked per stripe ROW (wire-header y_start, bytes 4:6): one capture frame can mix IDR and delta stripes (a lone stripe encoder re-init IDRs only its own row), so after any drop a row's delta chunks stay gated until that row's own IDR arrives — a delivered delta otherwise decodes against a reference the client never received. The wire type byte (offset 1) is stamped from the encoder's ACTUAL output picture type on every backend, and a requested recovery IDR covers every row (force_idr_all), so gated rows converge on the next request. JPEG chunks (0x03) have no reference chain: never gated, and a drop only costs a repaint request. A fresh relay starts fully gated, so a joining client waits for a keyframe instead of decoding mid-GOP garbage.
Attributes
attribute__slots__= ('server', 'display_id', 'ws', 'budget', 'backlog', 'backlog_bytes', 'live_rows', 'stopped', '_wake', '_task', '_next_sync_req')attributeserver= serverattributedisplay_id= display_idattributews= wsattributebudget= budgetSkip-ahead byte bound for the backlog (_video_relay_budget).
attributebacklogdeque= deque()Undrained fan-out items, oldest first.
attributebacklog_bytes= 0Payload bytes held in backlog.
attributelive_rowsset[int]= set()Stripe rows whose IDR was accepted into the current backlog; only their delta chunks are chain-continuous for this client.
attributestopped= FalseSet by stop; the drain task exits after its in-flight send.
attribute_wake= asyncio.Event()attribute_taskOptional[asyncio.Task]= Noneattribute_next_sync_req= 0.0Functions
func__init__(self, server, display_id, ws, budget) -> NoneSource Code
def __init__(self, server: "DataStreamingServer", display_id: str,
ws: web.WebSocketResponse, budget: int) -> None:
self.server = server
self.display_id = display_id
self.ws = ws
self.budget = budget
self.backlog: deque = deque()
self.backlog_bytes = 0
self.live_rows: set[int] = set()
self.stopped = False
self._wake = asyncio.Event()
self._task: Optional[asyncio.Task] = None
self._next_sync_req = 0.0paramselfparamserverDataStreamingServerparamdisplay_idstrparamwsweb.WebSocketResponseparambudgetintReturns
Nonefuncstart(self) -> NoneSource Code
def start(self) -> None:
self._task = asyncio.create_task(
self._run(), name=f"VideoRelay:{self.display_id}")paramselfReturns
Nonefuncstop(self) -> NoneGraceful: an in-flight send completes — cancelling mid-frame would tear the websocket framing on a socket that stays open for control.
Source Code
def stop(self) -> None:
"""Graceful: an in-flight send completes — cancelling mid-frame would
tear the websocket framing on a socket that stays open for control."""
self.stopped = True
self.backlog.clear()
self.backlog_bytes = 0
self._wake.set()paramselfReturns
Nonefuncflush_for_gate(self) -> NoneACK backpressure engaged: drop the undrained backlog and gate every row, so the client resumes only at the IDR that _set_backpressure_enabled requests when the gate lifts.
Source Code
def flush_for_gate(self) -> None:
"""ACK backpressure engaged: drop the undrained backlog and gate every
row, so the client resumes only at the IDR that
_set_backpressure_enabled requests when the gate lifts."""
if self.backlog or self.live_rows:
self.backlog.clear()
self.backlog_bytes = 0
self.live_rows.clear()paramselfReturns
Nonefunc_want_sync(self) -> boolRate-limit this relay's keyframe (re)requests to the sync floor.
Source Code
def _want_sync(self) -> bool:
"""Rate-limit this relay's keyframe (re)requests to the sync floor."""
now = time.monotonic()
if now >= self._next_sync_req:
self._next_sync_req = now + VIDEO_RELAY_SYNC_FLOOR_SECONDS
return True
return FalseparamselfReturns
boolfuncoffer(self, item) -> boolAccept, drop, or gate one encoded chunk.
Runs on the event loop and never awaits.
Source Code
def offer(self, item: dict) -> bool:
"""Accept, drop, or gate one encoded chunk.
Runs on the event loop and never awaits.
Args:
item: The fan-out item (`data` memoryview, `owner` frame,
`frame_id`).
Returns:
True when the caller should request a keyframe (data was dropped
that only a sync point recovers).
"""
data = item['data']
size = len(data)
is_h264 = size >= 10 and data[0] == 0x04
is_idr = is_h264 and data[1] == 0x01
dropped = False
if (not is_idr and self.backlog
and self.backlog_bytes + size > self.budget):
self.backlog.clear()
self.backlog_bytes = 0
self.live_rows.clear()
dropped = True
deliver = True
if is_h264:
row = (data[4] << 8) | data[5]
if is_idr:
self.live_rows.add(row)
elif row not in self.live_rows:
deliver = False
dropped = True
if deliver:
self.backlog.append(item)
self.backlog_bytes += size
self._wake.set()
return dropped and self._want_sync()paramselfparamitemdictThe fan-out item (data memoryview, owner frame,
frame_id).
Returns
boolTrue when the caller should request a keyframe (data was dropped
func_run(self) -> NoneDrain the backlog onto the socket until stopped or the socket dies.
Source Code
async def _run(self) -> None:
"""Drain the backlog onto the socket until stopped or the socket dies."""
try:
while True:
if self.stopped:
return
if not self.backlog:
self._wake.clear()
await self._wake.wait()
continue
item = self.backlog.popleft()
data = item['data']
self.backlog_bytes -= len(data)
# Stamped before the await, and only for the display's
# registered client: that is what the ACK RTT math measures.
ds = self.server.display_clients.get(self.display_id)
if ds is not None and ds.get('ws') is self.ws:
fid = item['frame_id']
ds['sent_timestamps'][fid] = time.monotonic()
ds['last_sent_frame_id'] = fid
ds['has_sent_any_frame'] = True
if len(ds['sent_timestamps']) > SENT_FRAME_TIMESTAMP_HISTORY_SIZE:
ds['sent_timestamps'].popitem(last=False)
try:
await asyncio.wait_for(
self.ws.send_bytes(data),
timeout=SHARED_STREAM_SEND_TIMEOUT_SECONDS,
)
except asyncio.TimeoutError:
# Checked before OSError: on 3.11+ TimeoutError subclasses it.
data_logger.warning(
f"Video relay for '{self.display_id}' send stalled past "
f"{SHARED_STREAM_SEND_TIMEOUT_SECONDS}s; dropping client.")
self.server.clients.discard(self.ws)
_close_abandoned_ws(self.ws)
return
except (ConnectionResetError, OSError, RuntimeError):
self.server.clients.discard(self.ws)
return
self.server._bytes_sent_in_interval += len(data)
finally:
group = self.server.video_relay_groups.get(self.display_id)
if group is not None and group.get(self.ws) is self:
del group[self.ws]paramselfReturns
None