code wiki / (root) / nx_vid_dur_gate.nx

nx_vid_dur_gate.nx source

↩ module page · 88 lines · 6234 B

1// nx_vid_dur_gate.nx -- SOVEREIGN gate for the container-duration parsers (vd_mp4_dur / vd_mkv_dur / vd_sniff). 2// Crafts minimal mp4 + mkv byte fixtures with KNOWN durations and asserts the parsers recover them. No files, 3// no external tools -- pure in-memory byte parsing. license_tier: ORIGINAL 4import "nx_syscalls.nx" 5import "nx_vid_dur_lib.nx" 6 7func g_p(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 } 8func g_n(v: i64) -> i64 { 9 let bb: *u8 = sys_mmap(28); var m: i64 = v; if m < 0 { sys_write(1, "-" as *u8, 1); m = 0 - m } 10 let t: *u8 = sys_mmap(28); var k: i64 = 0; if m == 0 { t[0] = 48 as u8; k = 1 } 11 while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 } 12 var i: i64 = 0; while i < k { bb[i] = t[k - 1 - i]; i = i + 1 } sys_write(1, bb, k); return 0 13} 14func g_eq(label: *u8, got: i64, want: i64, pass: *i64, fail: *i64) -> i64 { 15 if got == want { pass[0] = pass[0] + 1; g_p(" ok " as *u8); g_p(label); g_p("\n" as *u8) } 16 else { fail[0] = fail[0] + 1; g_p(" FAIL " as *u8); g_p(label); g_p(" got=" as *u8); g_n(got); g_p(" want=" as *u8); g_n(want); g_p("\n" as *u8) } 17 return 0 18} 19func g_str(buf: *u8, off: i64, s: *u8) -> i64 { var i: i64 = 0; while s[i] != (0 as u8) { buf[off + i] = s[i]; i = i + 1 } return off + i } 20 21func main(argc: i64, argv: *i64) -> i64 { 22 let pass: *i64 = sys_mmap(16) as *i64; pass[0] = 0 23 let fail: *i64 = sys_mmap(16) as *i64; fail[0] = 0 24 25 // ---- MP4 fixture: "ftypisom" + "mvhd" + v0(timescale=1000, duration=120000) -> 120000 ms ---- 26 let mp4: *u8 = sys_mmap(128) 27 var o: i64 = g_str(mp4, 0, "ftypisommvhd" as *u8) // ftyp (sniff) + mvhd at offset 8 28 // version(1)+flags(3) = 0 29 mp4[o]=0 as u8; mp4[o+1]=0 as u8; mp4[o+2]=0 as u8; mp4[o+3]=0 as u8; o=o+4 30 // creation(4)+modification(4) = 0 31 var z: i64 = 0; while z < 8 { mp4[o]=0 as u8; o=o+1; z=z+1 } 32 // timescale = 1000 = 00 00 03 E8 33 mp4[o]=0 as u8; mp4[o+1]=0 as u8; mp4[o+2]=0x03 as u8; mp4[o+3]=0xE8 as u8; o=o+4 34 // duration = 120000 = 00 01 D4 C0 35 mp4[o]=0 as u8; mp4[o+1]=0x01 as u8; mp4[o+2]=0xD4 as u8; mp4[o+3]=0xC0 as u8; o=o+4 36 g_eq("mp4 sniff=1" as *u8, vd_sniff(mp4, o), 1, pass, fail) 37 g_eq("mp4 dur=120000" as *u8, vd_mp4_dur(mp4, o), 120000, pass, fail) 38 39 // second mp4: timescale=600, duration=27000 -> 27000*1000/600 = 45000 ms (proves not hardcoded) 40 let mp4b: *u8 = sys_mmap(128) 41 var ob: i64 = g_str(mp4b, 0, "moovmvhd" as *u8) 42 mp4b[ob]=0 as u8; mp4b[ob+1]=0 as u8; mp4b[ob+2]=0 as u8; mp4b[ob+3]=0 as u8; ob=ob+4 43 var z2: i64 = 0; while z2 < 8 { mp4b[ob]=0 as u8; ob=ob+1; z2=z2+1 } 44 mp4b[ob]=0 as u8; mp4b[ob+1]=0 as u8; mp4b[ob+2]=0x02 as u8; mp4b[ob+3]=0x58 as u8; ob=ob+4 // 600 45 mp4b[ob]=0 as u8; mp4b[ob+1]=0 as u8; mp4b[ob+2]=0x69 as u8; mp4b[ob+3]=0x78 as u8; ob=ob+4 // 27000 46 g_eq("mp4b dur=45000" as *u8, vd_mp4_dur(mp4b, ob), 45000, pass, fail) 47 48 // ---- MKV fixture: EBML magic + TimecodeScale(1000000) + Duration(double 120000.0) -> 120000 ms ---- 49 let mkv: *u8 = sys_mmap(128); var mo: i64 = 0 50 mkv[mo]=0x1A as u8; mkv[mo+1]=0x45 as u8; mkv[mo+2]=0xDF as u8; mkv[mo+3]=0xA3 as u8; mo=mo+4 // EBML magic 51 mkv[mo]=0x2A as u8; mkv[mo+1]=0xD7 as u8; mkv[mo+2]=0xB1 as u8; mkv[mo+3]=0x83 as u8; mo=mo+4 // TimecodeScale id + size=3 52 mkv[mo]=0x0F as u8; mkv[mo+1]=0x42 as u8; mkv[mo+2]=0x40 as u8; mo=mo+3 // 1000000 53 mkv[mo]=0x44 as u8; mkv[mo+1]=0x89 as u8; mkv[mo+2]=0x88 as u8; mo=mo+3 // Duration id + size=8 54 mkv[mo]=0x40 as u8; mkv[mo+1]=0xFD as u8; mkv[mo+2]=0x4C as u8; mkv[mo+3]=0 as u8 // double 120000.0 55 mkv[mo+4]=0 as u8; mkv[mo+5]=0 as u8; mkv[mo+6]=0 as u8; mkv[mo+7]=0 as u8; mo=mo+8 56 g_eq("mkv sniff=2" as *u8, vd_sniff(mkv, mo), 2, pass, fail) 57 g_eq("mkv dur=120000" as *u8, vd_mkv_dur(mkv, mo), 120000, pass, fail) 58 59 // sanity: the IEEE decoders on a known small value (45000.0 double = 40 E5 F9 00 00 00 00 00) 60 let f: *u8 = sys_mmap(16) 61 f[0]=0x40 as u8; f[1]=0xE5 as u8; f[2]=0xF9 as u8; f[3]=0 as u8; f[4]=0 as u8; f[5]=0 as u8; f[6]=0 as u8; f[7]=0 as u8 62 g_eq("ieee64 45000.0" as *u8, vd_ieee64(f, 0), 45000, pass, fail) 63 64 // ---- >24h REJECT GUARD: a false 4-byte "mvhd" / 3-byte "44 89 8x" match in a multi-MB window decodes 65 // garbage into a huge duration. A real recording is never >24h, so the parsers must return -1, not a bogus 66 // runtime that sorts/badges as the "longest" video. mp4: timescale=1000, duration=90000000 -> 25h. 67 let mp4c: *u8 = sys_mmap(128) 68 var oc: i64 = g_str(mp4c, 0, "moovmvhd" as *u8) 69 mp4c[oc]=0 as u8; mp4c[oc+1]=0 as u8; mp4c[oc+2]=0 as u8; mp4c[oc+3]=0 as u8; oc=oc+4 70 var z3: i64 = 0; while z3 < 8 { mp4c[oc]=0 as u8; oc=oc+1; z3=z3+1 } 71 mp4c[oc]=0 as u8; mp4c[oc+1]=0 as u8; mp4c[oc+2]=0x03 as u8; mp4c[oc+3]=0xE8 as u8; oc=oc+4 // 1000 72 mp4c[oc]=0x05 as u8; mp4c[oc+1]=0x5D as u8; mp4c[oc+2]=0x4A as u8; mp4c[oc+3]=0x80 as u8; oc=oc+4 // 90000000 73 g_eq("mp4 >24h rejected=-1" as *u8, vd_mp4_dur(mp4c, oc), 0-1, pass, fail) 74 75 // mkv: TimecodeScale=1000000, Duration=double 90000000.0 (41 95 75 2A 00 00 00 00) -> 25h. 76 let mkv2: *u8 = sys_mmap(128); var m2: i64 = 0 77 mkv2[m2]=0x1A as u8; mkv2[m2+1]=0x45 as u8; mkv2[m2+2]=0xDF as u8; mkv2[m2+3]=0xA3 as u8; m2=m2+4 78 mkv2[m2]=0x2A as u8; mkv2[m2+1]=0xD7 as u8; mkv2[m2+2]=0xB1 as u8; mkv2[m2+3]=0x83 as u8; m2=m2+4 79 mkv2[m2]=0x0F as u8; mkv2[m2+1]=0x42 as u8; mkv2[m2+2]=0x40 as u8; m2=m2+3 // 1000000 80 mkv2[m2]=0x44 as u8; mkv2[m2+1]=0x89 as u8; mkv2[m2+2]=0x88 as u8; m2=m2+3 // Duration size=8 81 mkv2[m2]=0x41 as u8; mkv2[m2+1]=0x95 as u8; mkv2[m2+2]=0x75 as u8; mkv2[m2+3]=0x2A as u8 // double 90000000.0 82 mkv2[m2+4]=0 as u8; mkv2[m2+5]=0 as u8; mkv2[m2+6]=0 as u8; mkv2[m2+7]=0 as u8; m2=m2+8 83 g_eq("mkv >24h rejected=-1" as *u8, vd_mkv_dur(mkv2, m2), 0-1, pass, fail) 84 85 g_p("\nvid_dur gate pass=" as *u8); g_n(pass[0]); g_p(" fail=" as *u8); g_n(fail[0]); g_p("\n" as *u8) 86 if fail[0] == 0 { g_p("GREEN\n" as *u8); sys_exit(0) } else { g_p("RED\n" as *u8); sys_exit(1) } 87 return 0 88}