code wiki / _hdl_build / nx_vcodec_t8rd_gate.nx

nx_vcodec_t8rd_gate.nx source

↩ module page · 158 lines · 8834 B

1import "nx_gate_base.nx" 2// nx_vcodec_t8rd_gate.nx -- RD TRANSFORM-SELECT proof (task #46 rung 2b, encoder-only). The mad-of-SOURCE 3// policy classifies source pixels, but inter MBs code the MC RESIDUAL whose character differs; RD-AUTO 4// (emode bit2) costs BOTH transforms on the real residual per MB (exact CAVLC bit counters + recon SSE, 5// lambda = q^2/32 derived from the deadzone step) and patches the explicit t8 bit. Decoder is OBLIVIOUS -- 6// the same vv_dec_t8/vv_dec_rct8 must decode auto streams bit-exact. Proves, on key+5P chains with REAL 7// panning motion (flat / textured / mixed content): 8// (1) auto streams decode bit-exact with the unchanged decoder (every frame, every class) 9// (2) auto never loses bytes materially (<= policy*102% + 8B) at PSNR within 1 dB -- and should WIN where 10// the source policy misclassifies residuals (textured pan) 11// (3) auto encode time < 2x policy (trial costing is transform-stage work; ME still dominates) 12// (4) the rct8 (range) composition also decodes bit-exact under auto + bytes reported 13// license_tier: ORIGINAL 14import "nx_syscalls.nx" 15import "nx_video_codec_wasm.nx" 16 17func grow(name: *u8, ok: i64) -> i64 { if ok==1 { gw(" PASS " as *u8) } else { gw(" FAIL " as *u8) } gw(name); gw(" 18" as *u8); return ok } 19func gn(v: i64) -> i64 { 20 let b: *u8=sys_mmap(28); var m: i64=v; if m<0{sys_write(1,"-" as *u8,1);m=0-m} 21 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} 22 var i: i64=0; while i<k{b[i]=t[k-1-i];i=i+1} sys_write(1,b,k); return 0 } 23func eqb(a: *u8, b: *u8, n: i64) -> i64 { var i: i64=0; while i<n { if (a[i]&0xff)!=(b[i]&0xff) { return 0 } i=i+1 } return 1 } 24func cpb(d: *u8, s: *u8, n: i64) -> i64 { var i: i64=0; while i<n { d[i]=s[i]; i=i+1 } return 0 } 25func sseL(a: *u8, b: *u8, n: i64) -> i64 { var s: i64=0; var i: i64=0; while i<n { let d: i64=(a[i]&0xff)-(b[i]&0xff); s=s+d*d; i=i+1 } return s } 26func psnrdb(sse: i64, npix: i64) -> i64 { 27 if sse<=0 { return 99 } 28 let mse: i64 = (sse*100)/npix 29 var num: i64 = 6502500*100; var m: i64 = mse; if m<1 {m=1} 30 var ratio: i64 = num/m 31 var db: i64 = 0; var t: i64 = ratio 32 while t >= 100 { db=db+10; t=t/10 } 33 var fr: i64 = 0 34 if t>=13 { fr=1 } if t>=16 { fr=2 } if t>=20 { fr=3 } if t>=25 { fr=4 } 35 if t>=32 { fr=5 } if t>=40 { fr=6 } if t>=50 { fr=7 } if t>=63 { fr=8 } if t>=79 { fr=9 } 36 return db + fr } 37 38// content with REAL translation: the whole pattern pans right 3px/frame (kind 0 = flat gradient, 39// 1 = high-frequency texture, 2 = gradient + a textured square whose CONTENT moves with it). 40func fill_pan(yuv: *u8, W: i64, H: i64, sh: i64, kind: i64) -> i64 { 41 let N: i64=W*H; let C2: i64=(W/2)*(H/2) 42 let bx: i64 = 48 + sh*3 43 let by2: i64 = 32 + sh 44 var r: i64=0 45 while r<H { var c: i64=0 46 while c<W { 47 let cs: i64 = c + 512 - sh*3 // pan coordinate, kept positive for clean modulo 48 var v: i64 = 0 49 if kind == 0 { v = 90 + (cs + r) / 6 } 50 if kind == 1 { v = 128 + ((cs*7 + r*5) % 37) * 4 - 74 } 51 if kind == 2 { 52 v = 100 + (cs + r) / 8 53 if c>=bx { if c<bx+64 { if r>=by2 { if r<by2+48 { 54 v = 128 + (((c-bx)*7 + (r-by2)*5) % 37) * 4 - 74 } } } } 55 } 56 if v<0{v=0} if v>255{v=255} 57 yuv[r*W+c]=v as u8; c=c+1 } r=r+1 } 58 var i: i64=0 59 while i<C2 { let cr: i64=i/(W/2); let cc: i64=i%(W/2) 60 var u: i64 = 120 + (cc + 256 - sh)/32; if u>255{u=255} 61 yuv[N+i]=u as u8; yuv[N+C2+i]=(130 - cr/12) as u8; i=i+1 } 62 return 0 } 63 64func seedctx(rctx: *i64, emode: i64, est: *i64, probs: *i64, rcbuf: *u8, t8c: *i64) -> i64 { 65 rctx[0]=emode; rctx[1]=est as i64; rctx[2]=probs as i64; rctx[3]=rcbuf as i64; rctx[4]=t8c as i64; rctx[5]=0; return 0 } 66 67// key + 5 P chain of panning content `kind`; encodes POLICY (emode base) and AUTO (base+4) side by side, 68// decodes the AUTO stream with the ignorant decoder each frame. out[0]=policy bytes, out[1]=auto bytes, 69// out[2]=policy PSNR dB (aggregate), out[3]=auto PSNR dB, out[4]=frames bit-exact, out[5]=policy enc us, 70// out[6]=auto enc us. base: 0=CAVLC (vv_enc_t8), 1=range (vv_enc_rct8). 71func run_rd(W: i64, H: i64, qp: i64, base: i64, kind: i64, out: *i64) -> i64 { 72 let N: i64=W*H; let C2: i64=(W/2)*(H/2); let sz: i64=N+2*C2 73 let cur: *u8=sys_mmap(sz) 74 let prevP: *u8=sys_mmap(sz); let reconP: *u8=sys_mmap(sz) 75 let prevA: *u8=sys_mmap(sz); let reconA: *u8=sys_mmap(sz) 76 let prevD: *u8=sys_mmap(sz); let reconD: *u8=sys_mmap(sz) 77 let blk: *i64=sys_mmap(512) as *i64; let mv: *i64=sys_mmap(128) as *i64 78 let outP: *u8=sys_mmap(262144); let outA: *u8=sys_mmap(262144) 79 let est: *i64=sys_mmap(64) as *i64; let probs: *i64=sys_mmap(32*8) as *i64; let rcbuf: *u8=sys_mmap(262144) 80 let rctx: *i64=sys_mmap(8*8) as *i64 81 let t8c: *i64=sys_mmap(5120) as *i64 82 vc_t8_init(t8c) 83 out[0]=0; out[1]=0; out[4]=0; out[5]=0; out[6]=0 84 var sseP: i64=0; var sseA: i64=0 85 var f: i64=0 86 while f < 6 { 87 fill_pan(cur, W, H, f, kind) 88 var key: i64=0; if f==0 { key=1 } 89 // POLICY encode 90 seedctx(rctx, base, est, probs, rcbuf, t8c) 91 let t0: i64 = sys_now_us() 92 var pb: i64=0 93 if base==1 { pb = vv_enc_rct8(cur, prevP, reconP, W, H, qp, key, 6016, outP, 262144, blk, mv, rctx) } 94 else { pb = vv_enc_t8(cur, prevP, reconP, W, H, qp, key, 6016, outP, 262144, blk, mv, rctx) } 95 let t1: i64 = sys_now_us() 96 // AUTO encode (emode bit2) 97 seedctx(rctx, base+4, est, probs, rcbuf, t8c) 98 var ab: i64=0 99 if base==1 { ab = vv_enc_rct8(cur, prevA, reconA, W, H, qp, key, 6016, outA, 262144, blk, mv, rctx) } 100 else { ab = vv_enc_t8(cur, prevA, reconA, W, H, qp, key, 6016, outA, 262144, blk, mv, rctx) } 101 let t2: i64 = sys_now_us() 102 // the IGNORANT decoder must read the auto stream bit-exact 103 seedctx(rctx, base, est, probs, rcbuf, t8c) 104 if base==1 { vv_dec_rct8(prevD, reconD, W, H, qp, outA, ab, blk, mv, rctx) } 105 else { vv_dec_t8(prevD, reconD, W, H, qp, outA, ab, blk, mv, rctx) } 106 if eqb(reconD, reconA, sz)==1 { out[4]=out[4]+1 } 107 out[0]=out[0]+pb; out[1]=out[1]+ab 108 out[5]=out[5]+(t1-t0); out[6]=out[6]+(t2-t1) 109 sseP=sseP+sseL(reconP, cur, N); sseA=sseA+sseL(reconA, cur, N) 110 cpb(prevP, reconP, sz); cpb(prevA, reconA, sz); cpb(prevD, reconD, sz) 111 f=f+1 112 } 113 let dP: i64 = psnrdb(sseP, N*6) 114 let dA: i64 = psnrdb(sseA, N*6) 115 out[2]=dP; out[3]=dA 116 return 0 } 117 118func ck(p: *i64, t: *i64, ok: i64) -> i64 { t[0]=t[0]+1; if ok==1 { p[0]=p[0]+1 } return 0 } 119 120func report(name: *u8, o: *i64) -> i64 { 121 gw(" " as *u8); gw(name) 122 gw(": policy=" as *u8); gn(o[0]); gw("B@" as *u8); gn(o[2]); gw("dB auto=" as *u8); gn(o[1]) 123 gw("B@" as *u8); gn(o[3]); gw("dB (" as *u8); gn(o[1]*100/o[0]); gw("%) exact=" as *u8); gn(o[4]); gw("/6" as *u8) 124 gw(" enc " as *u8); gn(o[5]/1000); gw("ms->" as *u8); gn(o[6]/1000); gw("ms\n" as *u8) 125 return 0 } 126 127func main() -> i64 { 128 gw("=== nx_vcodec_t8rd_gate: RD transform-select (auto, emode bit2) vs mad policy, ignorant decoder ===\n" as *u8) 129 let p: *i64=sys_mmap(16) as *i64; let t: *i64=sys_mmap(16) as *i64 130 let o: *i64=sys_mmap(8*8) as *i64 131 // [A] FLAT pan, CAVLC: policy already picks 8x8 everywhere -- auto must agree or beat, never regress 132 run_rd(256, 192, 20, 0, 0, o) 133 report("FLAT pan CAVLC" as *u8, o) 134 ck(p, t, (o[4]==6) as i64) 135 ck(p, t, (o[1] <= (o[0]*102)/100 + 8) as i64) 136 ck(p, t, (o[3] >= o[2]-1) as i64) 137 // [B] TEXTURED pan, CAVLC: policy forces 4x4 (source mad high) -- auto reads the RESIDUAL instead 138 run_rd(256, 192, 20, 0, 1, o) 139 report("TEX pan CAVLC" as *u8, o) 140 ck(p, t, (o[4]==6) as i64) 141 ck(p, t, (o[1] <= (o[0]*102)/100 + 8) as i64) 142 ck(p, t, (o[3] >= o[2]-1) as i64) 143 let texSpdOk: i64 = (o[6] < o[5]*2) as i64 144 // [C] MIXED pan, CAVLC 145 run_rd(256, 192, 20, 0, 2, o) 146 report("MIX pan CAVLC" as *u8, o) 147 ck(p, t, (o[4]==6) as i64) 148 ck(p, t, (o[1] <= (o[0]*102)/100 + 8) as i64) 149 ck(p, t, (o[3] >= o[2]-1) as i64) 150 ck(p, t, texSpdOk) // trial costing must stay transform-stage cheap (< 2x whole-encode) -- worst case is textured 151 // [D] MIXED pan through the RANGE composition (rct8): auto + ignorant decoder + bytes 152 run_rd(256, 192, 20, 1, 2, o) 153 report("MIX pan RANGE" as *u8, o) 154 ck(p, t, (o[4]==6) as i64) 155 ck(p, t, (o[1] <= (o[0]*102)/100 + 8) as i64) 156 gw("T8RD: " as *u8); gn(p[0]); gw("/" as *u8); gn(t[0]) 157 if p[0]==t[0] { gw(" GREEN -- RD-auto never regresses, decoder oblivious, residual-true select live\n" as *u8); return 0 } 158 gw(" RED\n" as *u8); return 1 }