code wiki / (root) / nx_codec.nx

nx_codec.nx source

↩ module page · 185 lines · 7404 B

1// nx_codec.nx -- abstract codec base class. 2// 3// The reusable composition primitive that audio (NishiVoice v1/v2) 4// and video (NishiVideo v1/v2) codecs implement. Consumers (audio 5// session, video session, future passthrough/test fakes) hold a 6// `*nx_codec` and never touch concrete codec types directly -- the 7// vtable handles dispatch. 8// 9// Per cardinal feedback-bits-up-exceed-never-match: codecs grade 10// themselves via nx_codec_grade. The vtable's grade_card_fn lets 11// any consumer ask any codec for its honest WIN/LOSE/TIE/UNMEASURED 12// per-axis verdict at runtime. 13// 14// Per cardinal feedback-end-to-end-bit-traceability-architecture: 15// every codec frame carries a CAS hash via frame_cas_hash_fn so 16// streams become Merkle chains; any consumer can prove tamper- 17// freedom of replayed bytes. 18// 19// genealogy_id: nx_voice_codec_v1 + nx_video_codec_v1 + nx_codec_grade + 20// nx_attest_merkle_chain + nx_media_session 21// lineage_id: nx_codec_q10 22 23// nx_safety_envelope: 24// intended_use: OOP base for sovereign media codecs 25// sil_target: SIL2 26// evidence: composes nx_voice_codec v1 (voice_call_test.sh proves 27// two-process UDP round-trip) + nx_video_codec v1 28// (codec_grade_card.nx asserts 11 WINs vs incumbents) 29// verdict: NOT_YET_EVALUATED -- pending end-to-end smoke 30 31import "nx_syscalls.nx" 32 33// ---- Sealed codec-id enum ---- 34// Append-only. Re-numbering breaks the wire frame header. 35 36const NX_CODEC_ID_UNKNOWN: i64 = 0 37const NX_CODEC_ID_NISHIVOICE_V1: i64 = 1 38const NX_CODEC_ID_NISHIVOICE_V2: i64 = 2 39const NX_CODEC_ID_NISHIVIDEO_V1: i64 = 11 40const NX_CODEC_ID_NISHIVIDEO_V2: i64 = 12 41const NX_CODEC_ID_PASSTHROUGH: i64 = 99 // test fixture 42const NX_CODEC_ID_N: i64 = 100 43 44// ---- Sealed codec-kind enum (audio vs video vs other) ---- 45 46const NX_CODEC_KIND_UNKNOWN: i64 = 0 47const NX_CODEC_KIND_AUDIO: i64 = 1 48const NX_CODEC_KIND_VIDEO: i64 = 2 49const NX_CODEC_KIND_DATA: i64 = 3 50const NX_CODEC_KIND_N: i64 = 4 51 52// ---- Sealed verdict enum (returned by encode/decode/frame_cas_hash) ---- 53// 54// Negative = error; 0 = success; positive = number of bytes written 55// to the output buffer. Caller distinguishes via sign. 56 57const NX_CODEC_ERR_OUT_TOO_SMALL: i64 = -1 58const NX_CODEC_ERR_BAD_INPUT: i64 = -2 59const NX_CODEC_ERR_BAD_MAGIC: i64 = -3 60const NX_CODEC_ERR_BAD_TIER: i64 = -4 61const NX_CODEC_ERR_NOT_SUPPORTED: i64 = -5 62 63// ---- The base struct ---- 64// 65// Embedded as the FIRST field of concrete codec subtypes (e.g. 66// nx_voice_codec_v1_impl wraps the existing nx_voice_codec.nx state). 67// 68// 8 i64 config fields + 4 vtable slots = 12 * 8 = 96 bytes. 69 70struct nx_codec { 71 // -- identity -- 72 codec_id: i64, // NX_CODEC_ID_* 73 kind: i64, // NX_CODEC_KIND_* 74 75 // -- config -- 76 frame_size_in: i64, // input frame in samples (audio) or block-pixels (video) 77 frame_size_out: i64, // max wire-frame bytes per encode (for cap-pre-alloc) 78 sample_rate: i64, // audio only; 0 for video 79 bitrate_target: i64, // bits per second 80 tier: i64, // NX_HW_TIER_* (set by codec constructor from nx_hwprobe) 81 82 // -- private state pointer -- 83 state: i64, // codec-specific state struct (cast in impl) 84 85 // -- vtable -- 86 encode_fn: func(*nx_codec, *u8, i64, *u8, i64) -> i64, // (src, src_n, dst, dst_cap) -> dst_n or NX_CODEC_ERR_* 87 decode_fn: func(*nx_codec, *u8, i64, *u8, i64) -> i64, 88 frame_cas_hash_fn: func(*nx_codec, *u8, i64, *u8) -> i64, // (frame, frame_n, out_hash_32B) -> 0 or err 89 grade_card_fn: func(*nx_codec, *u8, i64) -> i64, // (out_buf, out_cap) -> bytes written 90} 91 92const NX_CODEC_BYTES: i64 = 96 93 94// ---- Generic methods (read state, no vtable dispatch) ---- 95 96func nx_codec_id(c: *nx_codec) -> i64 { return c.codec_id } 97func nx_codec_kind(c: *nx_codec) -> i64 { return c.kind } 98func nx_codec_frame_size_in(c: *nx_codec) -> i64 { return c.frame_size_in } 99func nx_codec_frame_size_out(c: *nx_codec) -> i64 { return c.frame_size_out } 100func nx_codec_sample_rate(c: *nx_codec) -> i64 { return c.sample_rate } 101func nx_codec_bitrate_target(c: *nx_codec) -> i64 { return c.bitrate_target } 102func nx_codec_tier(c: *nx_codec) -> i64 { return c.tier } 103 104// ---- Virtual call sites ---- 105 106// Virtual call sites dispatch through the vtable directly. The 107// parser supports `c.fn_ptr_field(args)` for any arity since the 108// 2026-05-19 four-pillar fix (see [[feedback-four-pillar-parser- 109// fnptr-struct-multiarg]] + bench/nx_fn_ptr_struct_call_smoke.nx). 110 111func nx_codec_encode(c: *nx_codec, src: *u8, src_n: i64, 112 dst: *u8, dst_cap: i64) -> i64 { 113 if src_n <= 0 { return NX_CODEC_ERR_BAD_INPUT } 114 if dst_cap <= 0 { return NX_CODEC_ERR_OUT_TOO_SMALL } 115 return c.encode_fn(c, src, src_n, dst, dst_cap) 116} 117 118func nx_codec_decode(c: *nx_codec, src: *u8, src_n: i64, 119 dst: *u8, dst_cap: i64) -> i64 { 120 if src_n <= 0 { return NX_CODEC_ERR_BAD_INPUT } 121 if dst_cap <= 0 { return NX_CODEC_ERR_OUT_TOO_SMALL } 122 return c.decode_fn(c, src, src_n, dst, dst_cap) 123} 124 125func nx_codec_frame_cas_hash(c: *nx_codec, frame: *u8, frame_n: i64, 126 out_hash_32B: *u8) -> i64 { 127 if frame_n <= 0 { return NX_CODEC_ERR_BAD_INPUT } 128 return c.frame_cas_hash_fn(c, frame, frame_n, out_hash_32B) 129} 130 131func nx_codec_grade_card(c: *nx_codec, out_buf: *u8, out_cap: i64) -> i64 { 132 if out_cap <= 0 { return NX_CODEC_ERR_OUT_TOO_SMALL } 133 return c.grade_card_fn(c, out_buf, out_cap) 134} 135 136// ---- Default vtable implementations ---- 137// 138// All four return NX_CODEC_ERR_NOT_SUPPORTED so a partially-wired 139// subtype is honest about its gaps rather than silently no-op. 140 141func nx_codec_default_encode(c: *nx_codec, src: *u8, src_n: i64, 142 dst: *u8, dst_cap: i64) -> i64 { 143 return NX_CODEC_ERR_NOT_SUPPORTED 144} 145 146func nx_codec_default_decode(c: *nx_codec, src: *u8, src_n: i64, 147 dst: *u8, dst_cap: i64) -> i64 { 148 return NX_CODEC_ERR_NOT_SUPPORTED 149} 150 151func nx_codec_default_frame_cas_hash(c: *nx_codec, frame: *u8, frame_n: i64, 152 out_hash_32B: *u8) -> i64 { 153 return NX_CODEC_ERR_NOT_SUPPORTED 154} 155 156func nx_codec_default_grade_card(c: *nx_codec, out_buf: *u8, out_cap: i64) -> i64 { 157 return NX_CODEC_ERR_NOT_SUPPORTED 158} 159 160// ---- Base-struct initializer ---- 161// 162// Subtypes call this from their constructors before wiring their own 163// vtable + private state. Sets identity + safe defaults so an 164// unmodified codec still returns NOT_SUPPORTED honestly instead of 165// crashing. 166 167func nx_codec_init(c: *nx_codec, 168 codec_id: i64, kind: i64, 169 frame_size_in: i64, frame_size_out: i64, 170 sample_rate: i64, bitrate_target: i64, 171 tier: i64) -> i64 { 172 c.codec_id = codec_id 173 c.kind = kind 174 c.frame_size_in = frame_size_in 175 c.frame_size_out = frame_size_out 176 c.sample_rate = sample_rate 177 c.bitrate_target = bitrate_target 178 c.tier = tier 179 c.state = 0 180 c.encode_fn = nx_codec_default_encode 181 c.decode_fn = nx_codec_default_decode 182 c.frame_cas_hash_fn = nx_codec_default_frame_cas_hash 183 c.grade_card_fn = nx_codec_default_grade_card 184 return 0 185}