nx_h264_nal.nx source
↩ module page · 65 lines · 2689 B
1// nx_h264_nal.nx -- H.264 NAL unit splitter + header decode (rung 2b).
2// A coded video sample is a sequence of NAL (Network Abstraction Layer) units.
3// Two framings:
4// AVCC (MP4 sample): [length:lenSize BE][NAL bytes] repeated. lenSize comes
5// from the avcC config (lengthSizeMinusOne+1), usually 4.
6// Annex B (raw .h264): start code 00 00 01 (or 00 00 00 01) before each NAL.
7// First NAL byte = forbidden_zero(1) + nal_ref_idc(2) + nal_unit_type(5):
8// type 7=SPS 8=PPS 6=SEI 5=IDR-slice 1=non-IDR-slice 9=AUD.
9// This locates each NAL + its type so the SPS/PPS/slice parsers (next rungs,
10// which use nx_h264_bits) know what to read. Settled framing; KAT-gated.
11//
12// genealogy_id: itu_t_h264_nal_framing + iso_bmff_avcc_length_prefix
13// lineage_id: nal_split_avcc + nal_split_annexb + nal_header_decode
14// license_tier: ORIGINAL
15import "nx_syscalls.nx"
16
17func nx_nal_type(first_byte: i64) -> i64 { return first_byte & 31 }
18func nx_nal_ref_idc(first_byte: i64) -> i64 { return (first_byte >> 5) & 3 }
19
20// read an n-byte big-endian integer at offset o
21func nal_be(d: *u8, o: i64, n: i64) -> i64 {
22 var v: i64 = 0
23 var i: i64 = 0
24 while i < n { v = (v << 8) | (d[o + i] as i64); i = i + 1 }
25 return v
26}
27
28// AVCC split over [start,end): each NAL = [len:len_size BE][bytes]. Records the
29// NAL payload offset (header byte) into offs[] and its type into types[].
30// Returns NAL count.
31func nx_nal_split_avcc(d: *u8, start: i64, end: i64, len_size: i64, offs: *i64, types: *i64, max: i64) -> i64 {
32 var pos: i64 = start
33 var cnt: i64 = 0
34 while pos + len_size < end {
35 let l: i64 = nal_be(d, pos, len_size)
36 if l <= 0 { pos = end }
37 if l > 0 {
38 let np: i64 = pos + len_size
39 if np >= end { pos = end }
40 if np < end {
41 if cnt < max { offs[cnt] = np; types[cnt] = (d[np] as i64) & 31; cnt = cnt + 1 }
42 pos = np + l
43 }
44 }
45 }
46 return cnt
47}
48
49// Annex B split over [start,end): find each 00 00 01 (handles 00 00 00 01 too,
50// matching the trailing 00 00 01). Records NAL payload offset + type.
51func nx_nal_split_annexb(d: *u8, start: i64, end: i64, offs: *i64, types: *i64, max: i64) -> i64 {
52 var cnt: i64 = 0
53 var i: i64 = start
54 while i + 3 <= end {
55 var hit: i64 = 0
56 if (d[i] as i64) == 0 { if (d[i + 1] as i64) == 0 { if (d[i + 2] as i64) == 1 { hit = 1 } } }
57 if hit == 1 {
58 let np: i64 = i + 3
59 if np < end { if cnt < max { offs[cnt] = np; types[cnt] = (d[np] as i64) & 31; cnt = cnt + 1 } }
60 i = i + 3
61 }
62 if hit == 0 { i = i + 1 }
63 }
64 return cnt
65}