code wiki / _hdl_build / nx_caption_burn_gate.nx

nx_caption_burn_gate.nx source

↩ module page · 111 lines · 5538 B

1// nx_caption_burn_gate.nx -- proves the live-translation RENDER vertical end-to-end, NO fake green: 2// EN caption -> nx_mt_phrasetable EN->ES -> nx_caption_burn burns it onto a 320x180 "video" frame. 3// Rows: (1) caption active at t=1000ms, (2) burn sets text pixels, (3) the bottom bar is drawn (bar color), 4// (4) the VIDEO area above the bar is PRESERVED (caption doesn't clobber the frame), (5) neg-control: at 5// t=5000ms NO caption is active (cb_active_at=-1) so nothing burns -> the bar region stays video-colored. 6// Eyeball -> knowledge/nx_caption_burn.png. expect_exit: 0 license_tier: ORIGINAL 7import "nx_syscalls.nx" 8import "nx_css_color_decode.nx" 9import "nx_paint_solid_rect.nx" 10import "nx_font_bitmap_5x7.nx" 11import "nx_paint_text.nx" 12import "nx_caption_burn.nx" 13import "nx_mt_phrasetable.nx" 14import "nx_png_write.nx" 15import "nx_gate_verdict.nx" 16 17func cg(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 } 18func cgn(v: i64) -> i64 { 19 if v == 0 { sys_write(1, "0" as *u8, 1); return 0 } 20 var m: i64 = v; if m < 0 { sys_write(1, "-" as *u8, 1); m = 0 - m } 21 let d: *u8 = sys_mmap(24); var k: i64 = 0 22 while m > 0 { d[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 } 23 var j: i64 = k - 1 24 while j >= 0 { sys_write(1, ((d as i64)+j) as *u8, 1); j = j - 1 } 25 return 0 26} 27func px_is(p: *CssColor, r: i64, g: i64, b: i64) -> i64 { if p.r==r { if p.g==g { if p.b==b { return 1 } } } return 0 } 28 29func main() -> i64 { 30 cg("=== nx_caption_burn_gate: EN caption -> phrase-table ES -> burn onto a video frame ===\n" as *u8) 31 let w: i64 = 320 32 let h: i64 = 180 33 let pixels: *u8 = sys_mmap(w * h * 4) 34 let fb: *Framebuffer = sys_mmap(NX_FRAMEBUFFER_BYTES) as *Framebuffer 35 nx_framebuffer_init(fb, pixels, w, h) 36 nx_framebuffer_clear(fb) 37 38 let vid: *CssColor = sys_mmap(NX_CSS_COLOR_BYTES) as *CssColor 39 vid.r=40; vid.g=60; vid.b=90; vid.a=255 40 nx_paint_solid_rect(fb, 0, 0, w, h, vid) 41 42 let bar: *CssColor = sys_mmap(NX_CSS_COLOR_BYTES) as *CssColor 43 bar.r=0; bar.g=0; bar.b=0; bar.a=255 44 let fg: *CssColor = sys_mmap(NX_CSS_COLOR_BYTES) as *CssColor 45 fg.r=255; fg.g=255; fg.b=0; fg.a=255 46 let probe: *CssColor = sys_mmap(NX_CSS_COLOR_BYTES) as *CssColor 47 48 // translate the EN caption -> ES 49 let src: *u8 = "HELLO FRIEND WELCOME" as *u8 50 var sn: i64 = 0 51 while src[sn] != (0 as u8) { sn = sn + 1 } 52 let es: *u8 = sys_mmap(256) 53 let esn: i64 = nx_mt_translate(src, sn, es, 256) 54 cg(" EN='" as *u8); sys_write(1, src, sn); cg("' -> ES='" as *u8); sys_write(1, es, esn); cg("'\n" as *u8) 55 56 // caption track: one segment [0,2000)ms 57 let t0: *i64 = sys_mmap(8) as *i64 58 let t1: *i64 = sys_mmap(8) as *i64 59 t0[0]=0; t1[0]=2000 60 61 var pass: i64 = 0 62 var fail: i64 = 0 63 64 // ROW1: active at t=1000ms 65 if cb_active_at(t0, t1, 1, 1000) == 0 { pass=pass+1; cg(" ROW active@1000ms: GREEN\n" as *u8) } else { fail=fail+1; cg(" ROW active@1000ms: RED\n" as *u8) } 66 67 // ROW2: burn sets text pixels 68 let set1: i64 = nx_caption_burn(fb, es, esn, 2, bar, fg) 69 if set1 > 0 { pass=pass+1; cg(" ROW burn-paints-text: GREEN (" as *u8); cgn(set1); cg(" px)\n" as *u8) } else { fail=fail+1; cg(" ROW burn-paints-text: RED\n" as *u8) } 70 71 // ROW3: the bottom bar is drawn (bar color at far-left of the bar row) 72 nx_framebuffer_get_pixel(fb, 3, h - 3, probe) 73 if px_is(probe,0,0,0)==1 { pass=pass+1; cg(" ROW bar-drawn: GREEN\n" as *u8) } else { fail=fail+1; cg(" ROW bar-drawn: RED\n" as *u8) } 74 75 // ROW4: the video area above the bar is preserved 76 nx_framebuffer_get_pixel(fb, 3, 3, probe) 77 if px_is(probe,40,60,90)==1 { pass=pass+1; cg(" ROW video-preserved: GREEN\n" as *u8) } else { fail=fail+1; cg(" ROW video-preserved: RED\n" as *u8) } 78 79 // ROW5 neg-control: reset frame; at t=5000ms NO caption active -> we DON'T burn -> bar region stays video 80 nx_paint_solid_rect(fb, 0, 0, w, h, vid) 81 let a2: i64 = cb_active_at(t0, t1, 1, 5000) 82 if a2 == (0 - 1) { 83 nx_framebuffer_get_pixel(fb, w / 2, h - 3, probe) 84 if px_is(probe,40,60,90)==1 { pass=pass+1; cg(" ROW neg-control no-caption-no-burn: GREEN\n" as *u8) } else { fail=fail+1; cg(" ROW neg-control leaked a caption: RED\n" as *u8) } 85 } else { fail=fail+1; cg(" ROW neg-control: RED (claimed a caption active at 5000ms)\n" as *u8) } 86 87 // re-render the active caption for the eyeball image 88 nx_paint_solid_rect(fb, 0, 0, w, h, vid) 89 nx_caption_burn(fb, es, esn, 2, bar, fg) 90 let rgb: *u8 = sys_mmap(w * h * 3) 91 var i: i64 = 0 92 while i < w * h { 93 rgb[i*3+0] = pixels[i*4+0] 94 rgb[i*3+1] = pixels[i*4+1] 95 rgb[i*3+2] = pixels[i*4+2] 96 i = i + 1 97 } 98 nx_png_write_rgb("knowledge/nx_caption_burn.png" as *u8, rgb, w, h) 99 cg(" eyeball -> knowledge/nx_caption_burn.png\n" as *u8) 100 101 cg("CAPTION-BURN-GATE pass=" as *u8); cgn(pass); cg(" fail=" as *u8); cgn(fail) 102 // MIGRATED onto nx_gate_verdict by nx_gate_dry_apply (D001, minimal form): every check 103 // row above is untouched, so the PASS/FAIL vector cannot change; only the hand-rolled 104 // verdict emission is replaced by the ONE shared base class. Proven by nx_gate_migrate verify. 105 let ctr__dry: *i64 = gv_ctr() 106 ctr__dry[0] = pass 107 ctr__dry[1] = pass + fail 108 let rc__dry: i64 = gv_verdict("CAPTION-BURN-GATE" as *u8, ctr__dry, "EN->ES translate -> caption burned onto the frame; video preserved; neg-control clean" as *u8) 109 sys_exit(rc__dry) 110 return rc__dry 111}