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 }