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 }