nx_jpeg_decode_image_test.nx source
↩ module page · 162 lines · 6755 B
1// nx_jpeg_decode_image_test.nx -- KAT for the top-level image
2// decoder. Minimal 8x8 grayscale: 1 component, 1 MCU, 1 block.
3//
4// Bitstream: DC category 0 + AC EOB = "0 0" packed MSB-first = 0x00.
5// All coefficients zero -> IDCT all zeros -> level shift -> 128.
6// Expected output plane: 8x8 of 128.
7//
8// expect_exit: 0
9// license_tier: ORIGINAL
10
11import "nx_syscalls.nx"
12import "nx_jpeg_sof.nx"
13import "nx_jpeg_sos.nx"
14import "nx_jpeg_dqt.nx"
15import "nx_jpeg_dht.nx"
16import "nx_jpeg_mcu.nx"
17import "nx_jpeg_decode_image.nx"
18
19func _fail(n: i64) -> i64 {
20 let b: *u8 = sys_mmap(16)
21 b[0]=0x46; b[1]=0x41; b[2]=0x49; b[3]=0x4C; b[4]=0x3D
22 sys_write(2, b, 5)
23 var x: i64 = n
24 if x < 0 { let m: *u8 = sys_mmap(4); m[0]=0x2D; sys_write(2, m, 1); x = 0 - x }
25 if x == 0 { let z: *u8 = sys_mmap(4); z[0]=0x30; sys_write(2, z, 1) }
26 else {
27 let buf: *u8 = sys_mmap(16)
28 var pos: i64 = 0
29 while x > 0 { buf[pos] = (0x30 + (x % 10)) as u8; x = x / 10; pos = pos + 1 }
30 let out: *u8 = sys_mmap(16)
31 var i: i64 = 0
32 while i < pos { out[i] = buf[pos - 1 - i]; i = i + 1 }
33 sys_write(2, out, pos)
34 }
35 let nl: *u8 = sys_mmap(4); nl[0]=0x0A; sys_write(2, nl, 1)
36 return 0
37}
38
39func main() -> i64 {
40 // ============================================================
41 // Build SOF: 1 component, 8x8, P=8, Y=8, X=8, comp{id=1, H=V=1, Tq=0}
42 // ============================================================
43 let sof_payload: *u8 = sys_mmap(16)
44 sof_payload[0] = 8
45 sof_payload[1] = 0; sof_payload[2] = 8 // Y=8
46 sof_payload[3] = 0; sof_payload[4] = 8 // X=8
47 sof_payload[5] = 1 // Nf=1
48 sof_payload[6] = 1; sof_payload[7] = 0x11; sof_payload[8] = 0
49
50 let frame: *NxJpegFrame = sys_mmap(NX_JPEG_FRAME_BYTES) as *NxJpegFrame
51 let sof_comps: *NxJpegSofComponent = sys_mmap(NX_JPEG_SOF_COMP_BYTES * 4) as *NxJpegSofComponent
52 frame.components = sof_comps
53 if nx_jpeg_sof_parse(sof_payload, 9, frame) != NX_JPEG_SOF_OK { _fail(1); return 1 }
54
55 // ============================================================
56 // Build SOS: 1 component, Cs=1, Td=0 Ta=0, Ss=0 Se=63 AhAl=0
57 // ============================================================
58 let sos_payload: *u8 = sys_mmap(16)
59 sos_payload[0] = 1
60 sos_payload[1] = 1; sos_payload[2] = 0x00
61 sos_payload[3] = 0; sos_payload[4] = 63; sos_payload[5] = 0
62
63 let scan: *NxJpegScan = sys_mmap(NX_JPEG_SCAN_BYTES) as *NxJpegScan
64 let sos_comps: *NxJpegSosComponent = sys_mmap(NX_JPEG_SOS_COMP_BYTES * 4) as *NxJpegSosComponent
65 scan.components = sos_comps
66 if nx_jpeg_sos_parse(sos_payload, 6, scan) != NX_JPEG_SOS_OK { _fail(2); return 2 }
67
68 // ============================================================
69 // Build DQT: 1 table, Tq=0 Pq=0, all 64 values = 1 (identity)
70 // ============================================================
71 let dqt_payload: *u8 = sys_mmap(128)
72 dqt_payload[0] = 0
73 var i: i64 = 0
74 while i < 64 { dqt_payload[1 + i] = 1; i = i + 1 }
75
76 let qtables: *NxJpegQTable = sys_mmap(NX_JPEG_QTABLE_BYTES * 4) as *NxJpegQTable
77 let qvalue_bufs: *i64 = sys_mmap(4 * 64 * 8) as *i64
78 let qcount_p: *i64 = sys_mmap(8) as *i64
79 if nx_jpeg_dqt_parse(dqt_payload, 65, qtables, qvalue_bufs, qcount_p) != NX_JPEG_DQT_OK { _fail(3); return 3 }
80 if qcount_p[0] != 1 { _fail(4); return 4 }
81
82 // ============================================================
83 // Build DHT: 2 tables stacked (DC tc=0/th=0, AC tc=1/th=0)
84 // DC BITS={1,0...}, HUFFVAL={0} -> sym 0 = "0"
85 // AC BITS={1,0...}, HUFFVAL={0x00} -> sym 0 = "0" EOB
86 // ============================================================
87 let dht_payload: *u8 = sys_mmap(128)
88 dht_payload[0] = 0x00 // DC tc=0 th=0
89 dht_payload[1] = 1
90 i = 2
91 while i <= 16 { dht_payload[i] = 0; i = i + 1 }
92 dht_payload[17] = 0
93 dht_payload[18] = 0x10 // AC tc=1 th=0
94 dht_payload[19] = 1
95 i = 20
96 while i <= 34 { dht_payload[i] = 0; i = i + 1 }
97 dht_payload[35] = 0x00
98
99 let htables: *NxJpegHTable = sys_mmap(NX_JPEG_HTABLE_BYTES * 4) as *NxJpegHTable
100 let hbits: *i64 = sys_mmap(4 * 17 * 8) as *i64
101 let hhv: *i64 = sys_mmap(4 * 256 * 8) as *i64
102 let hmc: *i64 = sys_mmap(4 * 17 * 8) as *i64
103 let hxc: *i64 = sys_mmap(4 * 17 * 8) as *i64
104 let hvp: *i64 = sys_mmap(4 * 17 * 8) as *i64
105 let hcount_p: *i64 = sys_mmap(8) as *i64
106 if nx_jpeg_dht_parse(dht_payload, 36, htables, hbits, hhv, hmc, hxc, hvp, hcount_p) != NX_JPEG_DHT_OK { _fail(5); return 5 }
107 if hcount_p[0] != 2 { _fail(6); return 6 }
108
109 // ============================================================
110 // Entropy bytes: 0x00 = "0 0" = DC cat 0 + AC EOB
111 // ============================================================
112 let ent: *u8 = sys_mmap(8)
113 ent[0] = 0x00
114 ent[1] = 0x00
115
116 let bs: *NxJpegBitStream = sys_mmap(NX_JPEG_BITSTREAM_BYTES) as *NxJpegBitStream
117 bs.src = ent
118 bs.src_end = 2
119 bs.byte_idx = 0
120 bs.bit_off = 0
121
122 // ============================================================
123 // Output planes: 1 plane (8x8 grayscale), init to 0xFF.
124 // The decoder expects a `planes` packed array of *u8.
125 // ============================================================
126 let plane: *u8 = sys_mmap(64)
127 i = 0
128 while i < 64 { plane[i] = 0xFF; i = i + 1 }
129 let planes_arr: *i64 = sys_mmap(8) as *i64
130 planes_arr[0] = plane as i64
131 let strides: *i64 = sys_mmap(8) as *i64
132 strides[0] = 8
133
134 // Scratch + state.
135 let sc: *NxJpegMcuScratch = sys_mmap(NX_JPEG_MCU_SCRATCH_BYTES) as *NxJpegMcuScratch
136 nx_jpeg_mcu_scratch_init(sc)
137 let cstates: *NxJpegDecCompState = sys_mmap(NX_JPEG_DEC_COMPSTATE_BYTES * 4) as *NxJpegDecCompState
138
139 // Resolve per-component tables/planes.
140 let rc_res: i64 = nx_jpeg_decode_image_resolve(frame, scan,
141 qtables, 1,
142 htables, 2,
143 planes_arr as *u8, strides,
144 cstates)
145 if rc_res != NX_JPEG_DEC_OK { _fail(10 + rc_res); return 10 }
146
147 // Walk MCUs.
148 let rc_walk: i64 = nx_jpeg_decode_image_walk_mcus(frame, scan, cstates, bs, sc)
149 if rc_walk != NX_JPEG_DEC_OK { _fail(20 + rc_walk); return 20 }
150
151 // Verify plane is all 128.
152 i = 0
153 while i < 64 {
154 if plane[i] != 128 { _fail(30 + i); return 30 }
155 i = i + 1
156 }
157
158 let pass: *u8 = sys_mmap(16)
159 pass[0]=0x50; pass[1]=0x41; pass[2]=0x53; pass[3]=0x53; pass[4]=0x0A
160 sys_write(1, pass, 5)
161 return 0
162}