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}