open-standards/wai/format-probe-conformance/format_probe_verify.py
Transaction Science f5a242a9a2
Some checks are pending
joule-moq-remote host agent / joule-moq-remote · does this change touch it (push) Successful in 23s
joule-moq-remote host agent / joule-moq-remote, every target (macos) (push) Waiting to run
joule-moq-room room service / joule-moq-room · does this change touch it (push) Successful in 21s
joule-moq-web browser client / joule-moq-web · does this change touch it (push) Successful in 22s
joule-moq-web browser client / joule-moq-web · browser end-to-end (macos) (push) Waiting to run
wai-app and Create / wai-app · does this change touch it (push) Successful in 31s
wai-app and Create / wai-app · Create, browser end-to-end (macos) (push) Waiting to run
WAI operation catalogue / does this change touch it (push) Successful in 20s
wai-audit collector and player integration / does this change touch it (push) Successful in 30s
wai-sink-swift native sink package / does this change touch it (push) Successful in 18s
wai-audit collector and player integration / collector, player integration and the browser end to end · macos (push) Waiting to run
wai-sink-swift native sink package / libwai slices, desktop tests, simulator tests · macos (push) Waiting to run
wai-quantum studio and desktop / does this change touch it (push) Successful in 14s
wai-ledger service / does this change touch it (push) Successful in 45s
wai-quantum studio and desktop / desktop app · macos (push) Waiting to run
wai-ledger service / service · macos (push) Waiting to run
wai-fleet service / does this change touch it (push) Successful in 1m1s
wai-sink-android native sink library / does this change touch it (push) Successful in 19s
wai-fleet service / service · macos (push) Waiting to run
wai-sink-android native sink library / every ABI, the AAR, and the instrumented tests in a headless emulator · macos (push) Waiting to run
wai-quantum for JavaScript / does this change touch it (push) Successful in 51s
WAI Studio / does this change touch it (push) Successful in 52s
WAI Studio / Studio in Chromium and Firefox · macos (push) Waiting to run
joule-moq-remote host agent / joule-moq-remote, every target (linux-arm64) (push) Successful in 2m14s
repository checks / lockfiles, advisories, tests in CI, workflow hygiene, spec and section references, public text (push) Successful in 5m12s
wai-sink-android native sink library / the JNI layer and the platform-free half on the host JVM · linux-arm64 (push) Successful in 5m30s
joule-moq-room room service / joule-moq-room, every target (push) Successful in 7m13s
WAI breaking changes and the conformance runner / WAI breaking · does this change touch WAI (push) Successful in 27s
WAI breaking changes and the conformance runner / WAI breaking · wire, record and API against main · linux (push) Waiting to run
WAI breaking changes and the conformance runner / WAI breaking and conform · their tests, and the independent verifiers through wai conform · linux (push) Waiting to run
wai-app and Create / wai-app · tests, clippy, the line language's verifier (linux) (push) Successful in 41s
wai-audit collector and player integration / collector · linux (push) Successful in 2m30s
wai-ledger service / service · linux (push) Successful in 1m53s
WAI Studio / Studio in WebKit · linux (push) Has started running
WAI Studio / the catalogue's actions, the unit tests and the core · linux (push) Successful in 1m5s
wai-quantum studio and desktop / studio · browser (push) Successful in 4m38s
wai-quantum for JavaScript / javascript · linux (push) Successful in 3m51s
wai-fleet service / service · linux (push) Successful in 4m2s
WAI operation catalogue / the catalogue and every door · linux (push) Successful in 8m54s
wai-quantum studio and desktop / desktop app · linux (push) Successful in 11m31s
wai-quantum studio and desktop / desktop app · windows (push) Has started running
wai: header probes for AV2, AC-4, IAMF and IVAS, their codec strings, and why EVC has none
format-probes §14 to §17 add probes of basis `standard`, each read from its published text:

- AV2 (`wai.video.av2`, AV2 v1.0.0): the length-delimited bitstream of Annex B, the OBU
  headers, the temporal delimiter a payload begins with, and the first sequence header OBU
  through its cropping window: profile, level, tier, chroma format, bit depth, maximum and
  cropped size, layer counts, with Annex A's reserved profiles and levels and each profile's
  chroma formats refused. No codec string: AOMedia's ISO BMFF binding is a working draft.
- AC-4 (`wai.audio.ac4`, ETSI TS 103 190-1 V1.4.1 and -2 V1.3.1): sync frames with their CRC
  checked and the first table of contents to the first presentation's md_compat; the codec
  string of TS 103 190-2 E.13.
- IAMF (`wai.audio.iamf`, IAMF v2.0.0): a standalone IA Sequence, its profiles, the order of
  its Descriptors, the Opus, FLAC and LPCM configurations as §3.13 constrains them, the start of
  each audio element; the codec string of §6.4.
- IVAS (`wai.audio.ivas`, 3GPP TS 26.253 V19.3.0 Annex A): one IVAS payload's E and ToC bytes,
  frame sizes, processing information, padding and the first IVAS frame's format; `sivs`
  (TS 26.244 A.2.2).

§18 says why EVC has no probe: its framing, NAL unit types and SPS are in ISO/IEC 23094-1,
which is not openly readable, and RFC 9584 gives only the NAL unit header. §2.6 and
platform-decode §2.5: the probes' `codec`, which browser-sink §4.2's gate refuses, so no user
agent is asked; a native sink reads the string from the payload. SPEC §5 pins the payload forms
of AC-4, IAMF and IVAS to what their probes read. Nothing is added to the floor or the
recommended set.

format-probe-conformance: hand-built vectors with known field values under gen/av2, gen/ac4,
gen/iamf and gen/ivas, the texts' codec-string examples among them, and negative controls;
format_probe_verify.py reads them with its own readers and requires the new planted faults
(stated profiles, levels, versions, bit rates and codec strings, header bytes under restated
digests) to fail, as tests/format_probe.rs requires of corpus::verify.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-10 15:29:02 -05:00

1760 lines
59 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""The second implementation of the format probes: written from extensions/format-probes.md
and extensions/projection.md, sharing no code with wai-rs.
python3 -I format_probe_verify.py <corpus-dir> [--fetched <dir>]
It probes every vector of <corpus-dir>/vectors.json and requires the outcome stated there
(the parameters, or the refusal), every binding's outcome, every fact (what an encoder was
asked for), that every file under ext/ and gen/ is a vector's, that vectors.json's probe and
refusal lists are the extension's §2.4 and §12 tables, and that every refusal is given. With
--fetched it requires every fetched LCEVC stream (fetch.sh) and what its encoder was asked for.
Then it mutates copies of the corpus and requires each copy to fail.
Exit status 0 only if everything verifies and every mutated copy fails. Python 3.8 or later;
standard library only.
"""
import copy
import hashlib
import json
import os
import re
import struct
import sys
HERE = os.path.dirname(os.path.abspath(__file__))
EXT = os.path.join(HERE, "..", "extensions")
class Refuse(Exception):
def __init__(self, code):
Exception.__init__(self, code)
self.code = code
# ---- bits (§2.2) -------------------------------------------------------------------
class Bits:
def __init__(self, data):
self.d = bytes(data)
self.p = 0
def left(self):
return len(self.d) * 8 - self.p
def u(self, n):
if self.left() < n:
raise Refuse("truncated")
v = 0
for _ in range(n):
v = (v << 1) | ((self.d[self.p >> 3] >> (7 - (self.p & 7))) & 1)
self.p += 1
return v
def flag(self):
return self.u(1) == 1
def skip(self, n):
if self.left() < n:
raise Refuse("truncated")
self.p += n
def ue(self):
zeros = 0
while self.u(1) == 0:
zeros += 1
if zeros > 31:
raise Refuse("reserved_value")
return (1 << zeros) - 1 + self.u(zeros) if zeros else 0
def aligned(self):
return self.p % 8 == 0
def align(self, bit):
while not self.aligned():
b = self.u(1)
if bit is not None and b != bit:
raise Refuse("reserved_value")
def be16(b, at):
if at + 2 > len(b):
raise Refuse("truncated")
return (b[at] << 8) | b[at + 1]
# ---- Annex B (§2.5) ----------------------------------------------------------------
def nal_units(b):
i = 0
while i < len(b) and b[i] == 0:
i += 1
if i < 2 or i >= len(b) or b[i] != 1:
raise Refuse("no_signature")
starts, j = [], 0
while j + 2 < len(b):
if b[j] == 0 and b[j + 1] == 0 and b[j + 2] == 1:
starts.append(j + 3)
j += 3
else:
j += 1
out = []
for k, s in enumerate(starts):
e = starts[k + 1] - 3 if k + 1 < len(starts) else len(b)
while e > s and b[e - 1] == 0:
e -= 1
out.append(b[s:e])
return out
def unescape(n):
out, zeros = bytearray(), 0
for x in n:
if zeros >= 2 and x == 3:
zeros = 0
continue
zeros = zeros + 1 if x == 0 else 0
out.append(x)
return bytes(out)
def crop(chroma, w, h, c):
sw, sh = {1: (2, 2), 2: (2, 1)}.get(chroma, (1, 1))
dw, dh = sw * (c[0] + c[1]), sh * (c[2] + c[3])
if dw >= w or dh >= h:
raise Refuse("reserved_value")
return [w - dw, h - dh]
# ---- JPEG XS (§3) ------------------------------------------------------------------
def spec_text(name):
return open(os.path.join(EXT, name), encoding="utf-8").read()
def section(text, heading):
at = text.index("\n" + heading)
nxt = text.find("\n## ", at + 1)
return text[at:nxt if nxt >= 0 else len(text)]
FP = spec_text("format-probes.md")
PROFILES = {}
for row in re.findall(r"^\|(.*)\|$", section(FP, "## 3. JPEG XS"), re.M):
cells = [c.strip() for c in row.split("|")]
for k in range(0, len(cells) - 1, 2):
m = re.fullmatch(r"`0x([0-9A-F]{4})`", cells[k])
if m and cells[k + 1]:
PROFILES[int(m.group(1), 16)] = cells[k + 1]
LEVELS = {0x00: "Unrestricted", 0x04: "1k-1", 0x10: "2k-1", 0x20: "4k-1", 0x24: "4k-2", 0x28: "4k-3",
0x2C: "5k-1", 0x30: "8k-1", 0x34: "8k-2", 0x38: "8k-3", 0x40: "10k-1"}
SUBLEVELS = {0x00: "Unrestricted", 0x80: "Full", 0x10: "Sublev12bpp", 0x0C: "Sublev9bpp", 0x08: "Sublev6bpp",
0x06: "Sublev4bpp", 0x04: "Sublev3bpp", 0x03: "Sublev2bpp"}
def jxs_codestream(b):
if len(b) < 2 or be16(b, 0) != 0xFF10:
raise Refuse("no_signature")
if be16(b, 2) != 0xFF50:
raise Refuse("out_of_order")
lcap = be16(b, 4)
if lcap < 2:
raise Refuse("length_mismatch")
if 4 + lcap > len(b):
raise Refuse("truncated")
cap_bits = [i * 8 + k for i, x in enumerate(b[6:4 + lcap]) for k in range(8) if x & (0x80 >> k)]
at = 4 + lcap
if be16(b, at) != 0xFF12:
raise Refuse("out_of_order")
if be16(b, at + 2) != 26:
raise Refuse("length_mismatch")
if at + 28 > len(b):
raise Refuse("truncated")
p = b[at + 4:at + 28]
lcod, ppih, plev, wf, hf, cw, hsl = struct.unpack(">IHHHHHH", p[:16])
nc, ng, ss, bw = p[16], p[17], p[18], p[19]
fq, br = p[20] >> 4, p[20] & 15
cpih = p[21] & 15
nlx, nly = p[22] >> 4, p[22] & 15
lh, rl, qpih = p[23] >> 7, (p[23] >> 6) & 1, (p[23] >> 4) & 3
if wf == 0 or hf == 0 or hsl == 0 or not 1 <= nc <= 8 or ng != 4 or ss != 8 or br != 4:
raise Refuse("reserved_value")
if cpih not in (0, 1, 3) or qpih > 1:
raise Refuse("reserved_value")
at += 28
cdt, wgt, cts, crg = None, False, False, False
while True:
m = be16(b, at)
if m == 0xFF20:
break
ln = be16(b, at + 2)
if ln < 2:
raise Refuse("length_mismatch")
if at + 2 + ln > len(b):
raise Refuse("truncated")
body = b[at + 4:at + 2 + ln]
if m == 0xFF13:
if ln != 2 + 2 * nc:
raise Refuse("length_mismatch")
comps = [[body[2 * i], body[2 * i + 1] >> 4, body[2 * i + 1] & 15] for i in range(nc)]
if any(0 in c for c in comps):
raise Refuse("reserved_value")
cdt = comps
elif m == 0xFF14:
wgt = True
elif m == 0xFF18:
cts = True
elif m == 0xFF19:
crg = True
elif m in (0xFF15, 0xFF16, 0xFF17):
pass
elif m in (0xFF10, 0xFF11, 0xFF12, 0xFF50):
raise Refuse("out_of_order")
else:
raise Refuse("reserved_value")
at += 2 + ln
if cdt is None or not wgt or (cpih == 3 and not (cts and crg)):
raise Refuse("missing_structure")
if len(b) < at + 4 or be16(b, len(b) - 2) != 0xFF11:
raise Refuse("missing_structure")
if lcod != 0 and lcod != len(b):
raise Refuse("length_mismatch")
structure = None
if len(cdt) >= 3 and cdt[0][1:] == [1, 1] and cdt[1][1:] == cdt[2][1:]:
structure = {(1, 1): "4:4:4", (2, 1): "4:2:2", (2, 2): "4:2:0"}.get(tuple(cdt[1][1:]))
return {
"profile": "0x%04x" % ppih, "level": "0x%04x" % plev, "width": wf, "height": hf,
"components": cdt, "structure": structure, "colour_transform": cpih,
"decompositions": [nlx, nly], "precinct_width": cw, "slice_height": hsl,
"wavelet_precision": bw, "fractional_bits": fq, "quantizer": qpih,
"long_header": lh == 1, "raw_mode": rl == 1, "cbr_bytes": lcod, "cap_bits": cap_bits,
"rtp": {
"profile": PROFILES.get(ppih), "level": LEVELS.get(plev >> 8), "sublevel": SUBLEVELS.get(plev & 0xFF),
"depth": max(c[0] for c in cdt), "width": wf, "height": hf,
"sampling": "RGB" if cpih != 0 and structure == "4:4:4" else None,
},
}
def jxs_video(b):
if len(b) < 20:
raise Refuse("truncated")
n, h, w, num, den = struct.unpack("<5I", b[:20])
if 0 in (n, h, w, num, den):
raise Refuse("framing_invalid")
at, first, lcods = 20, None, []
for _ in range(n):
if at + 4 > len(b):
raise Refuse("truncated")
ln = struct.unpack("<I", b[at:at + 4])[0]
if at + 4 + ln > len(b):
raise Refuse("truncated")
c = jxs_codestream(b[at + 4:at + 4 + ln])
if c["width"] > w or c["height"] > h:
raise Refuse("framing_invalid")
if first is None:
first = c
lcods.append(c["cbr_bytes"])
at += 4 + ln
if at != len(b):
raise Refuse("trailing_bytes")
constant = lcods[0] if all(x != 0 and x == lcods[0] for x in lcods) else None
return {"frames": n, "size": [w, h], "fps": [num, den], "constant_bytes": constant, "first": first}
# ---- H.265 (§4) --------------------------------------------------------------------
def h265_ptl(r, present, max_sub):
out = {"idc": None, "tier": None, "compat": 0}
if present:
r.u(2)
out["tier"] = r.u(1)
out["idc"] = r.u(5)
out["compat"] = r.u(32)
r.skip(48)
out["level"] = r.u(8)
flags = [(r.flag(), r.flag()) for _ in range(max_sub)]
if max_sub > 0:
r.skip((8 - max_sub) * 2)
for p, l in flags:
if p:
r.skip(88)
if l:
r.skip(8)
return out
def h265_hrd(r, common, prev, max_sub):
nal, vcl, sub = prev
if common:
nal, vcl, sub = r.flag(), r.flag(), False
if nal or vcl:
sub = r.flag()
if sub:
r.skip(19)
r.skip(8)
if sub:
r.skip(4)
r.skip(15)
for _ in range(max_sub + 1):
general = r.flag()
within = True if general else r.flag()
low_delay = False
if within:
r.ue()
else:
low_delay = r.flag()
cnt = 1 if low_delay else r.ue() + 1
if cnt > 32:
raise Refuse("reserved_value")
for present in (nal, vcl):
if present:
for _ in range(cnt):
r.ue()
r.ue()
if sub:
r.ue()
r.ue()
r.skip(1)
return (nal, vcl, sub)
def h265_vps(rbsp):
r = Bits(rbsp)
r.u(4)
internal = r.flag()
r.flag()
max_layers = r.u(6)
max_sub = r.u(3)
if max_sub > 6:
raise Refuse("reserved_value")
r.flag()
if r.u(16) != 0xFFFF:
raise Refuse("reserved_value")
base = h265_ptl(r, True, max_sub)
ordering = r.flag()
for _ in range(0 if ordering else max_sub, max_sub + 1):
r.ue()
r.ue()
r.ue()
max_layer_id = r.u(6)
sets = r.ue()
if sets > 1023:
raise Refuse("reserved_value")
r.skip(sets * (max_layer_id + 1))
if r.flag():
r.skip(64)
if r.flag():
r.ue()
num_hrd = r.ue()
if num_hrd > sets + 1:
raise Refuse("reserved_value")
prev = (False, False, False)
for i in range(num_hrd):
r.ue()
common = r.flag() if i > 0 else True
prev = h265_hrd(r, common, prev, max_sub)
out = {"max_layers": max_layers, "ext": None}
if not r.flag():
return out
r.align(1)
if max_layers == 0:
return out
out["ext"] = h265_vps_ext(r, internal, max_layers, max_sub, base)
return out
def inherit(p, prev):
if p["idc"] is None:
p = dict(p, idc=prev["idc"], tier=prev["tier"], compat=prev["compat"])
return p
def h265_vps_ext(r, internal, max_layers, max_sub, base):
ptls = []
if internal:
ptls.append(inherit(h265_ptl(r, False, max_sub), base))
splitting = r.flag()
mask = 0
for i in range(16):
if r.flag():
mask |= 1 << i
types = bin(mask).count("1")
lens = [0] * types
for j in range(types - (1 if splitting else 0)):
lens[j] = r.u(3) + 1
ml = min(62, max_layers)
if splitting and types > 0:
used = sum(lens[:types - 1])
if used >= 6:
raise Refuse("reserved_value")
lens[types - 1] = 6 - used
id_present = r.flag()
ids = [0] * (ml + 1)
dims = [[0] * types for _ in range(ml + 1)]
for i in range(1, ml + 1):
ids[i] = r.u(6) if id_present else i
if ids[i] <= ids[i - 1]:
raise Refuse("reserved_value")
if not splitting:
for j in range(types):
dims[i][j] = r.u(lens[j])
if splitting:
for i in range(ml + 1):
off = 0
for j in range(types):
dims[i][j] = (ids[i] >> off) & ((1 << lens[j]) - 1)
off += lens[j]
view_order, aux, views = [], [], 1
for i in range(ml + 1):
sid, j = [0] * 16, 0
for s in range(16):
if mask & (1 << s):
sid[s] = dims[i][j]
j += 1
if i > 0 and sid[1] not in view_order:
views += 1
view_order.append(sid[1])
aux.append(sid[3])
vlen = r.u(4)
view_ids = [r.u(vlen) for _ in range(views)] if vlen else [0] * views
n = ml + 1
deps = [[False] * n for _ in range(n)]
for i in range(1, n):
for j in range(i):
deps[i][j] = r.flag()
dep = [row[:] for row in deps]
for i in range(n):
for j in range(n):
for k in range(i):
if deps[i][k] and dep[k][j]:
dep[i][j] = True
sizes, listed = [], set()
for i in range(n):
if any(deps[i]):
continue
h = 1
for j in range(n):
if dep[j][i] and ids[j] not in listed:
listed.add(ids[j])
h += 1
sizes.append(h)
add = r.ue() if len(sizes) > 1 else 0
if add > 1023:
raise Refuse("reserved_value")
for _ in range(add):
for s in sizes[1:]:
r.skip(s.bit_length())
if r.flag():
r.skip(3 * n)
if r.flag():
for i in range(ml):
for j in range(i + 1, ml + 1):
if deps[j][i]:
r.skip(3)
r.flag()
num = r.ue()
if num > 63:
raise Refuse("reserved_value")
for _ in range(2 if internal else 1, num + 1):
present = r.flag()
p = h265_ptl(r, present, max_sub)
ptls.append(inherit(p, ptls[-1] if ptls else base))
return {"mask": mask, "ids": ids, "view_order": view_order, "aux": aux, "views": views, "view_ids": view_ids, "ptls": ptls}
def h265_sps(rbsp):
r = Bits(rbsp)
r.u(4)
max_sub = r.u(3)
if max_sub > 6:
raise Refuse("reserved_value")
r.flag()
p = h265_ptl(r, True, max_sub)
if r.ue() > 15:
raise Refuse("reserved_value")
chroma = r.ue()
if chroma > 3:
raise Refuse("reserved_value")
if chroma == 3:
r.skip(1)
w, h = r.ue(), r.ue()
if w == 0 or h == 0:
raise Refuse("reserved_value")
c = [r.ue() for _ in range(4)] if r.flag() else [0, 0, 0, 0]
bl, bc = r.ue(), r.ue()
if bl > 8 or bc > 8:
raise Refuse("reserved_value")
return p, chroma, w, h, c, bl + 8, bc + 8
def h265(b, multiview):
units = nal_units(b)
def has(t):
return any(len(u) >= 2 and (u[0] >> 1) & 0x3F == t and ((u[0] << 8 | u[1]) >> 3) & 0x3F == 0 for u in units)
complete = has(32) and has(33)
vps, sps, layers, vcl = None, None, set(), 0
for u in units:
if len(u) < 2:
raise Refuse("truncated")
h = u[0] << 8 | u[1]
if h & 0x8000:
raise Refuse("reserved_value")
nut, layer = (h >> 9) & 0x3F, (h >> 3) & 0x3F
if h & 7 == 0:
raise Refuse("reserved_value")
rbsp = unescape(u[2:])
if nut < 32:
if sps is None or vps is None:
raise Refuse("out_of_order" if complete else "missing_structure")
vcl += 1
layers.add(layer)
elif nut == 32 and vps is None:
vps = h265_vps(rbsp)
elif nut == 33 and layer == 0 and sps is None:
sps = h265_sps(rbsp)
if vps is None or sps is None or vcl == 0:
raise Refuse("missing_structure")
p, chroma, w, h, c, bl, bc = sps
cropped = crop(chroma, w, h, c)
e = vps["ext"]
views = (e["views"] if e["mask"] & 2 else 1) if e else 1
mvp = bool(e) and any(q["idc"] == 6 or q["compat"] & (1 << 6) for q in e["ptls"])
if multiview and (views < 2 or not any(x > 0 for x in layers)):
raise Refuse("not_multiview")
out = {
"profile_idc": p["idc"], "tier": p["tier"], "level_idc": p["level"], "chroma_format_idc": chroma,
"bit_depth": [bl, bc], "coded": [w, h], "cropped": cropped,
"layers": min(62, vps["max_layers"]) + 1, "layers_present": sorted(layers),
}
if e:
out["multilayer"] = {
"scalability_mask": e["mask"], "layer_ids": e["ids"], "view_order": e["view_order"], "aux": e["aux"],
"views": views, "view_ids": e["view_ids"], "profiles": [q["idc"] for q in e["ptls"]], "multiview_profile": mvp,
}
return out
# ---- H.266 (§5) --------------------------------------------------------------------
def h266_ptl(r, present, max_sub):
idc = tier = None
if present:
idc, tier = r.u(7), r.u(1)
level = r.u(8)
frame_only, multilayer = r.flag(), r.flag()
if present:
if r.flag():
r.skip(71)
r.skip(r.u(8))
r.align(0)
flags = [r.flag() for _ in range(max_sub)]
r.align(None)
for f in flags:
if f:
r.skip(8)
subs = []
if present:
subs = [r.u(32) for _ in range(r.u(8))]
return {"idc": idc, "tier": tier, "level": level, "frame_only": frame_only, "multilayer": multilayer, "subs": subs}
def h266(b):
units = nal_units(b)
has_sps = any(len(u) >= 2 and u[1] >> 3 == 15 for u in units)
sps, layers, vcl, vps_layers = None, set(), 0, None
for u in units:
if len(u) < 2:
raise Refuse("truncated")
h = u[0] << 8 | u[1]
if h & 0xC000:
raise Refuse("reserved_value")
layer, nut = (h >> 8) & 0x3F, (h >> 3) & 0x1F
if h & 7 == 0 or layer > 55:
raise Refuse("reserved_value")
rbsp = unescape(u[2:])
if nut <= 11:
if sps is None:
raise Refuse("out_of_order" if has_sps else "missing_structure")
vcl += 1
layers.add(layer)
elif nut == 14 and vps_layers is None:
r = Bits(rbsp)
r.u(4)
vps_layers = r.u(6) + 1
elif nut == 15 and sps is None:
r = Bits(rbsp)
r.u(4)
r.u(4)
max_sub = r.u(3)
if max_sub > 6:
raise Refuse("reserved_value")
chroma = r.u(2)
ctu = r.u(2)
if ctu > 2:
raise Refuse("reserved_value")
p = h266_ptl(r, True, max_sub) if r.flag() else None
r.flag()
if r.flag():
r.skip(1)
w, hh = r.ue(), r.ue()
if w == 0 or hh == 0:
raise Refuse("reserved_value")
c = [r.ue() for _ in range(4)] if r.flag() else [0, 0, 0, 0]
sps = (p, chroma, 1 << (ctu + 5), w, hh, c)
if sps is None or vcl == 0:
raise Refuse("missing_structure")
p, chroma, ctu, w, h, c = sps
return {
"profile_idc": p["idc"] if p else None, "tier": p["tier"] if p else None,
"level_idc": p["level"] if p else None, "frame_only": p["frame_only"] if p else None,
"multilayer_enabled": p["multilayer"] if p else None, "sub_profiles": p["subs"] if p else [],
"chroma_format_idc": chroma, "ctu_size": ctu, "coded": [w, h], "cropped": crop(chroma, w, h, c),
"layers": vps_layers if vps_layers is not None else 1, "layers_present": sorted(layers),
}
# ---- LCEVC (§6) --------------------------------------------------------------------
TABLE20 = [tuple(int(x) for x in m) for m in re.findall(r"(\d+)×(\d+)", section(FP, "## 6. LCEVC").split("Table 20, types 1 to 50:")[1])]
assert len(TABLE20) == 50, "Table 20 in format-probes §6.5"
def multibyte(b, at):
v = 0
for _ in range(10):
if at >= len(b):
raise Refuse("truncated")
x = b[at]
at += 1
v = (v << 7) | (x & 0x7F)
if not x & 0x80:
return v, at
raise Refuse("reserved_value")
def lcevc(b):
units = nal_units(b)
seq = glob = None
idr = non = pics = 0
for i, u in enumerate(units):
if len(u) < 3:
raise Refuse("truncated")
if u[0] & 0xC1 != 0x41 or u[1] != 0xFF:
raise Refuse("reserved_value")
t = (u[0] >> 1) & 0x1F
if t == 29:
idr += 1
elif t == 28:
non += 1
else:
raise Refuse("reserved_value")
if i == 0 and t != 29:
raise Refuse("out_of_order")
rbsp = unescape(u[2:])
if rbsp[-1] != 0x80:
raise Refuse("reserved_value")
pay, at = rbsp[:-1], 0
while at < len(pay):
st, kind = pay[at] >> 5, pay[at] & 0x1F
at += 1
if st <= 5:
size = st
elif st == 6:
raise Refuse("reserved_value")
else:
size, at = multibyte(pay, at)
if at + size > len(pay):
raise Refuse("length_mismatch")
body = pay[at:at + size]
at += size
if kind == 0 and seq is None:
seq = lcevc_seq(body)
elif kind == 1 and glob is None:
glob = lcevc_glob(body)
elif kind == 2:
if seq is None or glob is None:
raise Refuse("out_of_order")
pics += 1
if seq is None or glob is None:
raise Refuse("missing_structure")
out = {"nal_units": [idr, non], "pictures": pics}
out.update(seq)
out.update(glob)
return out
def lcevc_seq(b):
r = Bits(b)
prof, lev, sub, win = r.u(4), r.u(4), r.u(2), r.flag()
if r.u(5) != 0:
raise Refuse("reserved_value")
if prof == 15 or lev == 15:
raise Refuse("outside_probe")
at, window = 2, None
if win:
window = []
for _ in range(4):
v, at = multibyte(b, at)
window.append(v)
if at != len(b):
raise Refuse("length_mismatch")
return {"profile_idc": prof, "level_idc": lev, "sublevel_idc": sub, "conformance_window": window}
def lcevc_glob(b):
r = Bits(b)
planes, rt, tt = r.flag(), r.u(6), r.u(1)
chroma, bd, ed = r.u(2), r.u(2), r.u(2)
tsw = r.flag()
r.flag()
r.flag()
temporal, up, l1 = r.flag(), r.u(3), r.flag()
r.u(2)
r.u(2)
tiles = r.u(2)
r.u(2)
r.flag()
r.flag()
if planes:
r.skip(8)
if tsw:
r.skip(8)
if up == 4:
r.skip(64)
if l1:
r.skip(8)
if tiles > 0:
if tiles == 3:
r.skip(32)
r.skip(8)
if rt == 0 or 51 <= rt < 63 or up > 4:
raise Refuse("reserved_value")
if rt == 63:
size = [r.u(16), r.u(16)]
if 0 in size:
raise Refuse("reserved_value")
else:
size = list(TABLE20[rt - 1])
return {"resolution_type": rt, "size": size, "transform_type": tt, "chroma_sampling_type": chroma,
"base_depth": 8 + 2 * bd, "enhancement_depth": 8 + 2 * ed, "temporal_enabled": temporal,
"upsample_type": up, "tile_dimensions_type": tiles}
def unwrap_lcevcbin(b):
if b[:8] != b"lcevcbin":
raise ValueError("not the container")
at, out = 12, b""
while at < len(b):
size = struct.unpack(">I", b[at + 2:at + 6])[0]
out += b[at + 6 + 16:at + 6 + size]
at += 6 + size
return out
# ---- MHAS (§7) ---------------------------------------------------------------------
RATES = [96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050, 16000, 12000, 11025, 8000, 7350, None, None,
57600, 51200, 40000, 38400, 34150, 28800, 25600, 20000, 19200, 17075, 14400, 12800, 9600, None, None, None]
def escaped(r, n1, n2, n3):
v = r.u(n1)
if v == (1 << n1) - 1:
a = r.u(n2)
v += a
if a == (1 << n2) - 1:
v += r.u(n3)
return v
def mhas(b):
try:
first = escaped(Bits(b), 3, 8, 8)
except Refuse:
raise Refuse("no_signature")
if first not in (1, 6):
raise Refuse("no_signature")
packets, at = [], 0
while at < len(b):
r = Bits(b[at:])
t, lab, ln = escaped(r, 3, 8, 8), escaped(r, 2, 8, 32), escaped(r, 11, 24, 24)
s = at + r.p // 8
if s + ln > len(b):
raise Refuse("truncated")
packets.append((t, lab, b[s:s + ln]))
at = s + ln
cfg, frames, syncs, configs = None, 0, 0, 0
for t, lab, pay in packets:
if t == 6:
if lab != 0 or pay != b"\xa5":
raise Refuse("reserved_value")
syncs += 1
elif t == 1:
configs += 1
if cfg is None:
cfg = mhas_cfg(pay)
elif t == 2:
if cfg is None:
raise Refuse("out_of_order")
frames += 1
if cfg is None:
raise Refuse("missing_structure")
cfg.update(packets=len(packets), frames=frames, syncs=syncs, configs=configs)
return cfg
def mhas_cfg(b):
r = Bits(b)
pl, sfi = r.u(8), r.u(5)
if sfi == 31:
rate = r.u(24)
else:
rate = RATES[sfi]
if rate is None:
raise Refuse("reserved_value")
if rate == 0:
raise Refuse("reserved_value")
core = r.u(3)
r.u(1)
r.u(1)
lt = r.u(2)
cicp = speakers = None
if lt == 0:
cicp = r.u(6)
elif lt < 3:
speakers = escaped(r, 5, 8, 16) + 1
profile = level = None
if 0x0B <= pl <= 0x0F:
profile, level = "low-complexity", pl - 0x0A
elif 0x10 <= pl <= 0x14:
profile, level = "baseline", pl - 0x0F
return {"profile_level": pl, "profile": profile, "level": level, "sampling_rate": rate,
"core_frame_length_index": core, "speaker_layout_type": lt, "cicp_layout": cicp, "speakers": speakers}
# ---- AVS3 (§8, §9) -----------------------------------------------------------------
def avs3_units(b):
i = 0
while i < len(b) and b[i] == 0:
i += 1
if i < 2 or i >= len(b) or b[i] != 1:
raise Refuse("no_signature")
starts, j = [], 0
while j + 3 < len(b):
if b[j] == 0 and b[j + 1] == 0 and b[j + 2] == 1:
starts.append(j + 3)
j += 3
else:
j += 1
return [(b[s], b[s + 1:(starts[k + 1] - 3 if k + 1 < len(starts) else len(b))]) for k, s in enumerate(starts)]
def demulate(b):
bits = []
for i, x in enumerate(b):
n = 6 if i >= 2 and b[i - 2] == 0 and b[i - 1] == 0 and x == 2 else 8
bits.extend((x >> (7 - k)) & 1 for k in range(n))
while len(bits) % 8:
bits.append(0)
return bytes(int("".join(map(str, bits[k:k + 8])), 2) for k in range(0, len(bits), 8))
def avs3_video(b):
us = avs3_units(b)
if not us:
raise Refuse("no_signature")
seq = next((p for c, p in us if c == 0xB0), None)
if seq is None:
raise Refuse("missing_structure")
if us[0][0] != 0xB0:
raise Refuse("out_of_order")
r = Bits(demulate(seq))
def marker():
if r.u(1) != 1:
raise Refuse("reserved_value")
prof, lev, prog, field = r.u(8), r.u(8), r.flag(), r.flag()
if r.flag() or r.flag():
raise Refuse("outside_probe")
marker()
w = r.u(14)
marker()
h = r.u(14)
chroma, sp = r.u(2), r.u(3)
ep = r.u(3) if prof in (0x22, 0x32) else None
marker()
ar, frc = r.u(4), r.u(4)
marker()
lo = r.u(18)
marker()
hi = r.u(12)
ld, tid = r.flag(), r.flag()
marker()
bbv = r.u(18)
marker()
dpb = r.u(4) + 1
if w == 0 or h == 0 or chroma == 0 or sp == 0 or frc == 0 or frc > 13:
raise Refuse("reserved_value")
intra = sum(1 for c, _ in us if c == 0xB3)
inter = sum(1 for c, _ in us if c == 0xB6)
if intra == 0:
raise Refuse("missing_structure")
return {"profile_id": prof, "level_id": lev, "progressive": prog, "field_coded": field, "size": [w, h],
"chroma_format": chroma, "sample_precision": sp, "encoding_precision": ep, "aspect_ratio": ar,
"frame_rate_code": frc, "bit_rate": hi * (1 << 18) + lo, "low_delay": ld, "temporal_id_enabled": tid,
"bbv_buffer_size": bbv, "max_dpb_size": dpb, "pictures": [intra, inter],
"sequence_end": any(c == 0xB1 for c, _ in us)}
def avs3_audio(b):
r = Bits(b)
try:
sync = r.u(12)
except Refuse:
raise Refuse("no_signature")
if sync != 0xFFF:
raise Refuse("no_signature")
codec = r.u(4)
if codec == 1:
raise Refuse("outside_probe")
if codec != 2:
raise Refuse("reserved_value")
if r.flag():
raise Refuse("outside_probe")
nn = r.u(3)
if nn > 1:
raise Refuse("reserved_value")
prof = r.u(3)
if prof > 2:
raise Refuse("reserved_value")
sfi = r.u(4)
if sfi > 8:
raise Refuse("reserved_value")
r.skip(8)
out = {"codec_id": codec, "nn_type": nn, "coding_profile": prof,
"sampling_rate": [192000, 96000, 48000, 44100, 32000, 24000, 22050, 16000, 8000][sfi]}
if prof == 0:
out["channel_number_index"] = r.u(7)
elif prof == 1:
bed = r.u(2)
out["soundbed_type"] = bed
if bed == 0:
out["objects"] = r.u(7) + 1
out["bitrate_index_per_object"] = r.u(4)
elif bed == 1:
out["channel_number_index"] = r.u(7)
out["bitrate_index"] = r.u(4)
out["objects"] = r.u(7) + 1
out["bitrate_index_per_object"] = r.u(4)
else:
raise Refuse("reserved_value")
else:
order = r.u(4) + 1
if not 1 <= order <= 3:
raise Refuse("reserved_value")
out["ambisonic_order"] = order
res = r.u(2)
if res > 2:
raise Refuse("reserved_value")
out["resolution_bits"] = 8 * (res + 1)
if prof != 1:
out["bitrate_index"] = r.u(4)
r.skip(8)
return out
# ---- leb128 (§14.2, §16.2) ---------------------------------------------------------
def leb(b, at):
"""(value, bytes taken). At most eight bytes, the value at most 2^32 - 1."""
v = 0
for i in range(8):
if at + i >= len(b):
raise Refuse("truncated")
x = b[at + i]
v |= (x & 0x7F) << (7 * i)
if not x & 0x80:
if v > 0xFFFFFFFF:
raise Refuse("reserved_value")
return v, i + 1
raise Refuse("reserved_value")
def inside(f, *args):
"""A structure read inside a unit whose declared size is too short: length_mismatch."""
try:
return f(*args)
except Refuse as e:
if e.code == "truncated":
raise Refuse("length_mismatch")
raise
# ---- AV2 (§14) ---------------------------------------------------------------------
AV2_FRAMES = {4, 5, 6, 7, 10, 11, 12, 13, 14, 19, 21}
AV2_LEVELS = ["2.0", "2.1", "3.0", "3.1", "4.0", "4.1", "5.0", "5.1", "5.2", "5.3", "6.0", "6.1", "6.2", "6.3",
"7.0", "7.1", "7.2", "7.3", "8.0", "8.1", "8.2", "8.3"]
def uvlc(r):
lz = 0
while r.u(1) == 0:
lz += 1
if lz >= 32:
raise Refuse("reserved_value")
return r.u(lz) + (1 << lz) - 1
def av2(b):
try:
size, n = leb(b, 0)
if size == 0 or (b[n] >> 2) & 31 != 2:
raise Refuse("no_signature")
except (Refuse, IndexError):
raise Refuse("no_signature")
obus, at = [], 0
while at < len(b):
size, n = leb(b, at)
at += n
if at + size > len(b):
raise Refuse("truncated")
o = b[at:at + size]
if not o:
raise Refuse("length_mismatch")
typ, tl = (o[0] >> 2) & 31, o[0] & 3
if o[0] & 0x80:
if len(o) < 2:
raise Refuse("length_mismatch")
ml, xl, pay = o[1] >> 5, o[1] & 31, o[2:]
else:
ml, xl, pay = 0, (31 if typ in (2, 20) else 0), o[1:]
obus.append((typ, tl, ml, xl, pay))
at += size
for typ, tl, ml, xl, _ in obus:
if typ in (2, 20) and xl != 31:
raise Refuse("reserved_value")
if typ == 1 and (tl or ml):
raise Refuse("reserved_value")
types = [o[0] for o in obus]
if 1 not in types or not any(t in AV2_FRAMES for t in types):
raise Refuse("missing_structure")
sh = types.index(1)
if min(i for i, t in enumerate(types) if t in AV2_FRAMES) < sh:
raise Refuse("out_of_order")
out = inside(av2_header, obus[sh][4])
out.update(temporal_units=types.count(2), frames=sum(t in AV2_FRAMES for t in types), obus=len(obus), codec=None)
return out
def av2_header(p):
r = Bits(p)
def check(ok):
if not ok:
raise Refuse("reserved_value")
hid = uvlc(r)
check(hid < 16)
prof = r.u(5)
check(not 5 <= prof <= 30)
single = r.flag()
lev = r.u(5)
check(not 22 <= lev <= 30)
tier = r.u(1) if lev > 3 and not single else 0
cf = uvlc(r)
if cf > 3:
raise Refuse("reserved_value")
bdi = uvlc(r)
if bdi > 1:
raise Refuse("reserved_value")
allowed = {0: {0, 1}, 1: {0, 1}, 2: {0, 1}, 3: {0, 1, 3}, 4: {0, 1, 2}}.get(prof, {0, 1, 2, 3})
if cf not in allowed:
raise Refuse("reserved_value")
if single:
still, mt, mm, cnt = True, 0, 0, 1
else:
r.u(3)
still, mt, mm, cnt = r.flag(), r.u(2), r.u(3), 1
if mm > 0:
m1 = r.u(mm.bit_length()) # CeilLog2(max_mlayer_id + 1)
if m1 > mm:
raise Refuse("reserved_value")
cnt = m1 + 1
r.u(1)
wb, hb = r.u(4) + 1, r.u(4) + 1
w, h = r.u(wb) + 1, r.u(hb) + 1
crop = [uvlc(r) for _ in range(4)] if r.flag() else [0, 0, 0, 0]
l, rt, t, bt = crop
if max(l, rt) > w - 1 or max(t, bt) > h - 1 or l + rt >= w or t + bt >= h:
raise Refuse("reserved_value")
sub = {0: [1, 1], 1: [1, 1], 2: [0, 0], 3: [1, 0]}[cf]
return {"seq_header_id": hid, "profile": prof, "level_idx": lev, "level": "maximum" if lev == 31 else AV2_LEVELS[lev],
"tier": tier, "single_picture_header": single, "still_picture": still, "chroma_format_idc": cf,
"monochrome": cf == 1, "subsampling": sub, "bit_depth": 10 if bdi == 0 else 8, "max_size": [w, h],
"cropped": [w - l - rt, h - t - bt], "max_tlayer_id": mt, "max_mlayer_id": mm, "mlayers": cnt}
# ---- AC-4 (§15) --------------------------------------------------------------------
AC4_RATES = [(24000, 1001, 1920), (24, 1, 1920), (25, 1, 2048), (30000, 1001, 1536), (30, 1, 1536), (48000, 1001, 960),
(48, 1, 960), (50, 1, 1024), (60000, 1001, 768), (60, 1, 768), (100, 1, 512), (120000, 1001, 384),
(120, 1, 384), (375, 16, 2048)]
def crc16_ac4(data):
c = 0
for x in data:
c ^= x << 8
for _ in range(8):
c = ((c << 1) ^ 0x8005) & 0xFFFF if c & 0x8000 else (c << 1) & 0xFFFF
return c
def var_bits(r, n):
v = 0
while True:
v += r.u(n)
if not r.flag():
return v
v = (v << n) + (1 << n)
if v > 0xFFFFFFFF:
raise Refuse("outside_probe")
def ac4(b):
if b[:2] not in (b"\xac\x40", b"\xac\x41"):
raise Refuse("no_signature")
frames, at = [], 0
while at < len(b):
if at + 2 > len(b):
raise Refuse("truncated")
sync = b[at:at + 2]
if sync not in (b"\xac\x40", b"\xac\x41"):
raise Refuse("reserved_value")
if at + 4 > len(b):
raise Refuse("truncated")
size, head = int.from_bytes(b[at + 2:at + 4], "big"), 2
if size == 0xFFFF:
if at + 7 > len(b):
raise Refuse("truncated")
size, head = int.from_bytes(b[at + 4:at + 7], "big"), 5
start = at + 2 + head
end = start + size + (2 if sync == b"\xac\x41" else 0)
if end > len(b):
raise Refuse("truncated")
if sync == b"\xac\x41" and crc16_ac4(b[at + 2:end]) != 0:
raise Refuse("reserved_value")
frames.append((sync == b"\xac\x41", b[start:start + size]))
at = end
out = inside(ac4_toc, frames[0][1])
out.update(frames=len(frames), crc_frames=sum(1 for c, _ in frames if c))
return out
def ac4_toc(raw):
r = Bits(raw)
bv = r.u(2)
if bv == 3:
bv += var_bits(r, 2)
if bv > 2:
raise Refuse("outside_probe")
counter = r.u(10)
wait = None
if r.flag():
wait = r.u(3)
if wait:
r.u(2)
fs, fri = r.u(1), r.u(4)
if fri > 13 or (fs == 0 and fri != 13):
raise Refuse("reserved_value")
ifr = r.flag()
if r.flag():
n = 1
elif r.flag():
n = var_bits(r, 2) + 2
else:
n = 0
if r.flag() and r.u(5) == 31:
var_bits(r, 3)
prog = None
if bv >= 2 and r.flag():
prog = r.u(16)
if r.flag():
r.skip(128)
pres = codec = None
if n:
cfg = None
if not r.flag():
cfg = r.u(3)
if cfg == 7:
cfg += var_bits(r, 2)
pv = 0
while r.flag():
pv += 1
if pv > 2:
raise Refuse("reserved_value")
if (bv, pv) == (1, 1):
good = cfg == 7
elif (bv, pv) in ((0, 0), (1, 0), (2, 1), (2, 2)):
good = cfg is None or cfg <= 6
else:
good = False
if not good:
raise Refuse("reserved_value")
md = None if cfg == 6 else r.u(3)
pres = {"config": cfg, "version": pv, "md_compat": md}
if md is not None:
codec = "ac-4.%02x.%02x.%02x" % (bv, pv, md)
num, den, length = (11025, 512, 2048) if fs == 0 else AC4_RATES[fri]
return {"bitstream_version": bv, "sequence_counter": counter, "wait_frames": wait,
"sampling_rate": 48000 if fs else 44100, "frame_rate_index": fri, "frame_rate": [num, den],
"frame_length": length, "iframe_global": ifr, "presentations": n, "program_id": prog,
"presentation": pres, "codec": codec}
# ---- IAMF (§16) --------------------------------------------------------------------
class Body:
def __init__(self, b):
self.b, self.at = b, 0
def take(self, n):
if self.at + n > len(self.b):
raise Refuse("length_mismatch")
s = self.b[self.at:self.at + n]
self.at += n
return s
def num(self, n):
return int.from_bytes(self.take(n), "big")
def leb(self):
v, k = inside(leb, self.b, self.at)
self.at += k
return v
def iamf_obu(b, at):
if at >= len(b):
raise Refuse("truncated")
h = b[at]
typ, red, bit, ext = h >> 3, (h >> 2) & 1, (h >> 1) & 1, h & 1
size, n = leb(b, at + 1)
s = at + 1 + n
if s + size > len(b):
raise Refuse("truncated")
frame = 5 <= typ <= 23
if bit and not (typ in (2, 4) or frame):
raise Refuse("reserved_value")
if red and (typ == 4 or frame):
raise Refuse("reserved_value")
body = Body(b[s:s + size])
if frame and bit:
body.leb()
body.leb()
if ext:
body.take(body.leb())
return (typ, red, body.b[body.at:]), s + size
FLAC_RATES = {88200, 176400, 192000, 8000, 16000, 22050, 24000, 32000, 44100, 48000, 96000}
def iamf_codec(p):
r = Body(p)
cid = r.leb()
fourcc = r.take(4)
if fourcc not in (b"Opus", b"mp4a", b"fLaC", b"ipcm"):
raise Refuse("outside_probe")
n = r.leb()
if n == 0:
raise Refuse("reserved_value")
roll = r.num(2)
roll -= 0x10000 if roll >= 0x8000 else 0
want = {b"Opus": -((3840 + n - 1) // n), b"mp4a": -1}.get(fourcc, 0)
if roll != want:
raise Refuse("reserved_value")
rate = depth = None
if fourcc == b"Opus":
r.num(1)
ch = r.num(1)
r.num(2)
r.num(4)
gain, fam = r.num(2), r.num(1)
if ch != 2 or gain or fam:
raise Refuse("reserved_value")
rate = 48000
elif fourcc == b"fLaC":
first = True
while True:
hdr = r.num(4)
last, kind, ln = hdr >> 31, (hdr >> 24) & 0x7F, hdr & 0xFFFFFF
blk = r.take(ln)
if first:
if kind != 0 or ln != 34:
raise Refuse("reserved_value")
bits = Bits(blk)
mn, mx = bits.u(16), bits.u(16)
bits.u(24)
bits.u(24)
sr, ch, bps = bits.u(20), bits.u(3) + 1, bits.u(5) + 1
if mn != n or mx != n or sr not in FLAC_RATES or ch != 2 or bps not in (16, 24, 32):
raise Refuse("reserved_value")
rate, depth, first = sr, bps, False
if last:
break
elif fourcc == b"ipcm":
flags, size, sr = r.num(1), r.num(1), r.num(4)
if flags > 1 or size not in (16, 24, 32) or sr not in (16000, 32000, 44100, 48000, 96000):
raise Refuse("reserved_value")
rate, depth = sr, size
return {"id": cid, "codec_id": fourcc.decode(), "samples_per_frame": n, "roll_distance": roll,
"sample_rate": rate, "bit_depth": depth}
def iamf_element(p):
r = Body(p)
eid = r.leb()
kind = r.num(1) >> 5
cfg = r.leb()
n = r.leb()
if n == 0:
raise Refuse("reserved_value")
subs = [r.leb() for _ in range(n)]
if kind > 2:
raise Refuse("outside_probe")
return {"id": eid, "type": ["channel", "scene", "object"][kind], "codec_config_id": cfg, "substreams": subs}
def iamf(b):
try:
(typ, _, pay), _ = iamf_obu(b, 0)
ok = typ == 31 and pay[:4] == b"iamf"
except Refuse:
ok = False
if not ok:
raise Refuse("no_signature")
obus, at = [], 0
while at < len(b):
o, at = iamf_obu(b, at)
obus.append(o)
r = Body(obus[0][2])
r.take(4)
prim, add = r.num(1), r.num(1)
if prim > 5:
raise Refuse("reserved_value")
data = next((i for i, o in enumerate(obus) if o[0] in (3, 4) or 5 <= o[0] <= 23), len(obus))
desc = obus[1:data]
if data < len(obus) and not any(o[0] == 2 for o in desc):
raise Refuse("out_of_order" if any(o[0] == 2 for o in obus[data:]) else "missing_structure")
stage, cfgs, els, mixes = 0, [], [], 0
for typ, _, pay in desc:
if typ not in (0, 1, 2):
continue
if typ + 1 < stage:
raise Refuse("out_of_order")
stage = typ + 1
if typ == 0:
cfgs.append(iamf_codec(pay))
elif typ == 1:
els.append(iamf_element(pay))
else:
mixes += 1
if not cfgs or not els or not mixes:
raise Refuse("missing_structure")
if any(e["codec_config_id"] not in [c["id"] for c in cfgs] for e in els):
raise Refuse("missing_structure")
ids = [c["codec_id"] for c in cfgs]
if len(ids) > 2 or (len(ids) == 2 and "ipcm" not in ids):
raise Refuse("reserved_value")
named = next((c for c in ids if c != "ipcm"), "ipcm")
units = frames = blocks = 0
seqs = 1
for typ, red, pay in obus[data:]:
if typ == 4:
units += 1
elif typ == 3:
blocks += 1
elif typ == 5:
if Body(pay).leb() <= 17:
raise Refuse("reserved_value")
frames += 1
elif 6 <= typ <= 23:
frames += 1
elif typ == 31 and not red:
seqs += 1
if not frames:
raise Refuse("missing_structure")
element = {"Opus": "Opus", "mp4a": "mp4a.40.2", "fLaC": "fLaC", "ipcm": "ipcm"}[named]
return {"primary_profile": prim, "additional_profile": add, "codec_configs": cfgs, "audio_elements": els,
"mix_presentations": mixes, "temporal_units": units, "audio_frames": frames, "parameter_blocks": blocks,
"sequences": seqs, "codec": "iamf.%03d.%03d.%s" % (prim, add, element)}
# ---- IVAS (§17) --------------------------------------------------------------------
IVAS_RATES = [13200, 16400, 24400, 32000, 48000, 64000, 80000, 96000, 128000, 160000, 192000, 256000, 384000, 512000]
EVS_RATES = [2800, 7200, 8000, 9600, 13200, 16400, 24400, 32000, 48000, 64000, 96000, 128000, 2400]
def ivas_frame(ft):
evs, ind, br = ft >> 5, (ft >> 4) & 1, ft & 15
if not (evs == 0 and ind == 1):
if br == 15:
return {"mode": "no_data", "bitrate": None, "sid": False, "bytes": 0}
if br == 14:
return {"mode": "speech_lost", "bitrate": None, "sid": False, "bytes": 0}
if evs == 1:
raise Refuse("outside_probe" if br <= 9 else "reserved_value")
if br == 13:
raise Refuse("reserved_value")
rate = EVS_RATES[br]
return {"mode": "evs", "bitrate": rate, "sid": br == 12, "bytes": rate // 400}
if br == 14:
raise Refuse("outside_probe")
rate = 5200 if br == 15 else IVAS_RATES[br]
return {"mode": "ivas", "bitrate": rate, "sid": br == 15, "bytes": rate // 400}
def ivas_format(data, f):
r = Bits(data)
if f["sid"]:
v = r.u(3)
if v == 4:
raise Refuse("reserved_value")
return {0: "STEREO", 1: "STEREO", 2: "ISM", 3: "MASA", 7: "MASA", 5: "SBA", 6: "SBA"}[v]
v = r.u(2)
if v < 2:
return ["STEREO", "MC"][v]
if v == 3:
return "MASA" if r.u(1) else "SBA"
if f["bitrate"] < 24400:
return "ISM"
if r.u(1) == 0:
return "ISM"
return "OSBA" if r.u(1) else "OMASA"
def ivas(b):
at, cmr, ebytes, pi, skip, tocs = 0, None, 0, False, False, []
while True:
if at >= len(b):
raise Refuse("truncated")
x = b[at]
at += 1
if x & 0x80:
if at == 1:
cmr = {"t": (x >> 4) & 7, "value": x & 15}
elif not skip:
ebytes += 1
et = (x >> 4) & 7
if et == 1 and x & 0x08:
if at >= len(b):
raise Refuse("truncated")
at += 1
elif et == 2:
pi = True
elif et >= 4:
skip = True
continue
skip = False
tocs.append(x & 0x3F)
if (x & 0x3F) == 0x1E:
if at >= len(b):
raise Refuse("truncated")
at += 1
if not x & 0x40:
break
frames = [ivas_frame(t) for t in tocs]
fmt = None
for f in frames:
if at + f["bytes"] > len(b):
raise Refuse("truncated")
if fmt is None and f["mode"] == "ivas":
fmt = ivas_format(b[at:at + f["bytes"]], f)
at += f["bytes"]
rest = b[at:]
if pi and not rest:
raise Refuse("missing_structure")
if not pi and any(rest):
raise Refuse("trailing_bytes")
return {"cmr": cmr, "e_bytes": ebytes, "pi_data": pi, "frames": frames, "format": fmt,
"pi_bytes": len(rest) if pi else 0, "padding_bytes": 0 if pi else len(rest), "codec": "sivs"}
# ---- IEEE 1857.11 (§10) and the projection descriptor (projection.md) ---------------
def nic(b):
if len(b) < 13:
raise Refuse("truncated")
ids = int.from_bytes(b[0:3], "big")
h, w = struct.unpack(">II", b[3:11])
fmt = int.from_bytes(b[11:13], "big")
prof, depth = ids >> 21, (fmt >> 11) & 7
if prof > 2 or fmt >> 14 or depth not in (1, 2) or h == 0 or w == 0:
raise Refuse("reserved_value")
return {"profile_id": prof, "level_id": (ids >> 15) & 0x3F, "model_id": (ids >> 12) & 7,
"parameter_set_id": (ids >> 5) & 0x7F, "quality_id": ids & 0x1F, "size": [w, h],
"bit_depth": 8 if depth == 1 else 10, "picture_format": (fmt >> 8) & 7,
"slice_size": [1 << ((fmt & 15) + 6), 1 << (((fmt >> 4) & 15) + 6)]}
DEG = 1 << 16
PROJ = ["rectilinear", "equirectangular", "half-equirectangular", "fisheye"]
STEREO = ["mono", "side-by-side", "top-bottom", "layers"]
def projection_read(b):
if len(b) < 4 or b[:4] != b"WPJ1":
raise Refuse("no_signature")
if len(b) != 40:
raise Refuse("length_mismatch")
if b[4] != 1 or b[5] > 3 or b[6] > 3 or b[7] > 1 or any(b[34:]):
raise Refuse("reserved_value")
az, el = struct.unpack("<II", b[8:16])
ca, ce, ct = struct.unpack("<iii", b[16:28])
base = struct.unpack("<I", b[28:32])[0]
pr, st, fv, left, right = b[5], b[6], b[7], b[32], b[33]
ranges = {
0: (az == 0 and el == 0) or (0 < az < 180 * DEG and 0 < el < 180 * DEG),
1: az == 360 * DEG and el == 180 * DEG,
2: az == 180 * DEG and el == 180 * DEG,
3: 0 < az <= 360 * DEG and 0 < el <= 360 * DEG,
}[pr]
centre = -180 * DEG <= ca < 180 * DEG and -90 * DEG <= ce <= 90 * DEG and -180 * DEG <= ct < 180 * DEG
if st == 0:
views = fv == 0 and base == 0 and left == 0 and right == 0
elif st in (1, 2):
views = left == 0 and right == 0
else:
views = left != right and left <= 62 and right <= 62
if not (ranges and centre and views):
raise Refuse("descriptor_invalid")
return {"projection": PROJ[pr], "stereo": STEREO[st], "first_view": "left" if fv == 0 else "right",
"coverage": [az, el], "centre": [ca, ce, ct], "baseline_um": base,
"layers": [left, right] if st == 3 else None}
def binding(desc, base_cap, base_params):
if desc["stereo"] != "layers":
return "accept"
if base_cap != "wai.video.mvhevc" or not all(l in base_params["layers_present"] for l in desc["layers"]):
return {"refuse": "layer_absent"}
return "accept"
PROBES = {
"wai.image.jxs": jxs_codestream, "wai.video.jxs": jxs_video,
"wai.video.hevc": lambda b: h265(b, False), "wai.video.mvhevc": lambda b: h265(b, True),
"wai.video.vvc": h266, "wai.video.lcevc": lcevc, "wai.audio.mpegh": mhas,
"wai.video.avs3": avs3_video, "wai.audio.avs3": avs3_audio,
"wai.image.ieee1857_11": nic, "wai.meta.projection": projection_read,
"wai.video.av2": av2, "wai.audio.ac4": ac4, "wai.audio.iamf": iamf, "wai.audio.ivas": ivas,
}
def probe(cap, b):
if cap not in PROBES:
return {"refuse": "no_probe"}
try:
return {"accept": PROBES[cap](b)}
except Refuse as e:
return {"refuse": e.code}
def pointer(doc, ptr):
for part in ptr.strip("/").split("/"):
if isinstance(doc, list):
doc = doc[int(part)]
elif isinstance(doc, dict) and part in doc:
doc = doc[part]
else:
return None
return doc
# ---- The corpus --------------------------------------------------------------------
def spec_tables():
probes = [(m.group(1), m.group(2)) for m in re.finditer(r"^\| `(wai\.[a-z0-9_.]+)` \| (\w+) \| §\d+(?:\.\d+)? \|$", section(FP, "## 2. Common rules"), re.M)]
codes = re.findall(r"^\| `([a-z_]+)` \|", section(FP, "## 12. Refusals"), re.M)
return probes, codes
def check(doc, files, fetched=None):
fails = []
probes, codes = spec_tables()
if [(p["capability"], p["basis"]) for p in doc["probes"]] != probes:
fails.append("vectors.json's probes are not §2.4's table")
if doc["refusals"] != codes:
fails.append("vectors.json's refusals are not §12's table")
if sorted(c for c, _ in probes) != sorted(PROBES):
fails.append("§2.4's table names a probe this verifier does not have, or the reverse")
results, given, referenced = {}, set(), set()
for v in doc["vectors"]:
name, f = v["name"], v["file"]
referenced.add(f)
if f not in files:
fails.append("%s: %s missing" % (name, f))
continue
if hashlib.sha256(files[f]).hexdigest() != v["sha256"]:
fails.append("%s: %s's digest differs" % (name, f))
got = probe(v["capability"], files[f])
results[(f, v["capability"])] = got
if got != v["outcome"]:
fails.append("%s (%s): stated %s, probe gives %s" % (name, v["capability"], json.dumps(v["outcome"])[:160], json.dumps(got)[:160]))
if "refuse" in got:
given.add(got["refuse"])
for bnd in doc["bindings"]:
referenced.update([bnd["descriptor"], bnd["base"]])
try:
d = projection_read(files[bnd["descriptor"]])
base = PROBES[bnd["base_capability"]](files[bnd["base"]])
got = binding(d, bnd["base_capability"], base)
except (Refuse, KeyError) as e:
fails.append("binding %s: %s" % (bnd["name"], e))
continue
if got != bnd["outcome"]:
fails.append("binding %s: stated %s, gives %s" % (bnd["name"], bnd["outcome"], got))
if isinstance(got, dict):
given.add(got["refuse"])
for fact in doc["facts"]:
caps = [c for (f, c) in results if f == fact["file"]]
ok = any("accept" in results[(fact["file"], c)] and pointer(results[(fact["file"], c)]["accept"], fact["pointer"]) == fact["value"] for c in caps)
if not ok:
fails.append("fact %s%s = %s does not hold" % (fact["file"], fact["pointer"], json.dumps(fact["value"])))
for c in codes:
if c not in given:
fails.append("no vector is refused with %s" % c)
for f in files:
if (f.startswith("ext/") or f.startswith("gen/")) and f not in referenced:
fails.append("%s is no vector's" % f)
if fetched is not None:
for e in doc["fetched"]:
b = fetched.get(e["file"])
if b is None:
fails.append("fetched %s missing" % e["file"])
continue
if hashlib.sha256(b).hexdigest() != e["sha256"]:
fails.append("fetched %s: digest differs" % e["file"])
continue
got = probe("wai.video.lcevc", unwrap_lcevcbin(b))
if "accept" not in got:
fails.append("fetched %s: %s" % (e["file"], got))
continue
for ptr, want in e["expect"].items():
if pointer(got["accept"], ptr) != want:
fails.append("fetched %s%s: %s, expected %s" % (e["file"], ptr, pointer(got["accept"], ptr), want))
return fails
def load(corpus):
files = {}
for sub in ("ext", "gen"):
for root, _, names in os.walk(os.path.join(corpus, sub)):
for n in names:
p = os.path.join(root, n)
files[os.path.relpath(p, corpus).replace(os.sep, "/")] = open(p, "rb").read()
doc = json.load(open(os.path.join(corpus, "vectors.json"), encoding="utf-8"))
return doc, files
def mutations(doc, files):
"""(label, doc, files) copies, each of which must fail."""
out = []
def mutate(label, f):
d, fs = copy.deepcopy(doc), dict(files)
f(d, fs)
out.append((label, d, fs))
def vec(d, name, cap=None):
return next(v for v in d["vectors"] if v["name"] == name and (cap is None or v["capability"] == cap))
def rewrite(d, fs, name, cap, at, byte):
v = vec(d, name, cap)
b = bytearray(fs[v["file"]])
b[at] = byte
fs[v["file"]] = bytes(b)
v["sha256"] = hashlib.sha256(fs[v["file"]]).hexdigest()
mutate("the MHAS configuration's profile-level byte, its digest restated",
lambda d, fs: rewrite(d, fs, "lc3_48k_5_1", None, 5, 0x0E))
mutate("the H.266 vector's stated cropped width", lambda d, fs: vec(d, "vvc_main10_100x58.266")["outcome"]["accept"]["cropped"].__setitem__(0, 101))
mutate("a refusal stated with another code", lambda d, fs: vec(d, "no_soc")["outcome"].__setitem__("refuse", "truncated"))
mutate("a refused binding stated accepted", lambda d, fs: next(b for b in d["bindings"] if b["name"] == "layer_2_over_mvhevc").__setitem__("outcome", "accept"))
mutate("a fact restated", lambda d, fs: d["facts"][0].__setitem__("value", [65, 64]))
mutate("the JPEG XS codestream's Ppih, its digest restated",
lambda d, fs: rewrite(d, fs, "jxs_main422_10_64x64.jxs", None, 16, 0x3A))
mutate("a vector dropped from the list", lambda d, fs: d["vectors"].remove(vec(d, "erp_mono")))
mutate("a probe's basis restated", lambda d, fs: d["probes"][2].__setitem__("basis", "implementation"))
mutate("the LCEVC sequence configuration's level, its digest restated",
lambda d, fs: rewrite(d, fs, "main_1080p", None, 7, 0x13))
mutate("a projection descriptor's coverage stated otherwise",
lambda d, fs: vec(d, "half_erp_side_by_side")["outcome"]["accept"]["coverage"].__setitem__(0, 360 << 16))
mutate("the AVS3 audio header's rate index, its digest restated",
lambda d, fs: rewrite(d, fs, "channels_5_1", None, 3, 0x10))
# §14 to §17: a stated profile, level, version, bit rate or codec string changed, and a
# header byte changed with its digest restated.
def state(name, path, value):
def f(d, fs):
o = vec(d, name)["outcome"]["accept"]
for k in path[:-1]:
o = o[k]
o[path[-1]] = value
return f
def flip(name, at, x):
return lambda d, fs: rewrite(d, fs, name, None, at, fs[vec(d, name)["file"]][at] ^ x)
for label, f in [
("the AV2 vector's stated profile", state("main420_10_1080p", ["profile"], 1)),
("the AV2 vector's stated level", state("main420_10_1080p", ["level"], "4.1")),
("an AV2 codec string, where AOMedia has released none", state("main420_10_1080p", ["codec"], "av02.0.08M.10")),
("the AV2 sequence header's last profile bit, its digest restated", flip("main420_10_1080p", 4, 0x04)),
("the AC-4 vector's stated codec string", state("v2_crc_24fps", ["codec"], "ac-4.02.01.04")),
("the AC-4 vector's stated presentation version", state("v2_crc_24fps", ["presentation", "version"], 2)),
("the AC-4 table of contents' frame rate index, its digest restated", flip("v0_single_44k", 5, 0x01)),
("the IAMF vector's stated codec string", state("opus_simple", ["codec"], "iamf.000.000.opus")),
("the IAMF vector's stated primary profile", state("opus_simple", ["primary_profile"], 1)),
("the IAMF sequence header's primary profile, its digest restated", flip("opus_simple", 6, 0x01)),
("the IVAS vector's stated codec string", state("stereo_32k_two_frames_cmr", ["codec"], "sevs")),
("the IVAS vector's stated bit rate", state("stereo_32k_two_frames_cmr", ["frames", 0, "bitrate"], 24400)),
("the IVAS ToC byte's bit rate index, its digest restated", flip("stereo_32k_two_frames_cmr", 1, 0x07)),
]:
mutate(label, f)
return out
def main(argv):
corpus = argv[1]
fetched = None
if len(argv) == 4 and argv[2] == "--fetched":
fetched = {n: open(os.path.join(argv[3], n), "rb").read() for n in os.listdir(argv[3])}
elif len(argv) != 2:
print(__doc__)
return 2
doc, files = load(corpus)
fails = check(doc, files, fetched)
for f in fails:
print("FAIL", f)
print("%d vectors, %d bindings, %d facts%s: %d failures" % (
len(doc["vectors"]), len(doc["bindings"]), len(doc["facts"]),
", %d fetched" % len(doc["fetched"]) if fetched is not None else "", len(fails)))
caught_all = True
for label, d, fs in mutations(doc, files):
try:
caught = check(d, fs)
except Exception as e: # a crash on a mutated copy counts as a failure to read it
caught = ["raised %s" % e]
print(("PASS" if caught else "FAIL") + " mutated copy fails: %s%s" % (label, " (%s)" % caught[0][:90] if caught else ""))
caught_all &= bool(caught)
return 0 if not fails and caught_all else 1
if __name__ == "__main__":
sys.exit(main(sys.argv))