1use crate::frame::PixelFormat;
5use super::bitreader::{BitReader, find_next_start_code, remove_h264_rbsp_stuffing,
6 clamp_to_i8, more_rbsp_data};
7
8pub(super) fn detect_h264(sample: &[u8]) -> Option<PixelFormat> {
14 let sps = find_h264_sps(sample)?;
15 let rbsp = remove_h264_rbsp_stuffing(sps);
16 let mut br = BitReader::new(&rbsp);
17
18 let profile_idc = br.read_bits(8)? as u8;
19 let _constraint_flags = br.read_bits(8)?;
20 let _level_idc = br.read_bits(8)?;
21 let _seq_parameter_set_id = br.read_ue()?;
22
23 let profile_gates_chroma = matches!(
24 profile_idc,
25 100 | 110 | 122 | 244 | 44 | 83 | 86 | 118 | 128 | 138 | 139 | 134 | 135
26 );
27
28 let (chroma_format_idc, bit_depth_luma) = if profile_gates_chroma {
29 let chroma_format_idc = br.read_ue()? as u8;
30 if chroma_format_idc == 3 {
31 let _separate_colour_plane_flag = br.read_bits(1)?;
32 }
33 let bit_depth_luma_minus8 = br.read_ue()? as u8;
34 (chroma_format_idc, bit_depth_luma_minus8 + 8)
35 } else {
36 (1, 8)
38 };
39
40 Some(PixelFormat::from_chroma_and_depth(
41 chroma_format_idc,
42 bit_depth_luma,
43 ))
44}
45
46fn find_h264_sps(data: &[u8]) -> Option<&[u8]> {
50 let mut i = 0;
51 while i + 4 < data.len() {
52 let (start_len, nal_byte) = if data[i] == 0 && data[i + 1] == 0 && data[i + 2] == 1 {
53 (3, i + 3)
54 } else if data[i] == 0 && data[i + 1] == 0 && data[i + 2] == 0 && data[i + 3] == 1 {
55 (4, i + 4)
56 } else {
57 i += 1;
58 continue;
59 };
60 if nal_byte >= data.len() {
61 return None;
62 }
63 let nal_unit_type = data[nal_byte] & 0x1F;
64 if nal_unit_type == 7 {
65 let start = nal_byte + 1;
67 let end = find_next_start_code(&data[start..])
68 .map(|off| start + off)
69 .unwrap_or(data.len());
70 return Some(&data[start..end]);
71 }
72 i += start_len;
73 }
74 None
75}
76
77#[derive(Debug, Clone, PartialEq, Eq, Default)]
80pub struct H264SpsInfo {
81 pub profile_idc: u8,
82 pub constraint_set_flags: u8,
86 pub level_idc: u8,
87 pub chroma_format_idc: u8,
88 pub separate_colour_plane_flag: bool,
89 pub bit_depth_luma: u8,
90 pub bit_depth_chroma: u8,
91 pub frame_mbs_only: bool,
92 pub width: Option<u32>,
95 pub height: Option<u32>,
96 pub log2_max_frame_num_minus4: Option<u8>,
101 pub pic_order_cnt_type: Option<u8>,
104 pub log2_max_pic_order_cnt_lsb_minus4: Option<u8>,
107 pub delta_pic_order_always_zero_flag: Option<bool>,
110 pub qpprime_y_zero_transform_bypass_flag: Option<bool>,
112 pub seq_scaling_matrix_present_flag: Option<bool>,
113 pub max_num_ref_frames: Option<u8>,
114 pub gaps_in_frame_num_value_allowed_flag: Option<bool>,
115 pub mb_adaptive_frame_field_flag: Option<bool>,
117 pub direct_8x8_inference_flag: Option<bool>,
118 pub frame_cropping_flag: Option<bool>,
119 pub frame_crop_left_offset: Option<u32>,
120 pub frame_crop_right_offset: Option<u32>,
121 pub frame_crop_top_offset: Option<u32>,
122 pub frame_crop_bottom_offset: Option<u32>,
123 pub offset_for_non_ref_pic: Option<i32>,
125 pub offset_for_top_to_bottom_field: Option<i32>,
126 pub num_ref_frames_in_pic_order_cnt_cycle: Option<u8>,
127 pub offset_for_ref_frame: Vec<i32>,
132}
133
134pub fn parse_h264_sps(sample: &[u8]) -> Option<H264SpsInfo> {
143 let sps = find_h264_sps(sample)?;
144 let rbsp = remove_h264_rbsp_stuffing(sps);
145 let mut br = BitReader::new(&rbsp);
146
147 let profile_idc = br.read_bits(8)? as u8;
148 let constraint_set_flags = br.read_bits(8)? as u8;
149 let level_idc = br.read_bits(8)? as u8;
150 let _seq_parameter_set_id = br.read_ue()?;
151
152 let profile_gates_chroma = matches!(
153 profile_idc,
154 100 | 110 | 122 | 244 | 44 | 83 | 86 | 118 | 128 | 138 | 139 | 134 | 135
155 );
156
157 let (
158 chroma_format_idc,
159 separate_colour_plane_flag,
160 bit_depth_luma,
161 bit_depth_chroma,
162 qpprime_y_zero,
163 scaling_matrix,
164 ) = if profile_gates_chroma {
165 let chroma = br.read_ue()? as u8;
166 let separate = if chroma == 3 {
167 br.read_bits(1)? == 1
168 } else {
169 false
170 };
171 let bit_depth_luma_m8 = br.read_ue()?;
172 let bit_depth_chroma_m8 = br.read_ue()?;
173 let qpprime = br.read_bits(1)? == 1;
174 let scaling_matrix_present = br.read_bits(1)? == 1;
175 if scaling_matrix_present {
176 let num_lists = if chroma == 3 { 12 } else { 8 };
180 for i in 0..num_lists {
181 if br.read_bits(1)? == 1 {
182 let size = if i < 6 { 16 } else { 64 };
183 let mut last_scale: i32 = 8;
184 let mut next_scale: i32 = 8;
185 for _j in 0..size {
186 if next_scale != 0 {
187 let delta = br.read_se()?;
188 next_scale = (last_scale + delta + 256).rem_euclid(256);
189 }
190 if next_scale != 0 {
191 last_scale = next_scale;
192 }
193 }
194 }
195 }
196 }
197 (
198 chroma,
199 separate,
200 bit_depth_luma_m8 as u8 + 8,
201 bit_depth_chroma_m8 as u8 + 8,
202 qpprime,
203 scaling_matrix_present,
204 )
205 } else {
206 (1u8, false, 8u8, 8u8, false, false)
207 };
208
209 let info_prefix = H264SpsInfo {
214 profile_idc,
215 constraint_set_flags,
216 level_idc,
217 chroma_format_idc,
218 separate_colour_plane_flag,
219 bit_depth_luma,
220 bit_depth_chroma,
221 frame_mbs_only: true,
222 width: None,
223 height: None,
224 log2_max_frame_num_minus4: None,
225 pic_order_cnt_type: None,
226 log2_max_pic_order_cnt_lsb_minus4: None,
227 delta_pic_order_always_zero_flag: None,
228 qpprime_y_zero_transform_bypass_flag: Some(qpprime_y_zero),
229 seq_scaling_matrix_present_flag: Some(scaling_matrix),
230 max_num_ref_frames: None,
231 gaps_in_frame_num_value_allowed_flag: None,
232 mb_adaptive_frame_field_flag: None,
233 direct_8x8_inference_flag: None,
234 frame_cropping_flag: None,
235 frame_crop_left_offset: None,
236 frame_crop_right_offset: None,
237 frame_crop_top_offset: None,
238 frame_crop_bottom_offset: None,
239 offset_for_non_ref_pic: None,
240 offset_for_top_to_bottom_field: None,
241 num_ref_frames_in_pic_order_cnt_cycle: None,
242 offset_for_ref_frame: Vec::new(),
243 };
244
245 let Some(dims) = parse_h264_sps_dims(&mut br, chroma_format_idc, separate_colour_plane_flag)
246 else {
247 return Some(info_prefix);
248 };
249
250 Some(H264SpsInfo {
251 frame_mbs_only: dims.frame_mbs_only,
252 width: Some(dims.width),
253 height: Some(dims.height),
254 log2_max_frame_num_minus4: Some(dims.log2_max_frame_num_minus4),
255 pic_order_cnt_type: Some(dims.pic_order_cnt_type),
256 log2_max_pic_order_cnt_lsb_minus4: dims.log2_max_pic_order_cnt_lsb_minus4,
257 delta_pic_order_always_zero_flag: dims.delta_pic_order_always_zero_flag,
258 max_num_ref_frames: Some(dims.max_num_ref_frames),
259 gaps_in_frame_num_value_allowed_flag: Some(dims.gaps_in_frame_num_value_allowed_flag),
260 mb_adaptive_frame_field_flag: dims.mb_adaptive_frame_field_flag,
261 direct_8x8_inference_flag: Some(dims.direct_8x8_inference_flag),
262 frame_cropping_flag: Some(dims.frame_cropping_flag),
263 frame_crop_left_offset: Some(dims.crop_left),
264 frame_crop_right_offset: Some(dims.crop_right),
265 frame_crop_top_offset: Some(dims.crop_top),
266 frame_crop_bottom_offset: Some(dims.crop_bottom),
267 offset_for_non_ref_pic: dims.offset_for_non_ref_pic,
268 offset_for_top_to_bottom_field: dims.offset_for_top_to_bottom_field,
269 num_ref_frames_in_pic_order_cnt_cycle: dims.num_ref_frames_in_pic_order_cnt_cycle,
270 offset_for_ref_frame: dims.offset_for_ref_frame,
271 ..info_prefix
272 })
273}
274
275struct H264Dims {
276 width: u32,
277 height: u32,
278 frame_mbs_only: bool,
279 log2_max_frame_num_minus4: u8,
280 pic_order_cnt_type: u8,
281 log2_max_pic_order_cnt_lsb_minus4: Option<u8>,
282 delta_pic_order_always_zero_flag: Option<bool>,
283 offset_for_non_ref_pic: Option<i32>,
284 offset_for_top_to_bottom_field: Option<i32>,
285 num_ref_frames_in_pic_order_cnt_cycle: Option<u8>,
286 offset_for_ref_frame: Vec<i32>,
287 max_num_ref_frames: u8,
288 gaps_in_frame_num_value_allowed_flag: bool,
289 mb_adaptive_frame_field_flag: Option<bool>,
290 direct_8x8_inference_flag: bool,
291 frame_cropping_flag: bool,
292 crop_left: u32,
293 crop_right: u32,
294 crop_top: u32,
295 crop_bottom: u32,
296}
297
298fn parse_h264_sps_dims(
299 br: &mut BitReader,
300 chroma_format_idc: u8,
301 separate_colour_plane_flag: bool,
302) -> Option<H264Dims> {
303 let log2_max_frame_num_minus4 = br.read_ue()? as u8;
304 let pic_order_cnt_type = br.read_ue()? as u8;
305 let mut log2_max_pic_order_cnt_lsb_minus4 = None;
306 let mut delta_pic_order_always_zero_flag = None;
307 let mut offset_for_non_ref_pic = None;
308 let mut offset_for_top_to_bottom_field = None;
309 let mut num_ref_frames_in_pic_order_cnt_cycle: Option<u8> = None;
310 let mut offset_for_ref_frame: Vec<i32> = Vec::new();
311 match pic_order_cnt_type {
312 0 => {
313 log2_max_pic_order_cnt_lsb_minus4 = Some(br.read_ue()? as u8);
314 }
315 1 => {
316 delta_pic_order_always_zero_flag = Some(br.read_bits(1)? == 1);
317 offset_for_non_ref_pic = Some(br.read_se()?);
318 offset_for_top_to_bottom_field = Some(br.read_se()?);
319 let cycle_len = br.read_ue()?;
320 let capped = cycle_len.min(255) as u8;
323 num_ref_frames_in_pic_order_cnt_cycle = Some(capped);
324 offset_for_ref_frame.reserve(capped as usize);
325 for _ in 0..capped {
326 offset_for_ref_frame.push(br.read_se()?);
327 }
328 }
329 2 => { }
330 _ => return None, }
332 let max_num_ref_frames = br.read_ue()?.min(u8::MAX as u32) as u8;
333 let gaps_in_frame_num_value_allowed_flag = br.read_bits(1)? == 1;
334 let pic_width_in_mbs_minus1 = br.read_ue()?;
335 let pic_height_in_map_units_minus1 = br.read_ue()?;
336 let frame_mbs_only_flag = br.read_bits(1)?;
337 let mut mb_adaptive_frame_field_flag = None;
338 if frame_mbs_only_flag == 0 {
339 mb_adaptive_frame_field_flag = Some(br.read_bits(1)? == 1);
340 }
341 let direct_8x8_inference_flag = br.read_bits(1)? == 1;
342 let frame_cropping_flag = br.read_bits(1)? == 1;
343 let (cl, cr, ct, cb) = if frame_cropping_flag {
344 (br.read_ue()?, br.read_ue()?, br.read_ue()?, br.read_ue()?)
345 } else {
346 (0, 0, 0, 0)
347 };
348
349 let pic_width_in_mbs = pic_width_in_mbs_minus1.saturating_add(1);
350 let pic_height_in_map_units = pic_height_in_map_units_minus1.saturating_add(1);
351 let frame_mbs_only = frame_mbs_only_flag == 1;
352 let frame_height_in_mbs = if frame_mbs_only {
353 pic_height_in_map_units
354 } else {
355 pic_height_in_map_units.saturating_mul(2)
356 };
357
358 let chroma_array_type = if separate_colour_plane_flag {
360 0
361 } else {
362 chroma_format_idc
363 };
364 let (sub_w, sub_h) = match chroma_array_type {
365 0 => (1u32, 1u32), 1 => (2, 2), 2 => (2, 1), 3 => (1, 1), _ => (1, 1),
370 };
371 let (crop_x, crop_y) = if chroma_array_type == 0 {
372 (1u32, 2u32 - frame_mbs_only_flag)
373 } else {
374 (sub_w, sub_h * (2 - frame_mbs_only_flag))
375 };
376
377 let width = pic_width_in_mbs
378 .saturating_mul(16)
379 .saturating_sub(crop_x.saturating_mul(cl.saturating_add(cr)));
380 let height = frame_height_in_mbs
381 .saturating_mul(16)
382 .saturating_sub(crop_y.saturating_mul(ct.saturating_add(cb)));
383
384 Some(H264Dims {
385 width,
386 height,
387 frame_mbs_only,
388 log2_max_frame_num_minus4,
389 pic_order_cnt_type,
390 log2_max_pic_order_cnt_lsb_minus4,
391 delta_pic_order_always_zero_flag,
392 offset_for_non_ref_pic,
393 offset_for_top_to_bottom_field,
394 num_ref_frames_in_pic_order_cnt_cycle,
395 offset_for_ref_frame,
396 max_num_ref_frames,
397 gaps_in_frame_num_value_allowed_flag,
398 mb_adaptive_frame_field_flag,
399 direct_8x8_inference_flag,
400 frame_cropping_flag,
401 crop_left: cl,
402 crop_right: cr,
403 crop_top: ct,
404 crop_bottom: cb,
405 })
406}
407
408pub fn h264_first_slice_nal_offset(data: &[u8]) -> Option<u32> {
414 let mut i = 0;
415 while i + 4 < data.len() {
416 let (start_len, nal_byte) = if data[i] == 0 && data[i + 1] == 0 && data[i + 2] == 1 {
417 (3usize, i + 3)
418 } else if data[i] == 0 && data[i + 1] == 0 && data[i + 2] == 0 && data[i + 3] == 1 {
419 (4usize, i + 4)
420 } else {
421 i += 1;
422 continue;
423 };
424 if nal_byte >= data.len() {
425 return None;
426 }
427 let t = data[nal_byte] & 0x1F;
428 if matches!(t, 1 | 5 | 19) {
429 return Some(nal_byte as u32);
430 }
431 i += start_len;
432 }
433 None
434}
435
436#[derive(Debug, Clone, Copy, PartialEq, Eq)]
449pub struct H264PpsInfo {
450 pub pic_parameter_set_id: u8,
451 pub seq_parameter_set_id: u8,
452 pub entropy_coding_mode_flag: bool,
453 pub bottom_field_pic_order_in_frame_present_flag: bool,
457 pub num_slice_groups_minus1: u8,
458 pub num_ref_idx_l0_default_active_minus1: u8,
459 pub num_ref_idx_l1_default_active_minus1: u8,
460 pub weighted_pred_flag: bool,
461 pub weighted_bipred_idc: u8,
462 pub pic_init_qp_minus26: i8,
463 pub pic_init_qs_minus26: i8,
464 pub chroma_qp_index_offset: i8,
465 pub deblocking_filter_control_present_flag: bool,
466 pub constrained_intra_pred_flag: bool,
467 pub redundant_pic_cnt_present_flag: bool,
468 pub transform_8x8_mode_flag: Option<bool>,
472 pub pic_scaling_matrix_present_flag: Option<bool>,
473 pub second_chroma_qp_index_offset: Option<i8>,
474}
475
476pub fn parse_h264_pps(sample: &[u8]) -> Option<H264PpsInfo> {
487 let pps = find_h264_nal_by_type(sample, 8)?;
488 let rbsp = remove_h264_rbsp_stuffing(pps);
489 let mut br = BitReader::new(&rbsp);
490
491 let pic_parameter_set_id = br.read_ue()? as u8;
492 let seq_parameter_set_id = br.read_ue()? as u8;
493 let entropy_coding_mode_flag = br.read_bits(1)? == 1;
494 let bottom_field_pic_order_in_frame_present_flag = br.read_bits(1)? == 1;
495
496 let num_slice_groups_minus1 = br.read_ue()?;
497 if num_slice_groups_minus1 > 0 {
498 let slice_group_map_type = br.read_ue()?;
500 match slice_group_map_type {
501 0 => {
502 for _ in 0..=num_slice_groups_minus1 {
503 let _run_length_minus1 = br.read_ue()?;
504 }
505 }
506 2 => {
507 for _ in 0..num_slice_groups_minus1 {
508 let _top_left = br.read_ue()?;
509 let _bottom_right = br.read_ue()?;
510 }
511 }
512 3..=5 => {
513 let _slice_group_change_direction_flag = br.read_bits(1)?;
514 let _slice_group_change_rate_minus1 = br.read_ue()?;
515 }
516 6 => {
517 let pic_size_in_map_units_minus1 = br.read_ue()?;
518 let bits = ((num_slice_groups_minus1 + 1) as f64).log2().ceil() as usize;
519 let bits = bits.max(1);
520 for _ in 0..=pic_size_in_map_units_minus1 {
521 let _slice_group_id = br.read_bits(bits)?;
522 }
523 }
524 _ => {}
525 }
526 }
527
528 let num_ref_idx_l0_default_active_minus1 = br.read_ue()? as u8;
529 let num_ref_idx_l1_default_active_minus1 = br.read_ue()? as u8;
530 let weighted_pred_flag = br.read_bits(1)? == 1;
531 let weighted_bipred_idc = br.read_bits(2)? as u8;
532 let pic_init_qp_minus26 = clamp_to_i8(br.read_se()?);
533 let pic_init_qs_minus26 = clamp_to_i8(br.read_se()?);
534 let chroma_qp_index_offset = clamp_to_i8(br.read_se()?);
535 let deblocking_filter_control_present_flag = br.read_bits(1)? == 1;
536 let constrained_intra_pred_flag = br.read_bits(1)? == 1;
537 let redundant_pic_cnt_present_flag = br.read_bits(1)? == 1;
538
539 let (transform_8x8_mode_flag, pic_scaling_matrix_present_flag, second_chroma_qp_index_offset) =
545 if more_rbsp_data(&br, &rbsp) {
546 let t8 = br.read_bits(1).map(|v| v == 1);
547 let psm = br.read_bits(1).map(|v| v == 1);
548 if let Some(true) = psm {
552 let count = 6 + if let Some(true) = t8 { 2 } else { 0 };
557 for i in 0..count {
558 if br.read_bits(1) == Some(1) {
559 let size = if i < 6 { 16 } else { 64 };
560 let mut last_scale: i32 = 8;
561 let mut next_scale: i32 = 8;
562 for _ in 0..size {
563 if next_scale != 0 {
564 let delta = br.read_se().unwrap_or(0);
565 next_scale = (last_scale + delta + 256).rem_euclid(256);
566 }
567 if next_scale != 0 {
568 last_scale = next_scale;
569 }
570 }
571 }
572 }
573 }
574 let s2 = br.read_se().map(clamp_to_i8);
575 (t8, psm, s2)
576 } else {
577 (None, None, None)
578 };
579
580 Some(H264PpsInfo {
581 pic_parameter_set_id,
582 seq_parameter_set_id,
583 entropy_coding_mode_flag,
584 bottom_field_pic_order_in_frame_present_flag,
585 num_slice_groups_minus1: num_slice_groups_minus1.min(u8::MAX as u32) as u8,
586 num_ref_idx_l0_default_active_minus1,
587 num_ref_idx_l1_default_active_minus1,
588 weighted_pred_flag,
589 weighted_bipred_idc,
590 pic_init_qp_minus26,
591 pic_init_qs_minus26,
592 chroma_qp_index_offset,
593 deblocking_filter_control_present_flag,
594 constrained_intra_pred_flag,
595 redundant_pic_cnt_present_flag,
596 transform_8x8_mode_flag,
597 pic_scaling_matrix_present_flag,
598 second_chroma_qp_index_offset,
599 })
600}
601
602#[derive(Debug, Clone, Copy, PartialEq, Eq)]
610pub enum H264SliceType {
611 P,
612 B,
613 I,
614 SP,
615 SI,
616}
617
618impl H264SliceType {
619 pub(super) fn from_ue(v: u32) -> Option<Self> {
620 match v % 5 {
621 0 => Some(Self::P),
622 1 => Some(Self::B),
623 2 => Some(Self::I),
624 3 => Some(Self::SP),
625 4 => Some(Self::SI),
626 _ => None,
627 }
628 }
629}
630
631#[derive(Debug, Clone, Copy, PartialEq, Eq)]
638pub struct H264SliceHeader {
639 pub first_mb_in_slice: u32,
640 pub slice_type: H264SliceType,
641 pub pic_parameter_set_id: u8,
642 pub is_idr: bool,
646 pub frame_num: u32,
647 pub field_pic_flag: bool,
651 pub bottom_field_flag: bool,
652 pub colour_plane_id: Option<u8>,
653 pub idr_pic_id: Option<u32>,
655 pub pic_order_cnt_lsb: Option<u32>,
657 pub delta_pic_order_cnt_bottom: Option<i32>,
658 pub delta_pic_order_cnt: [Option<i32>; 2],
664}
665
666pub fn parse_h264_slice_header(
674 sample: &[u8],
675 sps: &H264SpsInfo,
676 pps: &H264PpsInfo,
677) -> Option<H264SliceHeader> {
678 let (nal_type, rbsp) = find_h264_slice_nal(sample)?;
682 let is_idr = nal_type == 5;
683
684 let mut br = BitReader::new(&rbsp);
685 let first_mb_in_slice = br.read_ue()?;
686 let slice_type_code = br.read_ue()?;
687 let slice_type = H264SliceType::from_ue(slice_type_code)?;
688 let pic_parameter_set_id = br.read_ue()? as u8;
689
690 let colour_plane_id = if sps.separate_colour_plane_flag {
691 Some(br.read_bits(2)? as u8)
692 } else {
693 None
694 };
695
696 let frame_num_bits = (sps.log2_max_frame_num_minus4? as usize) + 4;
697 let frame_num = br.read_bits(frame_num_bits)?;
698
699 let (field_pic_flag, bottom_field_flag) = if !sps.frame_mbs_only {
700 let f = br.read_bits(1)? == 1;
701 let b = if f { br.read_bits(1)? == 1 } else { false };
702 (f, b)
703 } else {
704 (false, false)
705 };
706
707 let idr_pic_id = if is_idr { Some(br.read_ue()?) } else { None };
708
709 let poc_type = sps.pic_order_cnt_type?;
710 let mut pic_order_cnt_lsb = None;
711 let mut delta_pic_order_cnt_bottom = None;
712 let mut delta_pic_order_cnt: [Option<i32>; 2] = [None, None];
713 match poc_type {
714 0 => {
715 let bits = (sps.log2_max_pic_order_cnt_lsb_minus4? as usize) + 4;
716 pic_order_cnt_lsb = Some(br.read_bits(bits)?);
717 if pps.bottom_field_pic_order_in_frame_present_flag && !field_pic_flag {
718 delta_pic_order_cnt_bottom = Some(br.read_se()?);
719 }
720 }
721 1 => {
722 let always_zero = sps.delta_pic_order_always_zero_flag.unwrap_or(false);
723 if !always_zero {
724 delta_pic_order_cnt[0] = Some(br.read_se()?);
725 if pps.bottom_field_pic_order_in_frame_present_flag && !field_pic_flag {
726 delta_pic_order_cnt[1] = Some(br.read_se()?);
727 }
728 }
729 }
730 2 => { }
731 _ => return None,
732 }
733
734 Some(H264SliceHeader {
735 first_mb_in_slice,
736 slice_type,
737 pic_parameter_set_id,
738 is_idr,
739 frame_num,
740 field_pic_flag,
741 bottom_field_flag,
742 colour_plane_id,
743 idr_pic_id,
744 pic_order_cnt_lsb,
745 delta_pic_order_cnt_bottom,
746 delta_pic_order_cnt,
747 })
748}
749
750fn find_h264_slice_nal(data: &[u8]) -> Option<(u8, Vec<u8>)> {
753 let mut i = 0;
754 while i + 4 < data.len() {
755 let (start_len, nal_byte) = if data[i] == 0 && data[i + 1] == 0 && data[i + 2] == 1 {
756 (3, i + 3)
757 } else if data[i] == 0 && data[i + 1] == 0 && data[i + 2] == 0 && data[i + 3] == 1 {
758 (4, i + 4)
759 } else {
760 i += 1;
761 continue;
762 };
763 if nal_byte >= data.len() {
764 return None;
765 }
766 let nal_unit_type = data[nal_byte] & 0x1F;
767 if matches!(nal_unit_type, 1 | 5 | 19) {
768 let start = nal_byte + 1;
769 let end = find_next_start_code(&data[start..])
770 .map(|off| start + off)
771 .unwrap_or(data.len());
772 let rbsp = remove_h264_rbsp_stuffing(&data[start..end]);
773 return Some((nal_unit_type, rbsp));
774 }
775 i += start_len;
776 }
777 None
778}
779
780fn find_h264_nal_by_type(data: &[u8], target_type: u8) -> Option<&[u8]> {
784 let mut i = 0;
785 while i + 4 < data.len() {
786 let (start_len, nal_byte) = if data[i] == 0 && data[i + 1] == 0 && data[i + 2] == 1 {
787 (3, i + 3)
788 } else if data[i] == 0 && data[i + 1] == 0 && data[i + 2] == 0 && data[i + 3] == 1 {
789 (4, i + 4)
790 } else {
791 i += 1;
792 continue;
793 };
794 if nal_byte >= data.len() {
795 return None;
796 }
797 let nal_unit_type = data[nal_byte] & 0x1F;
798 if nal_unit_type == target_type {
799 let start = nal_byte + 1;
800 let end = find_next_start_code(&data[start..])
801 .map(|off| start + off)
802 .unwrap_or(data.len());
803 return Some(&data[start..end]);
804 }
805 i += start_len;
806 }
807 None
808}