nx_uxf_ebml_test.nx source
↩ module page · 98 lines · 5253 B
1// nx_uxf_ebml_test.nx -- UXF arc #2 (real remux), rung 2: the EBML/Matroska parser primitive --
2// the INPUT side of an MKV->MP4 remux. MKV is an EBML document: a tree of elements
3// [element-ID (vint, marker KEPT)][size (vint, marker STRIPPED)][data].
4// A vint's first byte encodes its length: leading-zero count + 1 (the first 1-bit is the marker).
5// This builds vint length + ID read + size read, and KAT-proves them on the real EBML magic header
6// (0x1A45DFA3) + a size vint, plus a malformed-vint neg-control.
7//
8// HONEST SCOPE: this is the EBML element primitive (read IDs/sizes -> walk MKV structure). Mapping
9// MKV tracks/codec-private/SimpleBlock frames into MP4 sample tables (the actual rewrap) is the next
10// rung. No hardware writes (Rule 26). expect_exit: 0 license_tier: ORIGINAL
11import "nx_syscalls.nx"
12
13func e_puts(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 }
14func e_putn(v: i64) -> i64 { let bb: *u8 = sys_mmap(28); var m: i64 = v; if m < 0 { m = 0 - m; sys_write(1, "-" as *u8, 1) } let t: *u8 = sys_mmap(28); var k: i64 = 0; if m == 0 { t[0] = 48 as u8; k = 1 } while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 } var i: i64 = 0; while i < k { bb[i] = t[k - 1 - i]; i = i + 1 } sys_write(1, bb, k); return 0 }
15
16// vint byte-length from the first byte: leading-zero count + 1; 0 = invalid (no marker bit).
17func ebml_vint_len(b: i64) -> i64 {
18 if b >= 0x80 { return 1 }
19 if b >= 0x40 { return 2 }
20 if b >= 0x20 { return 3 }
21 if b >= 0x10 { return 4 }
22 if b >= 0x08 { return 5 }
23 if b >= 0x04 { return 6 }
24 if b >= 0x02 { return 7 }
25 if b >= 0x01 { return 8 }
26 return 0
27}
28
29// read an element ID at pos (marker bit KEPT = raw big-endian bytes); advance pos; -1 if invalid.
30func ebml_read_id(buf: *u8, pos: *i64) -> i64 {
31 let p: i64 = pos[0]
32 let len: i64 = ebml_vint_len(buf[p] as i64)
33 if len == 0 { return 0 - 1 }
34 var v: i64 = 0
35 var i: i64 = 0
36 while i < len { v = (v * 256) + (buf[p + i] as i64); i = i + 1 }
37 pos[0] = p + len
38 return v
39}
40
41// read a size at pos (marker bit STRIPPED from the first byte); advance pos; -1 if invalid.
42func ebml_read_size(buf: *u8, pos: *i64) -> i64 {
43 let p: i64 = pos[0]
44 let len: i64 = ebml_vint_len(buf[p] as i64)
45 if len == 0 { return 0 - 1 }
46 var v: i64 = (buf[p] as i64) & (255 >> len)
47 var i: i64 = 1
48 while i < len { v = (v * 256) + (buf[p + i] as i64); i = i + 1 }
49 pos[0] = p + len
50 return v
51}
52
53func main() -> i64 {
54 e_puts("#2 rung-2 EBML/MKV PARSER PRIMITIVE -- vint + element ID/size, KAT on real EBML header\n" as *u8)
55 // EBML magic ID 0x1A45DFA3 | size vint 0x84 (=4) | 4 data bytes
56 let buf: *u8 = sys_mmap(64)
57 buf[0] = 0x1A as u8; buf[1] = 0x45 as u8; buf[2] = 0xDF as u8; buf[3] = 0xA3 as u8
58 buf[4] = 0x84 as u8
59 buf[5] = 0xDE as u8; buf[6] = 0xAD as u8; buf[7] = 0xBE as u8; buf[8] = 0xEF as u8
60
61 var pass: i64 = 0
62 var ttl: i64 = 0
63
64 // T1: vint length of 0x1A is 4 (the EBML magic is a 4-byte vint)
65 ttl = ttl + 1; e_puts(" T1 vint_len(0x1A)==4: " as *u8); if ebml_vint_len(0x1A) == 4 { pass = pass + 1; e_puts("PASS\n" as *u8) } else { e_puts("FAIL\n" as *u8) }
66
67 // T2: read the EBML magic ID (marker kept) == 0x1A45DFA3 (=440786851); pos advances to 4
68 let pos: *i64 = sys_mmap(8) as *i64
69 pos[0] = 0
70 let id: i64 = ebml_read_id(buf, pos)
71 ttl = ttl + 1; e_puts(" T2 read_id==0x1A45DFA3 (got " as *u8); e_putn(id); e_puts(" pos=" as *u8); e_putn(pos[0]); e_puts("): " as *u8)
72 if id == 440786851 { if pos[0] == 4 { pass = pass + 1; e_puts("PASS\n" as *u8) } else { e_puts("FAIL\n" as *u8) } } else { e_puts("FAIL\n" as *u8) }
73
74 // T3: read the size vint (marker stripped) == 4; pos advances to 5
75 let sz: i64 = ebml_read_size(buf, pos)
76 ttl = ttl + 1; e_puts(" T3 read_size==4 (got " as *u8); e_putn(sz); e_puts(" pos=" as *u8); e_putn(pos[0]); e_puts("): " as *u8)
77 if sz == 4 { if pos[0] == 5 { pass = pass + 1; e_puts("PASS\n" as *u8) } else { e_puts("FAIL\n" as *u8) } } else { e_puts("FAIL\n" as *u8) }
78
79 // T4: vint_len across the length classes (1..8)
80 ttl = ttl + 1
81 var ok4: i64 = 1
82 if ebml_vint_len(0x80) != 1 { ok4 = 0 }
83 if ebml_vint_len(0x40) != 2 { ok4 = 0 }
84 if ebml_vint_len(0x20) != 3 { ok4 = 0 }
85 if ebml_vint_len(0x10) != 4 { ok4 = 0 }
86 if ebml_vint_len(0x08) != 5 { ok4 = 0 }
87 if ebml_vint_len(0x04) != 6 { ok4 = 0 }
88 if ebml_vint_len(0x02) != 7 { ok4 = 0 }
89 if ebml_vint_len(0x01) != 8 { ok4 = 0 }
90 e_puts(" T4 vint_len classes 1..8: " as *u8); if ok4 == 1 { pass = pass + 1; e_puts("PASS\n" as *u8) } else { e_puts("FAIL\n" as *u8) }
91
92 // T5 neg-control: a malformed vint (first byte 0x00, no marker) is rejected
93 ttl = ttl + 1; e_puts(" T5 neg vint_len(0x00)==0: " as *u8); if ebml_vint_len(0x00) == 0 { pass = pass + 1; e_puts("PASS\n" as *u8) } else { e_puts("FAIL\n" as *u8) }
94
95 e_puts("UXF-EBML-GATE passed " as *u8); e_putn(pass); e_puts("/" as *u8); e_putn(ttl)
96 if pass == ttl { e_puts(" verdict=GREEN (EBML element primitive; MKV-track->MP4-sample-table = downstream)\n" as *u8); sys_exit(0); return 0 }
97 e_puts(" verdict=RED\n" as *u8); sys_exit(1); return 1
98}