code wiki / _hdl_build / nx_vcodec_bitsplit_gate.nx

nx_vcodec_bitsplit_gate.nx source

↩ module page · 80 lines · 4313 B

1import "nx_gate_base.nx" 2// nx_vcodec_bitsplit_gate.nx -- WHERE do the coded-P-MB bits actually go: MV/headers (CAVLC section) vs residual 3// coefficients (range-coded section)? Decides the BIG entropy-vs-prediction question before building either. 4// The rct8 frame fn packs each luma plane as [cavlc_end:u16][CAVLC bits: skip+part+MV+qpel+t8][range bytes: 5// sig-map + levels]. yb (plane total) is in the vv header; cavlc_end is the plane's first 2 bytes -> range = 6// yb - cavlc_end. Accumulates the LUMA split over P-frames for baseline (emode 41) and partition (emode 169), on 7// /tmp/seq.y4m. If range >> cavlc, ENTROPY/residual is the lever; if cavlc is large, MV/prediction is. ORIGINAL 8import "nx_syscalls.nx" 9import "nx_video_codec_wasm.nx" 10 11const SW: i64 = 352 12const SH: i64 = 288 13const NF: i64 = 48 14 15func grow(name: *u8, ok: i64) -> i64 { if ok==1 { gw(" PASS " as *u8) } else { gw(" FAIL " as *u8) } gw(name); gw(" 16" as *u8); return ok } 17func gn(v: i64) -> i64 { 18 let b: *u8=sys_mmap(28); var m: i64=v; if m<0{sys_write(1,"-" as *u8,1);m=0-m} 19 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} 20 var i: i64=0; while i<k{b[i]=t[k-1-i];i=i+1} sys_write(1,b,k); return 0 } 21func cpb(d: *u8, s: *u8, n: i64) -> i64 { var i: i64=0; while i<n { d[i]=s[i]; i=i+1 } return 0 } 22 23func frames(yuv: *u8, hi: i64, total: i64, fp: *i64, fdata: i64) -> i64 { 24 var nf: i64=0; var p: i64=hi 25 while nf < NF { if p>=total { break } 26 var q: i64=p; while q<total { if (yuv[q]&0xff)==10 { break } q=q+1 } q=q+1 27 if q+fdata>total { break } fp[nf]=(yuv as i64)+q; nf=nf+1; p=q+fdata } 28 return nf } 29 30func run(fp: *i64, qp: i64, emode: i64, sz: i64) -> i64 { 31 let prevE: *u8=sys_mmap(sz+64); let reconE: *u8=sys_mmap(sz+64) 32 let wire: *u8=sys_mmap(4194304); let blk: *i64=sys_mmap(512) as *i64; let mv: *i64=sys_mmap(128) as *i64 33 let est: *i64=sys_mmap(64) as *i64; let probs: *i64=sys_mmap(32*8) as *i64; let rcbuf: *u8=sys_mmap(4194304) 34 let t8c: *i64=sys_mmap(5120) as *i64; let rctx: *i64=sys_mmap(64) as *i64 35 vc_t8_init(t8c) 36 var z: i64=0; while z<sz { prevE[z]=0 as u8; z=z+1 } 37 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 38 var cavlcB: i64=0; var rangeB: i64=0 39 var f: i64=0 40 while f < NF { 41 let cur: *u8=fp[f] as *u8 42 var key: i64=0; if f==0 { key=1 } 43 rctx[0]=emode 44 let nb: i64 = vv_enc_rct8(cur, prevE, reconE, SW, SH, qp, key, qp*30, wire, 4194304, blk, mv, rctx) 45 if nb<=0 { gw("enc fail\n" as *u8); return 1 } 46 if key==0 { 47 let yb: i64 = vv_rd_u32b(wire, 0) // luma plane byte count 48 let lo: i64 = wire[12] as i64 49 let hi2: i64 = wire[13] as i64 50 let ce: i64 = (lo & 0xff) | ((hi2 & 0xff) << 8) // luma cavlc_end (headers+MV bytes) 51 cavlcB = cavlcB + ce; rangeB = rangeB + (yb - ce) 52 } 53 cpb(prevE, reconE, sz) 54 f=f+1 55 } 56 let tot: i64 = cavlcB + rangeB 57 var pctc: i64 = 0; var pctr: i64 = 0 58 if tot > 0 { pctc = cavlcB*100/tot; pctr = rangeB*100/tot } 59 gw(" emode=" as *u8); gn(emode) 60 gw(" luma P: CAVLC(hdr+MV)=" as *u8); gn(cavlcB) 61 gw("B RANGE(residual)=" as *u8); gn(rangeB) 62 gw("B -> MV/hdr=" as *u8); gn(pctc); gw("% residual=" as *u8); gn(pctr); gw("%\n" as *u8) 63 return 0 } 64 65func main() -> i64 { 66 gw("=== nx_vcodec_bitsplit_gate: coded-P-MB bit split MV/hdr vs residual on /tmp/seq.y4m (qp=8) ===\n" as *u8) 67 let box: *i64 = sys_mmap(16) as *i64 68 let yuv: *u8 = sys_read_file("/tmp/seq.y4m" as *u8, box) 69 if (yuv as i64)==0 { gw("cannot read /tmp/seq.y4m -> RED\n" as *u8); return 1 } 70 let total: i64=box[0] 71 var hi: i64=0; while hi<total { if (yuv[hi]&0xff)==10 { break } hi=hi+1 } hi=hi+1 72 let C2: i64=(SW/2)*(SH/2); let fdata: i64=SW*SH+2*C2; let sz: i64=fdata 73 let fp: *i64=sys_mmap(128*8) as *i64 74 let nf: i64=frames(yuv, hi, total, fp, fdata) 75 if nf < NF { gw("too few frames -> RED\n" as *u8); return 1 } 76 gw(" (emode 41 = baseline no-partition; emode 169 = partition vcv-7)\n" as *u8) 77 run(fp, 8, 41, sz) 78 run(fp, 8, 41+128, sz) 79 gw("BITSPLIT: DONE\n" as *u8) 80 return 0 }