code wiki / (root) / nx_h264_nal.nx

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}