code wiki / (root) / nx_vcodec_color_wasm.nx

nx_vcodec_color_wasm.nx source

↩ module page · 108 lines · 6670 B

1// nx_vcodec_color_wasm.nx -- the BROWSER entry wrapper for the COLOR codec, fixed-offset linear-memory model 2// (mirrors nx_vcodec_wasm). wasm has NO syscalls, so every buffer is a fixed offset (no sys_mmap) and the 3// color glue (RGB<->YCbCr, 4:2:0 subsample/upsample) is inlined; the heavy lifting is the PROVEN nx_vcodec 4// engine (vc_enc/dec_frame_packed) run once per Y/Cb/Cr plane. JS only blits RGB in/out at the offsets; all 5// codec logic is sovereign nx -> nx_compile_wat -> nx_wat_compiler -> .wasm. Frame cap 128x128 (chroma 64x64). 6// license_tier: ORIGINAL 7import "nx_vcodec.nx" 8 9// ---- fixed linear-memory layout (bytes). Nmax=128*128=16384, CNmax=64*64=4096, RGBmax=49152 ---- 10const O_RGB: i64 = 0 // input RGB (interleaved), up to 49152 11const O_Y: i64 = 49152 // luma plane (16384) 12const O_CB: i64 = 65536 // full Cb (16384) 13const O_CR: i64 = 81920 // full Cr (16384) 14const O_CBS: i64 = 98304 // subsampled Cb (4096) 15const O_CRS: i64 = 102400 // subsampled Cr (4096) 16const O_PREVY: i64 = 106496 // prev recon Y (16384) 17const O_PREVCB: i64 = 122880 // prev recon Cb (4096) 18const O_PREVCR: i64 = 126976 // prev recon Cr (4096) 19const O_RECONY: i64 = 131072 // enc recon Y (16384) 20const O_RECONCB: i64 = 147456 // enc recon Cb (4096) 21const O_RECONCR: i64 = 151552 // enc recon Cr (4096) 22const O_STRY: i64 = 155648 // stream Y (16384) 23const O_STRCB: i64 = 172032 // stream Cb (8192) 24const O_STRCR: i64 = 180224 // stream Cr (8192) 25const O_DECY: i64 = 188416 // dec recon Y (16384) 26const O_DECCB: i64 = 204800 // dec recon Cb (4096) 27const O_DECCR: i64 = 208896 // dec recon Cr (4096) 28const O_DECCBU: i64 = 212992 // dec Cb upsampled (16384) 29const O_DECCRU: i64 = 229376 // dec Cr upsampled (16384) 30const O_RGBOUT: i64 = 245760 // output RGB (49152) 31const O_BLK: i64 = 294912 // 16 i64 transform scratch (128) 32const O_MV: i64 = 295040 // 2 i64 motion vector (16) 33const O_TMP: i64 = 295056 // 3 i64 color temp (24) -- end 295080 34 35func vc_clamp8(v: i64) -> i64 { if v < 0 { return 0 } if v > 255 { return 255 } return v } 36 37// encode the RGB frame at O_RGB as Y/Cb/Cr @ 4:2:0 via nx_vcodec per plane. returns total compressed bits. 38func vc_color_wasm_encode(W: i64, H: i64, qp: i64, keyframe: i64, sad: i64) -> i64 { 39 let N: i64 = W*H; let CW: i64 = W/2; let CH: i64 = H/2 40 let rgb: *u8 = (O_RGB as i64) as *u8 41 let Y: *u8 = (O_Y as i64) as *u8; let Cb: *u8 = (O_CB as i64) as *u8; let Cr: *u8 = (O_CR as i64) as *u8 42 // RGB -> YCbCr (inline BT.601 integer) 43 var i: i64 = 0 44 while i < N { 45 let r: i64 = rgb[i*3] as i64; let g: i64 = rgb[i*3+1] as i64; let b: i64 = rgb[i*3+2] as i64 46 Y[i] = vc_clamp8((77*r + 150*g + 29*b) >> 8) as u8 47 Cb[i] = vc_clamp8(((128*b - 43*r - 85*g) >> 8) + 128) as u8 48 Cr[i] = vc_clamp8(((128*r - 107*g - 21*b) >> 8) + 128) as u8 49 i = i + 1 50 } 51 // 4:2:0 box subsample (inline) 52 let Cbs: *u8 = (O_CBS as i64) as *u8; let Crs: *u8 = (O_CRS as i64) as *u8 53 var yy: i64 = 0 54 while yy < CH { var xx: i64 = 0 55 while xx < CW { 56 let cba: i64=Cb[(2*yy)*W+2*xx] as i64; let cbb: i64=Cb[(2*yy)*W+2*xx+1] as i64; let cbc: i64=Cb[(2*yy+1)*W+2*xx] as i64; let cbd: i64=Cb[(2*yy+1)*W+2*xx+1] as i64 57 Cbs[yy*CW+xx] = ((cba+cbb+cbc+cbd+2)/4) as u8 58 let cra: i64=Cr[(2*yy)*W+2*xx] as i64; let crb: i64=Cr[(2*yy)*W+2*xx+1] as i64; let crc: i64=Cr[(2*yy+1)*W+2*xx] as i64; let crd: i64=Cr[(2*yy+1)*W+2*xx+1] as i64 59 Crs[yy*CW+xx] = ((cra+crb+crc+crd+2)/4) as u8 60 xx = xx + 1 } 61 yy = yy + 1 } 62 // encode each plane via the proven engine 63 let blk: *i64 = (O_BLK as i64) as *i64; let mv: *i64 = (O_MV as i64) as *i64 64 let by: i64 = vc_enc_frame_packed(Y, (O_PREVY as i64) as *u8, (O_RECONY as i64) as *u8, W, H, qp, keyframe, sad, (O_STRY as i64) as *u8, blk, mv) 65 let bu: i64 = vc_enc_frame_packed(Cbs, (O_PREVCB as i64) as *u8, (O_RECONCB as i64) as *u8, CW, CH, qp, keyframe, sad, (O_STRCB as i64) as *u8, blk, mv) 66 let bv: i64 = vc_enc_frame_packed(Crs, (O_PREVCR as i64) as *u8, (O_RECONCR as i64) as *u8, CW, CH, qp, keyframe, sad, (O_STRCR as i64) as *u8, blk, mv) 67 return by + bu + bv 68} 69// decode the 3 plane streams -> RGB at O_RGBOUT. returns total bits consumed. 70func vc_color_wasm_decode(W: i64, H: i64, qp: i64) -> i64 { 71 let N: i64 = W*H; let CW: i64 = W/2; let CH: i64 = H/2 72 let blk: *i64 = (O_BLK as i64) as *i64; let mv: *i64 = (O_MV as i64) as *i64 73 let decY: *u8 = (O_DECY as i64) as *u8; let decCb: *u8 = (O_DECCB as i64) as *u8; let decCr: *u8 = (O_DECCR as i64) as *u8 74 let by: i64 = vc_dec_frame_packed((O_PREVY as i64) as *u8, decY, W, H, qp, (O_STRY as i64) as *u8, blk, mv) 75 let bu: i64 = vc_dec_frame_packed((O_PREVCB as i64) as *u8, decCb, CW, CH, qp, (O_STRCB as i64) as *u8, blk, mv) 76 let bv: i64 = vc_dec_frame_packed((O_PREVCR as i64) as *u8, decCr, CW, CH, qp, (O_STRCR as i64) as *u8, blk, mv) 77 // upsample chroma (replicate) 78 let decCbU: *u8 = (O_DECCBU as i64) as *u8; let decCrU: *u8 = (O_DECCRU as i64) as *u8 79 var yy: i64 = 0 80 while yy < CH { var xx: i64 = 0 81 while xx < CW { 82 let vb: i64 = decCb[yy*CW+xx] as i64; let vr: i64 = decCr[yy*CW+xx] as i64 83 decCbU[(2*yy)*W+2*xx]=vb as u8; decCbU[(2*yy)*W+2*xx+1]=vb as u8; decCbU[(2*yy+1)*W+2*xx]=vb as u8; decCbU[(2*yy+1)*W+2*xx+1]=vb as u8 84 decCrU[(2*yy)*W+2*xx]=vr as u8; decCrU[(2*yy)*W+2*xx+1]=vr as u8; decCrU[(2*yy+1)*W+2*xx]=vr as u8; decCrU[(2*yy+1)*W+2*xx+1]=vr as u8 85 xx = xx + 1 } 86 yy = yy + 1 } 87 // YCbCr -> RGB (inline inverse BT.601) 88 let rgbout: *u8 = (O_RGBOUT as i64) as *u8 89 var i: i64 = 0 90 while i < N { 91 let yv: i64 = decY[i] as i64; let d: i64 = (decCbU[i] as i64) - 128; let e: i64 = (decCrU[i] as i64) - 128 92 rgbout[i*3] = vc_clamp8(yv + ((359*e) >> 8)) as u8 93 rgbout[i*3+1] = vc_clamp8(yv - ((88*d + 183*e) >> 8)) as u8 94 rgbout[i*3+2] = vc_clamp8(yv + ((454*d) >> 8)) as u8 95 i = i + 1 96 } 97 return by + bu + bv 98} 99// offset accessors so the JS last-mile + the VM gate never hard-code addresses 100func vc_color_rgb_off() -> i64 { return O_RGB } 101func vc_color_rgbout_off() -> i64 { return O_RGBOUT } 102func vc_color_prevy_off() -> i64 { return O_PREVY } 103func vc_color_prevcb_off() -> i64 { return O_PREVCB } 104func vc_color_prevcr_off() -> i64 { return O_PREVCR } 105func vc_color_decy_off() -> i64 { return O_DECY } 106func vc_color_deccb_off() -> i64 { return O_DECCB } 107func vc_color_deccr_off() -> i64 { return O_DECCR } 108func main() -> i64 { return 0 }