code wiki / _hdl_build / nx_vcodec_drift_diag.nx

nx_vcodec_drift_diag.nx source

↩ module page · 75 lines · 4097 B

1import "nx_gate_base.nx" 2// nx_vcodec_drift_diag.nx -- WHY are our P-frames ~10 dB below the keyframe at the same qp (MSU: intra 1.75x but 3// overall 8x behind x264 => the P-frames are the catastrophe)? Encodes /tmp/seq.y4m at a given qp (live emode 169) 4// and prints EVERY frame's luma SSE, so the shell can plot per-frame PSNR: a monotonic climb = temporal DRIFT 5// (error accumulates through the GOP); a flat-high plateau = P-frames systematically coded worse than intra. That 6// distinction picks the fix (drift -> prediction/quant loop; flat -> P residual fidelity). CIF only. license: ORIGINAL 7import "nx_syscalls.nx" 8import "nx_video_codec_wasm.nx" 9const K_MAGIC_4194304: i64 = 4194304 10const K_MAGIC_5120: i64 = 5120 11 12const SW: i64 = 352 13const SH: i64 = 288 14const NF: i64 = 48 15 16func grow(name: *u8, ok: i64) -> i64 { if ok==1 { gw(" PASS " as *u8) } else { gw(" FAIL " as *u8) } gw(name); gw(" 17" as *u8); return ok } 18func gn(v: i64) -> i64 { 19 let b: *u8=sys_mmap(28); var m: i64=v; if m<0{sys_write(1,"-" as *u8,1);m=0-m} 20 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} 21 var i: i64=0; while i<k{b[i]=t[k-1-i];i=i+1} sys_write(1,b,k); return 0 } 22func cpb(d: *u8, s: *u8, n: i64) -> i64 { var i: i64=0; while i<n { d[i]=s[i]; i=i+1 } return 0 } 23 24func frames(yuv: *u8, hi: i64, total: i64, fp: *i64, fdata: i64) -> i64 { 25 var nf: i64=0; var p: i64=hi 26 while nf < NF { if p>=total { break } 27 var q: i64=p; while q<total { if (yuv[q]&0xff)==10 { break } q=q+1 } q=q+1 28 if q+fdata>total { break } fp[nf]=(yuv as i64)+q; nf=nf+1; p=q+fdata } 29 return nf } 30 31func run(fp: *i64, qp: i64, emode: i64, sz: i64, skipmul: i64) -> i64 { 32 let prevE: *u8=sys_mmap(sz+64); let reconE: *u8=sys_mmap(sz+64) 33 let wire: *u8=sys_mmap(K_MAGIC_4194304); let blk: *i64=sys_mmap(512) as *i64; let mv: *i64=sys_mmap(128) as *i64 34 let est: *i64=sys_mmap(64) as *i64; let probs: *i64=sys_mmap(32*8) as *i64; let rcbuf: *u8=sys_mmap(K_MAGIC_4194304) 35 let t8c: *i64=sys_mmap(K_MAGIC_5120) as *i64; let rctx: *i64=sys_mmap(64) as *i64 36 vc_t8_init(t8c) 37 var z: i64=0; while z<sz { prevE[z]=0 as u8; z=z+1 } 38 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 39 let NL: i64=SW*SH 40 var totB: i64=0; var keySSE: i64=0; var lastSSE: i64=0; var pSSEsum: i64=0 41 var f: i64=0 42 while f < NF { 43 let cur: *u8=fp[f] as *u8 44 var key: i64=0; if f==0 { key=1 } 45 rctx[0]=emode 46 let nb: i64 = vv_enc_rct8(cur, prevE, reconE, SW, SH, qp, key, qp*skipmul, wire, K_MAGIC_4194304, blk, mv, rctx) 47 if nb<=0 { gw("enc fail\n" as *u8); return 1 } 48 var pxi: i64=0; var fsse: i64=0 49 while pxi<NL { let d: i64=(reconE[pxi]&0xff)-(cur[pxi]&0xff); fsse=fsse+d*d; pxi=pxi+1 } 50 totB=totB+nb; if f==0 { keySSE=fsse } else { pSSEsum=pSSEsum+fsse; lastSSE=fsse } 51 cpb(prevE, reconE, sz) 52 f=f+1 53 } 54 // report keyframe sseY, P-avg sseY, P-last sseY (shell -> PSNR), total bytes 55 gw("SKIPMUL="); gn(skipmul); gw(" totB="); gn(totB); gw(" keySSE="); gn(keySSE) 56 gw(" pAvgSSE="); gn(pSSEsum/(NF-1)); gw(" pLastSSE="); gn(lastSSE); gw("\n" as *u8) 57 return 0 } 58 59func main() -> i64 { 60 let box: *i64 = sys_mmap(16) as *i64 61 let yuv: *u8 = sys_read_file("/tmp/seq.y4m" as *u8, box) 62 if (yuv as i64)==0 { gw("cannot read /tmp/seq.y4m -> RED\n" as *u8); return 1 } 63 let total: i64=box[0] 64 var hi: i64=0; while hi<total { if (yuv[hi]&0xff)==10 { break } hi=hi+1 } hi=hi+1 65 let C2: i64=(SW/2)*(SH/2); let fdata: i64=SW*SH+2*C2; let sz: i64=fdata 66 let fp: *i64=sys_mmap(128*8) as *i64 67 let nf: i64=frames(yuv, hi, total, fp, fdata) 68 if nf < NF { gw("too few frames -> RED\n" as *u8); return 1 } 69 // sweep the skip threshold: 188=baseline, lower=less skip (code more MBs). Does less skip fix the drift? 70 run(fp, 8, 169, sz, 188) 71 run(fp, 8, 169, sz, 60) 72 run(fp, 8, 169, sz, 20) 73 run(fp, 8, 169, sz, 4) 74 gw("DRIFT: DONE\n" as *u8) 75 return 0 }