code wiki / _hdl_build / nx_cam_poster_batch.nx
nx_cam_poster_batch.nx source
↩ module page · 131 lines · 6739 B
1// nx_cam_poster_batch.nx -- STEP 5 poster generator writing the <recording>-poster.jpg SIBLING that the
2// LIVE gallery serve already serves at GET /vidthumb/<id> (gs_vidthumb -> gs_poster_path -> read+serve).
3// ZERO serve change: the daemon serves the sibling the instant it exists. poster_sibling() is byte-identical
4// to the serve's gs_poster_path (truncate at the last '.', append "-poster.jpg").
5// nx_cam_poster_batch one <id> -- generate ONE recording's poster (on-demand, by catalog id)
6// nx_cam_poster_batch <start> <count> -- generate a range (idempotent skip-existing, forks 1 child/rec)
7// Forks nx_cam_poster (bounds memory: 8MiB scan + a frame, no munmap, reclaimed on child exit); skips CABAC
8// gracefully (child rc==10). Run from cwd=/volume1/ai/galx (the serve's cwd, where CATALOG resolves).
9// license_tier: ORIGINAL
10import "nx_syscalls.nx"
11const POSTER_MAGIC_1000000000: i64 = 1000000000
12const POSTER_MAGIC_2048: i64 = 2048
13
14const POSTER_ELF: *u8 = "/volume1/homes/elderwesto/nishihost/buildroot/_offc/nx_cam_poster.elf" as *u8
15const CATALOG: *u8 = "knowledge/status/galx_vid_paths.tsv" as *u8
16
17func bp_puts(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 }
18func bp_num(v: i64) -> i64 {
19 let b: *u8 = sys_mmap(28); var m: i64 = v
20 if m < 0 { m = 0 - m }
21 let t: *u8 = sys_mmap(28); var k: i64 = 0
22 if m == 0 { t[0] = 48 as u8; k = 1 }
23 while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 }
24 var i: i64 = 0
25 while i < k { b[i] = t[k-1-i]; i = i + 1 }
26 sys_write(1, b, k)
27 return 0
28}
29func bp_atoi(s: *u8) -> i64 { var v: i64 = 0; var i: i64 = 0; while s[i] != (0 as u8) { if s[i] >= (48 as u8) { if s[i] <= (57 as u8) { v = v*10 + ((s[i]-(48 as u8)) as i64) } } i = i + 1 } return v }
30func bp_streq(a: *u8, b: *u8) -> i64 { var i: i64 = 0; while a[i] != (0 as u8) { if a[i] != b[i] { return 0 } i = i + 1 } if b[i] != (0 as u8) { return 0 } return 1 }
31func bp_exists(path: *u8) -> i64 { let fd: i64 = sys_openat_rd(path); if fd < 0 { return 0 } sys_close(fd); return 1 }
32
33// byte-identical to the serve's gs_poster_path: truncate vid at its last '.', append "-poster.jpg".
34func poster_sibling(vid: *u8, out: *u8) -> i64 {
35 var nn: i64 = 0
36 while vid[nn] != (0 as u8) { nn = nn + 1 }
37 var dot: i64 = nn
38 var i: i64 = nn - 1
39 while i >= 0 { if vid[i] == (46 as u8) { if dot == nn { dot = i } } i = i - 1 }
40 var o: i64 = 0
41 var k: i64 = 0
42 while k < dot { out[o] = vid[k]; o = o + 1; k = k + 1 }
43 let suf: *u8 = "-poster.jpg" as *u8
44 var s: i64 = 0
45 while suf[s] != (0 as u8) { out[o] = suf[s]; o = o + 1; s = s + 1 }
46 out[o] = 0 as u8
47 return o
48}
49
50// fork nx_cam_poster <ts> <out>; returns child exit code (0=ok,7=partial,10=cabac,else err/sig).
51func bp_run(ts: *u8, out: *u8) -> i64 {
52 let pid: i64 = sys_fork()
53 if pid == 0 {
54 let av: *i64 = sys_mmap(8 * 4) as *i64
55 av[0] = POSTER_ELF as i64; av[1] = ts as i64; av[2] = out as i64; av[3] = 0
56 let envp: *i64 = sys_mmap(8 * 2) as *i64
57 envp[0] = "PATH=/usr/bin:/bin\x00" as *u8 as i64; envp[1] = 0
58 let dn: i64 = sys_openat_wr("/dev/null\x00" as *u8, 0x1a4)
59 if dn >= 0 { sys_dup3(dn, 1, 0) }
60 sys_execve(POSTER_ELF, av, envp)
61 sys_exit(127)
62 }
63 let st: *i64 = sys_mmap(16) as *i64
64 sys_wait4(pid, st, 0)
65 let sig: i64 = st[0] & 0x7f
66 if sig != 0 { return 128 + sig }
67 return (st[0] >> 8) & 0xff
68}
69
70func main(argc: i64, argv: *i64) -> i64 {
71 if argc < 2 { bp_puts("usage: nx_cam_poster_batch one <id> | <start> <count>\n\x00" as *u8); sys_exit(2); return 2 }
72 var single: i64 = 0
73 var oneid: i64 = 0
74 var start: i64 = 0
75 var count: i64 = POSTER_MAGIC_1000000000
76 if bp_streq(argv[1] as *u8, "one\x00" as *u8) == 1 {
77 single = 1
78 if argc >= 3 { oneid = bp_atoi(argv[2] as *u8) }
79 } else {
80 start = bp_atoi(argv[1] as *u8)
81 if argc >= 3 { count = bp_atoi(argv[2] as *u8) }
82 }
83
84 let szp: *i64 = sys_mmap(16) as *i64
85 let b: *u8 = sys_read_file(CATALOG, szp)
86 if (b as i64) == 0 { bp_puts("BATCH FAIL: no catalog\n\x00" as *u8); sys_exit(1); return 1 }
87 let sz: i64 = szp[0]
88 let endl: i64 = start + count
89 let path: *u8 = sys_mmap(POSTER_MAGIC_2048)
90 let outp: *u8 = sys_mmap(POSTER_MAGIC_2048)
91 var done: i64 = 0
92 var cabac: i64 = 0
93 var unsup: i64 = 0 // rc=3 no-SPS: unsupported container/codec (mp4/mkv). A CORRECT REFUSAL, not an error -- bucketing it as fail sends operators chasing a defect that does not exist.
94 var fail: i64 = 0
95 var skip: i64 = 0
96 var lineno: i64 = 0
97 var ls: i64 = 0
98 var i: i64 = 0
99 while i <= sz {
100 var nl: i64 = 0
101 if i == sz { nl = 1 } else { if b[i] == (10 as u8) { nl = 1 } }
102 if nl == 1 {
103 let llen: i64 = i - ls
104 if llen > 4 {
105 var inrange: i64 = 0
106 if single == 1 { if lineno == oneid { inrange = 1 } } else { if lineno >= start { if lineno < endl { inrange = 1 } } }
107 if inrange == 1 {
108 var po: i64 = 0
109 while po < llen { path[po] = b[ls + po]; po = po + 1 }
110 path[llen] = 0 as u8
111 poster_sibling(path, outp)
112 if bp_exists(outp) == 1 { skip = skip + 1 } else {
113 if bp_exists(path) == 0 { skip = skip + 1 } else {
114 let rc: i64 = bp_run(path, outp)
115 if rc == 0 { done = done + 1 } else { if rc == 10 { cabac = cabac + 1 } else { if rc == 3 { unsup = unsup + 1 } else { fail = fail + 1 } } }
116 if single == 1 { bp_puts(" id=\x00" as *u8); bp_num(oneid); bp_puts(" rec=\x00" as *u8); bp_puts(path); bp_puts("\n poster=\x00" as *u8); bp_puts(outp); bp_puts(" child_rc=\x00" as *u8); bp_num(rc); bp_puts("\n\x00" as *u8) }
117 if single == 0 { if ((done + cabac + fail) % 50) == 0 { bp_puts(" progress done=\x00" as *u8); bp_num(done); bp_puts(" cabac=\x00" as *u8); bp_num(cabac); bp_puts(" fail=\x00" as *u8); bp_num(fail); bp_puts(" at_id=\x00" as *u8); bp_num(lineno); bp_puts("\n\x00" as *u8) } }
118 }
119 }
120 }
121 }
122 lineno = lineno + 1
123 ls = i + 1
124 }
125 i = i + 1
126 }
127 bp_puts("BATCH done=\x00" as *u8); bp_num(done); bp_puts(" cabac_skipped=\x00" as *u8); bp_num(cabac); bp_puts(" unsupported_container=\x00" as *u8); bp_num(unsup)
128 bp_puts(" fail=\x00" as *u8); bp_num(fail); bp_puts(" skip_existing=\x00" as *u8); bp_num(skip); bp_puts("\n\x00" as *u8)
129 sys_exit(0)
130 return 0
131}