code wiki / _hdl_build / nx_vcodec_skiprate_gate.nx

nx_vcodec_skiprate_gate.nx source

↩ module page · 104 lines · 6241 B

1import "nx_gate_base.nx" 2// nx_vcodec_skiprate_gate.nx -- MEASURE the P-frame skip rate on standard akiyo (the 73%-of-stream leak). 3// The encoder skips an MB when vm_sad_zero(cur, prev_recon) < qp*188 (and MV==(0,0)). This gate replicates 4// that EXACT decision against the real reconstructed reference each frame (so zsad matches the encoder bit-for- 5// bit), and reports: skip rate at the shipping threshold, at 2x/4x/8x, and a zsad/threshold histogram so we can 6// see whether non-skipped MBs are genuine motion (high SAD) or just quant-noise blocks sitting a hair above the 7// gate. Also sums the added distortion (SSE) of the would-skip-if-2x blocks so we know if raising is SAFE. 8// Decides the highest-leverage P-frame fix WITHOUT guessing. license: ORIGINAL 9import "nx_syscalls.nx" 10import "nx_video_codec_wasm.nx" 11import "nx_vmotion.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 } 24 25// SSE of luma MB (bx,by) cur vs prev co-located (what a true-skip would reconstruct as error) 26func mb_sse(cur: *u8, prev: *u8, W: i64, bx: i64, by: i64) -> i64 { 27 let cx: i64=bx*16; let cy: i64=by*16; var s: i64=0; var j: i64=0 28 while j<16 { var i: i64=0 29 while i<16 { let d: i64=(cur[(cy+j)*W+(cx+i)]&0xff) - (prev[(cy+j)*W+(cx+i)]&0xff); s=s+d*d; i=i+1 } j=j+1 } 30 return s } 31 32func run(yuv: *u8, hi: i64, total: i64, qp: i64) -> i64 { 33 let N: i64=SW*SH; let C2: i64=(SW/2)*(SH/2); let fdata: i64=N+2*C2; let sz: i64=fdata 34 let fp: *i64 = sys_mmap(128*8) as *i64 35 var nf: i64=0; var p: i64=hi 36 while nf < NF { if p>=total { break } 37 var q: i64=p; while q<total { if (yuv[q]&0xff)==10 { break } q=q+1 } q=q+1 38 if q+fdata>total { break } fp[nf]=(yuv as i64)+q; nf=nf+1; p=q+fdata } 39 if nf < NF { gw("too few frames\n" as *u8); return 1 } 40 let prevE: *u8=sys_mmap(sz+64); let reconE: *u8=sys_mmap(sz+64) 41 let wire: *u8=sys_mmap(2097152); let blk: *i64=sys_mmap(512) as *i64; let mv: *i64=sys_mmap(128) as *i64 42 let est: *i64=sys_mmap(64) as *i64; let probs: *i64=sys_mmap(32*8) as *i64; let rcbuf: *u8=sys_mmap(2097152) 43 let t8c: *i64=sys_mmap(5120) as *i64; let rctx: *i64=sys_mmap(64) as *i64 44 vc_t8_init(t8c) 45 var z: i64=0; while z<sz { prevE[z]=0 as u8; z=z+1 } 46 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 47 let mbx: i64=SW/16; let mby: i64=SH/16; let nmb: i64=mbx*mby 48 let thr: i64=qp*188 49 var tot_mb: i64=0; var sk1: i64=0; var sk2: i64=0; var sk4: i64=0; var sk8: i64=0 50 var h_lt1: i64=0; var h12: i64=0; var h24: i64=0; var h48: i64=0; var h8p: i64=0 51 var extra_sse_2x: i64=0; var extra_mb_2x: i64=0 52 var f: i64=0 53 while f < NF { 54 let cur: *u8=fp[f] as *u8 55 var key: i64=0; if f==0 { key=1 } 56 // BEFORE encoding this frame, prevE = recon of prior frame = EXACTLY what the encoder's skip decision sees. 57 if key==0 { 58 var by: i64=0 59 while by<mby { var bx: i64=0 60 while bx<mbx { 61 let zsad: i64=vm_sad_zero(cur, prevE, SW, bx, by, 16) 62 tot_mb=tot_mb+1 63 if zsad < thr { sk1=sk1+1 } 64 if zsad < thr*2 { sk2=sk2+1 } else { } 65 if zsad < thr*4 { sk4=sk4+1 } 66 if zsad < thr*8 { sk8=sk8+1 } 67 // histogram of zsad/thr 68 if zsad < thr { h_lt1=h_lt1+1 } 69 if zsad>=thr { if zsad<thr*2 { h12=h12+1 } } 70 if zsad>=thr*2 { if zsad<thr*4 { h24=h24+1 } } 71 if zsad>=thr*4 { if zsad<thr*8 { h48=h48+1 } } 72 if zsad>=thr*8 { h8p=h8p+1 } 73 // added distortion if we RAISED to 2x (blocks in [thr,2thr) that would newly skip) 74 if zsad>=thr { if zsad<thr*2 { extra_sse_2x=extra_sse_2x+mb_sse(cur,prevE,SW,bx,by); extra_mb_2x=extra_mb_2x+1 } } 75 bx=bx+1 } by=by+1 } 76 } 77 rctx[0]=1 78 let nb: i64 = vv_enc_rct8(cur, prevE, reconE, SW, SH, qp, key, thr, wire, 2097152, blk, mv, rctx) 79 if nb<=0 { gw("enc fail\n" as *u8); return 1 } 80 cpb(prevE, reconE, sz) 81 f=f+1 82 } 83 gw(" qp=" as *u8); gn(qp); gw(" thr=qp*188=" as *u8); gn(thr); gw(" MBs/P-frame=" as *u8); gn(nmb); gw("\n" as *u8) 84 gw(" SKIP RATE @1x(shipping)=" as *u8); gn(sk1*100/tot_mb); gw("% @2x=" as *u8); gn(sk2*100/tot_mb) 85 gw("% @4x=" as *u8); gn(sk4*100/tot_mb); gw("% @8x=" as *u8); gn(sk8*100/tot_mb); gw("%\n" as *u8) 86 gw(" zsad/thr HISTO [<1 skip]=" as *u8); gn(h_lt1); gw(" [1-2)=" as *u8); gn(h12) 87 gw(" [2-4)=" as *u8); gn(h24); gw(" [4-8)=" as *u8); gn(h48); gw(" [8+]=" as *u8); gn(h8p); gw("\n" as *u8) 88 // avg per-MB SSE of the [1,2) band -> is raising to 2x SAFE? (small SSE = yes) 89 var avg_extra: i64=0; if extra_mb_2x>0 { avg_extra=extra_sse_2x/extra_mb_2x } 90 gw(" RAISE-TO-2x would newly-skip " as *u8); gn(extra_mb_2x); gw(" MBs, avg added SSE/MB=" as *u8); gn(avg_extra) 91 gw(" (256px*small = safe; large = real motion)\n" as *u8) 92 return 0 } 93 94func main() -> i64 { 95 gw("=== nx_vcodec_skiprate_gate: P-frame SKIP RATE on akiyo (is the 73% leak skip-starvation?) ===\n" as *u8) 96 let box: *i64 = sys_mmap(16) as *i64 97 let yuv: *u8 = sys_read_file("/tmp/akiyo_cif.y4m" as *u8, box) 98 if (yuv as i64)==0 { gw("cannot read /tmp/akiyo_cif.y4m -> RED\n" as *u8); return 1 } 99 let total: i64=box[0] 100 var hi: i64=0; while hi<total { if (yuv[hi]&0xff)==10 { break } hi=hi+1 } hi=hi+1 101 run(yuv, hi, total, 8) 102 run(yuv, hi, total, 4) 103 gw("SKIPRATE: DONE (diagnostic -- skip rate + headroom)\n" as *u8) 104 return 0 }