46 lines
1.8 KiB
Python
46 lines
1.8 KiB
Python
"""Pass-through decoder for deterministic RGB24 synthetic frames."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from collections.abc import Iterable, Iterator
|
|
|
|
from yovision_brain.input import CancellationToken, InputPacket
|
|
|
|
from .models import DecodedFrame, DecoderError
|
|
|
|
|
|
class RawRGBDecoder:
|
|
media_formats = frozenset({"rgb24"})
|
|
|
|
def decode(
|
|
self,
|
|
packets: Iterable[InputPacket],
|
|
cancellation: CancellationToken | None = None,
|
|
) -> Iterator[DecodedFrame]:
|
|
previous_dimensions: tuple[int, int] | None = None
|
|
for packet in packets:
|
|
if cancellation is not None and cancellation.cancelled:
|
|
return
|
|
if packet.media_format != "rgb24":
|
|
raise DecoderError(f"raw RGB decoder does not support {packet.media_format!r}")
|
|
expected = packet.width * packet.height * 3
|
|
if len(packet.payload) != expected:
|
|
raise DecoderError(
|
|
f"RGB24 frame {packet.sequence} has {len(packet.payload)} bytes; expected {expected}"
|
|
)
|
|
if packet.timestamp_ns is None:
|
|
raise DecoderError(f"RGB24 frame {packet.sequence} has no source timestamp")
|
|
dimensions = (packet.width, packet.height)
|
|
yield DecodedFrame(
|
|
sequence=packet.sequence,
|
|
timestamp_ns=packet.timestamp_ns,
|
|
logical_device_id=packet.logical_device_id,
|
|
profile_id=packet.profile_id,
|
|
width=packet.width,
|
|
height=packet.height,
|
|
pixel_format="rgb24",
|
|
payload=packet.payload,
|
|
dimensions_changed=previous_dimensions is not None and dimensions != previous_dimensions,
|
|
)
|
|
previous_dimensions = dimensions
|