code wiki / _hdl_build / nx_vcodec_stdseq_gate.nx
nx_vcodec_stdseq_gate.nx source
↩ module page · 160 lines · 8316 B
1import "nx_gate_base.nx"
2// nx_vcodec_stdseq_gate.nx -- FIRST measurement on a STANDARD test sequence (MSU/media.xiph.org methodology,
3// operator: MSU codec comparison = our foundation). Loads akiyo_cif.y4m (352x288, the canonical Xiph talking-
4// head standard clip MSU uses), encodes a key+P GOP through our codec at a qp sweep, and reports the RD curve
5// in the field-standard terms: bitrate (kbps@30) vs PSNR(dB) + SSIM. Then computes BD-RATE (Bjontegaard
6// delta-rate, piecewise-linear over matched PSNR) of our best mode (rct8) vs legacy -- the metric the WHOLE
7// field (MSU/JCT-VC) uses, so our gains become world-comparable. This replaces single-clip single-point %
8// with the standard sequence + standard metric. External anchor (vs x264) = the next step (install x264 as a
9// benchmark oracle). license_tier: ORIGINAL
10import "nx_syscalls.nx"
11import "nx_video_codec_wasm.nx"
12import "nx_quality_metric.nx"
13import "nx_f32.nx"
14import "nx_f32_log.nx"
15import "nx_f32_exp.nx"
16import "nx_f32_div.nx"
17import "nx_f32_cvt.nx"
18
19const SW: i64 = 352
20const SH: i64 = 288
21const GOP: i64 = 48 // 48 frames, keyframe at f=0 (matches the live client GOP + the ffmpeg -g 48 external anchor)
22
23func grow(name: *u8, ok: i64) -> i64 { if ok==1 { gw(" PASS " as *u8) } else { gw(" FAIL " as *u8) } gw(name); gw("
24" as *u8); return ok }
25func gn(v: i64) -> i64 {
26 let b: *u8=sys_mmap(28); var m: i64=v; if m<0{sys_write(1,"-" as *u8,1);m=0-m}
27 let t: *u8=sys_mmap(28); var k: i64=0; if m==0{t[0]=48 as u8;k=1} while m>0{t[k]=(48+(m%10)) as u8;m=m/10;k=k+1}
28 var i: i64=0; while i<k{b[i]=t[k-1-i];i=i+1} sys_write(1,b,k); return 0 }
29func g2(v: i64) -> i64 { gn(v/100); gw("." as *u8); let f: i64=v%100; if f<10{gw("0" as *u8)} gn(f); return 0 }
30func cpb(d: *u8, s: *u8, n: i64) -> i64 { var i: i64=0; while i<n { d[i]=s[i]; i=i+1 } return 0 }
31
32func main() -> i64 {
33 gw("=== nx_vcodec_stdseq_gate: RD curve on STANDARD sequence akiyo_cif (MSU/Xiph), BD-rate metric ===\n" as *u8)
34 let box: *i64 = sys_mmap(16) as *i64
35 let raw: *u8 = sys_read_file("/tmp/akiyo_cif.y4m" as *u8, box)
36 if (raw as i64) == 0 { gw("cannot read /tmp/akiyo_cif.y4m -> RED (fetch it first)\n" as *u8); return 1 }
37 let total: i64 = box[0]
38 // header end index = first position after the first '\n'
39 var hi: i64 = 0
40 while hi < total { if (raw[hi]&0xff)==10 { break } hi=hi+1 }
41 if hi >= total { gw("no y4m header -> RED\n" as *u8); return 1 }
42 hi = hi + 1
43 let N: i64 = SW*SH; let C2: i64 = (SW/2)*(SH/2); let fdata: i64 = N + 2*C2
44
45 // collect up to GOP frame data pointers (skip each "FRAME...\n" marker)
46 let fp: *i64 = sys_mmap(64*8) as *i64
47 var nf: i64 = 0
48 var p: i64 = hi
49 while nf < GOP {
50 if p >= total { break }
51 // expect "FRAME"; scan to the next '\n'
52 var q: i64 = p
53 while q < total { if (raw[q]&0xff)==10 { break } q=q+1 }
54 q = q + 1 // start of YUV data
55 if q + fdata > total { break }
56 fp[nf] = (raw as i64) + q
57 nf = nf + 1
58 p = q + fdata
59 }
60 gw(" loaded " as *u8); gn(nf); gw(" frames of akiyo_cif " as *u8); gn(SW); gw("x" as *u8); gn(SH); gw("\n" as *u8)
61 if nf < 6 { gw("too few frames -> RED\n" as *u8); return 1 }
62
63 let sz: i64 = N+2*C2
64 let prevE: *u8=sys_mmap(sz+64); let reconE: *u8=sys_mmap(sz+64)
65 let wire: *u8=sys_mmap(2097152); let blk: *i64=sys_mmap(512) as *i64; let mv: *i64=sys_mmap(128) as *i64
66 let est: *i64=sys_mmap(64) as *i64; let probs: *i64=sys_mmap(32*8) as *i64; let rcbuf: *u8=sys_mmap(2097152)
67 let t8c: *i64=sys_mmap(5120) as *i64; let rctx: *i64=sys_mmap(64) as *i64
68 vc_t8_init(t8c)
69
70 let qs: *i64=sys_mmap(64) as *i64; qs[0]=12; qs[1]=18; qs[2]=26; qs[3]=34
71 // per-qp results: [kbps, psnr_cdb] x 2 modes (0=legacy,1=rct8)
72 let RL: *i64=sys_mmap(64*8) as *i64 // legacy: kbps
73 let PL: *i64=sys_mmap(64*8) as *i64 // legacy: psnr
74 let RT: *i64=sys_mmap(64*8) as *i64 // rct8: kbps
75 let PT: *i64=sys_mmap(64*8) as *i64 // rct8: psnr
76
77 var qi: i64=0
78 while qi < 4 {
79 let qp: i64 = qs[qi]
80 // ---- legacy + rct8 arms ----
81 var mode: i64 = 0
82 while mode < 2 {
83 var z: i64=0; while z<sz { prevE[z]=0 as u8; z=z+1 }
84 rctx[0]=1; rctx[1]=est as i64; rctx[2]=probs as i64; rctx[3]=rcbuf as i64; rctx[4]=t8c as i64; rctx[5]=0; rctx[6]=0; rctx[7]=0
85 var bytes: i64=0; var cdb: i64=0
86 var f: i64=0
87 while f < nf {
88 let cur: *u8 = fp[f] as *u8
89 var key: i64=0; if f==0 { key=1 }
90 var nb: i64=0
91 if mode==0 { nb = vv_enc(cur, prevE, reconE, SW, SH, qp, key, qp*188, wire, 2097152, blk, mv) }
92 else { rctx[0]=1; nb = vv_enc_rct8(cur, prevE, reconE, SW, SH, qp, key, qp*188, wire, 2097152, blk, mv, rctx) }
93 if nb<=0 { gw("enc fail\n" as *u8); return 1 }
94 bytes=bytes+nb
95 cdb=cdb+qm_psnr_cdb(reconE, cur, N)
96 cpb(prevE, reconE, sz)
97 f=f+1
98 }
99 let kbps: i64 = (bytes*8*30)/(nf*1000)
100 let psnr: i64 = cdb/nf
101 if mode==0 { RL[qi]=kbps; PL[qi]=psnr } else { RT[qi]=kbps; PT[qi]=psnr }
102 mode=mode+1
103 }
104 gw(" qp=" as *u8); gn(qp)
105 gw(" legacy " as *u8); gn(RL[qi]); gw("kbps/" as *u8); g2(PL[qi])
106 gw("dB rct8 " as *u8); gn(RT[qi]); gw("kbps/" as *u8); g2(PT[qi]); gw("dB\n" as *u8)
107 qi=qi+1
108 }
109
110 // ---- BD-RATE (Bjontegaard), rct8 vs legacy anchor, piecewise-linear over matched PSNR ----
111 // overlap PSNR range = [max(min PL,min PT), min(max PL,max PT)]; sample, interp log(rate) on each, avg
112 // the ln-rate delta, exp -> % bitrate difference (negative = rct8 needs fewer bits at equal quality).
113 var loP: i64 = PL[3]; if PT[3] > loP { loP = PT[3] } // qs sorted so qp34 = lowest psnr
114 var hiP: i64 = PL[0]; if PT[0] < hiP { hiP = PT[0] } // qp12 = highest psnr
115 let f_one: i64 = nx_i32_to_f32(1)
116 var acc: i64 = 0 // f32 accumulator of ln(Rtest)-ln(Rref)
117 var ns: i64 = 0
118 var s: i64 = 0
119 while s < 10 {
120 let pv: i64 = loP + (hiP-loP)*s/9 // sample PSNR (cdb)
121 // interp kbps at pv on each 4-point curve (curves are qp12..qp34 = high..low psnr)
122 let rL: i64 = interp_rate(PL, RL, pv)
123 let rT: i64 = interp_rate(PT, RT, pv)
124 if rL>0 { if rT>0 {
125 let d: i64 = nx_f32_sub(nx_f32_log(nx_i32_to_f32(rT)), nx_f32_log(nx_i32_to_f32(rL)))
126 acc = nx_f32_add(acc, d); ns=ns+1
127 } }
128 s=s+1
129 }
130 var bd: i64 = 0
131 if ns>0 { let mean: i64 = nx_f32_div(acc, nx_i32_to_f32(ns)); let ratio: i64 = nx_f32_exp(mean)
132 bd = f_to_i(nx_f32_mul(nx_f32_sub(ratio, f_one), nx_i32_to_f32(1000))) }
133 gw(" BD-RATE (rct8 vs legacy) = " as *u8); gn(bd); gw("permille (negative = rct8 saves bits at equal PSNR)\n" as *u8)
134
135 var pass: i64=0; var tot: i64=0
136 tot=tot+1; if nf >= 6 { pass=pass+1 }
137 tot=tot+1; if RT[0] < RL[0] { pass=pass+1 } // rct8 cheaper than legacy at high quality
138 tot=tot+1; if bd < 0 { pass=pass+1 } // BD-rate negative = rct8 is better in the field metric
139 gw("STDSEQ: " as *u8); gn(pass); gw("/" as *u8); gn(tot)
140 if pass==tot { gw(" GREEN -- FIRST standard-sequence RD + BD-rate measured (MSU-grounded foundation live)\n" as *u8); return 0 }
141 gw(" RED\n" as *u8); return 1 }
142
143// linear-interp bitrate at target PSNR pv over a 4-point curve (P[] high->low psnr, R[] matching rates)
144func interp_rate(P: *i64, R: *i64, pv: i64) -> i64 {
145 var i: i64 = 0
146 while i < 3 {
147 let phi: i64 = P[i]; let plo: i64 = P[i+1] // phi > plo (curve descends)
148 if pv <= phi { if pv >= plo {
149 if phi==plo { return R[i] }
150 return R[i] + (R[i+1]-R[i])*(phi-pv)/(phi-plo)
151 } }
152 i=i+1
153 }
154 return 0 }
155func f_to_i(raw: i64) -> i64 {
156 let sgn: i64=(raw>>31)&1; let e: i64=((raw>>23)&0xff)-127
157 if e<0 { return 0 }
158 let mant: i64=(raw&0x7fffff)|0x800000
159 var v: i64=0; if e>=23 { v=mant<<(e-23) } else { v=mant>>(23-e) }
160 if sgn==1 { return 0-v } return v }