Every registered string now lives in one table (codecs/registry.rs) with its kind, status, media class, registering SPEC section, edition and registration date. `wai registry export` writes registry/capabilities.json, its JSON Schema, the generated table in REGISTRY.md and vocab v2; --check fails on drift. vocab v1 stays stable. A candidate capability (a registered string whose payload format no revision has pinned) must not be emitted. The C packers, the browser writers and `wai wrap` refuse one, and `codecs::is_dispatchable` is the single dispatch and selection predicate (SPEC §4): candidates, companion-only capabilities, records and derivations are not dispatchable, and an unregistered string is decoded only where the sink advertises it. The codec glossary is linked to the registry through a reviewed table and held to its schema by a library test; `org` becomes `body`, from a closed allowlist. The SPEC gains §5 sections on kinds and candidates, a §8 edition rule, corrected citations and rewritten appendices. The quantum-ops vectors are regenerated with neutral device ids. CI declares the feature-gated test targets with required-features, checks the registry export, builds wai-web for wasm32, and runs two public-text checks (comparative prose, and private name patterns) with a self-test. The specification, extensions, research notes, READMEs, glossary and source comments are rewritten to name no company or product and to make no comparisons. Co-Authored-By: Claude Opus 5.5 <[email protected]>
298 lines
17 KiB
Shell
Executable file
298 lines
17 KiB
Shell
Executable file
#!/usr/bin/env bash
|
|
# Demonstrate WAI carrying the registered media classes end-to-end on REAL
|
|
# bytes. WAI's job is carriage + dispatch; the decoder is sink-supplied. So for
|
|
# each class this:
|
|
# 1. obtains REAL canonical bytes of the format (where an open encoder is
|
|
# installed) or a representative payload otherwise,
|
|
# 2. `wai wrap`s them into an envelope and `wai unwrap`s them back,
|
|
# 3. asserts the payload is BYTE-IDENTICAL (the §2 carriage guarantee),
|
|
# 4. hands the extracted bytes to a sink decoder (OpenJPEG / ffmpeg) where one
|
|
# is installed — the full carry → dispatch → decode path on a real file.
|
|
#
|
|
# Honest status per row:
|
|
# real+decode = real canonical bytes, carried byte-exact, decoded by a real
|
|
# reference tool acting as the sink (JPEG 2000, IAMF, and the
|
|
# AVC / HEVC / VP9 / AAC broadcast rows via ffmpeg).
|
|
# companion = a companion-only capability (SPEC §5: HDR dynamic metadata,
|
|
# LCEVC) carried the one conforming way, as a WAI2 companion
|
|
# bound to a base rendition: the companion comes back
|
|
# byte-exact, the envelope passes the role check, `wai wrap`
|
|
# refuses the WAI1 form, and a real base decodes.
|
|
# real+parse = real canonical bytes (a genuine encoder built the bitstream),
|
|
# carried byte-exact, structurally decoded into the format's
|
|
# units by a real reference parser as the sink (V-PCC → V3C).
|
|
# real = real canonical bytes carried byte-exact (sink decoder not
|
|
# installed here; payload is genuine).
|
|
# carriage = representative payload carried byte-exact; decoder
|
|
# sink-supplied (no open encoder installed for the format).
|
|
# proprietary = carried byte-exact; decoder is proprietary (sink-supplied).
|
|
# candidate = a registered capability with no pinned payload format (SPEC §5); `wai wrap` must refuse it and write nothing.
|
|
#
|
|
# ./tools/wai_carriage_demo.sh
|
|
#
|
|
# The volumetric / immersive-audio rows decode for real only when their sink
|
|
# tools are on PATH (G-PCC tmc3, V-PCC tmc2 + TMC2_CFG, IVAS_cod/IVAS_dec).
|
|
# `tools/build_reference_decoders.sh` fetches and builds them at pinned
|
|
# versions and prints the exact PATH/TMC2_CFG to export here. Rows fall back to
|
|
# byte-exact carriage when a tool is absent.
|
|
|
|
set -uo pipefail
|
|
ROOT="$(cd "$(dirname "$0")/.." && pwd)"
|
|
WAI="$ROOT/wai-rs/target/release/wai"
|
|
TMP="$(mktemp -d)"
|
|
trap 'rm -rf "$TMP"' EXIT
|
|
|
|
echo "building wai CLI…"
|
|
( cd "$ROOT/wai-rs" && cargo build --release --features codecs --bin wai >/dev/null 2>&1 ) \
|
|
|| { echo "build failed"; exit 1; }
|
|
|
|
have() { command -v "$1" >/dev/null 2>&1; }
|
|
src_png="$TMP/src.png"
|
|
# a small real image (any source) — fall back to a generated gradient
|
|
if have sips && [ -f "/System/Library/Desktop Pictures/Sonoma.heic" ]; then
|
|
sips -s format png -Z 128 "/System/Library/Desktop Pictures/Sonoma.heic" --out "$src_png" >/dev/null 2>&1
|
|
fi
|
|
[ -f "$src_png" ] || ffmpeg -hide_banner -loglevel error -y -f lavfi -i "testsrc=size=128x128:duration=1" -frames:v 1 "$src_png" 2>/dev/null
|
|
|
|
printf '\n%-22s %-7s %-13s %s\n' "capability" "fidelity" "status" "round-trip"
|
|
printf '%-22s %-7s %-13s %s\n' "----------------------" "-------" "-------------" "----------"
|
|
|
|
# $1 capability $2 payload-file $3 status-label $4 decode-cmd (optional; runs on the unwrapped payload)
|
|
demo() {
|
|
local cap="$1" pay="$2" status="$3" decode="${4:-}"
|
|
local env="$TMP/e.wai" out="$TMP/p.out"
|
|
local tier; tier="$("$WAI" capabilities 2>/dev/null | awk -v c="$cap" '$1==c{print $2}')"
|
|
"$WAI" wrap "$cap" "$pay" -o "$env" >/dev/null 2>&1
|
|
"$WAI" unwrap "$env" -o "$out" >/dev/null 2>&1
|
|
local rt="✗ MISMATCH"
|
|
if cmp -s "$pay" "$out"; then rt="✓ byte-exact"; fi
|
|
if [ -n "$decode" ]; then
|
|
if eval "$decode" >/dev/null 2>&1; then rt="$rt → decoded"; else rt="$rt → decode FAILED"; fi
|
|
fi
|
|
printf '%-22s %-7s %-13s %s\n' "$cap" "${tier:-?}" "$status" "$rt"
|
|
}
|
|
|
|
rep() { head -c "${2:-512}" /dev/urandom > "$1"; } # representative payload
|
|
|
|
# ---- cinema: JPEG 2000 (real, decoded by OpenJPEG) ----
|
|
if have opj_compress && have opj_decompress; then
|
|
opj_compress -i "$src_png" -o "$TMP/c.j2k" >/dev/null 2>&1
|
|
demo wai.image.jp2 "$TMP/c.j2k" "real+decode" "opj_decompress -i $TMP/p.out -o $TMP/c_dec.png"
|
|
else
|
|
rep "$TMP/c.j2k" 4096; demo wai.image.jp2 "$TMP/c.j2k" "carriage"
|
|
fi
|
|
|
|
# ---- immersive audio: IAMF (real, demuxed by ffmpeg) ----
|
|
if have ffmpeg; then
|
|
ffmpeg -hide_banner -loglevel error -y -f lavfi -i "sine=frequency=440:duration=1,aformat=channel_layouts=stereo" \
|
|
-c:a libopus -stream_group "type=iamf_audio_element:id=1:st=0,layer=ch_layout=stereo" \
|
|
-stream_group "type=iamf_mix_presentation:id=2:stg=0,submix=parameter_id=100|parameter_rate=48000|element=stg=0:headphones_rendering_mode=stereo" \
|
|
-map 0 -f iamf "$TMP/a.iamf" >/dev/null 2>&1
|
|
if [ -s "$TMP/a.iamf" ]; then
|
|
demo wai.audio.iamf "$TMP/a.iamf" "real+decode" "ffmpeg -hide_banner -loglevel error -y -i $TMP/p.out -f f32le $TMP/a.pcm"
|
|
else rep "$TMP/a.iamf" 2048; demo wai.audio.iamf "$TMP/a.iamf" "carriage"; fi
|
|
else rep "$TMP/a.iamf" 2048; demo wai.audio.iamf "$TMP/a.iamf" "carriage"; fi
|
|
|
|
# ---- the rest: representative payloads, decoder sink-supplied / proprietary ----
|
|
rep "$TMP/v.j2k" 4096; demo wai.video.j2k "$TMP/v.j2k" "carriage"
|
|
rep "$TMP/ac4" 2048; demo wai.audio.ac4 "$TMP/ac4" "proprietary"
|
|
# ---- immersive voice/audio: 3GPP IVAS (real, decoded by IVAS_dec) ----
|
|
# IVAS_cod / IVAS_dec = the 3GPP TS 26.258 reference (build from
|
|
# forge.3gpp.org/rep/ivas-codec-pc/ivas-codec). Encode real stereo PCM and
|
|
# decode it back — a full PCM -> bitstream -> PCM round-trip via the sink.
|
|
if have IVAS_cod && have IVAS_dec && have ffmpeg; then
|
|
ffmpeg -hide_banner -loglevel error -y -f lavfi -i "sine=frequency=440:duration=1" \
|
|
-f lavfi -i "sine=frequency=660:duration=1" \
|
|
-filter_complex "[0:a][1:a]join=inputs=2:channel_layout=stereo[a]" -map "[a]" \
|
|
-ar 48000 -f s16le -acodec pcm_s16le "$TMP/ivas_in.pcm" >/dev/null 2>&1
|
|
IVAS_cod -stereo 48000 48 "$TMP/ivas_in.pcm" "$TMP/ivas" >/dev/null 2>&1
|
|
if [ -s "$TMP/ivas" ]; then
|
|
demo wai.audio.ivas "$TMP/ivas" "real+decode" "IVAS_dec STEREO 48 $TMP/p.out $TMP/ivas_dec.pcm"
|
|
else rep "$TMP/ivas" 2048; demo wai.audio.ivas "$TMP/ivas" "carriage"; fi
|
|
else rep "$TMP/ivas" 2048; demo wai.audio.ivas "$TMP/ivas" "carriage"; fi
|
|
# ---- 3D geometry: Draco (real, decoded by draco_decoder) ----
|
|
if have draco_encoder && have draco_decoder; then
|
|
python3 - "$TMP/sphere.obj" <<'PY'
|
|
import math, sys
|
|
S=16; verts=[]; faces=[]
|
|
for i in range(S+1):
|
|
lat=math.pi*(-0.5+i/S)
|
|
for j in range(S):
|
|
lon=2*math.pi*j/S
|
|
verts.append((math.cos(lat)*math.cos(lon), math.sin(lat), math.cos(lat)*math.sin(lon)))
|
|
for i in range(S):
|
|
for j in range(S):
|
|
a=i*S+j+1;b=i*S+(j+1)%S+1;c=(i+1)*S+j+1;d=(i+1)*S+(j+1)%S+1
|
|
faces+=[(a,c,b),(b,c,d)]
|
|
open(sys.argv[1],'w').write(''.join(f'v {x:.5f} {y:.5f} {z:.5f}\n' for x,y,z in verts)
|
|
+''.join(f'f {a} {b} {c}\n' for a,b,c in faces))
|
|
PY
|
|
draco_encoder -i "$TMP/sphere.obj" -o "$TMP/drc" >/dev/null 2>&1
|
|
demo wai.mesh.draco "$TMP/drc" "real+decode" "draco_decoder -i $TMP/p.out -o $TMP/m_dec.obj"
|
|
else rep "$TMP/drc" 4096; demo wai.mesh.draco "$TMP/drc" "carriage"; fi
|
|
# ---- point cloud: MPEG G-PCC (real, decoded by tmc3 if built/on PATH) ----
|
|
# tmc3 = the MPEG G-PCC reference (build from github.com/MPEGGroup/mpeg-pcc-tmc13).
|
|
if have tmc3; then
|
|
python3 - "$TMP/cloud.ply" <<'PY'
|
|
import math, random, sys
|
|
random.seed(0); pts=[]
|
|
for _ in range(2000):
|
|
u,v=random.random(),random.random(); th=2*math.pi*u; ph=math.acos(2*v-1)
|
|
pts.append((int(200*math.sin(ph)*math.cos(th))+256,
|
|
int(200*math.sin(ph)*math.sin(th))+256, int(200*math.cos(ph))+256))
|
|
f=open(sys.argv[1],'w')
|
|
f.write('ply\nformat ascii 1.0\nelement vertex %d\nproperty float x\nproperty float y\nproperty float z\nend_header\n'%len(pts))
|
|
[f.write(f'{x} {y} {z}\n') for x,y,z in pts]
|
|
PY
|
|
tmc3 --mode=0 --uncompressedDataPath="$TMP/cloud.ply" --compressedStreamPath="$TMP/gpcc" --positionQuantizationScale=1 >/dev/null 2>&1
|
|
demo wai.pc.gpcc "$TMP/gpcc" "real+decode" "tmc3 --mode=1 --compressedStreamPath=$TMP/p.out --reconstructedDataPath=$TMP/pc_dec.ply"
|
|
else rep "$TMP/gpcc" 4096; demo wai.pc.gpcc "$TMP/gpcc" "carriage"; fi
|
|
# ---- point cloud: MPEG V-PCC (real encode + structural V3C decode if tmc2 built) ----
|
|
# tmc2 = the MPEG V-PCC reference (build from github.com/MPEGGroup/mpeg-pcc-tmc2,
|
|
# bundles its HM video codec). Set TMC2_CFG to the reference cfg/ directory.
|
|
# Encode is geometry-only (--noAttributes) so the RGB→YUV color pipeline (which
|
|
# needs HDRTools) is not required; the bitstream is still a conformant V3C stream.
|
|
if have PccAppEncoder && have PccAppParser && [ -n "${TMC2_CFG:-}" ] && [ -d "${TMC2_CFG:-}" ]; then
|
|
python3 - "$TMP/vpcc_f0000.ply" <<'PY'
|
|
import math, random, sys
|
|
random.seed(1); pts=[]
|
|
for _ in range(4000):
|
|
u,v=random.random(),random.random(); th=2*math.pi*u; ph=math.acos(2*v-1); r=128
|
|
x=int(r*math.sin(ph)*math.cos(th))+256; y=int(r*math.sin(ph)*math.sin(th))+256; z=int(r*math.cos(ph))+256
|
|
pts.append((x,y,z,(x*7)%256,(y*5)%256,(z*3)%256))
|
|
f=open(sys.argv[1],'w')
|
|
f.write('ply\nformat ascii 1.0\nelement vertex %d\nproperty float x\nproperty float y\nproperty float z\nproperty uchar red\nproperty uchar green\nproperty uchar blue\nend_header\n'%len(pts))
|
|
[f.write('%d %d %d %d %d %d\n'%p) for p in pts]
|
|
PY
|
|
PccAppEncoder --configurationFolder="$TMC2_CFG/" \
|
|
--uncompressedDataPath="$TMP/vpcc_f%04d.ply" --compressedStreamPath="$TMP/vpcc" \
|
|
--frameCount=1 --startFrameNumber=0 --resolution=1023 --noAttributes=1 --absoluteD1=1 --absoluteT1=1 \
|
|
--geometryConfig=hm/ctc-hm-geometry-ai.cfg --attributeConfig=hm/ctc-hm-attribute-ai.cfg \
|
|
--occupancyMapConfig=hm/ctc-hm-occupancy-map-ai-main.cfg \
|
|
--videoEncoderOccupancyPath="$(command -v PccAppVideoEncoder)" \
|
|
--videoEncoderGeometryPath="$(command -v PccAppVideoEncoder)" \
|
|
--videoEncoderAttributePath="$(command -v PccAppVideoEncoder)" >/dev/null 2>&1
|
|
if [ -s "$TMP/vpcc" ]; then
|
|
# sink = PccAppParser: structurally decode the carried payload into V3C units.
|
|
# Parse to a file then grep — a `... | grep -q` pipe SIGPIPEs the parser early
|
|
# (its dump is large), which trips `set -o pipefail` into a false failure.
|
|
demo wai.pc.vpcc "$TMP/vpcc" "real+parse" "PccAppParser $TMP/p.out >$TMP/v3c.txt 2>&1; grep -q V3C_VPS $TMP/v3c.txt"
|
|
else rep "$TMP/vpcc" 4096; demo wai.pc.vpcc "$TMP/vpcc" "carriage"; fi
|
|
else rep "$TMP/vpcc" 4096; demo wai.pc.vpcc "$TMP/vpcc" "carriage"; fi
|
|
rep "$TMP/sog" 4096; rm -f "$TMP/sog.wai"
|
|
if "$WAI" wrap wai.splat.sog "$TMP/sog" -o "$TMP/sog.wai" >/dev/null 2>&1 || [ -e "$TMP/sog.wai" ]; then sog_rt="✗ wrap ACCEPTED a candidate"; else sog_rt="✓ refused, nothing written"; fi
|
|
printf '%-22s %-7s %-13s %s\n' "wai.splat.sog" "$("$WAI" capabilities 2>/dev/null | awk '$1=="wai.splat.sog"{print $2}')" "candidate" "$sog_rt"
|
|
echo '{"version":1,"avatars":[]}' > "$TMP/h.hjif"
|
|
demo wai.haptic.mihs "$TMP/h.hjif" "carriage"
|
|
|
|
# ---- broadcast and streaming codecs ----
|
|
# Where ffmpeg has an encoder, build the REAL payload in the framing SPEC §5 pins
|
|
# (Annex B byte stream / IVF / ADTS) and decode the carried bytes with the
|
|
# matching raw demuxer FORCED (-f h264 / hevc / ivf / aac), so the row shows a
|
|
# real decoder consumes exactly the pinned framing. The others carry a
|
|
# representative payload; their decoders are sink-supplied.
|
|
# The decode must yield every encoded frame, not merely exit 0: 10 video frames,
|
|
# and for AAC the frame count of the encoded ADTS stream, counted independently
|
|
# of the decoder by walking its frame headers.
|
|
# Encoder list captured once: `ffmpeg -encoders | grep -q` would SIGPIPE ffmpeg
|
|
# and trip `set -o pipefail` into a false "no encoder".
|
|
ENCODERS=""; have ffmpeg && ENCODERS="$(ffmpeg -hide_banner -encoders 2>/dev/null)"
|
|
has_enc() { grep -q " $1 " <<<"$ENCODERS"; }
|
|
# $1 capability $2 encoder $3 muxer (the pinned framing) $4 extension
|
|
bcast_video() {
|
|
local cap="$1" enc="$2" fmt="$3" ext="$4"
|
|
if has_enc "$enc"; then
|
|
ffmpeg -hide_banner -loglevel error -y -f lavfi -i "testsrc=size=128x96:rate=10:duration=1" \
|
|
-c:v "$enc" -pix_fmt yuv420p -f "$fmt" "$TMP/b.$ext" >/dev/null 2>&1
|
|
if [ -s "$TMP/b.$ext" ]; then
|
|
demo "$cap" "$TMP/b.$ext" "real+decode" \
|
|
"ffmpeg -hide_banner -loglevel error -y -f $fmt -i $TMP/p.out -f framemd5 $TMP/d.md5 && [ \$(grep -vc '^#' $TMP/d.md5) -eq 10 ]"
|
|
return
|
|
fi
|
|
fi
|
|
rep "$TMP/b.$ext" 4096; demo "$cap" "$TMP/b.$ext" "carriage"
|
|
}
|
|
bcast_video wai.video.avc libx264 h264 h264
|
|
bcast_video wai.video.hevc libx265 hevc hevc
|
|
bcast_video wai.video.vp9 libvpx-vp9 ivf ivf
|
|
# Count the ADTS frames of a stream by walking each header's frame_length.
|
|
# Prints nothing unless the walk lands exactly on the end of the file.
|
|
adts_frames() {
|
|
python3 - "$1" <<'ADTS'
|
|
import sys
|
|
b = open(sys.argv[1], 'rb').read(); i = n = 0
|
|
while i + 7 <= len(b) and b[i] == 0xFF and (b[i+1] & 0xF6) == 0xF0:
|
|
fl = ((b[i+3] & 3) << 11) | (b[i+4] << 3) | (b[i+5] >> 5)
|
|
if fl < 7 or i + fl > len(b): break
|
|
i += fl; n += 1
|
|
print(n if n > 0 and i == len(b) else "")
|
|
ADTS
|
|
}
|
|
if has_enc aac; then
|
|
ffmpeg -hide_banner -loglevel error -y -f lavfi -i "sine=frequency=440:duration=1" \
|
|
-c:a aac -f adts "$TMP/b.aac" >/dev/null 2>&1
|
|
fi
|
|
if [ -s "$TMP/b.aac" ]; then
|
|
AAC_FRAMES="$(adts_frames "$TMP/b.aac")"
|
|
demo wai.audio.aac "$TMP/b.aac" "real+decode" \
|
|
"[ -n '$AAC_FRAMES' ] && ffmpeg -hide_banner -loglevel error -y -f aac -i $TMP/p.out -f framemd5 $TMP/d.md5 && [ \$(grep -vc '^#' $TMP/d.md5) -eq '$AAC_FRAMES' ]"
|
|
else rep "$TMP/b.aac" 2048; demo wai.audio.aac "$TMP/b.aac" "carriage"; fi
|
|
for cap in wai.video.av2 wai.video.vvc wai.video.evc wai.video.evc.baseline \
|
|
wai.video.avs3 wai.audio.mpegh wai.audio.avs3; do
|
|
rep "$TMP/b.bin" 4096; demo "$cap" "$TMP/b.bin" "carriage"
|
|
done
|
|
|
|
# ---- companion-only capabilities: HDR dynamic metadata, LCEVC (SPEC §5) ----
|
|
# Their payload means nothing without its base, so the only conforming carriage
|
|
# is a WAI2 companion bound to a base rendition. Each row wraps base + companion,
|
|
# requires the role check to pass, unwraps the companion byte-exact, requires
|
|
# `wai wrap` to refuse the WAI1 form, and (for a real base) decodes the base —
|
|
# the picture a sink without the companion's decoder presents. The base is a
|
|
# real AVC Annex B stream when libx264 is installed. The companion payloads are
|
|
# representative: no open encoder for them is installed here.
|
|
BASE_CAP=wai.video.avc; BASE="$TMP/base.h264"; BASE_REAL=""
|
|
if has_enc libx264; then
|
|
ffmpeg -hide_banner -loglevel error -y -f lavfi -i "testsrc=size=128x96:rate=10:duration=1" \
|
|
-c:v libx264 -pix_fmt yuv420p -f h264 "$BASE" >/dev/null 2>&1
|
|
[ -s "$BASE" ] && BASE_REAL=1
|
|
fi
|
|
[ -n "$BASE_REAL" ] || rep "$BASE" 4096
|
|
# $1 companion capability $2 companion payload [$3 a second payload of the
|
|
# same capability, which must be refused when stacked on the same base]
|
|
demo_companion() {
|
|
local cap="$1" pay="$2" env="$TMP/c.wai" out="$TMP/c.out" ins
|
|
local tier; tier="$("$WAI" capabilities 2>/dev/null | awk -v c="$cap" '$1==c{print $2}')"
|
|
rm -f "$env" "$out"
|
|
"$WAI" wrap "$BASE_CAP" "$BASE" -o "$env" --companion "$cap" "$pay" >/dev/null 2>&1
|
|
"$WAI" unwrap "$env" --component 1 -o "$out" >/dev/null 2>&1
|
|
local rt="✗ MISMATCH"
|
|
if cmp -s "$pay" "$out"; then rt="✓ byte-exact"; fi
|
|
# capture first: `wai inspect | grep -q` would SIGPIPE wai under pipefail
|
|
ins="$("$WAI" inspect "$env" 2>/dev/null)"
|
|
if grep -q 'component roles: *✓' <<<"$ins"; then rt="$rt · roles ✓"; else rt="$rt · roles ✗"; fi
|
|
if "$WAI" wrap "$cap" "$pay" -o "$TMP/refused.wai" >/dev/null 2>&1; then
|
|
rt="$rt · WAI1 ✗ ACCEPTED"; else rt="$rt · WAI1 refused"; fi
|
|
if [ -n "${3:-}" ]; then
|
|
if "$WAI" wrap "$BASE_CAP" "$BASE" -o "$TMP/stacked.wai" --companion "$cap" "$pay" \
|
|
--companion "$cap" "$3" >/dev/null 2>&1; then
|
|
rt="$rt · 2 on 1 base ✗ ACCEPTED"; else rt="$rt · 2 on 1 base refused"; fi
|
|
fi
|
|
if [ -n "$BASE_REAL" ]; then
|
|
rm -f "$TMP/base.out" "$TMP/base.md5"
|
|
"$WAI" unwrap "$env" -o "$TMP/base.out" >/dev/null 2>&1
|
|
if ffmpeg -hide_banner -loglevel error -y -f h264 -i "$TMP/base.out" -f framemd5 "$TMP/base.md5" >/dev/null 2>&1 \
|
|
&& [ "$(grep -vc '^#' "$TMP/base.md5")" -eq 10 ]; then
|
|
rt="$rt → base decoded"; else rt="$rt → base decode FAILED"; fi
|
|
fi
|
|
printf '%-22s %-7s %-13s %s\n' "$cap" "${tier:-?}" "companion" "$rt"
|
|
}
|
|
rep "$TMP/hdr" 256; demo_companion wai.meta.hdr10plus "$TMP/hdr"
|
|
rep "$TMP/dovi" 256; demo_companion wai.meta.dovi "$TMP/dovi"
|
|
rep "$TMP/lcevc" 1024; rep "$TMP/lcevc2" 1024
|
|
demo_companion wai.video.lcevc "$TMP/lcevc" "$TMP/lcevc2"
|
|
|
|
echo
|
|
echo "carriage is byte-exact for every class (§2). 'real+decode' rows ran a real"
|
|
echo "reference decoder (OpenJPEG / ffmpeg) on the unwrapped payload — the full"
|
|
echo "carry → dispatch → decode path. The rest carry identically; their decoders"
|
|
echo "are sink-supplied (open) or proprietary, by WAI's design."
|