code wiki / _hdl_build / nx_caption_burn_gate.nx
nx_caption_burn_gate.nx source
↩ module page · 103 lines · 5149 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"
15
16func cg(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 }
17func cgn(v: i64) -> i64 {
18 if v == 0 { sys_write(1, "0" as *u8, 1); return 0 }
19 var m: i64 = v; if m < 0 { sys_write(1, "-" as *u8, 1); m = 0 - m }
20 let d: *u8 = sys_mmap(24); var k: i64 = 0
21 while m > 0 { d[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 }
22 var j: i64 = k - 1
23 while j >= 0 { sys_write(1, ((d as i64)+j) as *u8, 1); j = j - 1 }
24 return 0
25}
26func 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 }
27
28func main() -> i64 {
29 cg("=== nx_caption_burn_gate: EN caption -> phrase-table ES -> burn onto a video frame ===\n" as *u8)
30 let w: i64 = 320
31 let h: i64 = 180
32 let pixels: *u8 = sys_mmap(w * h * 4)
33 let fb: *Framebuffer = sys_mmap(NX_FRAMEBUFFER_BYTES) as *Framebuffer
34 nx_framebuffer_init(fb, pixels, w, h)
35 nx_framebuffer_clear(fb)
36
37 let vid: *CssColor = sys_mmap(NX_CSS_COLOR_BYTES) as *CssColor
38 vid.r=40; vid.g=60; vid.b=90; vid.a=255
39 nx_paint_solid_rect(fb, 0, 0, w, h, vid)
40
41 let bar: *CssColor = sys_mmap(NX_CSS_COLOR_BYTES) as *CssColor
42 bar.r=0; bar.g=0; bar.b=0; bar.a=255
43 let fg: *CssColor = sys_mmap(NX_CSS_COLOR_BYTES) as *CssColor
44 fg.r=255; fg.g=255; fg.b=0; fg.a=255
45 let probe: *CssColor = sys_mmap(NX_CSS_COLOR_BYTES) as *CssColor
46
47 // translate the EN caption -> ES
48 let src: *u8 = "HELLO FRIEND WELCOME" as *u8
49 var sn: i64 = 0
50 while src[sn] != (0 as u8) { sn = sn + 1 }
51 let es: *u8 = sys_mmap(256)
52 let esn: i64 = nx_mt_translate(src, sn, es, 256)
53 cg(" EN='" as *u8); sys_write(1, src, sn); cg("' -> ES='" as *u8); sys_write(1, es, esn); cg("'\n" as *u8)
54
55 // caption track: one segment [0,2000)ms
56 let t0: *i64 = sys_mmap(8) as *i64
57 let t1: *i64 = sys_mmap(8) as *i64
58 t0[0]=0; t1[0]=2000
59
60 var pass: i64 = 0
61 var fail: i64 = 0
62
63 // ROW1: active at t=1000ms
64 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) }
65
66 // ROW2: burn sets text pixels
67 let set1: i64 = nx_caption_burn(fb, es, esn, 2, bar, fg)
68 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) }
69
70 // ROW3: the bottom bar is drawn (bar color at far-left of the bar row)
71 nx_framebuffer_get_pixel(fb, 3, h - 3, probe)
72 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) }
73
74 // ROW4: the video area above the bar is preserved
75 nx_framebuffer_get_pixel(fb, 3, 3, probe)
76 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) }
77
78 // ROW5 neg-control: reset frame; at t=5000ms NO caption active -> we DON'T burn -> bar region stays video
79 nx_paint_solid_rect(fb, 0, 0, w, h, vid)
80 let a2: i64 = cb_active_at(t0, t1, 1, 5000)
81 if a2 == (0 - 1) {
82 nx_framebuffer_get_pixel(fb, w / 2, h - 3, probe)
83 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) }
84 } else { fail=fail+1; cg(" ROW neg-control: RED (claimed a caption active at 5000ms)\n" as *u8) }
85
86 // re-render the active caption for the eyeball image
87 nx_paint_solid_rect(fb, 0, 0, w, h, vid)
88 nx_caption_burn(fb, es, esn, 2, bar, fg)
89 let rgb: *u8 = sys_mmap(w * h * 3)
90 var i: i64 = 0
91 while i < w * h {
92 rgb[i*3+0] = pixels[i*4+0]
93 rgb[i*3+1] = pixels[i*4+1]
94 rgb[i*3+2] = pixels[i*4+2]
95 i = i + 1
96 }
97 nx_png_write_rgb("knowledge/nx_caption_burn.png" as *u8, rgb, w, h)
98 cg(" eyeball -> knowledge/nx_caption_burn.png\n" as *u8)
99
100 cg("CAPTION-BURN-GATE pass=" as *u8); cgn(pass); cg(" fail=" as *u8); cgn(fail)
101 if fail == 0 { cg(" verdict=GREEN -- EN->ES translate -> caption burned onto the frame; video preserved; neg-control clean\n" as *u8); sys_exit(0); return 0 }
102 cg(" verdict=RED\n" as *u8); sys_exit(1); return 1
103}