code wiki / _hdl_build / nx_vcodec_ltr_gate.nx

nx_vcodec_ltr_gate.nx source

↩ module page · 67 lines · 4195 B

1// nx_vcodec_ltr_gate.nx -- proves the VIDEO loss-recovery keystone: a Long-Term Reference (LTR). When frames are lost 2// across the ocean, the decoder is stuck at the last ACK'd frame (the LTR). Instead of an expensive full keyframe, the 3// encoder codes the recovery frame as a P-frame against that LTR (which the decoder still has) -> recovers WITHOUT a 4// retransmit, far cheaper than a keyframe. Cited research: LTR-P is 40-50% smaller than a keyframe; ~20% fewer keyframes 5// under loss (Meta). Our codec already predicts against an arbitrary reference, so the LTR is just the ACK'd recon. 6import "nx_syscalls.nx" 7import "nx_gate_emit_lib.nx" 8import "nx_vcodec.nx" 9 10func g_abs(v: i64) -> i64 { if v < 0 { return 0 - v } return v } 11func 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 } 12func frame_maxerr(a: *u8, b: *u8, n: i64) -> i64 { var m: i64=0; var i: i64=0; while i<n { let e: i64=g_abs((a[i] as i64)-(b[i] as i64)); if e>m { m=e } i=i+1 } return m } 13// flat backdrop + object panning 1px/frame 14func mkframe(f: *u8, W: i64, H: i64, t: i64) -> i64 { 15 var y: i64 = 0 16 while y < H { var x: i64 = 0 17 while x < W { f[y*W+x] = (40 + ((x*11 + y*7) % 120)) as u8; x = x + 1 } y = y + 1 } // TEXTURED backdrop (keyframe is expensive) 18 let sqx: i64 = 8 + t 19 var yy: i64 = 8 20 while yy < 24 { var xx: i64 = 0 21 while xx < 16 { let px: i64 = sqx + xx; if px < W { f[yy*W + px] = 240 as u8 } xx = xx + 1 } yy = yy + 1 } // bright object panning over it 22 return 0 23} 24 25func main() -> i64 { 26 g_puts("nx_vcodec LTR gate (loss recovery via Long-Term Reference, no retransmit, MEASURED)\n" as *u8) 27 var pass: i64 = 0; var total: i64 = 0 28 let W: i64 = 48; let H: i64 = 32; let N: i64 = W*H 29 let QP: i64 = 12; let SAD_THRESH: i64 = 64 30 31 let f0: *u8 = sys_mmap(N) as *u8 32 let f4: *u8 = sys_mmap(N) as *u8 33 let ltr: *u8 = sys_mmap(N) as *u8 // the ACK'd Long-Term Reference (recon of f0) both sides hold 34 let enc_r: *u8 = sys_mmap(N) as *u8 35 let dec_r: *u8 = sys_mmap(N) as *u8 36 let stream: *u8 = sys_mmap(8192) as *u8 37 let blk: *i64 = sys_mmap(16*8) as *i64 38 let mv: *i64 = sys_mmap(2*8) as *i64 39 40 mkframe(f0, W, H, 0) 41 mkframe(f4, W, H, 4) // 4 frames later (frames 1-3 were lost in transit) 42 43 // establish the LTR: keyframe f0, both sides decode + ACK it 44 vc_enc_frame_packed(f0, ltr, ltr, W, H, QP, 1, SAD_THRESH, stream, blk, mv) 45 vc_dec_frame_packed(ltr, ltr, W, H, QP, stream, blk, mv) // ltr now = the shared ACK'd reference 46 47 // --- recovery option A: a full KEYFRAME of f4 (the expensive way) --- 48 let kf_bits: i64 = vc_enc_frame_packed(f4, ltr, enc_r, W, H, QP, 1, SAD_THRESH, stream, blk, mv) 49 let kf_bytes: i64 = (kf_bits + 7) / 8 50 51 // --- recovery option B: an LTR-P frame (f4 predicted against the ACK'd LTR) --- 52 let ltr_bits: i64 = vc_enc_frame_packed(f4, ltr, enc_r, W, H, QP, 0, SAD_THRESH, stream, blk, mv) 53 let ltr_bytes: i64 = (ltr_bits + 7) / 8 54 vc_dec_frame_packed(ltr, dec_r, W, H, QP, stream, blk, mv) // decoder recovers from the LTR it still holds 55 let eq: i64 = frame_equal(enc_r, dec_r, N) 56 let q: i64 = frame_maxerr(enc_r, f4, N) 57 58 g_puts(" [measure] recover f4 after losing frames 1-3: KEYFRAME=" as *u8); g_pn(kf_bytes); g_puts(" B vs LTR-P=" as *u8); g_pn(ltr_bytes); g_puts(" B (" as *u8); g_pn((kf_bytes - ltr_bytes) * 100 / kf_bytes); g_puts("% smaller) LTR-P recon max-err=" as *u8); g_pn(q); g_puts("\n" as *u8) 59 60 pass = pass + g_check("LTR-P recovers the stream BIT-EXACT off the ACK'd reference (no retransmit)" as *u8, eq); total=total+1 61 pass = pass + g_check("LTR-P recovery is cheaper than a keyframe (the loss-recovery win)" as *u8, ltr_bytes < kf_bytes); total=total+1 62 pass = pass + g_check("reconstruction faithful (max-err <= 16)" as *u8, q <= 16); total=total+1 63 64 g_puts("---- vcodec LTR gate: passed " as *u8); g_pn(pass); g_puts(" / " as *u8); g_pn(total); g_puts(" ----\n" as *u8) 65 if pass == total { g_puts("verdict=GREEN\n" as *u8); sys_exit(0); return 0 } 66 g_puts("verdict=RED\n" as *u8); sys_exit(1); return 1 67}