code wiki / _hdl_build / nx_vcodec_deblock8_gate.nx
nx_vcodec_deblock8_gate.nx source
↩ module page · 99 lines · 6095 B
1import "nx_gate_base.nx"
2// nx_vcodec_deblock8_gate.nx -- vcv-8: prove the GENTLE in-loop deblock (emode bit9 = 512) on the SHIPPED rct8
3// path, on /tmp/seq.y4m. The deblock is IN-LOOP (filters the recon that becomes the next-frame reference) so enc
4// and dec MUST apply the identical filter or the reference diverges -> multi-second rot. This gate runs a full
5// enc->dec roundtrip with SEPARATE recon chains and memcmps EVERY frame. Compares emode 41 (FULL deblock
6// c1=qp*1.5+2 = shipped vcv<8, over-aggressive) vs 553 (41|512 = GENTLE c1=qp/2+2 = vcv-8): P-total bytes + luma
7// MSE vs source + BIT-EXACT verdict. Gentle should be bit-exact GREEN with LOWER MSE + fewer/equal P-bytes (less
8// over-smoothing of the reference -> a sharper, better predictor). Real BD-rate is the MSU oracle; this is the
9// correctness + direction gate. license: ORIGINAL
10import "nx_syscalls.nx"
11import "nx_video_codec_wasm.nx"
12
13const SW: i64 = 352
14const SH: i64 = 288
15const NF: i64 = 48
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 cpb(d: *u8, s: *u8, n: i64) -> i64 { var i: i64=0; while i<n { d[i]=s[i]; i=i+1 } return 0 }
24func eqb(a: *u8, b: *u8, n: i64) -> i64 { var i: i64=0; while i<n { if a[i]!=b[i] { return i } i=i+1 } return 0-1 }
25
26func frames(yuv: *u8, hi: i64, total: i64, fp: *i64, fdata: i64) -> i64 {
27 var nf: i64=0; var p: i64=hi
28 while nf < NF { if p>=total { break }
29 var q: i64=p; while q<total { if (yuv[q]&0xff)==10 { break } q=q+1 } q=q+1
30 if q+fdata>total { break } fp[nf]=(yuv as i64)+q; nf=nf+1; p=q+fdata }
31 return nf }
32
33func roundtrip(fp: *i64, qp: i64, emode: i64, sz: i64, ok: *i64) -> i64 {
34 let prevE: *u8=sys_mmap(sz+64); let reconE: *u8=sys_mmap(sz+64)
35 let prevD: *u8=sys_mmap(sz+64); let reconD: *u8=sys_mmap(sz+64)
36 let wire: *u8=sys_mmap(4194304); let blk: *i64=sys_mmap(512) as *i64; let mv: *i64=sys_mmap(128) as *i64
37 let estE: *i64=sys_mmap(64) as *i64; let probsE: *i64=sys_mmap(32*8) as *i64; let rcE: *u8=sys_mmap(4194304); let t8cE: *i64=sys_mmap(5120) as *i64
38 let estD: *i64=sys_mmap(64) as *i64; let probsD: *i64=sys_mmap(32*8) as *i64; let t8cD: *i64=sys_mmap(5120) as *i64
39 let rctxE: *i64=sys_mmap(64) as *i64; let rctxD: *i64=sys_mmap(64) as *i64
40 vc_t8_init(t8cE); vc_t8_init(t8cD)
41 var z: i64=0; while z<sz { prevE[z]=0 as u8; prevD[z]=0 as u8; z=z+1 }
42 rctxE[1]=estE as i64; rctxE[2]=probsE as i64; rctxE[3]=rcE as i64; rctxE[4]=t8cE as i64; rctxE[5]=0; rctxE[6]=0; rctxE[7]=0
43 rctxD[1]=estD as i64; rctxD[2]=probsD as i64; rctxD[3]=0; rctxD[4]=t8cD as i64; rctxD[5]=0; rctxD[6]=0; rctxD[7]=0
44 ok[0]=0-1; ok[1]=0
45 var pB: i64=0
46 var f: i64=0
47 while f < NF {
48 let cur: *u8=fp[f] as *u8
49 var key: i64=0; if f==0 { key=1 }
50 rctxE[0]=emode
51 let nb: i64 = vv_enc_rct8(cur, prevE, reconE, SW, SH, qp, key, qp*30, wire, 4194304, blk, mv, rctxE)
52 if nb<=0 { gw(" enc FAIL frame " as *u8); gn(f); gw("\n" as *u8); ok[0]=f; return pB }
53 rctxD[0]=emode
54 let dr: i64 = vv_dec_rct8(prevD, reconD, SW, SH, qp, wire, nb, blk, mv, rctxD)
55 if dr<0 { gw(" dec FAIL frame " as *u8); gn(f); gw("\n" as *u8); ok[0]=f; return pB }
56 let mm: i64 = eqb(reconE, reconD, sz)
57 if mm >= 0 { if ok[0] < 0 { ok[0]=f; gw(" DESYNC frame " as *u8); gn(f); gw(" at byte " as *u8); gn(mm); gw("\n" as *u8) } }
58 var pxi: i64=0; let NLp: i64=SW*SH
59 while pxi<NLp { let d: i64=(reconE[pxi]&0xff)-(cur[pxi]&0xff); ok[1]=ok[1]+d*d; pxi=pxi+1 }
60 if key==1 { } else { pB=pB+nb }
61 cpb(prevE, reconE, sz); cpb(prevD, reconD, sz)
62 f=f+1
63 }
64 return pB }
65
66func onerun(fp: *i64, sz: i64, qp: i64, emode: i64, label: *u8) -> i64 {
67 let ok: *i64=sys_mmap(16) as *i64
68 let pB: i64=roundtrip(fp, qp, emode, sz, ok)
69 let NL: i64=NF*SW*SH; let mmse: i64=ok[1]*1000/NL
70 gw(" " as *u8); gw(label); gw(" emode=" as *u8); gn(emode); gw(" P-total=" as *u8); gn(pB); gw("B lumaMSEx1000=" as *u8); gn(mmse); gw(" bitexact=" as *u8)
71 if ok[0] < 0 { gw("GREEN" as *u8) } else { gw("RED(frame " as *u8); gn(ok[0]); gw(")" as *u8) }
72 gw("\n" as *u8)
73 return pB }
74func sweepqp(fp: *i64, sz: i64, qp: i64) -> i64 {
75 gw(" --- qp=" as *u8); gn(qp); gw(" ---\n" as *u8)
76 let base: i64=onerun(fp, sz, qp, 41, "FULL deblk isol (41) " as *u8)
77 let feat: i64=onerun(fp, sz, qp, 41+512, "GENTLE deblk isol (553) " as *u8)
78 let cbase: i64=onerun(fp, sz, qp, 169, "CLIENT base full-deblk (169) " as *u8)
79 let cship: i64=onerun(fp, sz, qp, 169+512, "CLIENT SHIP gentle (681) " as *u8)
80 if base>0 { gw(" --> gentle vs full (isolated) = " as *u8); gn((base-feat)*1000/base); gw(" per-mille\n" as *u8) }
81 if cbase>0 { gw(" --> CLIENT-CONFIG gentle win = " as *u8); gn((cbase-cship)*1000/cbase); gw(" per-mille (169->681, the ACTUAL shipped path)\n" as *u8) }
82 return 0 }
83
84func main() -> i64 {
85 gw("=== nx_vcodec_deblock8_gate: vcv-8 GENTLE in-loop deblock rct8 roundtrip on /tmp/seq.y4m ===\n" as *u8)
86 let box: *i64 = sys_mmap(16) as *i64
87 let yuv: *u8 = sys_read_file("/tmp/seq.y4m" as *u8, box)
88 if (yuv as i64)==0 { gw("cannot read /tmp/seq.y4m -> RED\n" as *u8); return 1 }
89 let total: i64=box[0]
90 var hi: i64=0; while hi<total { if (yuv[hi]&0xff)==10 { break } hi=hi+1 } hi=hi+1
91 let C2: i64=(SW/2)*(SH/2); let fdata: i64=SW*SH+2*C2; let sz: i64=fdata
92 let fp: *i64=sys_mmap(128*8) as *i64
93 let nf: i64=frames(yuv, hi, total, fp, fdata)
94 if nf < NF { gw("too few frames -> RED\n" as *u8); return 1 }
95 sweepqp(fp, sz, 8)
96 sweepqp(fp, sz, 20)
97 sweepqp(fp, sz, 32)
98 gw("DEBLOCK8: DONE\n" as *u8)
99 return 0 }