1use crate::avc::AvcConfig;
13
14pub fn parse_hvcc(hvcc: &[u8]) -> Option<AvcConfig> {
17 if hvcc.len() < 23 || hvcc[0] != 1 {
18 return None;
19 }
20 let nal_len = (hvcc[21] & 0x03) as usize + 1;
21 let num_arrays = hvcc[22] as usize;
22 let mut headers = Vec::new();
23 let mut i = 23;
24 for _ in 0..num_arrays {
25 let nal_type = *hvcc.get(i)? & 0x3f;
26 i += 1;
27 let count = be16(hvcc, i)? as usize;
28 i += 2;
29 for _ in 0..count {
30 let len = be16(hvcc, i)? as usize;
31 i += 2;
32 let nal = hvcc.get(i..i + len)?;
33 if matches!(nal_type, 32 | 33 | 34) {
36 headers.extend_from_slice(&[0, 0, 0, 1]);
37 headers.extend_from_slice(nal);
38 }
39 i += len;
40 }
41 }
42 if headers.is_empty() {
43 return None;
44 }
45 Some(AvcConfig { nal_len, headers_annexb: headers })
46}
47
48#[derive(Debug, Clone, Copy, PartialEq, Eq)]
50pub struct SpsInfo {
51 pub profile_space: u8,
52 pub tier_flag: bool,
53 pub profile_idc: u8,
54 pub profile_compatibility_flags: u32,
55 pub constraint_flags: [u8; 6],
56 pub level_idc: u8,
57 pub chroma_format_idc: u8,
58 pub bit_depth_luma: u8,
59 pub bit_depth_chroma: u8,
60 pub max_sub_layers: u8,
61 pub temporal_id_nesting: bool,
62 pub width: u32,
63 pub height: u32,
64}
65
66pub fn sps_info(nal: &[u8]) -> Option<SpsInfo> {
69 let payload = if !nal.is_empty() && (nal[0] >> 1) & 0x3f == 33 { nal.get(2..)? } else { nal };
71 let rbsp = unescape(payload);
72 let mut r = Bits::new(&rbsp);
73 r.bits(4)?; let max_sub_layers_minus1 = r.bits(3)? as u8;
75 let temporal_id_nesting = r.bit()?;
76 let profile_space = r.bits(2)? as u8;
78 let tier_flag = r.bit()?;
79 let profile_idc = r.bits(5)? as u8;
80 let profile_compatibility_flags = r.bits(32)?;
81 let mut constraint_flags = [0u8; 6];
82 for c in constraint_flags.iter_mut() {
83 *c = r.bits(8)? as u8;
84 }
85 let level_idc = r.bits(8)? as u8;
86 let mut sub_profile = [false; 8];
87 let mut sub_level = [false; 8];
88 for i in 0..max_sub_layers_minus1 as usize {
89 sub_profile[i] = r.bit()?;
90 sub_level[i] = r.bit()?;
91 }
92 if max_sub_layers_minus1 > 0 {
93 for _ in max_sub_layers_minus1 as usize..8 {
94 r.bits(2)?;
95 }
96 }
97 for i in 0..max_sub_layers_minus1 as usize {
98 if sub_profile[i] {
99 r.bits(32)?;
100 r.bits(32)?;
101 r.bits(24)?;
102 }
103 if sub_level[i] {
104 r.bits(8)?;
105 }
106 }
107 r.ue()?; let chroma_format_idc = r.ue()? as u8;
109 if chroma_format_idc == 3 {
110 r.bit()?; }
112 let width = r.ue()?;
113 let height = r.ue()?;
114 let (mut cl, mut cr, mut ct, mut cb) = (0, 0, 0, 0);
115 if r.bit()? {
116 cl = r.ue()?;
117 cr = r.ue()?;
118 ct = r.ue()?;
119 cb = r.ue()?;
120 }
121 let bit_depth_luma = r.ue()? as u8 + 8;
122 let bit_depth_chroma = r.ue()? as u8 + 8;
123 let (sw, sh) = match chroma_format_idc {
124 1 => (2, 2),
125 2 => (2, 1),
126 _ => (1, 1),
127 };
128 Some(SpsInfo {
129 profile_space,
130 tier_flag,
131 profile_idc,
132 profile_compatibility_flags,
133 constraint_flags,
134 level_idc,
135 chroma_format_idc,
136 bit_depth_luma,
137 bit_depth_chroma,
138 max_sub_layers: max_sub_layers_minus1 + 1,
139 temporal_id_nesting,
140 width: width.saturating_sub(sw * (cl + cr)),
141 height: height.saturating_sub(sh * (ct + cb)),
142 })
143}
144
145pub fn sps_dimensions(nal: &[u8]) -> Option<(u32, u32)> {
147 sps_info(nal).map(|s| (s.width, s.height))
148}
149
150pub fn build_hvcc_record(vps: &[u8], sps: &[u8], pps: &[u8]) -> Option<Vec<u8>> {
152 let info = sps_info(sps)?;
153 let mut out = Vec::with_capacity(64 + vps.len() + sps.len() + pps.len());
154 out.push(1); out.push((info.profile_space << 6) | ((info.tier_flag as u8) << 5) | info.profile_idc);
156 out.extend_from_slice(&info.profile_compatibility_flags.to_be_bytes());
157 out.extend_from_slice(&info.constraint_flags);
158 out.push(info.level_idc);
159 out.extend_from_slice(&[0xf0, 0x00]); out.push(0xfc); out.push(0xfc | info.chroma_format_idc);
162 out.push(0xf8 | (info.bit_depth_luma - 8));
163 out.push(0xf8 | (info.bit_depth_chroma - 8));
164 out.extend_from_slice(&[0, 0]); out.push((info.max_sub_layers << 3) | ((info.temporal_id_nesting as u8) << 2) | 3);
167 let arrays: [(u8, &[u8]); 3] = [(32, vps), (33, sps), (34, pps)];
168 let present = arrays.iter().filter(|(_, n)| !n.is_empty()).count();
169 out.push(present as u8);
170 for (t, nal) in arrays {
171 if nal.is_empty() {
172 continue;
173 }
174 out.push(0x80 | t); out.extend_from_slice(&1u16.to_be_bytes());
176 out.extend_from_slice(&(nal.len() as u16).to_be_bytes());
177 out.extend_from_slice(nal);
178 }
179 Some(out)
180}
181
182pub fn find_nal_annexb(data: &[u8], nal_type: u8) -> Option<&[u8]> {
184 for nal in crate::avc::split_annexb(data) {
185 if !nal.is_empty() && (nal[0] >> 1) & 0x3f == nal_type {
186 return Some(nal);
187 }
188 }
189 None
190}
191
192fn be16(d: &[u8], i: usize) -> Option<u16> {
193 Some(u16::from_be_bytes([*d.get(i)?, *d.get(i + 1)?]))
194}
195
196fn unescape(ebsp: &[u8]) -> Vec<u8> {
197 let mut out = Vec::with_capacity(ebsp.len());
198 let mut zeros = 0;
199 for &b in ebsp {
200 if zeros >= 2 && b == 3 {
201 zeros = 0;
202 continue;
203 }
204 out.push(b);
205 zeros = if b == 0 { zeros + 1 } else { 0 };
206 }
207 out
208}
209
210struct Bits<'a> {
211 d: &'a [u8],
212 p: usize,
213}
214
215impl<'a> Bits<'a> {
216 fn new(d: &'a [u8]) -> Self {
217 Bits { d, p: 0 }
218 }
219 fn bit(&mut self) -> Option<bool> {
220 let b = *self.d.get(self.p / 8)?;
221 let v = (b >> (7 - self.p % 8)) & 1;
222 self.p += 1;
223 Some(v == 1)
224 }
225 fn bits(&mut self, n: u32) -> Option<u32> {
226 let mut v = 0u32;
227 for _ in 0..n {
228 v = (v << 1) | self.bit()? as u32;
229 }
230 Some(v)
231 }
232 fn ue(&mut self) -> Option<u32> {
233 let mut lz = 0;
234 while !self.bit()? {
235 lz += 1;
236 if lz > 31 {
237 return None;
238 }
239 }
240 if lz == 0 {
241 return Some(0);
242 }
243 Some((1u32 << lz) - 1 + self.bits(lz)?)
244 }
245}
246
247#[cfg(test)]
248mod tests {
249 use super::*;
250
251 const VPS: &[u8] = &[
254 0x40, 0x01, 0x0c, 0x01, 0xff, 0xff, 0x01, 0x60, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00,
255 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x99, 0xf0, 0x24,
256 ];
257 const SPS: &[u8] = &[
258 0x42, 0x01, 0x01, 0x01, 0x60, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00,
259 0x00, 0x03, 0x00, 0x99, 0xa0, 0x06, 0x82, 0x01, 0xe1, 0xfe, 0x5f, 0x92, 0x46, 0xd9, 0x6c,
260 0x80,
261 ];
262 const PPS: &[u8] = &[0x44, 0x01, 0xc1, 0x90, 0x95, 0x81, 0x12];
263
264 #[test]
265 fn reads_geometry_and_profile() {
266 let i = sps_info(SPS).expect("sps");
267 assert_eq!((i.width, i.height), (832, 480));
268 assert_eq!(i.level_idc, 153);
269 assert_eq!(i.max_sub_layers, 1);
270 assert_eq!(i.chroma_format_idc, 1);
271 assert_eq!(i.bit_depth_luma, 8);
272 assert_eq!(i.bit_depth_chroma, 8);
273 assert_eq!(i.profile_idc, 1);
274 assert_eq!(sps_dimensions(SPS), Some((832, 480)));
275 assert_eq!(sps_dimensions(&SPS[2..]), Some((832, 480)));
277 }
278
279 #[test]
280 fn hvcc_roundtrip() {
281 let (vps, pps) = (VPS, PPS);
282 let rec = build_hvcc_record(vps, SPS, pps).expect("build");
283 assert_eq!(rec[0], 1);
284 assert_eq!(rec[21] & 3, 3, "4-byte NAL length");
285 assert_eq!(rec[22], 3, "three arrays");
286 let cfg = parse_hvcc(&rec).expect("parse");
287 assert_eq!(cfg.nal_len, 4);
288 let mut want = Vec::new();
290 for n in [vps, SPS, pps] {
291 want.extend_from_slice(&[0, 0, 0, 1]);
292 want.extend_from_slice(n);
293 }
294 assert_eq!(cfg.headers_annexb, want);
295 }
296
297 #[test]
298 fn rejects_junk() {
299 assert!(parse_hvcc(&[]).is_none());
300 assert!(parse_hvcc(&[0u8; 40]).is_none());
301 assert!(sps_info(&[0x42, 0x01]).is_none());
302 }
303}