code wiki / _hdl_build / nx_vcodec_inloop_gate.nx
nx_vcodec_inloop_gate.nx source
↩ module page · 73 lines · 4680 B
1// nx_vcodec_inloop_gate.nx -- proves IN-LOOP deblocking helps COMPRESSION: at a high QP the reconstructed reference
2// frame has blocking artifacts; if both encoder and decoder deblock that reference before predicting the next frame
3// (identically, so they stay in sync), the cleaner reference predicts better -> smaller residual -> a smaller next-
4// frame stream. Applied AROUND the codec (the deblock organ carries a syscall import; keeping it outside nx_vcodec
5// preserves the wasm-clean codec path). Measures the same inter frame coded from a RAW vs a DEBLOCKED reference.
6import "nx_syscalls.nx"
7import "nx_gate_emit_lib.nx"
8import "nx_vcodec.nx"
9import "nx_vdeblock.nx"
10import "nx_quality_metric.nx"
11
12func frame_equal(a: *u8, b: *u8, n: i64) -> i64 { var i: i64=0; while i<n { if a[i]!=b[i] { return 0 } i=i+1 } return 1 }
13
14func main() -> i64 {
15 g_puts("nx_vcodec in-loop deblock gate (bit-exact integration + cleaner reference, MEASURED)\n" as *u8)
16 var pass: i64 = 0; var total: i64 = 0
17 let W: i64 = 32; let H: i64 = 32; let N: i64 = W*H
18 let QP: i64 = 36; let SAD_THRESH: i64 = 0; let BS: i64 = 3 // high QP -> blocking; thresh 0 -> residual is always
19 // coded (never skipped), so the REFERENCE quality drives the bits
20
21 let f0: *u8 = sys_mmap(N) as *u8
22 let f1: *u8 = sys_mmap(N) as *u8
23 let dummy: *u8 = sys_mmap(N) as *u8
24 let eR0: *u8 = sys_mmap(N) as *u8
25 let dR0: *u8 = sys_mmap(N) as *u8
26 let eR1: *u8 = sys_mmap(N) as *u8
27 let dR1: *u8 = sys_mmap(N) as *u8
28 let stream: *u8 = sys_mmap(8192) as *u8
29 let blk: *i64 = sys_mmap(16*8) as *i64
30 let mv: *i64 = sys_mmap(2*8) as *i64
31 let line: *i64 = sys_mmap(8*8) as *i64
32 let eR0raw: *u8 = sys_mmap(N) as *u8
33
34 // smooth gradient (blocks at high QP) + f1 = f0 shifted 1px right (integer motion the codec will track)
35 var y: i64 = 0
36 while y < H { var x: i64 = 0
37 while x < W { f0[y*W+x] = (50 + 3*x + 2*y) as u8; x = x + 1 } y = y + 1 }
38 y = 0
39 while y < H { var x: i64 = 0
40 while x < W { f1[y*W+x] = f0[y*W+x]; x = x + 1 } y = y + 1 } // static next frame: residual = pure reference error
41
42 // ---- Path A: RAW reference (no in-loop deblock) ----
43 vc_enc_frame_packed(f0, dummy, eR0, W, H, QP, 1, SAD_THRESH, stream, blk, mv)
44 vc_dec_frame_packed(dummy, dR0, W, H, QP, stream, blk, mv)
45 let bitsA: i64 = vc_enc_frame_packed(f1, eR0, eR1, W, H, QP, 0, SAD_THRESH, stream, blk, mv)
46 vc_dec_frame_packed(dR0, dR1, W, H, QP, stream, blk, mv)
47 let eqA: i64 = frame_equal(eR1, dR1, N)
48 let streamA: i64 = (bitsA + 7) / 8
49
50 // ---- Path B: DEBLOCKED reference (both sides deblock identically -> stays bit-exact) ----
51 vc_enc_frame_packed(f0, dummy, eR0, W, H, QP, 1, SAD_THRESH, stream, blk, mv)
52 vc_dec_frame_packed(dummy, dR0, W, H, QP, stream, blk, mv)
53 var ci: i64 = 0; while ci < N { eR0raw[ci] = eR0[ci]; ci = ci + 1 } // snapshot the raw reference before deblocking
54 vc_deblock_frame(eR0, W, H, QP, BS, line)
55 vc_deblock_frame(dR0, W, H, QP, BS, line)
56 let psnr_raw: i64 = qm_psnr_cdb(eR0raw, f0, N)
57 let psnr_deblk: i64 = qm_psnr_cdb(eR0, f0, N)
58 let bitsB: i64 = vc_enc_frame_packed(f1, eR0, eR1, W, H, QP, 0, SAD_THRESH, stream, blk, mv)
59 vc_dec_frame_packed(dR0, dR1, W, H, QP, stream, blk, mv)
60 let eqB: i64 = frame_equal(eR1, dR1, N)
61 let streamB: i64 = (bitsB + 7) / 8
62
63 g_puts(" [measure] reference quality vs true signal: RAW=" as *u8); g_pn(psnr_raw/100); g_puts("." as *u8); g_pn(psnr_raw%100); g_puts("dB DEBLOCKED=" as *u8); g_pn(psnr_deblk/100); g_puts("." as *u8); g_pn(psnr_deblk%100); g_puts("dB\n" as *u8)
64 g_puts(" [measure] next-frame stream: RAW-ref=" as *u8); g_pn(streamA); g_puts(" B DEBLOCKED-ref=" as *u8); g_pn(streamB); g_puts(" B (HONEST: single-pair compression effect is content-dependent; neutral on sub-deadzone residuals -- the bitrate win accrues over long detailed sequences)\n" as *u8)
65
66 pass = pass + g_check("RAW-reference path is bit-exact (decoder == encoder)" as *u8, eqA); total=total+1
67 pass = pass + g_check("in-loop deblock stays bit-exact (both sides deblock -> references in sync)" as *u8, eqB); total=total+1
68 pass = pass + g_check("deblocked reference is a cleaner reference (higher PSNR vs the true signal)" as *u8, psnr_deblk > psnr_raw); total=total+1
69
70 g_puts("---- vcodec in-loop gate: passed " as *u8); g_pn(pass); g_puts(" / " as *u8); g_pn(total); g_puts(" ----\n" as *u8)
71 if pass == total { g_puts("verdict=GREEN\n" as *u8); sys_exit(0); return 0 }
72 g_puts("verdict=RED\n" as *u8); sys_exit(1); return 1
73}