1pub struct AvcConfig {
15 pub nal_len: usize,
17 pub headers_annexb: Vec<u8>,
20}
21
22pub fn parse_avcc(avcc: &[u8]) -> Option<AvcConfig> {
24 if avcc.len() < 6 {
25 return None;
26 }
27 let nal_len = (avcc[4] & 0x03) as usize + 1;
28 let mut headers = Vec::new();
29 let mut i = 5;
30 let num_sps = avcc[i] & 0x1F;
31 i += 1;
32 for _ in 0..num_sps {
33 let len = be16(avcc, i)? as usize;
34 i += 2;
35 let nal = avcc.get(i..i + len)?;
36 headers.extend_from_slice(&[0, 0, 0, 1]);
37 headers.extend_from_slice(nal);
38 i += len;
39 }
40 let num_pps = *avcc.get(i)?;
41 i += 1;
42 for _ in 0..num_pps {
43 let len = be16(avcc, i)? as usize;
44 i += 2;
45 let nal = avcc.get(i..i + len)?;
46 headers.extend_from_slice(&[0, 0, 0, 1]);
47 headers.extend_from_slice(nal);
48 i += len;
49 }
50 Some(AvcConfig {
51 nal_len,
52 headers_annexb: headers,
53 })
54}
55
56pub fn avcc_to_annexb(sample: &[u8], nal_len: usize, out: &mut Vec<u8>) {
59 let mut i = 0;
60 while i + nal_len <= sample.len() {
61 let mut len = 0usize;
62 for _ in 0..nal_len {
63 len = (len << 8) | sample[i] as usize;
64 i += 1;
65 }
66 if i + len > sample.len() {
67 break;
68 }
69 out.extend_from_slice(&[0, 0, 0, 1]);
70 out.extend_from_slice(&sample[i..i + len]);
71 i += len;
72 }
73}
74
75pub fn find_sps_annexb(data: &[u8]) -> Option<&[u8]> {
78 let mut i = 0;
79 let mut nal_start: Option<usize> = None;
80 while i + 3 <= data.len() {
81 if data[i] == 0 && data[i + 1] == 0 && data[i + 2] == 1 {
82 if let Some(s) = nal_start {
83 let end = if i > 0 && data[i - 1] == 0 { i - 1 } else { i };
85 if data[s] & 0x1F == 7 {
86 return Some(&data[s..end]);
87 }
88 }
89 nal_start = Some(i + 3);
90 i += 3;
91 } else {
92 i += 1;
93 }
94 }
95 let s = nal_start?;
96 (*data.get(s)? & 0x1F == 7).then(|| &data[s..])
97}
98
99pub fn sps_dimensions(nal: &[u8]) -> Option<(u32, u32)> {
103 if nal.first()? & 0x1F != 7 {
104 return None;
105 }
106 let mut rbsp = Vec::with_capacity(nal.len());
108 let mut zeros = 0u32;
109 for &b in &nal[1..] {
110 if zeros >= 2 && b == 3 {
111 zeros = 0;
112 continue;
113 }
114 zeros = if b == 0 { zeros + 1 } else { 0 };
115 rbsp.push(b);
116 }
117
118 let mut r = Bits::new(&rbsp);
119 let profile_idc = r.bits(8)?;
120 r.bits(16)?; r.ue()?; let mut chroma_format_idc = 1; let mut separate_colour_plane = false;
125 if matches!(
126 profile_idc,
127 100 | 110 | 122 | 244 | 44 | 83 | 86 | 118 | 128 | 138 | 139 | 134 | 135
128 ) {
129 chroma_format_idc = r.ue()?;
130 if chroma_format_idc == 3 {
131 separate_colour_plane = r.bit()? == 1;
132 }
133 r.ue()?; r.ue()?; r.bit()?; if r.bit()? == 1 {
137 let lists = if chroma_format_idc != 3 { 8 } else { 12 };
139 for i in 0..lists {
140 if r.bit()? == 1 {
141 skip_scaling_list(&mut r, if i < 6 { 16 } else { 64 })?;
142 }
143 }
144 }
145 }
146
147 r.ue()?; match r.ue()? {
149 0 => {
150 r.ue()?; }
152 1 => {
153 r.bit()?; r.se()?; r.se()?; let n = r.ue()?;
157 for _ in 0..n {
158 r.se()?; }
160 }
161 _ => {}
162 }
163 r.ue()?; r.bit()?; let width_mbs = r.ue()? + 1;
167 let height_map_units = r.ue()? + 1;
168 let frame_mbs_only = r.bit()?;
169 if frame_mbs_only == 0 {
170 r.bit()?; }
172 r.bit()?; let mut width = width_mbs.checked_mul(16)?;
175 let mut height = (2 - frame_mbs_only)
176 .checked_mul(height_map_units)?
177 .checked_mul(16)?;
178 if r.bit()? == 1 {
179 let (left, right, top, bottom) = (r.ue()?, r.ue()?, r.ue()?, r.ue()?);
181 let chroma_array_type = if separate_colour_plane {
182 0
183 } else {
184 chroma_format_idc
185 };
186 let (sub_w, sub_h) = match chroma_array_type {
187 1 => (2, 2), 2 => (2, 1), _ => (1, 1), };
191 let crop_y = sub_h * (2 - frame_mbs_only);
192 width = width.checked_sub((left + right).checked_mul(sub_w)?)?;
193 height = height.checked_sub((top + bottom).checked_mul(crop_y)?)?;
194 }
195 (width > 0 && height > 0).then_some((width, height))
196}
197
198pub fn split_annexb(data: &[u8]) -> Vec<&[u8]> {
202 let mut nals = Vec::new();
203 let mut i = 0;
204 let mut nal_start: Option<usize> = None;
205 while i + 3 <= data.len() {
206 if data[i] == 0 && data[i + 1] == 0 && data[i + 2] == 1 {
207 if let Some(s) = nal_start {
208 let end = if i > s && data[i - 1] == 0 { i - 1 } else { i };
210 if end > s {
211 nals.push(&data[s..end]);
212 }
213 }
214 i += 3;
215 nal_start = Some(i);
216 } else {
217 i += 1;
218 }
219 }
220 if let Some(s) = nal_start {
221 if s < data.len() {
222 nals.push(&data[s..]);
223 }
224 }
225 nals
226}
227
228pub fn build_avcc_record(sps: &[u8], pps: &[u8]) -> Vec<u8> {
232 let mut b = Vec::new();
233 b.push(1); b.push(*sps.get(1).unwrap_or(&0x42)); b.push(*sps.get(2).unwrap_or(&0)); b.push(*sps.get(3).unwrap_or(&30)); b.push(0xFF); b.push(0xE1); b.extend_from_slice(&(sps.len() as u16).to_be_bytes());
240 b.extend_from_slice(sps);
241 b.push(1); b.extend_from_slice(&(pps.len() as u16).to_be_bytes());
243 b.extend_from_slice(pps);
244 b
245}
246
247fn skip_scaling_list(r: &mut Bits, size: u32) -> Option<()> {
249 let mut next = 8i32;
250 for _ in 0..size {
251 if next != 0 {
252 next = (next + r.se()? + 256) % 256;
253 }
254 if next == 0 {
255 break; }
257 }
258 Some(())
259}
260
261struct Bits<'a> {
263 d: &'a [u8],
264 pos: usize, }
266
267impl<'a> Bits<'a> {
268 fn new(d: &'a [u8]) -> Bits<'a> {
269 Bits { d, pos: 0 }
270 }
271
272 fn bit(&mut self) -> Option<u32> {
273 let b = *self.d.get(self.pos / 8)?;
274 let v = (b >> (7 - self.pos % 8)) & 1;
275 self.pos += 1;
276 Some(v as u32)
277 }
278
279 fn bits(&mut self, n: u32) -> Option<u32> {
280 let mut v = 0;
281 for _ in 0..n {
282 v = (v << 1) | self.bit()?;
283 }
284 Some(v)
285 }
286
287 fn ue(&mut self) -> Option<u32> {
289 let mut zeros = 0;
290 while self.bit()? == 0 {
291 zeros += 1;
292 if zeros > 31 {
293 return None;
294 }
295 }
296 Some((1u32 << zeros) - 1 + if zeros > 0 { self.bits(zeros)? } else { 0 })
297 }
298
299 fn se(&mut self) -> Option<i32> {
301 let k = self.ue()? as i64;
302 Some(if k % 2 == 1 { (k + 1) / 2 } else { -(k / 2) } as i32)
303 }
304}
305
306fn be16(d: &[u8], i: usize) -> Option<u16> {
307 Some(((*d.get(i)? as u16) << 8) | *d.get(i + 1)? as u16)
308}
309
310#[cfg(test)]
311mod tests {
312 use super::*;
313
314 #[test]
315 fn avcc_roundtrip_to_annexb() {
316 let avcc = [
318 1, 100, 0, 31, 0xFF, 0xE1, 0, 3, 0x67, 0xAA, 0xBB, 1, 0, 2, 0x68, 0xCC,
319 ];
320 let cfg = parse_avcc(&avcc).unwrap();
321 assert_eq!(cfg.nal_len, 4);
322 assert_eq!(
323 cfg.headers_annexb,
324 &[0, 0, 0, 1, 0x67, 0xAA, 0xBB, 0, 0, 0, 1, 0x68, 0xCC]
325 );
326
327 let sample = [0, 0, 0, 2, 0x41, 0x9A, 0, 0, 0, 1, 0x06];
328 let mut out = Vec::new();
329 avcc_to_annexb(&sample, 4, &mut out);
330 assert_eq!(out, &[0, 0, 0, 1, 0x41, 0x9A, 0, 0, 0, 1, 0x06]);
331 }
332
333 #[test]
334 fn finds_sps_between_start_codes() {
335 let data = [
336 0, 0, 0, 1, 0x09, 0xF0, 0, 0, 0, 1, 0x67, 0xAA, 0, 0, 1, 0x68,
337 ];
338 assert_eq!(find_sps_annexb(&data), Some(&[0x67u8, 0xAA][..]));
339 let data = [0, 0, 1, 0x67, 0xAA, 0xBB];
341 assert_eq!(find_sps_annexb(&data), Some(&[0x67u8, 0xAA, 0xBB][..]));
342 assert_eq!(find_sps_annexb(&[0, 0, 1, 0x68, 0x00]), None);
343 }
344
345 #[test]
346 fn sps_dimensions_x264_640x360() {
347 let sps = [
349 0x67, 0x64, 0x00, 0x1E, 0xAC, 0xD9, 0x40, 0xA0, 0x2F, 0xF9, 0x70, 0x11, 0x00, 0x00,
350 0x03, 0x00, 0x01, 0x00, 0x00, 0x03, 0x00, 0x30, 0x0F, 0x16, 0x2D, 0x96,
351 ];
352 assert_eq!(sps_dimensions(&sps), Some((640, 360)));
353 }
354
355 #[test]
356 fn sps_dimensions_baseline_176x144() {
357 let sps = [
359 0x67, 0x42, 0xC0, 0x0D, 0x8C, 0x8D, 0x41, 0x62, 0x64, 0x0A, 0x60, 0x80,
360 ];
361 assert_eq!(sps_dimensions(&sps), Some((176, 144)));
362 }
363}