code wiki / _hdl_build / nx_ts_lumadiff.nx
nx_ts_lumadiff.nx source
↩ module page · 231 lines · 10633 B
1// nx_ts_lumadiff.nx -- VISUAL dead-air measurement.
2// Byte-rate analysis CANNOT see dead air in this corpus (measured 2026-07-31: audio is CBR AAC,
3// video is rate-controlled, p25/p50 = 79-94%). But "nothing is happening" IS visible in the
4// PIXELS. This seeks to NXVI keyframe byte offsets, decodes luma with the gate-proven CAVLC
5// I-frame decoder, reduces each frame to a 16x9 luma signature, and reports the mean absolute
6// difference between consecutive sampled frames. Low MAD run = static = dead air.
7// Reuses nx_ts_es (lifted verbatim from nx_cam_poster, byte-identical proven) + nx_h264_iframe.
8// nx_ts_lumadiff <in.ts> <in.idx> [max_samples]
9// license_tier: ORIGINAL
10import "nx_syscalls.nx"
11import "nx_itoa_lib.nx" // shared MSB-first emitter -- _hdl_build MAY import runtime/ (not the reverse)
12import "nx_ts_es.nx"
13import "nx_h264_sps.nx"
14import "nx_h264_pps.nx"
15import "nx_h264_iframe.nx"
16const LD_MAGIC_8388608: i64 = 8388608
17const LD_MAGIC_1048576: i64 = 1048576
18const LD_MAGIC_1024: i64 = 1024
19
20const LD_WIN: i64 = 3145728 // bytes read at each keyframe offset; one IDR access unit fits
21const LD_SIGW: i64 = 16 // signature grid width (cells)
22const LD_SIGH: i64 = 9 // signature grid height (cells)
23const LD_NALCAP: i64 = 4194304
24const LD_HEAD: i64 = 262144 // head read for SPS/PPS
25const LD_DEFSAMP: i64 = 40 // default number of keyframes sampled across the file
26
27func ld_puts(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 }
28// MIGRATED to the shared emitter (debt 1785557603). THIS FUNCTION TOOK 28.5GB OF A 36GB HOST.
29// Measured 2026-08-01: this organ held 29166124 kB RSS on a 2,383,652-byte (2MB) input -- ~12,000x
30// the input size -- froze every seat, OOM-killed sibling builds, and made the build admitter DENY.
31// Cause: TWO sys_mmap(28) per call, neither freed; each rounds to a 4096B page, so 8192B leaked per
32// call, and 28.5GB / 8192B is ~3.66 MILLION calls from 9 call sites inside per-sample loops.
33// nxi_out is MSB-first, allocates NOTHING, and emits identical bytes including the sign (gate T9/T10).
34func ld_num(v: i64) -> i64 { nxi_out(v); return 0 }
35func ld_atoi(s: *u8) -> i64 {
36 var v: i64 = 0
37 var i: i64 = 0
38 while s[i] != (0 as u8) { if s[i] >= (48 as u8) { if s[i] <= (57 as u8) { v = v*10 + ((s[i]-(48 as u8)) as i64) } } i = i + 1 }
39 return v
40}
41func ld_r32(b: *u8, o: i64) -> i64 {
42 return ((b[o] as i64)<<24) | ((b[o+1] as i64)<<16) | ((b[o+2] as i64)<<8) | (b[o+3] as i64)
43}
44func ld_r64(b: *u8, o: i64) -> i64 {
45 var v: i64 = 0
46 var i: i64 = 0
47 while i < 8 { v = (v<<8) | (b[o+i] as i64); i = i + 1 }
48 return v
49}
50// reduce a decoded luma plane to a LD_SIGW x LD_SIGH mean-luma signature
51func ld_signature(yf: *u8, W: i64, cropW: i64, cropH: i64, sig: *i64) -> i64 {
52 var cy: i64 = 0
53 while cy < LD_SIGH {
54 var cx: i64 = 0
55 while cx < LD_SIGW {
56 let x0: i64 = cx * cropW / LD_SIGW
57 var x1: i64 = (cx+1) * cropW / LD_SIGW
58 let y0: i64 = cy * cropH / LD_SIGH
59 var y1: i64 = (cy+1) * cropH / LD_SIGH
60 if x1 <= x0 { x1 = x0 + 1 }
61 if y1 <= y0 { y1 = y0 + 1 }
62 var acc: i64 = 0
63 var n: i64 = 0
64 var yy: i64 = y0
65 while yy < y1 {
66 var xx: i64 = x0
67 while xx < x1 { acc = acc + (yf[yy*W + xx] as i64); n = n + 1; xx = xx + 1 }
68 yy = yy + 1
69 }
70 if n < 1 { n = 1 }
71 sig[cy*LD_SIGW + cx] = acc / n
72 cx = cx + 1
73 }
74 cy = cy + 1
75 }
76 return 0
77}
78
79func main(argc: i64, argv: *i64) -> i64 {
80 if argc < 3 { ld_puts("usage: nx_ts_lumadiff <in.ts> <in.idx> [max_samples]\n\x00" as *u8); return 2 }
81 let tspath: *u8 = argv[1] as *u8
82 let ixpath: *u8 = argv[2] as *u8
83 var maxs: i64 = LD_DEFSAMP
84 if argc >= 4 { maxs = ld_atoi(argv[3] as *u8) }
85 if maxs < 0 { maxs = 0 } // arg is WHICH keyframe now; never silently rewrite it
86
87 // ---- read the NXVI index
88 let ixfd: i64 = sys_openat_rd(ixpath)
89 if ixfd < 0 { ld_puts("ERR: cannot open index\n\x00" as *u8); return 1 }
90 let ib: *u8 = sys_mmap(LD_MAGIC_8388608)
91 var ilen: i64 = 0
92 var g: i64 = 1
93 while g == 1 {
94 let r: i64 = sys_read(ixfd, ((ib as i64)+ilen) as *u8, LD_MAGIC_1048576)
95 if r <= 0 { g = 0 }
96 if r > 0 { ilen = ilen + r }
97 }
98 sys_close(ixfd)
99 if ilen < 40 { ld_puts("ERR: index too short\n\x00" as *u8); return 3 }
100 if ib[0] != (78 as u8) { ld_puts("ERR: not NXVI\n\x00" as *u8); return 3 }
101 let ver: i64 = ld_r32(ib, 4)
102 var o: i64 = 8
103 o = o + 8 + 4 + 4 + 4 + 4 // dur_ms, arate, achan, vidpid, audpid
104 // v3 inserted srcsize(8) here. A FORMAT BUMP MUST UPDATE EVERY READER: parsing
105 // v3 at v2 offsets reads srcsize AS spslen and seeks out of bounds (core dump).
106 if ver >= 3 { o = o + 8 }
107 let spl: i64 = ld_r32(ib, o); o = o + 4 + spl
108 let ppl: i64 = ld_r32(ib, o); o = o + 4 + ppl
109 let nkf: i64 = ld_r64(ib, o); o = o + 8
110 if nkf < 2 { ld_puts("REFUSED: index has fewer than 2 keyframes\n\x00" as *u8); return 4 }
111 let ktab: i64 = o
112
113 // ---- SPS/PPS from the head of the TS
114 let tsfd: i64 = sys_openat_rd(tspath)
115 if tsfd < 0 { ld_puts("ERR: cannot open ts\n\x00" as *u8); return 1 }
116 let hb: *u8 = sys_mmap(LD_HEAD + 512)
117 var hl: i64 = 0
118 var g2: i64 = 1
119 while g2 == 1 {
120 let r: i64 = sys_read(tsfd, ((hb as i64)+hl) as *u8, LD_HEAD - hl)
121 if r <= 0 { g2 = 0 }
122 if r > 0 { hl = hl + r; if hl >= LD_HEAD { g2 = 0 } }
123 }
124 let es: *u8 = sys_mmap(LD_WIN + 512)
125 let pidout: *i64 = sys_mmap(64) as *i64
126 var eslen: i64 = demux_video_es(hb, hl, es, pidout)
127 let spsn: *u8 = sys_mmap(LD_MAGIC_1024)
128 let ppsn: *u8 = sys_mmap(LD_MAGIC_1024)
129 let sl: i64 = find_first_nal(es, eslen, 7, spsn, LD_MAGIC_1024)
130 let pl: i64 = find_first_nal(es, eslen, 8, ppsn, LD_MAGIC_1024)
131 if sl <= 0 { ld_puts("REFUSED: no SPS in head\n\x00" as *u8); return 5 }
132 if pl <= 0 { ld_puts("REFUSED: no PPS in head\n\x00" as *u8); return 5 }
133 let srb: *u8 = sys_mmap(LD_MAGIC_1024)
134 let prb: *u8 = sys_mmap(LD_MAGIC_1024)
135 let srl: i64 = nal_to_rbsp(spsn, sl, srb)
136 let prl: i64 = nal_to_rbsp(ppsn, pl, prb)
137 let sps: *i64 = sys_mmap(8*128) as *i64
138 let pps: *i64 = sys_mmap(8*128) as *i64
139 nx_h264_parse_sps(srb, srl, sps)
140 nx_h264_parse_pps(prb, prl, pps)
141 if pps[2] == 1 { ld_puts("SKIP: CABAC stream (CAVLC decoder only)\n\x00" as *u8); return 10 }
142 let mbW: i64 = sps[4] + 1
143 let mbH: i64 = sps[5] + 1
144 let W: i64 = mbW * 16
145 let H: i64 = mbH * 16
146 let cpW: i64 = mbW * 8
147 var cropW: i64 = sps[2]
148 var cropH: i64 = sps[3]
149 if cropW <= 0 { cropW = W }
150 if cropH <= 0 { cropH = H }
151 if cropW > W { cropW = W }
152 if cropH > H { cropH = H }
153 let yf: *u8 = sys_mmap(W*H + 64)
154 let uf: *u8 = sys_mmap(cpW*(H/2) + 64)
155 let vf: *u8 = sys_mmap(cpW*(H/2) + 64)
156 let win: *u8 = sys_mmap(LD_WIN + 512)
157 let idrn: *u8 = sys_mmap(LD_NALCAP)
158 let irb: *u8 = sys_mmap(LD_NALCAP)
159 let sig: *i64 = sys_mmap(8 * LD_SIGW * LD_SIGH) as *i64
160 let prev: *i64 = sys_mmap(8 * LD_SIGW * LD_SIGH) as *i64
161 let cells: i64 = LD_SIGW * LD_SIGH
162
163 ld_puts("LUMADIFF nkf=\x00" as *u8); ld_num(nkf)
164 ld_puts(" res=\x00" as *u8); ld_num(cropW); ld_puts("x\x00" as *u8); ld_num(cropH)
165 ld_puts(" samples=\x00" as *u8); ld_num(maxs); ld_puts("\n\x00" as *u8)
166
167 // GUARD: single-decode mode never uses step, but this line still ran and maxs
168 // can legitimately be 0 (decode keyframe 0), so it divided by zero -> SIGFPE on
169 // the FIRST child of every scan. A vestigial computation still faults.
170 var step: i64 = 1
171 if maxs > 0 { step = nkf / maxs }
172 if step < 1 { step = 1 }
173 var have: i64 = 0
174 var decoded: i64 = 0
175 var failed: i64 = 0
176 var lowruns: i64 = 0
177 var k: i64 = maxs
178 while k < nkf {
179 let t_ms: i64 = ld_r64(ib, ktab + k*16)
180 let boff: i64 = ld_r64(ib, ktab + k*16 + 8)
181 sys_lseek(tsfd, boff, 0)
182 var wl: i64 = 0
183 var g3: i64 = 1
184 while g3 == 1 {
185 let r: i64 = sys_read(tsfd, ((win as i64)+wl) as *u8, LD_WIN - wl)
186 if r <= 0 { g3 = 0 }
187 if r > 0 { wl = wl + r; if wl >= LD_WIN { g3 = 0 } }
188 }
189 ld_puts(" [seek] \x00" as *u8); ld_num(boff); ld_puts(" wl=\x00" as *u8); ld_num(wl); ld_puts("\n\x00" as *u8)
190 var el: i64 = demux_video_es(win, wl, es, pidout)
191 ld_puts(" [demux] el=\x00" as *u8); ld_num(el); ld_puts("\n\x00" as *u8)
192 let il: i64 = find_first_nal(es, el, 5, idrn, LD_NALCAP)
193 ld_puts(" [nal] il=\x00" as *u8); ld_num(il); ld_puts("\n\x00" as *u8)
194 if il > 0 {
195 let irl: i64 = nal_to_rbsp(idrn, il, irb)
196 ld_puts(" [pre-decode] irl=\x00" as *u8); ld_num(irl); ld_puts("\n\x00" as *u8)
197 let ok: i64 = nx_h264_decode_iframe(irb, irl, 5, sps, pps, yf, uf, vf, mbW, mbH)
198 ld_puts(" [decode] ok=\x00" as *u8); ld_num(ok); ld_puts("\n\x00" as *u8)
199 if ok == 1 {
200 ld_signature(yf, W, cropW, cropH, sig)
201 ld_puts("SIG k=\x00" as *u8); ld_num(k); ld_puts(" t_ms=\x00" as *u8); ld_num(t_ms)
202 var sq: i64 = 0
203 while sq < cells { ld_puts(" \x00" as *u8); ld_num(sig[sq]); sq = sq + 1 }
204 ld_puts("\n\x00" as *u8)
205 return 0
206 decoded = decoded + 1
207 if have == 1 {
208 var acc: i64 = 0
209 var c: i64 = 0
210 while c < cells { var d: i64 = sig[c] - prev[c]; if d < 0 { d = 0 - d } acc = acc + d; c = c + 1 }
211 let mad: i64 = acc / cells
212 ld_puts(" t_ms=\x00" as *u8); ld_num(t_ms)
213 ld_puts(" mad=\x00" as *u8); ld_num(mad)
214 if mad < 3 { ld_puts(" STATIC\x00" as *u8); lowruns = lowruns + 1 }
215 ld_puts("\n\x00" as *u8)
216 }
217 var c2: i64 = 0
218 while c2 < cells { prev[c2] = sig[c2]; c2 = c2 + 1 }
219 have = 1
220 } else { failed = failed + 1 }
221 } else { failed = failed + 1 }
222 k = k + step
223 }
224 sys_close(tsfd)
225 ld_puts("LUMADIFF decoded=\x00" as *u8); ld_num(decoded)
226 ld_puts(" failed=\x00" as *u8); ld_num(failed)
227 ld_puts(" static_samples=\x00" as *u8); ld_num(lowruns)
228 ld_puts("\n\x00" as *u8)
229 if decoded < 2 { return 6 }
230 return 0
231}