Complete VIDEO-001 through VIDEO-004 software video studies
This commit is contained in:
50
protocol/video003_compact_header.py
Normal file
50
protocol/video003_compact_header.py
Normal file
@@ -0,0 +1,50 @@
|
||||
"""Отдельная проверка 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:])
|
||||
Reference in New Issue
Block a user