"""Отдельная проверка 13-байтного видеозаголовка; формат VIDEO-002 не меняется.""" from __future__ import annotations import struct from protocol.video_stream_transport import ( MAX_FRAGMENTS, FrameType, VideoFragment, VideoTransportError, ) VERSION = 2 HEADER_FORMAT = "!BIIBBH" HEADER_SIZE = struct.calcsize(HEADER_FORMAT) # 13 байт def encode(fragment: VideoFragment, max_phy_payload: int) -> bytes: """Оставить поток и кадр 32-битными; кодировать count как count-1.""" if not 0 <= fragment.stream_id <= 0xFFFFFFFF or not 0 <= fragment.frame_id <= 0xFFFFFFFF: raise VideoTransportError("номер потока или кадра вне диапазона") if not 1 <= fragment.fragment_count <= MAX_FRAGMENTS: raise VideoTransportError("неверное число фрагментов") if not 0 <= fragment.fragment_index < fragment.fragment_count: raise VideoTransportError("неверный номер фрагмента") if fragment.frame_type not in (FrameType.KEYFRAME, FrameType.DELTA_FRAME): raise VideoTransportError("неверный тип кадра") if not 0 <= fragment.age_ms <= 0xFFFF: raise VideoTransportError("неверный возраст кадра") if not isinstance(fragment.data, bytes) or not 1 <= len(fragment.data) <= max_phy_payload - HEADER_SIZE: raise VideoTransportError("данные не помещаются в PHY payload") flags = (VERSION << 4) | int(fragment.frame_type) header = struct.pack(HEADER_FORMAT, flags, fragment.stream_id, fragment.frame_id, fragment.fragment_index, fragment.fragment_count - 1, fragment.age_ms) return header + fragment.data def decode(wire: bytes, max_phy_payload: int) -> VideoFragment: """Размер данных берётся из длины внешнего CRC-проверенного payload.""" if not isinstance(wire, bytes) or not HEADER_SIZE < len(wire) <= max_phy_payload: raise VideoTransportError("длина видеопакета вне диапазона") flags, stream_id, frame_id, index, count_minus_one, age_ms = struct.unpack( HEADER_FORMAT, wire[:HEADER_SIZE]) if flags >> 4 != VERSION or (flags & 0x0F) not in (1, 2): raise VideoTransportError("версия или тип кадра не поддерживается") count = count_minus_one + 1 if index >= count: raise VideoTransportError("неверный номер фрагмента") return VideoFragment(stream_id, frame_id, index, count, FrameType(flags & 0x0F), age_ms, wire[HEADER_SIZE:])