1use crate::frame::PixelFormat;
16
17pub fn detect(codec: &str, samples: &[Vec<u8>]) -> PixelFormat {
22 if samples.is_empty() {
23 return PixelFormat::Yuv420p;
24 }
25
26 let result = match codec.to_lowercase().as_str() {
27 "h264" | "avc1" | "avc" => detect_h264(&samples[0]),
28 "h265" | "hevc" | "hvc1" | "hev1" => detect_hevc(&samples[0]),
29 "vp9" | "vp09" => detect_vp9(&samples[0]),
30 "av1" | "av01" => detect_av1(&samples[0]),
31 _ => None,
32 };
33
34 result.unwrap_or(PixelFormat::Yuv420p)
35}
36
37struct BitReader<'a> {
39 data: &'a [u8],
40 pos: usize,
41}
42
43impl<'a> BitReader<'a> {
44 fn new(data: &'a [u8]) -> Self {
45 Self { data, pos: 0 }
46 }
47
48 fn read_bits(&mut self, n: usize) -> Option<u32> {
49 let mut val = 0u32;
50 for _ in 0..n {
51 let byte_idx = self.pos / 8;
52 let bit_idx = 7 - (self.pos % 8);
53 if byte_idx >= self.data.len() {
54 return None;
55 }
56 val = (val << 1) | (((self.data[byte_idx] >> bit_idx) & 1) as u32);
57 self.pos += 1;
58 }
59 Some(val)
60 }
61
62 fn read_ue(&mut self) -> Option<u32> {
64 let mut zeros = 0;
65 while self.read_bits(1)? == 0 {
66 zeros += 1;
67 if zeros > 31 {
68 return None;
72 }
73 }
74 if zeros == 0 {
75 return Some(0);
76 }
77 let suffix = self.read_bits(zeros)?;
78 Some((1u32 << zeros) - 1 + suffix)
79 }
80
81 fn read_se(&mut self) -> Option<i32> {
87 let code = self.read_ue()? as i64;
88 let signed = if code & 1 == 1 {
89 ((code + 1) / 2) as i32
90 } else {
91 -((code / 2) as i32)
92 };
93 Some(signed)
94 }
95
96 fn bit_pos(&self) -> usize {
99 self.pos
100 }
101
102 fn byte_align(&mut self) {
105 let rem = self.pos & 7;
106 if rem != 0 {
107 self.pos += 8 - rem;
108 }
109 }
110
111 fn read_su(&mut self, n: usize) -> Option<i32> {
114 let raw = self.read_bits(n)?;
115 let sign_bit = 1u32 << (n - 1);
116 let signed = if raw & sign_bit != 0 {
117 (raw as i32) - (1i32 << n)
118 } else {
119 raw as i32
120 };
121 Some(signed)
122 }
123}
124
125fn detect_h264(sample: &[u8]) -> Option<PixelFormat> {
131 let sps = find_h264_sps(sample)?;
132 let rbsp = remove_h264_rbsp_stuffing(sps);
133 let mut br = BitReader::new(&rbsp);
134
135 let profile_idc = br.read_bits(8)? as u8;
136 let _constraint_flags = br.read_bits(8)?;
137 let _level_idc = br.read_bits(8)?;
138 let _seq_parameter_set_id = br.read_ue()?;
139
140 let profile_gates_chroma = matches!(
141 profile_idc,
142 100 | 110 | 122 | 244 | 44 | 83 | 86 | 118 | 128 | 138 | 139 | 134 | 135
143 );
144
145 let (chroma_format_idc, bit_depth_luma) = if profile_gates_chroma {
146 let chroma_format_idc = br.read_ue()? as u8;
147 if chroma_format_idc == 3 {
148 let _separate_colour_plane_flag = br.read_bits(1)?;
149 }
150 let bit_depth_luma_minus8 = br.read_ue()? as u8;
151 (chroma_format_idc, bit_depth_luma_minus8 + 8)
152 } else {
153 (1, 8)
155 };
156
157 Some(PixelFormat::from_chroma_and_depth(
158 chroma_format_idc,
159 bit_depth_luma,
160 ))
161}
162
163fn find_h264_sps(data: &[u8]) -> Option<&[u8]> {
167 let mut i = 0;
168 while i + 4 < data.len() {
169 let (start_len, nal_byte) = if data[i] == 0 && data[i + 1] == 0 && data[i + 2] == 1 {
170 (3, i + 3)
171 } else if data[i] == 0 && data[i + 1] == 0 && data[i + 2] == 0 && data[i + 3] == 1 {
172 (4, i + 4)
173 } else {
174 i += 1;
175 continue;
176 };
177 if nal_byte >= data.len() {
178 return None;
179 }
180 let nal_unit_type = data[nal_byte] & 0x1F;
181 if nal_unit_type == 7 {
182 let start = nal_byte + 1;
184 let end = find_next_start_code(&data[start..])
185 .map(|off| start + off)
186 .unwrap_or(data.len());
187 return Some(&data[start..end]);
188 }
189 i += start_len;
190 }
191 None
192}
193
194fn find_next_start_code(data: &[u8]) -> Option<usize> {
195 (0..data.len().saturating_sub(3)).find(|&i| {
196 data[i] == 0
197 && data[i + 1] == 0
198 && (data[i + 2] == 1 || (data[i + 2] == 0 && data[i + 3] == 1))
199 })
200}
201
202fn remove_h264_rbsp_stuffing(sps: &[u8]) -> Vec<u8> {
204 let mut out = Vec::with_capacity(sps.len());
205 let mut i = 0;
206 while i < sps.len() {
207 if i + 2 < sps.len() && sps[i] == 0 && sps[i + 1] == 0 && sps[i + 2] == 3 {
208 out.push(0);
209 out.push(0);
210 i += 3;
211 } else {
212 out.push(sps[i]);
213 i += 1;
214 }
215 }
216 out
217}
218
219fn detect_hevc(sample: &[u8]) -> Option<PixelFormat> {
223 let sps = find_hevc_sps(sample)?;
224 let rbsp = remove_h264_rbsp_stuffing(sps);
225 let mut br = BitReader::new(&rbsp);
226
227 let _sps_video_parameter_set_id = br.read_bits(4)?;
228 let sps_max_sub_layers_minus1 = br.read_bits(3)? as usize;
229 let _sps_temporal_id_nesting_flag = br.read_bits(1)?;
230
231 skip_hevc_profile_tier_level(&mut br, sps_max_sub_layers_minus1)?;
235
236 let _sps_seq_parameter_set_id = br.read_ue()?;
237 let chroma_format_idc = br.read_ue()? as u8;
238 if chroma_format_idc == 3 {
239 let _separate_colour_plane_flag = br.read_bits(1)?;
240 }
241 let _pic_width = br.read_ue()?;
242 let _pic_height = br.read_ue()?;
243 let conformance_window_flag = br.read_bits(1)?;
244 if conformance_window_flag == 1 {
245 let _ = br.read_ue()?;
246 let _ = br.read_ue()?;
247 let _ = br.read_ue()?;
248 let _ = br.read_ue()?;
249 }
250 let bit_depth_luma = br.read_ue()? as u8 + 8;
251 let _bit_depth_chroma_minus8 = br.read_ue()?;
252
253 Some(PixelFormat::from_chroma_and_depth(
254 chroma_format_idc,
255 bit_depth_luma,
256 ))
257}
258
259fn find_hevc_sps(data: &[u8]) -> Option<&[u8]> {
260 let mut i = 0;
261 while i + 4 < data.len() {
262 let (start_len, nal_byte) = if data[i] == 0 && data[i + 1] == 0 && data[i + 2] == 1 {
263 (3, i + 3)
264 } else if data[i] == 0 && data[i + 1] == 0 && data[i + 2] == 0 && data[i + 3] == 1 {
265 (4, i + 4)
266 } else {
267 i += 1;
268 continue;
269 };
270 if nal_byte + 1 >= data.len() {
271 return None;
272 }
273 let nal_unit_type = (data[nal_byte] >> 1) & 0x3F;
275 if nal_unit_type == 33 {
276 let start = nal_byte + 2;
278 let end = find_next_start_code(&data[start..])
279 .map(|off| start + off)
280 .unwrap_or(data.len());
281 return Some(&data[start..end]);
282 }
283 i += start_len;
284 }
285 None
286}
287
288fn skip_hevc_profile_tier_level(br: &mut BitReader, max_sub_layers_minus1: usize) -> Option<()> {
289 let _ = br.read_bits(8)?;
291 let _ = br.read_bits(32)?;
293 let _ = br.read_bits(48)?;
296 let _ = br.read_bits(8)?;
297
298 let mut sub_layer_profile_present = Vec::with_capacity(max_sub_layers_minus1);
300 let mut sub_layer_level_present = Vec::with_capacity(max_sub_layers_minus1);
301 for _ in 0..max_sub_layers_minus1 {
302 sub_layer_profile_present.push(br.read_bits(1)?);
303 sub_layer_level_present.push(br.read_bits(1)?);
304 }
305 if max_sub_layers_minus1 > 0 {
306 for _ in max_sub_layers_minus1..8 {
308 let _ = br.read_bits(2)?;
309 }
310 }
311 for i in 0..max_sub_layers_minus1 {
312 if sub_layer_profile_present[i] == 1 {
313 let _ = br.read_bits(8)?;
314 let _ = br.read_bits(32)?;
315 let _ = br.read_bits(48)?;
316 }
317 if sub_layer_level_present[i] == 1 {
318 let _ = br.read_bits(8)?;
319 }
320 }
321 Some(())
322}
323
324fn detect_vp9(sample: &[u8]) -> Option<PixelFormat> {
328 if sample.len() < 2 {
329 return None;
330 }
331 let mut br = BitReader::new(sample);
332 let frame_marker = br.read_bits(2)?;
333 if frame_marker != 2 {
334 return None;
335 }
336 let profile_low = br.read_bits(1)?;
337 let profile_high = br.read_bits(1)?;
338 let profile = (profile_high << 1) | profile_low;
339 if profile == 3 {
340 let _reserved_zero = br.read_bits(1)?;
341 }
342 let show_existing_frame = br.read_bits(1)?;
343 if show_existing_frame == 1 {
344 return None;
345 }
346 let frame_type = br.read_bits(1)?;
347 let _show_frame = br.read_bits(1)?;
348 let _error_resilient = br.read_bits(1)?;
349
350 if frame_type != 0 {
352 return None;
353 }
354
355 let sync = br.read_bits(24)?;
357 if sync != 0x498342 {
358 return None;
359 }
360
361 let bit_depth = if profile >= 2 {
362 if br.read_bits(1)? == 0 { 10 } else { 12 }
363 } else {
364 8
365 };
366 let _color_space = br.read_bits(3)?;
367 let (sx, sy) = if profile == 1 || profile == 3 {
371 let _color_range = br.read_bits(1)?;
372 let sx = br.read_bits(1)?;
373 let sy = br.read_bits(1)?;
374 (sx, sy)
375 } else {
376 (1, 1) };
378
379 let chroma_idc = match (sx, sy) {
380 (1, 1) => 1, (1, 0) => 2, (0, 0) => 3, _ => 1,
384 };
385
386 Some(PixelFormat::from_chroma_and_depth(chroma_idc, bit_depth))
387}
388
389fn detect_av1(sample: &[u8]) -> Option<PixelFormat> {
394 let obu = find_av1_obu(sample, 1)?;
396 let mut br = BitReader::new(obu);
397
398 let _seq_profile = br.read_bits(3)?;
399 let _still_picture = br.read_bits(1)?;
400 let reduced_still_picture_header = br.read_bits(1)?;
401
402 if reduced_still_picture_header == 0 {
403 let timing_info_present = br.read_bits(1)?;
407 if timing_info_present == 1 {
408 let _num_units_in_display_tick = br.read_bits(32)?;
409 let _time_scale = br.read_bits(32)?;
410 let equal_picture_interval = br.read_bits(1)?;
411 if equal_picture_interval == 1 {
412 let _num_ticks_per_picture = br.read_ue()?; }
414 let decoder_model_info_present = br.read_bits(1)?;
415 if decoder_model_info_present == 1 {
416 let _buffer_delay_length_minus_1 = br.read_bits(5)?;
417 let _num_units_in_decoding_tick = br.read_bits(32)?;
418 let _buffer_removal_time_length_minus_1 = br.read_bits(5)?;
419 let _frame_presentation_time_length_minus_1 = br.read_bits(5)?;
420 }
421 }
422 return Some(PixelFormat::Yuv420p);
429 }
430
431 let _seq_level_idx_0 = br.read_bits(5)?;
434
435 Some(PixelFormat::Yuv420p)
439}
440
441fn find_av1_obu(data: &[u8], target_type: u8) -> Option<&[u8]> {
448 find_av1_obu_with_offset(data, target_type).map(|(bytes, _)| bytes)
449}
450
451pub fn find_av1_obu_with_offset_pub(data: &[u8], target_type: u8) -> Option<(&[u8], usize)> {
454 find_av1_obu_with_offset(data, target_type)
455}
456
457fn find_av1_obu_with_offset(data: &[u8], target_type: u8) -> Option<(&[u8], usize)> {
462 let mut i = 0;
463 while i < data.len() {
464 let header = data[i];
465 let obu_type = (header >> 3) & 0x0F;
466 let extension_flag = (header >> 2) & 0x01;
467 let has_size_field = (header >> 1) & 0x01;
468 i += 1;
469 if extension_flag == 1 {
470 i += 1;
471 }
472 if has_size_field == 0 {
473 return None;
474 }
475 let (size, leb_bytes) = read_leb128(&data[i..])?;
476 i += leb_bytes;
477 if obu_type == target_type {
478 let end = (i + size as usize).min(data.len());
479 return Some((&data[i..end], i));
480 }
481 i += size as usize;
482 }
483 None
484}
485
486fn read_leb128(data: &[u8]) -> Option<(u64, usize)> {
487 let mut value = 0u64;
488 for i in 0..8 {
489 if i >= data.len() {
490 return None;
491 }
492 let byte = data[i];
493 value |= ((byte & 0x7F) as u64) << (i * 7);
494 if byte & 0x80 == 0 {
495 return Some((value, i + 1));
496 }
497 }
498 None
499}
500
501#[derive(Debug, Clone, PartialEq, Eq)]
528pub struct H264SpsInfo {
529 pub profile_idc: u8,
530 pub constraint_set_flags: u8,
534 pub level_idc: u8,
535 pub chroma_format_idc: u8,
536 pub separate_colour_plane_flag: bool,
537 pub bit_depth_luma: u8,
538 pub bit_depth_chroma: u8,
539 pub frame_mbs_only: bool,
540 pub width: Option<u32>,
543 pub height: Option<u32>,
544 pub log2_max_frame_num_minus4: Option<u8>,
549 pub pic_order_cnt_type: Option<u8>,
552 pub log2_max_pic_order_cnt_lsb_minus4: Option<u8>,
555 pub delta_pic_order_always_zero_flag: Option<bool>,
558 pub qpprime_y_zero_transform_bypass_flag: Option<bool>,
560 pub seq_scaling_matrix_present_flag: Option<bool>,
561 pub max_num_ref_frames: Option<u8>,
562 pub gaps_in_frame_num_value_allowed_flag: Option<bool>,
563 pub mb_adaptive_frame_field_flag: Option<bool>,
565 pub direct_8x8_inference_flag: Option<bool>,
566 pub frame_cropping_flag: Option<bool>,
567 pub frame_crop_left_offset: Option<u32>,
568 pub frame_crop_right_offset: Option<u32>,
569 pub frame_crop_top_offset: Option<u32>,
570 pub frame_crop_bottom_offset: Option<u32>,
571 pub offset_for_non_ref_pic: Option<i32>,
573 pub offset_for_top_to_bottom_field: Option<i32>,
574 pub num_ref_frames_in_pic_order_cnt_cycle: Option<u8>,
575 pub offset_for_ref_frame: Vec<i32>,
580}
581
582#[derive(Debug, Clone, PartialEq, Eq)]
588pub struct HevcSpsInfo {
589 pub sps_video_parameter_set_id: u8,
590 pub sps_seq_parameter_set_id: u8,
591 pub sps_max_sub_layers_minus1: u8,
592 pub sps_temporal_id_nesting_flag: bool,
593 pub chroma_format_idc: u8,
594 pub separate_colour_plane_flag: bool,
595 pub bit_depth_luma: u8,
596 pub bit_depth_chroma: u8,
597 pub width: Option<u32>,
598 pub height: Option<u32>,
599 pub conf_win_left_offset: u32,
601 pub conf_win_right_offset: u32,
602 pub conf_win_top_offset: u32,
603 pub conf_win_bottom_offset: u32,
604 pub log2_max_pic_order_cnt_lsb_minus4: u8,
605 pub log2_min_luma_coding_block_size_minus3: u8,
606 pub log2_diff_max_min_luma_coding_block_size: u8,
607 pub log2_min_luma_transform_block_size_minus2: u8,
608 pub log2_diff_max_min_luma_transform_block_size: u8,
609 pub max_transform_hierarchy_depth_inter: u8,
610 pub max_transform_hierarchy_depth_intra: u8,
611 pub scaling_list_enabled_flag: bool,
612 pub sps_sub_layer_ordering_info_present_flag: bool,
613 pub amp_enabled_flag: bool,
614 pub sample_adaptive_offset_enabled_flag: bool,
615 pub pcm_enabled_flag: bool,
616 pub pcm_loop_filter_disabled_flag: bool,
618 pub num_short_term_ref_pic_sets: u8,
619 pub long_term_ref_pics_present_flag: bool,
620 pub sps_temporal_mvp_enabled_flag: bool,
621 pub strong_intra_smoothing_enabled_flag: bool,
622 pub profile_idc: u8,
623 pub level_idc: u8,
624 pub tier_flag: bool,
625 pub max_dec_pic_buffering_minus1: [u8; 7],
629 pub max_num_reorder_pics: [u8; 7],
630 pub max_latency_increase_plus1: [u32; 7],
631 pub profile_compatibility_flags: u32,
634}
635
636#[derive(Debug, Clone, Copy, PartialEq, Eq)]
638pub struct H265VpsInfo {
639 pub vps_video_parameter_set_id: u8,
640 pub vps_max_sub_layers_minus1: u8,
641 pub vps_temporal_id_nesting_flag: bool,
642 pub profile_idc: u8,
643 pub level_idc: u8,
644 pub tier_flag: bool,
645}
646
647#[derive(Debug, Clone, Copy, PartialEq, Eq)]
649pub struct H265PpsInfo {
650 pub pps_pic_parameter_set_id: u8,
651 pub pps_seq_parameter_set_id: u8,
652 pub dependent_slice_segments_enabled_flag: bool,
653 pub output_flag_present_flag: bool,
654 pub num_extra_slice_header_bits: u8,
655 pub sign_data_hiding_enabled_flag: bool,
656 pub cabac_init_present_flag: bool,
657 pub num_ref_idx_l0_default_active_minus1: u8,
658 pub num_ref_idx_l1_default_active_minus1: u8,
659 pub init_qp_minus26: i8,
660 pub constrained_intra_pred_flag: bool,
661 pub transform_skip_enabled_flag: bool,
662 pub cu_qp_delta_enabled_flag: bool,
663 pub diff_cu_qp_delta_depth: u8,
664 pub pps_cb_qp_offset: i8,
665 pub pps_cr_qp_offset: i8,
666 pub pps_slice_chroma_qp_offsets_present_flag: bool,
667 pub weighted_pred_flag: bool,
668 pub weighted_bipred_flag: bool,
669 pub transquant_bypass_enabled_flag: bool,
670 pub tiles_enabled_flag: bool,
671 pub entropy_coding_sync_enabled_flag: bool,
672 pub num_tile_columns_minus1: u8,
675 pub num_tile_rows_minus1: u8,
676 pub uniform_spacing_flag: bool,
677 pub loop_filter_across_tiles_enabled_flag: bool,
678 pub pps_loop_filter_across_slices_enabled_flag: bool,
680 pub deblocking_filter_control_present_flag: bool,
681 pub deblocking_filter_override_enabled_flag: bool,
682 pub pps_deblocking_filter_disabled_flag: bool,
683 pub pps_beta_offset_div2: i8,
684 pub pps_tc_offset_div2: i8,
685 pub pps_scaling_list_data_present_flag: bool,
686 pub lists_modification_present_flag: bool,
687 pub log2_parallel_merge_level_minus2: u8,
688 pub slice_segment_header_extension_present_flag: bool,
689 pub pps_extension_present_flag: bool,
690}
691
692#[derive(Debug, Clone, Copy, PartialEq, Eq)]
694pub struct H265SliceHeader {
695 pub first_slice_segment_in_pic_flag: bool,
696 pub nal_unit_type: u8,
697 pub slice_pic_parameter_set_id: u8,
698 pub slice_type: H265SliceType,
699 pub pic_order_cnt_lsb: u32,
700 pub short_term_ref_pic_set_sps_flag: bool,
701 pub short_term_ref_pic_set_idx: Option<u8>,
702 pub is_irap: bool,
704 pub is_idr: bool,
706}
707
708#[derive(Debug, Clone, Copy, PartialEq, Eq)]
709pub enum H265SliceType {
710 B,
711 P,
712 I,
713}
714
715impl H265SliceType {
716 fn from_ue(v: u32) -> Option<Self> {
717 match v {
718 0 => Some(Self::B),
719 1 => Some(Self::P),
720 2 => Some(Self::I),
721 _ => None,
722 }
723 }
724}
725
726#[derive(Debug, Clone, Copy, PartialEq, Eq)]
730pub struct Av1SequenceHeader {
731 pub seq_profile: u8,
732 pub still_picture: bool,
733 pub reduced_still_picture_header: bool,
734 pub max_frame_width_minus1: u32,
735 pub max_frame_height_minus1: u32,
736 pub seq_level_idx_0: u8,
737 pub seq_tier_0: u8,
743 pub bit_depth: u8,
744 pub monochrome: bool,
745 pub color_primaries: u8,
746 pub transfer_characteristics: u8,
747 pub matrix_coefficients: u8,
748 pub color_range: bool,
749 pub chroma_subsampling_x: bool,
750 pub chroma_subsampling_y: bool,
751 pub film_grain_params_present: bool,
752 pub enable_filter_intra: bool,
753 pub enable_intra_edge_filter: bool,
754 pub enable_interintra_compound: bool,
755 pub enable_masked_compound: bool,
756 pub enable_warped_motion: bool,
757 pub enable_dual_filter: bool,
758 pub enable_order_hint: bool,
759 pub enable_jnt_comp: bool,
760 pub enable_ref_frame_mvs: bool,
761 pub enable_superres: bool,
762 pub enable_cdef: bool,
763 pub enable_restoration: bool,
764 pub order_hint_bits: u8,
765 pub seq_force_screen_content_tools: u8,
770 pub seq_force_integer_mv: u8,
773 pub frame_width_bits_minus_1: u8,
778 pub frame_height_bits_minus_1: u8,
779 pub use_128x128_superblock: bool,
780 pub separate_uv_delta_q: bool,
785}
786
787#[derive(Debug, Clone)]
792pub struct Av1FrameHeader {
793 pub show_frame: bool,
794 pub showable_frame: bool,
795 pub frame_type: Av1FrameType,
796 pub error_resilient_mode: bool,
797 pub disable_cdf_update: bool,
798 pub allow_screen_content_tools: bool,
799 pub force_integer_mv: bool,
800 pub order_hint: u32,
801 pub primary_ref_frame: u8,
802 pub refresh_frame_flags: u8,
803 pub frame_width: u32,
804 pub frame_height: u32,
805 pub render_width: u32,
806 pub render_height: u32,
807 pub use_ref_frame_mvs: bool,
808 pub allow_high_precision_mv: bool,
809 pub is_filter_switchable: bool,
810 pub disable_frame_end_update_cdf: bool,
811 pub allow_warped_motion: bool,
812 pub reduced_tx_set: bool,
813 pub allow_intrabc: bool,
815 pub frame_size_override_flag: bool,
816 pub use_superres: bool,
817 pub is_motion_mode_switchable: bool,
818 pub reference_select: bool,
819 pub skip_mode_present: bool,
820 pub tile_cols: u8,
823 pub tile_rows: u8,
824 pub uniform_tile_spacing_flag: bool,
825 pub tile_cols_log2: u8,
826 pub tile_rows_log2: u8,
827 pub mi_col_starts: Vec<u16>, pub mi_row_starts: Vec<u16>, pub width_in_sbs_minus_1: Vec<u16>, pub height_in_sbs_minus_1: Vec<u16>, pub context_update_tile_id: u16,
832 pub tile_size_bytes_minus_1: u8,
833 pub base_q_idx: u8,
835 pub delta_q_y_dc: i8,
836 pub delta_q_u_dc: i8,
837 pub delta_q_u_ac: i8,
838 pub delta_q_v_dc: i8,
839 pub delta_q_v_ac: i8,
840 pub using_qmatrix: bool,
841 pub qm_y: u8,
842 pub qm_u: u8,
843 pub qm_v: u8,
844 pub delta_q_present: bool,
846 pub delta_q_res: u8,
847 pub delta_lf_present: bool,
848 pub delta_lf_res: u8,
849 pub delta_lf_multi: bool,
850 pub segmentation_enabled: bool,
854 pub segmentation_update_map: bool,
855 pub segmentation_temporal_update: bool,
856 pub segmentation_update_data: bool,
857 pub feature_enabled: [[bool; 8]; 8],
858 pub feature_data: [[i16; 8]; 8],
859 pub loop_filter_level: [u8; 4],
861 pub loop_filter_sharpness: u8,
862 pub loop_filter_delta_enabled: bool,
863 pub loop_filter_delta_update: bool,
864 pub update_ref_delta_mask: u8, pub loop_filter_ref_deltas: [i8; 8],
866 pub update_mode_delta_mask: u8, pub loop_filter_mode_deltas: [i8; 2],
868 pub cdef_damping_minus_3: u8,
870 pub cdef_bits: u8,
871 pub cdef_y_pri_strength: [u8; 8],
872 pub cdef_y_sec_strength: [u8; 8],
873 pub cdef_uv_pri_strength: [u8; 8],
874 pub cdef_uv_sec_strength: [u8; 8],
875 pub lr_type: [u8; 3], pub lr_unit_shift: u8,
878 pub lr_uv_shift: u8,
879 pub tx_mode: u8,
881 pub interpolation_filter: u8,
882 pub tile_group_offset_in_obu: u32,
889 pub coded_lossless: bool,
891}
892
893impl Default for Av1FrameHeader {
894 fn default() -> Self {
895 Self {
896 show_frame: false,
897 showable_frame: false,
898 frame_type: Av1FrameType::Key,
899 error_resilient_mode: false,
900 disable_cdf_update: false,
901 allow_screen_content_tools: false,
902 force_integer_mv: false,
903 order_hint: 0,
904 primary_ref_frame: 7,
905 refresh_frame_flags: 0,
906 frame_width: 0,
907 frame_height: 0,
908 render_width: 0,
909 render_height: 0,
910 use_ref_frame_mvs: false,
911 allow_high_precision_mv: false,
912 is_filter_switchable: false,
913 disable_frame_end_update_cdf: false,
914 allow_warped_motion: false,
915 reduced_tx_set: false,
916 allow_intrabc: false,
917 frame_size_override_flag: false,
918 use_superres: false,
919 is_motion_mode_switchable: false,
920 reference_select: false,
921 skip_mode_present: false,
922 tile_cols: 1,
923 tile_rows: 1,
924 uniform_tile_spacing_flag: true,
925 tile_cols_log2: 0,
926 tile_rows_log2: 0,
927 mi_col_starts: Vec::new(),
928 mi_row_starts: Vec::new(),
929 width_in_sbs_minus_1: Vec::new(),
930 height_in_sbs_minus_1: Vec::new(),
931 context_update_tile_id: 0,
932 tile_size_bytes_minus_1: 3,
933 base_q_idx: 0,
934 delta_q_y_dc: 0,
935 delta_q_u_dc: 0,
936 delta_q_u_ac: 0,
937 delta_q_v_dc: 0,
938 delta_q_v_ac: 0,
939 using_qmatrix: false,
940 qm_y: 0,
941 qm_u: 0,
942 qm_v: 0,
943 delta_q_present: false,
944 delta_q_res: 0,
945 delta_lf_present: false,
946 delta_lf_res: 0,
947 delta_lf_multi: false,
948 segmentation_enabled: false,
949 segmentation_update_map: false,
950 segmentation_temporal_update: false,
951 segmentation_update_data: false,
952 feature_enabled: [[false; 8]; 8],
953 feature_data: [[0; 8]; 8],
954 loop_filter_level: [0; 4],
955 loop_filter_sharpness: 0,
956 loop_filter_delta_enabled: false,
957 loop_filter_delta_update: false,
958 update_ref_delta_mask: 0,
959 loop_filter_ref_deltas: [0; 8],
960 update_mode_delta_mask: 0,
961 loop_filter_mode_deltas: [0; 2],
962 cdef_damping_minus_3: 0,
963 cdef_bits: 0,
964 cdef_y_pri_strength: [0; 8],
965 cdef_y_sec_strength: [0; 8],
966 cdef_uv_pri_strength: [0; 8],
967 cdef_uv_sec_strength: [0; 8],
968 lr_type: [0; 3],
969 lr_unit_shift: 0,
970 lr_uv_shift: 0,
971 tx_mode: 0,
972 interpolation_filter: 0,
973 tile_group_offset_in_obu: 0,
974 coded_lossless: false,
975 }
976 }
977}
978
979#[derive(Debug, Clone, Copy, PartialEq, Eq)]
980pub enum Av1FrameType {
981 Key,
982 Inter,
983 IntraOnly,
984 Switch,
985}
986
987pub fn parse_av1_sequence_header(sample: &[u8]) -> Option<Av1SequenceHeader> {
992 let obu = find_av1_obu(sample, 1)?;
993 let mut br = BitReader::new(obu);
994 let seq_profile = br.read_bits(3)? as u8;
995 let still_picture = br.read_bits(1)? == 1;
996 let reduced_still_picture_header = br.read_bits(1)? == 1;
997
998 let mut seq_level_idx_0 = 0u8;
999 let mut seq_tier_0 = 0u8;
1000 let (_operating_points_cnt_minus_1, _timing_info_present_flag);
1001 let mut order_hint_bits = 0u8;
1002 let mut enable_order_hint = false;
1003
1004 if reduced_still_picture_header {
1005 seq_level_idx_0 = br.read_bits(5)? as u8;
1006 _operating_points_cnt_minus_1 = 0;
1007 _timing_info_present_flag = false;
1008 } else {
1009 let timing_info_present_flag = br.read_bits(1)? == 1;
1010 _timing_info_present_flag = timing_info_present_flag;
1011 let mut decoder_model_info_present_flag = false;
1012 let mut buffer_delay_length_minus_1 = 0u32;
1013 if timing_info_present_flag {
1014 let _num_units_in_display_tick = br.read_bits(32)?;
1015 let _time_scale = br.read_bits(32)?;
1016 let equal_picture_interval = br.read_bits(1)? == 1;
1017 if equal_picture_interval {
1018 let _num_ticks_per_picture_minus_1 = read_av1_uvlc(&mut br)?;
1019 }
1020 decoder_model_info_present_flag = br.read_bits(1)? == 1;
1021 if decoder_model_info_present_flag {
1022 buffer_delay_length_minus_1 = br.read_bits(5)?;
1023 let _num_units_in_decoding_tick = br.read_bits(32)?;
1024 let _buffer_removal_time_length_minus_1 = br.read_bits(5)?;
1025 let _frame_presentation_time_length_minus_1 = br.read_bits(5)?;
1026 }
1027 }
1028 let initial_display_delay_present_flag = br.read_bits(1)? == 1;
1033 let operating_points_cnt_minus_1 = br.read_bits(5)? as u8;
1034 _operating_points_cnt_minus_1 = operating_points_cnt_minus_1;
1035 for i in 0..=operating_points_cnt_minus_1 {
1036 let _operating_point_idc = br.read_bits(12)?;
1037 let seq_level_idx_i = br.read_bits(5)? as u8;
1038 let seq_tier_i = if seq_level_idx_i > 7 {
1041 br.read_bits(1)? as u8
1042 } else {
1043 0
1044 };
1045 if i == 0 {
1046 seq_level_idx_0 = seq_level_idx_i;
1047 seq_tier_0 = seq_tier_i;
1048 }
1049 if decoder_model_info_present_flag {
1052 let decoder_model_present_for_this_op = br.read_bits(1)? == 1;
1053 if decoder_model_present_for_this_op {
1054 let n = (buffer_delay_length_minus_1 + 1) as usize;
1055 let _buffer_delay = br.read_bits(n)?;
1056 let _encoder_buffer_delay = br.read_bits(n)?;
1057 let _low_delay_mode_flag = br.read_bits(1)?;
1058 }
1059 }
1060 if initial_display_delay_present_flag {
1061 let idd_present_for_this_op = br.read_bits(1)? == 1;
1062 if idd_present_for_this_op {
1063 let _initial_display_delay_minus_1 = br.read_bits(4)?;
1064 }
1065 }
1066 }
1067 }
1068 let frame_width_bits_minus_1 = br.read_bits(4)? as usize;
1069 let frame_height_bits_minus_1 = br.read_bits(4)? as usize;
1070 let max_frame_width_minus1 = br.read_bits(frame_width_bits_minus_1 + 1)?;
1071 let max_frame_height_minus1 = br.read_bits(frame_height_bits_minus_1 + 1)?;
1072
1073 let frame_id_numbers_present_flag = if reduced_still_picture_header {
1074 false
1075 } else {
1076 br.read_bits(1)? == 1
1077 };
1078 if frame_id_numbers_present_flag {
1079 let _delta_frame_id_length_minus_2 = br.read_bits(4)?;
1080 let _additional_frame_id_length_minus_1 = br.read_bits(3)?;
1081 }
1082 let use_128x128_superblock = br.read_bits(1)? == 1;
1083 let enable_filter_intra = br.read_bits(1)? == 1;
1084 let enable_intra_edge_filter = br.read_bits(1)? == 1;
1085 let mut enable_interintra_compound = false;
1086 let mut enable_masked_compound = false;
1087 let mut enable_warped_motion = false;
1088 let mut enable_dual_filter = false;
1089 let mut enable_jnt_comp = false;
1090 let mut enable_ref_frame_mvs = false;
1091 let mut seq_force_screen_content_tools: u8 = 2; let mut seq_force_integer_mv: u8 = 2;
1093 if !reduced_still_picture_header {
1094 enable_interintra_compound = br.read_bits(1)? == 1;
1095 enable_masked_compound = br.read_bits(1)? == 1;
1096 enable_warped_motion = br.read_bits(1)? == 1;
1097 enable_dual_filter = br.read_bits(1)? == 1;
1098 enable_order_hint = br.read_bits(1)? == 1;
1099 if enable_order_hint {
1100 enable_jnt_comp = br.read_bits(1)? == 1;
1101 enable_ref_frame_mvs = br.read_bits(1)? == 1;
1102 }
1103 let seq_choose_screen_content_tools = br.read_bits(1)? == 1;
1104 seq_force_screen_content_tools = if seq_choose_screen_content_tools {
1105 2u8
1106 } else {
1107 br.read_bits(1)? as u8
1108 };
1109 if seq_force_screen_content_tools > 0 {
1110 let seq_choose_integer_mv = br.read_bits(1)? == 1;
1111 seq_force_integer_mv = if seq_choose_integer_mv {
1112 2u8
1113 } else {
1114 br.read_bits(1)? as u8
1115 };
1116 }
1117 if enable_order_hint {
1118 order_hint_bits = br.read_bits(3)? as u8 + 1;
1119 }
1120 }
1121 let enable_superres = br.read_bits(1)? == 1;
1122 let enable_cdef = br.read_bits(1)? == 1;
1123 let enable_restoration = br.read_bits(1)? == 1;
1124
1125 let high_bitdepth = br.read_bits(1)? == 1;
1127 let bit_depth = if seq_profile == 2 && high_bitdepth {
1128 if br.read_bits(1)? == 1 { 12 } else { 10 }
1129 } else if high_bitdepth {
1130 10
1131 } else {
1132 8
1133 };
1134 let monochrome = if seq_profile == 1 {
1135 false
1136 } else {
1137 br.read_bits(1)? == 1
1138 };
1139 let color_description_present_flag = br.read_bits(1)? == 1;
1140 let (color_primaries, transfer_characteristics, matrix_coefficients) =
1141 if color_description_present_flag {
1142 (
1143 br.read_bits(8)? as u8,
1144 br.read_bits(8)? as u8,
1145 br.read_bits(8)? as u8,
1146 )
1147 } else {
1148 (2u8, 2u8, 2u8) };
1150 let color_range;
1151 let (subx, suby);
1152 let mut separate_uv_delta_q = false;
1153 if monochrome {
1154 color_range = br.read_bits(1)? == 1;
1155 subx = true;
1156 suby = true;
1157 } else if color_primaries == 1 && transfer_characteristics == 13 && matrix_coefficients == 0 {
1158 color_range = true;
1159 subx = false;
1160 suby = false;
1161 } else {
1162 color_range = br.read_bits(1)? == 1;
1163 match seq_profile {
1164 0 => {
1165 subx = true;
1166 suby = true;
1167 }
1168 1 => {
1169 subx = false;
1170 suby = false;
1171 }
1172 2 => {
1173 if bit_depth == 12 {
1174 subx = br.read_bits(1)? == 1;
1175 suby = if subx { br.read_bits(1)? == 1 } else { false };
1176 } else {
1177 subx = true;
1178 suby = false;
1179 }
1180 }
1181 _ => {
1182 subx = true;
1183 suby = true;
1184 }
1185 }
1186 if subx && suby {
1187 let _chroma_sample_position = br.read_bits(2)?;
1188 }
1189 separate_uv_delta_q = br.read_bits(1)? == 1;
1190 }
1191 let film_grain_params_present = br.read_bits(1)? == 1;
1192
1193 Some(Av1SequenceHeader {
1194 seq_profile,
1195 still_picture,
1196 reduced_still_picture_header,
1197 max_frame_width_minus1,
1198 max_frame_height_minus1,
1199 seq_level_idx_0,
1200 seq_tier_0,
1201 bit_depth,
1202 monochrome,
1203 color_primaries,
1204 transfer_characteristics,
1205 matrix_coefficients,
1206 color_range,
1207 chroma_subsampling_x: subx,
1208 chroma_subsampling_y: suby,
1209 film_grain_params_present,
1210 enable_filter_intra,
1211 enable_intra_edge_filter,
1212 enable_interintra_compound,
1213 enable_masked_compound,
1214 enable_warped_motion,
1215 enable_dual_filter,
1216 enable_order_hint,
1217 enable_jnt_comp,
1218 enable_ref_frame_mvs,
1219 enable_superres,
1220 enable_cdef,
1221 enable_restoration,
1222 order_hint_bits,
1223 seq_force_screen_content_tools,
1224 seq_force_integer_mv,
1225 frame_width_bits_minus_1: frame_width_bits_minus_1 as u8,
1226 frame_height_bits_minus_1: frame_height_bits_minus_1 as u8,
1227 use_128x128_superblock,
1228 separate_uv_delta_q,
1229 })
1230}
1231
1232pub fn parse_av1_frame_header(sample: &[u8], seq: &Av1SequenceHeader) -> Option<Av1FrameHeader> {
1246 let obu_bytes = find_av1_obu(sample, 3).or_else(|| find_av1_obu(sample, 6))?;
1247 let mut br = BitReader::new(obu_bytes);
1248 let mut h = Av1FrameHeader::default();
1249
1250 if seq.reduced_still_picture_header {
1252 h.frame_type = Av1FrameType::Key;
1253 h.show_frame = true;
1254 h.showable_frame = false;
1255 h.error_resilient_mode = true;
1256 } else {
1257 let show_existing_frame = br.read_bits(1)? == 1;
1258 if show_existing_frame {
1259 let _frame_to_show_map_idx = br.read_bits(3)?;
1265 h.show_frame = true;
1266 h.showable_frame = true;
1267 h.frame_type = Av1FrameType::Key;
1268 h.frame_width = seq.max_frame_width_minus1 + 1;
1269 h.frame_height = seq.max_frame_height_minus1 + 1;
1270 h.render_width = h.frame_width;
1271 h.render_height = h.frame_height;
1272 return Some(h);
1273 }
1274 let ft_code = br.read_bits(2)?;
1275 h.frame_type = match ft_code {
1276 0 => Av1FrameType::Key,
1277 1 => Av1FrameType::Inter,
1278 2 => Av1FrameType::IntraOnly,
1279 3 => Av1FrameType::Switch,
1280 _ => return None,
1281 };
1282 h.show_frame = br.read_bits(1)? == 1;
1283 h.showable_frame = if h.show_frame {
1284 !matches!(h.frame_type, Av1FrameType::Key)
1285 } else {
1286 br.read_bits(1)? == 1
1287 };
1288 let is_key = matches!(h.frame_type, Av1FrameType::Key);
1289 let is_switch = matches!(h.frame_type, Av1FrameType::Switch);
1290 h.error_resilient_mode = if is_switch || (is_key && h.show_frame) {
1291 true
1292 } else {
1293 br.read_bits(1)? == 1
1294 };
1295 }
1296
1297 let frame_is_intra = matches!(h.frame_type, Av1FrameType::Key | Av1FrameType::IntraOnly);
1298
1299 h.disable_cdf_update = br.read_bits(1)? == 1;
1300 h.allow_screen_content_tools = if seq.seq_force_screen_content_tools == 2 {
1304 br.read_bits(1)? == 1
1305 } else {
1306 seq.seq_force_screen_content_tools == 1
1307 };
1308 if h.allow_screen_content_tools {
1309 h.force_integer_mv = if seq.seq_force_integer_mv == 2 {
1310 br.read_bits(1)? == 1
1311 } else {
1312 seq.seq_force_integer_mv == 1
1313 };
1314 } else {
1315 h.force_integer_mv = false;
1316 }
1317 if frame_is_intra {
1318 h.force_integer_mv = true;
1319 }
1320
1321 let is_switch = matches!(h.frame_type, Av1FrameType::Switch);
1323 h.frame_size_override_flag = if is_switch {
1324 true
1325 } else if seq.reduced_still_picture_header {
1326 false
1327 } else {
1328 br.read_bits(1)? == 1
1329 };
1330
1331 if seq.enable_order_hint && seq.order_hint_bits > 0 {
1333 h.order_hint = br.read_bits(seq.order_hint_bits as usize)?;
1334 }
1335
1336 h.primary_ref_frame = if frame_is_intra || h.error_resilient_mode {
1338 7 } else {
1340 br.read_bits(3)? as u8
1341 };
1342
1343 let all_frames = 0xFFu8;
1345 h.refresh_frame_flags = if matches!(h.frame_type, Av1FrameType::Key) && h.show_frame {
1346 all_frames
1347 } else if is_switch {
1348 all_frames
1349 } else {
1350 br.read_bits(8)? as u8
1351 };
1352
1353 let (frame_width, frame_height) = if frame_is_intra {
1355 let (w, h2) = parse_av1_frame_size(&mut br, seq, h.frame_size_override_flag)?;
1356 h.use_superres = if seq.enable_superres {
1359 br.read_bits(1)? == 1
1360 } else {
1361 false
1362 };
1363 if h.use_superres {
1364 let _superres_denom_minus9 = br.read_bits(3)?;
1365 }
1366 parse_av1_render_size(&mut br, w, h2, &mut h.render_width, &mut h.render_height)?;
1367 if h.allow_screen_content_tools
1368 {
1370 h.allow_intrabc = br.read_bits(1)? == 1;
1371 }
1372 (w, h2)
1373 } else {
1374 let frame_refs_short_signaling = if seq.enable_order_hint {
1380 br.read_bits(1)? == 1
1381 } else {
1382 false
1383 };
1384 if frame_refs_short_signaling {
1385 let _last_frame_idx = br.read_bits(3)?;
1386 let _gold_frame_idx = br.read_bits(3)?;
1387 }
1388 for _ in 0..7u8
1389 {
1391 if !frame_refs_short_signaling {
1392 let _ref_frame_idx = br.read_bits(3)?;
1393 }
1394 }
1397 let (w, h2) = if h.frame_size_override_flag && !h.error_resilient_mode {
1398 parse_av1_frame_size_with_refs(&mut br, seq)?
1399 } else {
1400 let (w, h2) = parse_av1_frame_size(&mut br, seq, h.frame_size_override_flag)?;
1401 h.use_superres = if seq.enable_superres {
1403 br.read_bits(1)? == 1
1404 } else {
1405 false
1406 };
1407 if h.use_superres {
1408 let _superres_denom_minus9 = br.read_bits(3)?;
1409 }
1410 parse_av1_render_size(&mut br, w, h2, &mut h.render_width, &mut h.render_height)?;
1411 (w, h2)
1412 };
1413 h.allow_high_precision_mv = if h.force_integer_mv {
1414 false
1415 } else {
1416 br.read_bits(1)? == 1
1417 };
1418 h.is_filter_switchable = br.read_bits(1)? == 1;
1420 h.interpolation_filter = if h.is_filter_switchable {
1421 4 } else {
1423 br.read_bits(2)? as u8
1424 };
1425 h.is_motion_mode_switchable = br.read_bits(1)? == 1;
1426 h.use_ref_frame_mvs = if h.error_resilient_mode || !seq.enable_ref_frame_mvs {
1427 false
1428 } else {
1429 br.read_bits(1)? == 1
1430 };
1431 (w, h2)
1432 };
1433 h.frame_width = frame_width;
1434 h.frame_height = frame_height;
1435 if h.render_width == 0 {
1436 h.render_width = frame_width;
1437 }
1438 if h.render_height == 0 {
1439 h.render_height = frame_height;
1440 }
1441
1442 h.disable_frame_end_update_cdf = if seq.reduced_still_picture_header {
1443 true
1444 } else {
1445 br.read_bits(1)? == 1
1446 };
1447
1448 let sb_size_log2: u32 = 4; let mi_cols_raw = 2 * ((frame_width.saturating_sub(1) + 8) >> 3);
1455 let mi_rows_raw = 2 * ((frame_height.saturating_sub(1) + 8) >> 3);
1456 let sb_cols = (mi_cols_raw + (1 << sb_size_log2) - 1) >> sb_size_log2;
1458 let sb_rows = (mi_rows_raw + (1 << sb_size_log2) - 1) >> sb_size_log2;
1459 parse_av1_tile_info(
1460 &mut br,
1461 &mut h,
1462 sb_cols,
1463 sb_rows,
1464 sb_size_log2,
1465 mi_cols_raw,
1466 mi_rows_raw,
1467 )?;
1468
1469 parse_av1_quantization_params(&mut br, &mut h, seq)?;
1471
1472 parse_av1_segmentation_params(&mut br, &mut h)?;
1474
1475 h.delta_q_present = if h.base_q_idx > 0 {
1477 br.read_bits(1)? == 1
1478 } else {
1479 false
1480 };
1481 h.delta_q_res = if h.delta_q_present {
1482 br.read_bits(2)? as u8
1483 } else {
1484 0
1485 };
1486 h.delta_lf_present = if h.delta_q_present && !h.allow_intrabc {
1487 br.read_bits(1)? == 1
1488 } else {
1489 false
1490 };
1491 if h.delta_lf_present {
1492 h.delta_lf_res = br.read_bits(2)? as u8;
1493 h.delta_lf_multi = br.read_bits(1)? == 1;
1494 }
1495
1496 h.coded_lossless = h.base_q_idx == 0
1502 && h.delta_q_y_dc == 0
1503 && h.delta_q_u_dc == 0
1504 && h.delta_q_u_ac == 0
1505 && h.delta_q_v_dc == 0
1506 && h.delta_q_v_ac == 0;
1507
1508 parse_av1_loop_filter_params(&mut br, &mut h, frame_is_intra)?;
1510
1511 let num_planes_u32: u32 = if seq.monochrome { 1 } else { 3 };
1513 if !h.coded_lossless && !h.allow_intrabc && seq.enable_cdef {
1514 parse_av1_cdef_params(&mut br, &mut h, num_planes_u32)?;
1515 } else {
1516 h.cdef_bits = 0;
1518 h.cdef_damping_minus_3 = 0;
1519 h.cdef_y_pri_strength = [0; 8];
1520 h.cdef_y_sec_strength = [0; 8];
1521 h.cdef_uv_pri_strength = [0; 8];
1522 h.cdef_uv_sec_strength = [0; 8];
1523 }
1524
1525 if !h.coded_lossless && !h.allow_intrabc && seq.enable_restoration {
1527 parse_av1_lr_params(&mut br, &mut h, num_planes_u32, seq)?;
1528 }
1529
1530 h.tx_mode = if h.coded_lossless {
1532 0 } else if br.read_bits(1)? == 1 {
1534 2 } else {
1536 1 };
1538
1539 h.reference_select = if !frame_is_intra {
1541 br.read_bits(1)? == 1
1542 } else {
1543 false
1544 };
1545
1546 let skip_mode_allowed = false; h.skip_mode_present = if skip_mode_allowed {
1553 br.read_bits(1)? == 1
1554 } else {
1555 false
1556 };
1557
1558 h.allow_warped_motion =
1561 if !frame_is_intra && !h.error_resilient_mode && seq.enable_warped_motion {
1562 br.read_bits(1)? == 1
1563 } else {
1564 false
1565 };
1566
1567 h.reduced_tx_set = br.read_bits(1)? == 1;
1573
1574 if !frame_is_intra {
1579 skip_av1_global_motion_params(&mut br)?;
1580 }
1581
1582 if seq.film_grain_params_present && (h.show_frame || h.showable_frame) {
1584 skip_av1_film_grain_params(&mut br, seq)?;
1585 }
1586
1587 br.byte_align();
1592 h.tile_group_offset_in_obu = (br.bit_pos() / 8) as u32;
1593
1594 Some(h)
1595}
1596
1597fn parse_av1_frame_size(
1599 br: &mut BitReader,
1600 seq: &Av1SequenceHeader,
1601 frame_size_override_flag: bool,
1602) -> Option<(u32, u32)> {
1603 if frame_size_override_flag {
1604 let w_bits = av1_bits_for_max(seq.max_frame_width_minus1 + 1);
1605 let h_bits = av1_bits_for_max(seq.max_frame_height_minus1 + 1);
1606 let w = br.read_bits(w_bits)? + 1;
1607 let hgt = br.read_bits(h_bits)? + 1;
1608 Some((w, hgt))
1609 } else {
1610 Some((
1611 seq.max_frame_width_minus1 + 1,
1612 seq.max_frame_height_minus1 + 1,
1613 ))
1614 }
1615}
1616
1617fn parse_av1_render_size(
1619 br: &mut BitReader,
1620 frame_w: u32,
1621 frame_h: u32,
1622 out_w: &mut u32,
1623 out_h: &mut u32,
1624) -> Option<()> {
1625 let render_and_frame_size_different = br.read_bits(1)? == 1;
1626 if render_and_frame_size_different {
1627 *out_w = br.read_bits(16)? + 1;
1628 *out_h = br.read_bits(16)? + 1;
1629 } else {
1630 *out_w = frame_w;
1631 *out_h = frame_h;
1632 }
1633 Some(())
1634}
1635
1636fn parse_av1_frame_size_with_refs(
1642 br: &mut BitReader,
1643 seq: &Av1SequenceHeader,
1644) -> Option<(u32, u32)> {
1645 let mut found_ref = false;
1646 for _ in 0..7u8 {
1647 if br.read_bits(1)? == 1 {
1648 found_ref = true;
1649 }
1650 }
1651 if !found_ref {
1652 let (w, hgt) = parse_av1_frame_size(br, seq, true)?;
1653 let mut rw = 0;
1654 let mut rh = 0;
1655 parse_av1_render_size(br, w, hgt, &mut rw, &mut rh)?;
1656 if seq.enable_superres && br.read_bits(1)? == 1 {
1658 let _denom = br.read_bits(3)?;
1659 }
1660 Some((w, hgt))
1661 } else {
1662 Some((
1665 seq.max_frame_width_minus1 + 1,
1666 seq.max_frame_height_minus1 + 1,
1667 ))
1668 }
1669}
1670
1671fn av1_bits_for_max(v: u32) -> usize {
1672 let mut bits = 0usize;
1675 let mut x = v.saturating_sub(1);
1676 while x > 0 {
1677 bits += 1;
1678 x >>= 1;
1679 }
1680 bits.max(1)
1681}
1682
1683fn parse_av1_tile_info(
1685 br: &mut BitReader,
1686 h: &mut Av1FrameHeader,
1687 sb_cols: u32,
1688 sb_rows: u32,
1689 sb_size_log2: u32,
1690 mi_cols: u32,
1691 mi_rows: u32,
1692) -> Option<()> {
1693 let max_tile_width_sb = 4096 >> (sb_size_log2 + 2); let max_tile_area_sb = (4096 * 2304) >> (2 * sb_size_log2 + 4); let min_log2_tile_cols = av1_tile_log2(max_tile_width_sb, sb_cols);
1698 let max_log2_tile_cols = av1_tile_log2(1, sb_cols.min(64));
1699 let max_log2_tile_rows = av1_tile_log2(1, sb_rows.min(64));
1700 let min_log2_tiles = min_log2_tile_cols.max(av1_tile_log2(max_tile_area_sb, sb_rows * sb_cols));
1701
1702 h.uniform_tile_spacing_flag = br.read_bits(1)? == 1;
1703 let tile_cols_log2: u32;
1704 let tile_rows_log2: u32;
1705 h.mi_col_starts.clear();
1706 h.mi_row_starts.clear();
1707 h.width_in_sbs_minus_1.clear();
1708 h.height_in_sbs_minus_1.clear();
1709
1710 if h.uniform_tile_spacing_flag {
1711 let mut tcl = min_log2_tile_cols;
1712 while tcl < max_log2_tile_cols {
1713 if br.read_bits(1)? == 0 {
1714 break;
1715 }
1716 tcl += 1;
1717 }
1718 tile_cols_log2 = tcl;
1719 let tile_width_sb = (sb_cols + (1 << tile_cols_log2) - 1) >> tile_cols_log2;
1720 let mut start_sb = 0u32;
1721 let mut mi_starts: Vec<u16> = vec![0];
1722 let mut widths: Vec<u16> = Vec::new();
1723 while start_sb < sb_cols {
1724 let size_sb = tile_width_sb.min(sb_cols - start_sb);
1725 widths.push((size_sb - 1) as u16);
1726 start_sb += size_sb;
1727 mi_starts.push(((start_sb << sb_size_log2).min(mi_cols)) as u16);
1728 }
1729 h.mi_col_starts = mi_starts;
1730 h.width_in_sbs_minus_1 = widths;
1731 h.tile_cols = h.width_in_sbs_minus_1.len() as u8;
1732
1733 let min_log2_tile_rows = min_log2_tiles.saturating_sub(tile_cols_log2);
1734 let mut trl = min_log2_tile_rows;
1735 while trl < max_log2_tile_rows {
1736 if br.read_bits(1)? == 0 {
1737 break;
1738 }
1739 trl += 1;
1740 }
1741 tile_rows_log2 = trl;
1742 let tile_height_sb = (sb_rows + (1 << tile_rows_log2) - 1) >> tile_rows_log2;
1743 let mut start_sb_r = 0u32;
1744 let mut mi_starts_r: Vec<u16> = vec![0];
1745 let mut heights: Vec<u16> = Vec::new();
1746 while start_sb_r < sb_rows {
1747 let size_sb = tile_height_sb.min(sb_rows - start_sb_r);
1748 heights.push((size_sb - 1) as u16);
1749 start_sb_r += size_sb;
1750 mi_starts_r.push(((start_sb_r << sb_size_log2).min(mi_rows)) as u16);
1751 }
1752 h.mi_row_starts = mi_starts_r;
1753 h.height_in_sbs_minus_1 = heights;
1754 h.tile_rows = h.height_in_sbs_minus_1.len() as u8;
1755 } else {
1756 let mut start_sb = 0u32;
1758 let mut mi_starts: Vec<u16> = vec![0];
1759 let mut widths: Vec<u16> = Vec::new();
1760 while start_sb < sb_cols {
1761 let max_width = (sb_cols - start_sb).min(max_tile_width_sb);
1762 let size_minus_1 = av1_read_ns(br, max_width)?;
1763 let size = size_minus_1 + 1;
1764 widths.push(size_minus_1 as u16);
1765 start_sb += size;
1766 mi_starts.push(((start_sb << sb_size_log2).min(mi_cols)) as u16);
1767 }
1768 h.mi_col_starts = mi_starts;
1769 h.width_in_sbs_minus_1 = widths;
1770 h.tile_cols = h.width_in_sbs_minus_1.len() as u8;
1771 tile_cols_log2 = av1_tile_log2(1, h.tile_cols as u32);
1772
1773 let tile_cols = h.tile_cols as u32;
1774 let max_tile_area_sb_r = if min_log2_tiles > 0 {
1775 (sb_rows * sb_cols) >> (min_log2_tiles + 1)
1776 } else {
1777 sb_rows * sb_cols
1778 };
1779 let max_tile_height_sb = (max_tile_area_sb_r / tile_cols).max(1);
1780
1781 let mut start_sb_r = 0u32;
1782 let mut mi_starts_r: Vec<u16> = vec![0];
1783 let mut heights: Vec<u16> = Vec::new();
1784 while start_sb_r < sb_rows {
1785 let max_height = (sb_rows - start_sb_r).min(max_tile_height_sb);
1786 let size_minus_1 = av1_read_ns(br, max_height)?;
1787 let size = size_minus_1 + 1;
1788 heights.push(size_minus_1 as u16);
1789 start_sb_r += size;
1790 mi_starts_r.push(((start_sb_r << sb_size_log2).min(mi_rows)) as u16);
1791 }
1792 h.mi_row_starts = mi_starts_r;
1793 h.height_in_sbs_minus_1 = heights;
1794 h.tile_rows = h.height_in_sbs_minus_1.len() as u8;
1795 tile_rows_log2 = av1_tile_log2(1, h.tile_rows as u32);
1796 }
1797 h.tile_cols_log2 = tile_cols_log2 as u8;
1798 h.tile_rows_log2 = tile_rows_log2 as u8;
1799
1800 if (tile_cols_log2 + tile_rows_log2) > 0 {
1801 let n = (tile_cols_log2 + tile_rows_log2) as usize;
1802 h.context_update_tile_id = br.read_bits(n)? as u16;
1803 h.tile_size_bytes_minus_1 = br.read_bits(2)? as u8;
1804 } else {
1805 h.context_update_tile_id = 0;
1806 h.tile_size_bytes_minus_1 = 0;
1807 }
1808 Some(())
1809}
1810
1811fn av1_tile_log2(blksize: u32, target: u32) -> u32 {
1813 let mut k = 0u32;
1814 while (blksize << k) < target {
1815 k += 1;
1816 }
1817 k
1818}
1819
1820fn av1_read_ns(br: &mut BitReader, n: u32) -> Option<u32> {
1822 if n == 0 {
1823 return Some(0);
1824 }
1825 let w = av1_ceil_log2(n);
1826 if w == 0 {
1827 return Some(0);
1828 }
1829 let m = (1u32 << w) - n;
1830 let v = br.read_bits((w - 1) as usize)?;
1831 if v < m {
1832 Some(v)
1833 } else {
1834 let extra = br.read_bits(1)?;
1835 Some((v << 1) - m + extra)
1836 }
1837}
1838
1839fn av1_ceil_log2(n: u32) -> u32 {
1840 if n <= 1 {
1841 return 1;
1842 }
1843 let mut k = 0;
1844 let mut x = n - 1;
1845 while x > 0 {
1846 k += 1;
1847 x >>= 1;
1848 }
1849 k
1850}
1851
1852fn parse_av1_quantization_params(
1854 br: &mut BitReader,
1855 h: &mut Av1FrameHeader,
1856 seq: &Av1SequenceHeader,
1857) -> Option<()> {
1858 h.base_q_idx = br.read_bits(8)? as u8;
1859 h.delta_q_y_dc = read_delta_q(br)?;
1860 let (diff_uv_delta, num_planes) = if seq.monochrome {
1861 (false, 1u32)
1862 } else {
1863 let diff = if seq.seq_profile == 2 {
1864 br.read_bits(1)? == 1
1865 } else {
1866 false
1867 };
1868 (diff, 3u32)
1869 };
1870 if num_planes > 1 {
1871 h.delta_q_u_dc = read_delta_q(br)?;
1872 h.delta_q_u_ac = read_delta_q(br)?;
1873 if diff_uv_delta {
1874 h.delta_q_v_dc = read_delta_q(br)?;
1875 h.delta_q_v_ac = read_delta_q(br)?;
1876 } else {
1877 h.delta_q_v_dc = h.delta_q_u_dc;
1878 h.delta_q_v_ac = h.delta_q_u_ac;
1879 }
1880 }
1881 h.using_qmatrix = br.read_bits(1)? == 1;
1882 if h.using_qmatrix {
1883 h.qm_y = br.read_bits(4)? as u8;
1884 h.qm_u = br.read_bits(4)? as u8;
1885 h.qm_v = if seq.monochrome {
1886 h.qm_u
1887 } else if br.read_bits(1)? == 0 {
1888 h.qm_u
1889 } else {
1890 br.read_bits(4)? as u8
1891 };
1892 }
1893 Some(())
1894}
1895
1896fn read_delta_q(br: &mut BitReader) -> Option<i8> {
1897 let present = br.read_bits(1)? == 1;
1898 if present {
1899 Some(br.read_su(7)? as i8)
1900 } else {
1901 Some(0)
1902 }
1903}
1904
1905fn parse_av1_segmentation_params(br: &mut BitReader, h: &mut Av1FrameHeader) -> Option<()> {
1907 h.segmentation_enabled = br.read_bits(1)? == 1;
1908 if h.segmentation_enabled {
1909 if h.primary_ref_frame == 7 {
1910 h.segmentation_update_map = true;
1912 h.segmentation_temporal_update = false;
1913 h.segmentation_update_data = true;
1914 } else {
1915 h.segmentation_update_map = br.read_bits(1)? == 1;
1916 if h.segmentation_update_map {
1917 h.segmentation_temporal_update = br.read_bits(1)? == 1;
1918 }
1919 h.segmentation_update_data = br.read_bits(1)? == 1;
1920 }
1921 if h.segmentation_update_data {
1922 const FEAT_INFO: [(u32, bool); 8] = [
1926 (8, true), (6, true), (6, true), (6, true), (6, true), (3, false), (0, false), (0, false), ];
1935 for seg in 0..8 {
1936 for (feat, &(bits, signed)) in FEAT_INFO.iter().enumerate() {
1937 let enabled = br.read_bits(1)? == 1;
1938 h.feature_enabled[seg][feat] = enabled;
1939 if enabled {
1940 if bits == 0 {
1941 h.feature_data[seg][feat] = 1;
1942 } else if signed {
1943 h.feature_data[seg][feat] = br.read_su(bits as usize + 1)? as i16;
1944 } else {
1945 h.feature_data[seg][feat] = br.read_bits(bits as usize)? as i16;
1946 }
1947 }
1948 }
1949 }
1950 }
1951 }
1952 Some(())
1953}
1954
1955fn parse_av1_loop_filter_params(
1957 br: &mut BitReader,
1958 h: &mut Av1FrameHeader,
1959 frame_is_intra: bool,
1960) -> Option<()> {
1961 if h.coded_lossless || h.allow_intrabc {
1962 h.loop_filter_level = [0; 4];
1963 h.loop_filter_sharpness = 0;
1964 h.loop_filter_delta_enabled = false;
1965 h.loop_filter_ref_deltas = [1, 0, 0, 0, -1, 0, -1, -1];
1966 h.loop_filter_mode_deltas = [0, 0];
1967 return Some(());
1968 }
1969 h.loop_filter_level[0] = br.read_bits(6)? as u8;
1970 h.loop_filter_level[1] = br.read_bits(6)? as u8;
1971 if h.loop_filter_level[0] > 0 || h.loop_filter_level[1] > 0 {
1972 h.loop_filter_level[2] = br.read_bits(6)? as u8;
1973 h.loop_filter_level[3] = br.read_bits(6)? as u8;
1974 }
1975 h.loop_filter_sharpness = br.read_bits(3)? as u8;
1976 h.loop_filter_delta_enabled = br.read_bits(1)? == 1;
1977 h.loop_filter_ref_deltas = [1, 0, 0, 0, -1, 0, -1, -1];
1979 h.loop_filter_mode_deltas = [0, 0];
1980 if h.loop_filter_delta_enabled {
1981 h.loop_filter_delta_update = br.read_bits(1)? == 1;
1982 if h.loop_filter_delta_update {
1983 let mut update_mask = 0u8;
1984 for i in 0..8 {
1985 let update = br.read_bits(1)? == 1;
1986 if update {
1987 update_mask |= 1 << i;
1988 h.loop_filter_ref_deltas[i] = br.read_su(7)? as i8;
1989 }
1990 }
1991 h.update_ref_delta_mask = update_mask;
1992 let mut mode_mask = 0u8;
1993 for i in 0..2 {
1994 let update = br.read_bits(1)? == 1;
1995 if update {
1996 mode_mask |= 1 << i;
1997 h.loop_filter_mode_deltas[i] = br.read_su(7)? as i8;
1998 }
1999 }
2000 h.update_mode_delta_mask = mode_mask;
2001 }
2002 }
2003 let _ = frame_is_intra; Some(())
2005}
2006
2007fn parse_av1_cdef_params(
2009 br: &mut BitReader,
2010 h: &mut Av1FrameHeader,
2011 num_planes: u32,
2012) -> Option<()> {
2013 h.cdef_damping_minus_3 = br.read_bits(2)? as u8;
2014 h.cdef_bits = br.read_bits(2)? as u8;
2015 let count = 1usize << h.cdef_bits;
2016 for i in 0..count {
2017 h.cdef_y_pri_strength[i] = br.read_bits(4)? as u8;
2018 let y_sec = br.read_bits(2)? as u8;
2019 h.cdef_y_sec_strength[i] = if y_sec == 3 { 4 } else { y_sec };
2023 if num_planes > 1 {
2024 h.cdef_uv_pri_strength[i] = br.read_bits(4)? as u8;
2025 let uv_sec = br.read_bits(2)? as u8;
2026 h.cdef_uv_sec_strength[i] = if uv_sec == 3 { 4 } else { uv_sec };
2027 }
2028 }
2029 Some(())
2030}
2031
2032fn parse_av1_lr_params(
2034 br: &mut BitReader,
2035 h: &mut Av1FrameHeader,
2036 num_planes: u32,
2037 seq: &Av1SequenceHeader,
2038) -> Option<()> {
2039 let mut uses_lr = false;
2040 let mut uses_chroma_lr = false;
2041 for i in 0..(num_planes as usize) {
2042 let lr_type = br.read_bits(2)? as u8;
2043 h.lr_type[i] = lr_type;
2044 if lr_type != 0 {
2045 uses_lr = true;
2046 if i > 0 {
2047 uses_chroma_lr = true;
2048 }
2049 }
2050 }
2051 if uses_lr {
2052 let base = br.read_bits(1)? as u8;
2057 h.lr_unit_shift = if base != 0 {
2058 let extra = br.read_bits(1)? as u8;
2059 base + extra
2060 } else {
2061 0
2062 };
2063 if num_planes > 1 && uses_chroma_lr && seq.chroma_subsampling_x && seq.chroma_subsampling_y
2066 {
2067 h.lr_uv_shift = br.read_bits(1)? as u8;
2068 }
2069 }
2070 Some(())
2071}
2072
2073fn skip_av1_global_motion_params(br: &mut BitReader) -> Option<()> {
2077 for _ in 0..7 {
2078 let is_global = br.read_bits(1)? == 1;
2079 let is_rot_zoom = if is_global {
2080 br.read_bits(1)? == 1
2081 } else {
2082 false
2083 };
2084 let _is_translation = if is_global && !is_rot_zoom {
2085 br.read_bits(1)? == 1
2086 } else {
2087 false
2088 };
2089 let gm_type = if is_global && !is_rot_zoom {
2090 2u8 } else if is_rot_zoom {
2092 3u8 } else if is_global {
2094 4u8 } else {
2096 0u8 };
2098 if gm_type >= 3 {
2099 for _ in 0..2 {
2101 let _a = av1_read_subexp(br, 12, 0)?;
2102 let _b = av1_read_subexp(br, 12, 0)?;
2103 }
2104 }
2105 if gm_type >= 2 {
2106 for _ in 0..2 {
2108 let _a = av1_read_subexp(br, 12, 0)?;
2109 }
2110 }
2111 }
2112 Some(())
2113}
2114
2115fn av1_read_subexp(br: &mut BitReader, num_syms: u32, _ref: i32) -> Option<i32> {
2116 let bits = av1_ceil_log2(num_syms) as usize + 1; let _ = br.read_bits(bits.min(16))?;
2122 Some(0)
2123}
2124
2125fn skip_av1_film_grain_params(br: &mut BitReader, seq: &Av1SequenceHeader) -> Option<()> {
2129 let apply_grain = br.read_bits(1)? == 1;
2130 if !apply_grain {
2131 return Some(());
2132 }
2133 let _grain_seed = br.read_bits(16)?;
2134 let update_grain = br.read_bits(1)? == 1;
2135 if !update_grain {
2136 let _film_grain_params_ref_idx = br.read_bits(3)?;
2137 return Some(());
2138 }
2139 let num_y_points = br.read_bits(4)?;
2140 for _ in 0..num_y_points {
2141 let _point_y_value = br.read_bits(8)?;
2142 let _point_y_scaling = br.read_bits(8)?;
2143 }
2144 let chroma_scaling_from_luma = if seq.monochrome {
2145 false
2146 } else {
2147 br.read_bits(1)? == 1
2148 };
2149 let num_cb_points: u32;
2150 let num_cr_points: u32;
2151 if seq.monochrome
2152 || chroma_scaling_from_luma
2153 || (seq.chroma_subsampling_x && seq.chroma_subsampling_y && num_y_points == 0)
2154 {
2155 num_cb_points = 0;
2156 num_cr_points = 0;
2157 } else {
2158 num_cb_points = br.read_bits(4)?;
2159 for _ in 0..num_cb_points {
2160 let _point_cb_value = br.read_bits(8)?;
2161 let _point_cb_scaling = br.read_bits(8)?;
2162 }
2163 num_cr_points = br.read_bits(4)?;
2164 for _ in 0..num_cr_points {
2165 let _point_cr_value = br.read_bits(8)?;
2166 let _point_cr_scaling = br.read_bits(8)?;
2167 }
2168 }
2169 let _grain_scaling_minus_8 = br.read_bits(2)?;
2170 let ar_coeff_lag = br.read_bits(2)?;
2171 let num_pos_y = 2 * ar_coeff_lag * (ar_coeff_lag + 1);
2172 let num_pos_chroma = if num_y_points > 0 {
2173 num_pos_y + 1
2174 } else {
2175 num_pos_y
2176 };
2177 for _ in 0..num_pos_y {
2178 let _ar_coeff_y_plus_128 = br.read_bits(8)?;
2179 }
2180 if chroma_scaling_from_luma || num_cb_points > 0 {
2181 for _ in 0..num_pos_chroma {
2182 let _ar_coeff_cb_plus_128 = br.read_bits(8)?;
2183 }
2184 }
2185 if chroma_scaling_from_luma || num_cr_points > 0 {
2186 for _ in 0..num_pos_chroma {
2187 let _ar_coeff_cr_plus_128 = br.read_bits(8)?;
2188 }
2189 }
2190 let _ar_coeff_shift_minus_6 = br.read_bits(2)?;
2191 let _grain_scale_shift = br.read_bits(2)?;
2192 if num_cb_points > 0 {
2193 let _cb_mult = br.read_bits(8)?;
2194 let _cb_luma_mult = br.read_bits(8)?;
2195 let _cb_offset = br.read_bits(9)?;
2196 }
2197 if num_cr_points > 0 {
2198 let _cr_mult = br.read_bits(8)?;
2199 let _cr_luma_mult = br.read_bits(8)?;
2200 let _cr_offset = br.read_bits(9)?;
2201 }
2202 let _overlap_flag = br.read_bits(1)?;
2203 let _clip_to_restricted_range = br.read_bits(1)?;
2204 Some(())
2205}
2206
2207pub fn av1_frame_header_offset(sample: &[u8]) -> Option<u32> {
2218 let mut i = 0usize;
2219 while i < sample.len() {
2220 let header = sample[i];
2221 let obu_type = (header >> 3) & 0x0F;
2222 let extension_flag = (header >> 2) & 0x01;
2223 let has_size_field = (header >> 1) & 0x01;
2224 let mut p = i + 1;
2225 if extension_flag == 1 {
2226 p += 1;
2227 }
2228 let (size, leb) = if has_size_field == 1 {
2229 let (s, n) = read_leb128(&sample[p..])?;
2230 p += n;
2231 (s as usize, n)
2232 } else {
2233 return None;
2236 };
2237 let _ = leb;
2238 if obu_type == 3 || obu_type == 6 {
2239 return Some(p as u32);
2240 }
2241 p += size;
2242 i = p;
2243 }
2244 None
2245}
2246
2247pub fn av1_tile_group_offset(sample: &[u8], seq: &Av1SequenceHeader) -> Option<u32> {
2259 let mut i = 0usize;
2262 while i < sample.len() {
2263 let header = sample[i];
2264 let obu_type = (header >> 3) & 0x0F;
2265 let extension_flag = (header >> 2) & 0x01;
2266 let has_size_field = (header >> 1) & 0x01;
2267 let mut p = i + 1;
2268 if extension_flag == 1 {
2269 p += 1;
2270 }
2271 let size = if has_size_field == 1 {
2272 let (s, n) = read_leb128(&sample[p..])?;
2273 p += n;
2274 s as usize
2275 } else {
2276 return None;
2277 };
2278 if obu_type == 4 {
2279 return Some(p as u32);
2280 }
2281 p += size;
2282 i = p;
2283 }
2284 let (_obu_bytes, payload_offset) = find_av1_obu_with_offset(sample, 6)?;
2287 let hdr = parse_av1_frame_header(sample, seq)?;
2288 Some(payload_offset as u32 + hdr.tile_group_offset_in_obu)
2289}
2290
2291pub fn av1_tile_group_offset_fallback(sample: &[u8]) -> Option<u32> {
2296 let mut i = 0usize;
2297 while i < sample.len() {
2298 let header = sample[i];
2299 let obu_type = (header >> 3) & 0x0F;
2300 let extension_flag = (header >> 2) & 0x01;
2301 let has_size_field = (header >> 1) & 0x01;
2302 let mut p = i + 1;
2303 if extension_flag == 1 {
2304 p += 1;
2305 }
2306 let size = if has_size_field == 1 {
2307 let (s, n) = read_leb128(&sample[p..])?;
2308 p += n;
2309 s as usize
2310 } else {
2311 return None;
2312 };
2313 if obu_type == 4 {
2314 return Some(p as u32);
2315 }
2316 p += size;
2317 i = p;
2318 }
2319 av1_frame_header_offset(sample)
2320}
2321
2322fn read_av1_uvlc(br: &mut BitReader) -> Option<u32> {
2325 let mut leading_zeros = 0;
2326 while leading_zeros < 32 {
2327 if br.read_bits(1)? == 1 {
2328 break;
2329 }
2330 leading_zeros += 1;
2331 }
2332 if leading_zeros >= 32 {
2333 return None;
2334 }
2335 if leading_zeros == 0 {
2336 return Some(0);
2337 }
2338 let suffix = br.read_bits(leading_zeros)?;
2339 Some((1u32 << leading_zeros) - 1 + suffix)
2340}
2341
2342#[derive(Debug, Clone, Copy, PartialEq, Eq)]
2352pub struct Mpeg2SeqInfo {
2353 pub width: u32,
2354 pub height: u32,
2355}
2356
2357pub fn detect_dims(codec: &str, samples: &[Vec<u8>]) -> Option<(u32, u32)> {
2366 if samples.is_empty() {
2367 return None;
2368 }
2369 let sample = &samples[0];
2370 match codec.to_lowercase().as_str() {
2371 "h264" | "avc1" | "avc" | "avc3" => {
2372 let info = parse_h264_sps(sample)?;
2373 Some((info.width?, info.height?))
2374 }
2375 "h265" | "hevc" | "hvc1" | "hev1" | "hvc2" | "hev2" => {
2376 let info = parse_hevc_sps(sample)?;
2377 Some((info.width?, info.height?))
2378 }
2379 "mpeg2" | "mpeg2video" | "mp2v" => {
2380 let info = parse_mpeg2_sequence_header(sample)?;
2381 Some((info.width, info.height))
2382 }
2383 _ => None,
2384 }
2385}
2386
2387pub fn parse_h264_sps(sample: &[u8]) -> Option<H264SpsInfo> {
2394 let sps = find_h264_sps(sample)?;
2395 let rbsp = remove_h264_rbsp_stuffing(sps);
2396 let mut br = BitReader::new(&rbsp);
2397
2398 let profile_idc = br.read_bits(8)? as u8;
2399 let constraint_set_flags = br.read_bits(8)? as u8;
2400 let level_idc = br.read_bits(8)? as u8;
2401 let _seq_parameter_set_id = br.read_ue()?;
2402
2403 let profile_gates_chroma = matches!(
2404 profile_idc,
2405 100 | 110 | 122 | 244 | 44 | 83 | 86 | 118 | 128 | 138 | 139 | 134 | 135
2406 );
2407
2408 let (
2409 chroma_format_idc,
2410 separate_colour_plane_flag,
2411 bit_depth_luma,
2412 bit_depth_chroma,
2413 qpprime_y_zero,
2414 scaling_matrix,
2415 ) = if profile_gates_chroma {
2416 let chroma = br.read_ue()? as u8;
2417 let separate = if chroma == 3 {
2418 br.read_bits(1)? == 1
2419 } else {
2420 false
2421 };
2422 let bit_depth_luma_m8 = br.read_ue()?;
2423 let bit_depth_chroma_m8 = br.read_ue()?;
2424 let qpprime = br.read_bits(1)? == 1;
2425 let scaling_matrix_present = br.read_bits(1)? == 1;
2426 if scaling_matrix_present {
2427 let num_lists = if chroma == 3 { 12 } else { 8 };
2431 for i in 0..num_lists {
2432 if br.read_bits(1)? == 1 {
2433 let size = if i < 6 { 16 } else { 64 };
2434 let mut last_scale: i32 = 8;
2435 let mut next_scale: i32 = 8;
2436 for _j in 0..size {
2437 if next_scale != 0 {
2438 let delta = br.read_se()?;
2439 next_scale = (last_scale + delta + 256).rem_euclid(256);
2440 }
2441 if next_scale != 0 {
2442 last_scale = next_scale;
2443 }
2444 }
2445 }
2446 }
2447 }
2448 (
2449 chroma,
2450 separate,
2451 bit_depth_luma_m8 as u8 + 8,
2452 bit_depth_chroma_m8 as u8 + 8,
2453 qpprime,
2454 scaling_matrix_present,
2455 )
2456 } else {
2457 (1u8, false, 8u8, 8u8, false, false)
2458 };
2459
2460 let info_prefix = H264SpsInfo {
2465 profile_idc,
2466 constraint_set_flags,
2467 level_idc,
2468 chroma_format_idc,
2469 separate_colour_plane_flag,
2470 bit_depth_luma,
2471 bit_depth_chroma,
2472 frame_mbs_only: true,
2473 width: None,
2474 height: None,
2475 log2_max_frame_num_minus4: None,
2476 pic_order_cnt_type: None,
2477 log2_max_pic_order_cnt_lsb_minus4: None,
2478 delta_pic_order_always_zero_flag: None,
2479 qpprime_y_zero_transform_bypass_flag: Some(qpprime_y_zero),
2480 seq_scaling_matrix_present_flag: Some(scaling_matrix),
2481 max_num_ref_frames: None,
2482 gaps_in_frame_num_value_allowed_flag: None,
2483 mb_adaptive_frame_field_flag: None,
2484 direct_8x8_inference_flag: None,
2485 frame_cropping_flag: None,
2486 frame_crop_left_offset: None,
2487 frame_crop_right_offset: None,
2488 frame_crop_top_offset: None,
2489 frame_crop_bottom_offset: None,
2490 offset_for_non_ref_pic: None,
2491 offset_for_top_to_bottom_field: None,
2492 num_ref_frames_in_pic_order_cnt_cycle: None,
2493 offset_for_ref_frame: Vec::new(),
2494 };
2495
2496 let Some(dims) = parse_h264_sps_dims(&mut br, chroma_format_idc, separate_colour_plane_flag)
2497 else {
2498 return Some(info_prefix);
2499 };
2500
2501 Some(H264SpsInfo {
2502 frame_mbs_only: dims.frame_mbs_only,
2503 width: Some(dims.width),
2504 height: Some(dims.height),
2505 log2_max_frame_num_minus4: Some(dims.log2_max_frame_num_minus4),
2506 pic_order_cnt_type: Some(dims.pic_order_cnt_type),
2507 log2_max_pic_order_cnt_lsb_minus4: dims.log2_max_pic_order_cnt_lsb_minus4,
2508 delta_pic_order_always_zero_flag: dims.delta_pic_order_always_zero_flag,
2509 max_num_ref_frames: Some(dims.max_num_ref_frames),
2510 gaps_in_frame_num_value_allowed_flag: Some(dims.gaps_in_frame_num_value_allowed_flag),
2511 mb_adaptive_frame_field_flag: dims.mb_adaptive_frame_field_flag,
2512 direct_8x8_inference_flag: Some(dims.direct_8x8_inference_flag),
2513 frame_cropping_flag: Some(dims.frame_cropping_flag),
2514 frame_crop_left_offset: Some(dims.crop_left),
2515 frame_crop_right_offset: Some(dims.crop_right),
2516 frame_crop_top_offset: Some(dims.crop_top),
2517 frame_crop_bottom_offset: Some(dims.crop_bottom),
2518 offset_for_non_ref_pic: dims.offset_for_non_ref_pic,
2519 offset_for_top_to_bottom_field: dims.offset_for_top_to_bottom_field,
2520 num_ref_frames_in_pic_order_cnt_cycle: dims.num_ref_frames_in_pic_order_cnt_cycle,
2521 offset_for_ref_frame: dims.offset_for_ref_frame,
2522 ..info_prefix
2523 })
2524}
2525
2526struct H264Dims {
2527 width: u32,
2528 height: u32,
2529 frame_mbs_only: bool,
2530 log2_max_frame_num_minus4: u8,
2531 pic_order_cnt_type: u8,
2532 log2_max_pic_order_cnt_lsb_minus4: Option<u8>,
2533 delta_pic_order_always_zero_flag: Option<bool>,
2534 offset_for_non_ref_pic: Option<i32>,
2535 offset_for_top_to_bottom_field: Option<i32>,
2536 num_ref_frames_in_pic_order_cnt_cycle: Option<u8>,
2537 offset_for_ref_frame: Vec<i32>,
2538 max_num_ref_frames: u8,
2539 gaps_in_frame_num_value_allowed_flag: bool,
2540 mb_adaptive_frame_field_flag: Option<bool>,
2541 direct_8x8_inference_flag: bool,
2542 frame_cropping_flag: bool,
2543 crop_left: u32,
2544 crop_right: u32,
2545 crop_top: u32,
2546 crop_bottom: u32,
2547}
2548
2549fn parse_h264_sps_dims(
2550 br: &mut BitReader,
2551 chroma_format_idc: u8,
2552 separate_colour_plane_flag: bool,
2553) -> Option<H264Dims> {
2554 let log2_max_frame_num_minus4 = br.read_ue()? as u8;
2555 let pic_order_cnt_type = br.read_ue()? as u8;
2556 let mut log2_max_pic_order_cnt_lsb_minus4 = None;
2557 let mut delta_pic_order_always_zero_flag = None;
2558 let mut offset_for_non_ref_pic = None;
2559 let mut offset_for_top_to_bottom_field = None;
2560 let mut num_ref_frames_in_pic_order_cnt_cycle: Option<u8> = None;
2561 let mut offset_for_ref_frame: Vec<i32> = Vec::new();
2562 match pic_order_cnt_type {
2563 0 => {
2564 log2_max_pic_order_cnt_lsb_minus4 = Some(br.read_ue()? as u8);
2565 }
2566 1 => {
2567 delta_pic_order_always_zero_flag = Some(br.read_bits(1)? == 1);
2568 offset_for_non_ref_pic = Some(br.read_se()?);
2569 offset_for_top_to_bottom_field = Some(br.read_se()?);
2570 let cycle_len = br.read_ue()?;
2571 let capped = cycle_len.min(255) as u8;
2574 num_ref_frames_in_pic_order_cnt_cycle = Some(capped);
2575 offset_for_ref_frame.reserve(capped as usize);
2576 for _ in 0..capped {
2577 offset_for_ref_frame.push(br.read_se()?);
2578 }
2579 }
2580 2 => { }
2581 _ => return None, }
2583 let max_num_ref_frames = br.read_ue()?.min(u8::MAX as u32) as u8;
2584 let gaps_in_frame_num_value_allowed_flag = br.read_bits(1)? == 1;
2585 let pic_width_in_mbs_minus1 = br.read_ue()?;
2586 let pic_height_in_map_units_minus1 = br.read_ue()?;
2587 let frame_mbs_only_flag = br.read_bits(1)?;
2588 let mut mb_adaptive_frame_field_flag = None;
2589 if frame_mbs_only_flag == 0 {
2590 mb_adaptive_frame_field_flag = Some(br.read_bits(1)? == 1);
2591 }
2592 let direct_8x8_inference_flag = br.read_bits(1)? == 1;
2593 let frame_cropping_flag = br.read_bits(1)? == 1;
2594 let (cl, cr, ct, cb) = if frame_cropping_flag {
2595 (br.read_ue()?, br.read_ue()?, br.read_ue()?, br.read_ue()?)
2596 } else {
2597 (0, 0, 0, 0)
2598 };
2599
2600 let pic_width_in_mbs = pic_width_in_mbs_minus1.saturating_add(1);
2601 let pic_height_in_map_units = pic_height_in_map_units_minus1.saturating_add(1);
2602 let frame_mbs_only = frame_mbs_only_flag == 1;
2603 let frame_height_in_mbs = if frame_mbs_only {
2604 pic_height_in_map_units
2605 } else {
2606 pic_height_in_map_units.saturating_mul(2)
2607 };
2608
2609 let chroma_array_type = if separate_colour_plane_flag {
2611 0
2612 } else {
2613 chroma_format_idc
2614 };
2615 let (sub_w, sub_h) = match chroma_array_type {
2616 0 => (1u32, 1u32), 1 => (2, 2), 2 => (2, 1), 3 => (1, 1), _ => (1, 1),
2621 };
2622 let (crop_x, crop_y) = if chroma_array_type == 0 {
2623 (1u32, 2u32 - frame_mbs_only_flag)
2624 } else {
2625 (sub_w, sub_h * (2 - frame_mbs_only_flag))
2626 };
2627
2628 let width = pic_width_in_mbs
2629 .saturating_mul(16)
2630 .saturating_sub(crop_x.saturating_mul(cl.saturating_add(cr)));
2631 let height = frame_height_in_mbs
2632 .saturating_mul(16)
2633 .saturating_sub(crop_y.saturating_mul(ct.saturating_add(cb)));
2634
2635 Some(H264Dims {
2636 width,
2637 height,
2638 frame_mbs_only,
2639 log2_max_frame_num_minus4,
2640 pic_order_cnt_type,
2641 log2_max_pic_order_cnt_lsb_minus4,
2642 delta_pic_order_always_zero_flag,
2643 offset_for_non_ref_pic,
2644 offset_for_top_to_bottom_field,
2645 num_ref_frames_in_pic_order_cnt_cycle,
2646 offset_for_ref_frame,
2647 max_num_ref_frames,
2648 gaps_in_frame_num_value_allowed_flag,
2649 mb_adaptive_frame_field_flag,
2650 direct_8x8_inference_flag,
2651 frame_cropping_flag,
2652 crop_left: cl,
2653 crop_right: cr,
2654 crop_top: ct,
2655 crop_bottom: cb,
2656 })
2657}
2658
2659pub fn parse_hevc_sps(sample: &[u8]) -> Option<HevcSpsInfo> {
2664 let sps = find_hevc_sps(sample)?;
2665 let rbsp = remove_h264_rbsp_stuffing(sps);
2666 let mut br = BitReader::new(&rbsp);
2667
2668 let sps_video_parameter_set_id = br.read_bits(4)? as u8;
2669 let sps_max_sub_layers_minus1 = br.read_bits(3)? as u8;
2670 let sps_temporal_id_nesting_flag = br.read_bits(1)? == 1;
2671 let general_profile_space = br.read_bits(2)?;
2675 let tier_flag = br.read_bits(1)? == 1;
2676 let profile_idc = br.read_bits(5)? as u8;
2677 let _ = general_profile_space;
2678 let profile_compatibility_flags = br.read_bits(32)?;
2680 let _ = br.read_bits(48)?;
2683 let level_idc = br.read_bits(8)? as u8;
2684 let mut spl = Vec::with_capacity(sps_max_sub_layers_minus1 as usize);
2687 let mut sll = Vec::with_capacity(sps_max_sub_layers_minus1 as usize);
2688 for _ in 0..sps_max_sub_layers_minus1 {
2689 spl.push(br.read_bits(1)?);
2690 sll.push(br.read_bits(1)?);
2691 }
2692 if sps_max_sub_layers_minus1 > 0 {
2693 for _ in sps_max_sub_layers_minus1 as usize..8 {
2694 let _ = br.read_bits(2)?;
2695 }
2696 }
2697 for i in 0..sps_max_sub_layers_minus1 as usize {
2698 if spl[i] == 1 {
2699 let _ = br.read_bits(8)?;
2700 let _ = br.read_bits(32)?;
2701 let _ = br.read_bits(48)?;
2702 }
2703 if sll[i] == 1 {
2704 let _ = br.read_bits(8)?;
2705 }
2706 }
2707
2708 let sps_seq_parameter_set_id = br.read_ue()? as u8;
2709 let chroma_format_idc = br.read_ue()? as u8;
2710 let separate_colour_plane_flag = if chroma_format_idc == 3 {
2711 br.read_bits(1)? == 1
2712 } else {
2713 false
2714 };
2715 let pic_width = br.read_ue()?;
2716 let pic_height = br.read_ue()?;
2717 let conformance_window_flag = br.read_bits(1)?;
2718 let (cl, cr, ct, cb) = if conformance_window_flag == 1 {
2719 (br.read_ue()?, br.read_ue()?, br.read_ue()?, br.read_ue()?)
2720 } else {
2721 (0u32, 0u32, 0u32, 0u32)
2722 };
2723 let bit_depth_luma_m8 = br.read_ue()?;
2724 let bit_depth_chroma_m8 = br.read_ue()?;
2725 let log2_max_pic_order_cnt_lsb_minus4 = br.read_ue()? as u8;
2726
2727 let sps_sub_layer_ordering_info_present_flag = br.read_bits(1)? == 1;
2734 let mut max_dec_pic_buffering_minus1 = [0u8; 7];
2735 let mut max_num_reorder_pics = [0u8; 7];
2736 let mut max_latency_increase_plus1 = [0u32; 7];
2737 let start = if sps_sub_layer_ordering_info_present_flag {
2738 0
2739 } else {
2740 sps_max_sub_layers_minus1
2741 };
2742 for i in start..=sps_max_sub_layers_minus1 {
2743 let dec = br.read_ue()?;
2744 let nro = br.read_ue()?;
2745 let latency = br.read_ue()?;
2746 let idx = (i as usize).min(6);
2747 max_dec_pic_buffering_minus1[idx] = dec.min(u8::MAX as u32) as u8;
2748 max_num_reorder_pics[idx] = nro.min(u8::MAX as u32) as u8;
2749 max_latency_increase_plus1[idx] = latency;
2750 }
2751 if !sps_sub_layer_ordering_info_present_flag {
2753 let top = sps_max_sub_layers_minus1 as usize;
2754 for i in 0..top {
2755 max_dec_pic_buffering_minus1[i] = max_dec_pic_buffering_minus1[top];
2756 max_num_reorder_pics[i] = max_num_reorder_pics[top];
2757 max_latency_increase_plus1[i] = max_latency_increase_plus1[top];
2758 }
2759 }
2760
2761 let log2_min_luma_coding_block_size_minus3 = br.read_ue()? as u8;
2762 let log2_diff_max_min_luma_coding_block_size = br.read_ue()? as u8;
2763 let log2_min_luma_transform_block_size_minus2 = br.read_ue()? as u8;
2764 let log2_diff_max_min_luma_transform_block_size = br.read_ue()? as u8;
2765 let max_transform_hierarchy_depth_inter = br.read_ue()? as u8;
2766 let max_transform_hierarchy_depth_intra = br.read_ue()? as u8;
2767
2768 let scaling_list_enabled_flag = br.read_bits(1)? == 1;
2769 if scaling_list_enabled_flag {
2770 let sps_scaling_list_data_present_flag = br.read_bits(1)? == 1;
2771 if sps_scaling_list_data_present_flag {
2772 skip_hevc_scaling_list_data(&mut br)?;
2773 }
2774 }
2775 let amp_enabled_flag = br.read_bits(1)? == 1;
2776 let sample_adaptive_offset_enabled_flag = br.read_bits(1)? == 1;
2777 let pcm_enabled_flag = br.read_bits(1)? == 1;
2778 let mut pcm_loop_filter_disabled_flag = false;
2779 if pcm_enabled_flag {
2780 let _pcm_sample_bit_depth_luma_minus1 = br.read_bits(4)?;
2781 let _pcm_sample_bit_depth_chroma_minus1 = br.read_bits(4)?;
2782 let _log2_min_pcm_luma_cb_size_minus3 = br.read_ue()?;
2783 let _log2_diff_max_min_pcm_luma_cb_size = br.read_ue()?;
2784 pcm_loop_filter_disabled_flag = br.read_bits(1)? == 1;
2785 }
2786 let num_short_term_ref_pic_sets = br.read_ue()? as u8;
2787 let mut st_rps_offsets: Vec<()> = Vec::with_capacity(num_short_term_ref_pic_sets as usize);
2793 for rps_idx in 0..num_short_term_ref_pic_sets {
2794 skip_hevc_short_term_rps(&mut br, rps_idx, num_short_term_ref_pic_sets)?;
2795 st_rps_offsets.push(());
2796 }
2797 let long_term_ref_pics_present_flag = br.read_bits(1)? == 1;
2798 if long_term_ref_pics_present_flag {
2799 let num_long_term_ref_pics_sps = br.read_ue()?;
2800 let lsb_bits = (log2_max_pic_order_cnt_lsb_minus4 as usize) + 4;
2801 for _ in 0..num_long_term_ref_pics_sps {
2802 let _lt_ref_pic_poc_lsb_sps = br.read_bits(lsb_bits)?;
2803 let _used_by_curr_pic_lt_sps_flag = br.read_bits(1)?;
2804 }
2805 }
2806 let sps_temporal_mvp_enabled_flag = br.read_bits(1)? == 1;
2807 let strong_intra_smoothing_enabled_flag = br.read_bits(1)? == 1;
2808 let chroma_array_type = if separate_colour_plane_flag {
2811 0
2812 } else {
2813 chroma_format_idc
2814 };
2815 let (sub_w, sub_h) = match chroma_array_type {
2816 0 => (1u32, 1u32),
2817 1 => (2, 2),
2818 2 => (2, 1),
2819 3 => (1, 1),
2820 _ => (1, 1),
2821 };
2822 let width = pic_width.saturating_sub(sub_w.saturating_mul(cl.saturating_add(cr)));
2823 let height = pic_height.saturating_sub(sub_h.saturating_mul(ct.saturating_add(cb)));
2824
2825 Some(HevcSpsInfo {
2826 sps_video_parameter_set_id,
2827 sps_seq_parameter_set_id,
2828 sps_max_sub_layers_minus1,
2829 sps_temporal_id_nesting_flag,
2830 chroma_format_idc,
2831 separate_colour_plane_flag,
2832 bit_depth_luma: bit_depth_luma_m8 as u8 + 8,
2833 bit_depth_chroma: bit_depth_chroma_m8 as u8 + 8,
2834 width: Some(width),
2835 height: Some(height),
2836 conf_win_left_offset: cl,
2837 conf_win_right_offset: cr,
2838 conf_win_top_offset: ct,
2839 conf_win_bottom_offset: cb,
2840 log2_max_pic_order_cnt_lsb_minus4,
2841 log2_min_luma_coding_block_size_minus3,
2842 log2_diff_max_min_luma_coding_block_size,
2843 log2_min_luma_transform_block_size_minus2,
2844 log2_diff_max_min_luma_transform_block_size,
2845 max_transform_hierarchy_depth_inter,
2846 max_transform_hierarchy_depth_intra,
2847 scaling_list_enabled_flag,
2848 sps_sub_layer_ordering_info_present_flag,
2849 amp_enabled_flag,
2850 sample_adaptive_offset_enabled_flag,
2851 pcm_enabled_flag,
2852 pcm_loop_filter_disabled_flag,
2853 num_short_term_ref_pic_sets,
2854 long_term_ref_pics_present_flag,
2855 sps_temporal_mvp_enabled_flag,
2856 strong_intra_smoothing_enabled_flag,
2857 profile_idc,
2858 level_idc,
2859 tier_flag,
2860 max_dec_pic_buffering_minus1,
2861 max_num_reorder_pics,
2862 max_latency_increase_plus1,
2863 profile_compatibility_flags,
2864 })
2865}
2866
2867fn skip_hevc_scaling_list_data(br: &mut BitReader) -> Option<()> {
2872 for size_id in 0..4 {
2873 let matrix_count = if size_id == 3 { 2 } else { 6 };
2874 for _matrix_id in 0..matrix_count {
2875 let scaling_list_pred_mode_flag = br.read_bits(1)? == 1;
2876 if !scaling_list_pred_mode_flag {
2877 let _scaling_list_pred_matrix_id_delta = br.read_ue()?;
2878 } else {
2879 let coef_num: usize = (1 << (4 + (size_id << 1))).min(64);
2880 if size_id > 1 {
2881 let _scaling_list_dc_coef_minus8 = br.read_se()?;
2882 }
2883 for _ in 0..coef_num {
2884 let _scaling_list_delta_coef = br.read_se()?;
2885 }
2886 }
2887 }
2888 }
2889 Some(())
2890}
2891
2892fn skip_hevc_short_term_rps(br: &mut BitReader, st_rps_idx: u8, num_st_rps: u8) -> Option<()> {
2896 let inter_ref_pic_set_prediction_flag = if st_rps_idx != 0 {
2897 br.read_bits(1)? == 1
2898 } else {
2899 false
2900 };
2901 if inter_ref_pic_set_prediction_flag {
2902 if st_rps_idx == num_st_rps {
2903 let _delta_idx_minus1 = br.read_ue()?;
2904 }
2905 let _delta_rps_sign = br.read_bits(1)?;
2906 let _abs_delta_rps_minus1 = br.read_ue()?;
2907 for _ in 0..16 {
2912 let used = br.read_bits(1)?;
2913 if used == 0 {
2914 let _use_delta_flag = br.read_bits(1)?;
2915 }
2916 }
2917 } else {
2918 let num_negative_pics = br.read_ue()?;
2919 let num_positive_pics = br.read_ue()?;
2920 for _ in 0..num_negative_pics {
2921 let _delta_poc_s0_minus1 = br.read_ue()?;
2922 let _used_by_curr_pic_s0_flag = br.read_bits(1)?;
2923 }
2924 for _ in 0..num_positive_pics {
2925 let _delta_poc_s1_minus1 = br.read_ue()?;
2926 let _used_by_curr_pic_s1_flag = br.read_bits(1)?;
2927 }
2928 }
2929 Some(())
2930}
2931
2932pub fn parse_h265_vps(sample: &[u8]) -> Option<H265VpsInfo> {
2934 let nal = find_hevc_nal_by_type(sample, 32)?;
2935 let rbsp = remove_h264_rbsp_stuffing(nal);
2936 let mut br = BitReader::new(&rbsp);
2937 let vps_video_parameter_set_id = br.read_bits(4)? as u8;
2938 let _vps_base_layer_internal_flag = br.read_bits(1)?;
2939 let _vps_base_layer_available_flag = br.read_bits(1)?;
2940 let _vps_max_layers_minus1 = br.read_bits(6)?;
2941 let vps_max_sub_layers_minus1 = br.read_bits(3)? as u8;
2942 let vps_temporal_id_nesting_flag = br.read_bits(1)? == 1;
2943 let _vps_reserved_0xffff_16bits = br.read_bits(16)?;
2944 let _gp_space = br.read_bits(2)?;
2947 let tier_flag = br.read_bits(1)? == 1;
2948 let profile_idc = br.read_bits(5)? as u8;
2949 let _ = br.read_bits(32)?; let _ = br.read_bits(48)?; let level_idc = br.read_bits(8)? as u8;
2952 Some(H265VpsInfo {
2953 vps_video_parameter_set_id,
2954 vps_max_sub_layers_minus1,
2955 vps_temporal_id_nesting_flag,
2956 profile_idc,
2957 level_idc,
2958 tier_flag,
2959 })
2960}
2961
2962pub fn parse_h265_pps(sample: &[u8]) -> Option<H265PpsInfo> {
2964 let nal = find_hevc_nal_by_type(sample, 34)?;
2965 let rbsp = remove_h264_rbsp_stuffing(nal);
2966 let mut br = BitReader::new(&rbsp);
2967 let pps_pic_parameter_set_id = br.read_ue()? as u8;
2968 let pps_seq_parameter_set_id = br.read_ue()? as u8;
2969 let dependent_slice_segments_enabled_flag = br.read_bits(1)? == 1;
2970 let output_flag_present_flag = br.read_bits(1)? == 1;
2971 let num_extra_slice_header_bits = br.read_bits(3)? as u8;
2972 let sign_data_hiding_enabled_flag = br.read_bits(1)? == 1;
2973 let cabac_init_present_flag = br.read_bits(1)? == 1;
2974 let num_ref_idx_l0_default_active_minus1 = br.read_ue()? as u8;
2975 let num_ref_idx_l1_default_active_minus1 = br.read_ue()? as u8;
2976 let init_qp_minus26 = clamp_to_i8(br.read_se()?);
2977 let constrained_intra_pred_flag = br.read_bits(1)? == 1;
2978 let transform_skip_enabled_flag = br.read_bits(1)? == 1;
2979 let cu_qp_delta_enabled_flag = br.read_bits(1)? == 1;
2980 let diff_cu_qp_delta_depth = if cu_qp_delta_enabled_flag {
2981 br.read_ue()? as u8
2982 } else {
2983 0
2984 };
2985 let pps_cb_qp_offset = clamp_to_i8(br.read_se()?);
2986 let pps_cr_qp_offset = clamp_to_i8(br.read_se()?);
2987 let pps_slice_chroma_qp_offsets_present_flag = br.read_bits(1)? == 1;
2988 let weighted_pred_flag = br.read_bits(1)? == 1;
2989 let weighted_bipred_flag = br.read_bits(1)? == 1;
2990 let transquant_bypass_enabled_flag = br.read_bits(1)? == 1;
2991 let tiles_enabled_flag = br.read_bits(1)? == 1;
2992 let entropy_coding_sync_enabled_flag = br.read_bits(1)? == 1;
2993
2994 let mut num_tile_columns_minus1 = 0u8;
2999 let mut num_tile_rows_minus1 = 0u8;
3000 let mut uniform_spacing_flag = true;
3001 let mut loop_filter_across_tiles_enabled_flag = true;
3002 if tiles_enabled_flag {
3003 num_tile_columns_minus1 = br.read_ue().unwrap_or(0) as u8;
3004 num_tile_rows_minus1 = br.read_ue().unwrap_or(0) as u8;
3005 uniform_spacing_flag = br.read_bits(1).unwrap_or(1) == 1;
3006 if !uniform_spacing_flag {
3007 for _ in 0..num_tile_columns_minus1 {
3010 let _ = br.read_ue();
3011 }
3012 for _ in 0..num_tile_rows_minus1 {
3013 let _ = br.read_ue();
3014 }
3015 }
3016 loop_filter_across_tiles_enabled_flag = br.read_bits(1).unwrap_or(1) == 1;
3017 }
3018 let pps_loop_filter_across_slices_enabled_flag = br.read_bits(1)? == 1;
3019
3020 let deblocking_filter_control_present_flag = br.read_bits(1)? == 1;
3022 let mut deblocking_filter_override_enabled_flag = false;
3023 let mut pps_deblocking_filter_disabled_flag = false;
3024 let mut pps_beta_offset_div2 = 0i8;
3025 let mut pps_tc_offset_div2 = 0i8;
3026 if deblocking_filter_control_present_flag {
3027 deblocking_filter_override_enabled_flag = br.read_bits(1)? == 1;
3028 pps_deblocking_filter_disabled_flag = br.read_bits(1)? == 1;
3029 if !pps_deblocking_filter_disabled_flag {
3030 pps_beta_offset_div2 = clamp_to_i8(br.read_se()?);
3031 pps_tc_offset_div2 = clamp_to_i8(br.read_se()?);
3032 }
3033 }
3034
3035 let pps_scaling_list_data_present_flag = br.read_bits(1)? == 1;
3037 let lists_modification_present_flag = br.read_bits(1)? == 1;
3044 let log2_parallel_merge_level_minus2 = br.read_ue().unwrap_or(0) as u8;
3045 let slice_segment_header_extension_present_flag = br.read_bits(1)? == 1;
3046 let pps_extension_present_flag = br.read_bits(1).unwrap_or(0) == 1;
3047
3048 Some(H265PpsInfo {
3049 pps_pic_parameter_set_id,
3050 pps_seq_parameter_set_id,
3051 dependent_slice_segments_enabled_flag,
3052 output_flag_present_flag,
3053 num_extra_slice_header_bits,
3054 sign_data_hiding_enabled_flag,
3055 cabac_init_present_flag,
3056 num_ref_idx_l0_default_active_minus1,
3057 num_ref_idx_l1_default_active_minus1,
3058 init_qp_minus26,
3059 constrained_intra_pred_flag,
3060 transform_skip_enabled_flag,
3061 cu_qp_delta_enabled_flag,
3062 diff_cu_qp_delta_depth,
3063 pps_cb_qp_offset,
3064 pps_cr_qp_offset,
3065 pps_slice_chroma_qp_offsets_present_flag,
3066 weighted_pred_flag,
3067 weighted_bipred_flag,
3068 transquant_bypass_enabled_flag,
3069 tiles_enabled_flag,
3070 entropy_coding_sync_enabled_flag,
3071 num_tile_columns_minus1,
3072 num_tile_rows_minus1,
3073 uniform_spacing_flag,
3074 loop_filter_across_tiles_enabled_flag,
3075 pps_loop_filter_across_slices_enabled_flag,
3076 deblocking_filter_control_present_flag,
3077 deblocking_filter_override_enabled_flag,
3078 pps_deblocking_filter_disabled_flag,
3079 pps_beta_offset_div2,
3080 pps_tc_offset_div2,
3081 pps_scaling_list_data_present_flag,
3082 lists_modification_present_flag,
3083 log2_parallel_merge_level_minus2,
3084 slice_segment_header_extension_present_flag,
3085 pps_extension_present_flag,
3086 })
3087}
3088
3089pub fn parse_h265_slice_header(
3093 sample: &[u8],
3094 sps: &HevcSpsInfo,
3095 pps: &H265PpsInfo,
3096) -> Option<H265SliceHeader> {
3097 let (nal_unit_type, rbsp) = find_hevc_slice_nal(sample)?;
3098 let mut br = BitReader::new(&rbsp);
3099 let first_slice_segment_in_pic_flag = br.read_bits(1)? == 1;
3100 let is_irap = (16..=23).contains(&nal_unit_type);
3101 let is_idr = matches!(nal_unit_type, 19 | 20);
3102 if is_irap {
3103 let _no_output_of_prior_pics_flag = br.read_bits(1)?;
3104 }
3105 let slice_pic_parameter_set_id = br.read_ue()? as u8;
3106 let dependent_slice_segment_flag =
3107 if !first_slice_segment_in_pic_flag && pps.dependent_slice_segments_enabled_flag {
3108 br.read_bits(1)? == 1
3109 } else {
3110 false
3111 };
3112 if !first_slice_segment_in_pic_flag {
3113 return None;
3120 }
3121 let _ = dependent_slice_segment_flag;
3122 for _ in 0..pps.num_extra_slice_header_bits {
3124 let _ = br.read_bits(1)?;
3125 }
3126 let slice_type_code = br.read_ue()?;
3127 let slice_type = H265SliceType::from_ue(slice_type_code)?;
3128 if pps.output_flag_present_flag {
3129 let _pic_output_flag = br.read_bits(1)?;
3130 }
3131 if sps.separate_colour_plane_flag {
3132 let _colour_plane_id = br.read_bits(2)?;
3133 }
3134
3135 let (pic_order_cnt_lsb, short_term_ref_pic_set_sps_flag, short_term_ref_pic_set_idx) =
3136 if !is_idr {
3137 let lsb_bits = (sps.log2_max_pic_order_cnt_lsb_minus4 as usize) + 4;
3138 let lsb = br.read_bits(lsb_bits)?;
3139 let sps_flag = br.read_bits(1)? == 1;
3140 let idx = if sps_flag {
3141 if sps.num_short_term_ref_pic_sets > 1 {
3142 let bits =
3143 ((sps.num_short_term_ref_pic_sets as f64).log2().ceil() as usize).max(1);
3144 Some(br.read_bits(bits)? as u8)
3145 } else {
3146 Some(0)
3147 }
3148 } else {
3149 None
3150 };
3151 (lsb, sps_flag, idx)
3152 } else {
3153 (0, false, None)
3154 };
3155
3156 Some(H265SliceHeader {
3157 first_slice_segment_in_pic_flag,
3158 nal_unit_type,
3159 slice_pic_parameter_set_id,
3160 slice_type,
3161 pic_order_cnt_lsb,
3162 short_term_ref_pic_set_sps_flag,
3163 short_term_ref_pic_set_idx,
3164 is_irap,
3165 is_idr,
3166 })
3167}
3168
3169fn find_hevc_nal_by_type(data: &[u8], target: u8) -> Option<&[u8]> {
3171 let mut i = 0;
3172 while i + 4 < data.len() {
3173 let (start_len, nal_byte) = if data[i] == 0 && data[i + 1] == 0 && data[i + 2] == 1 {
3174 (3, i + 3)
3175 } else if data[i] == 0 && data[i + 1] == 0 && data[i + 2] == 0 && data[i + 3] == 1 {
3176 (4, i + 4)
3177 } else {
3178 i += 1;
3179 continue;
3180 };
3181 if nal_byte + 1 >= data.len() {
3182 return None;
3183 }
3184 let nal_unit_type = (data[nal_byte] >> 1) & 0x3F;
3185 if nal_unit_type == target {
3186 let start = nal_byte + 2; let end = find_next_start_code(&data[start..])
3188 .map(|off| start + off)
3189 .unwrap_or(data.len());
3190 return Some(&data[start..end]);
3191 }
3192 i += start_len;
3193 }
3194 None
3195}
3196
3197pub fn hevc_first_slice_nal_offset(data: &[u8]) -> Option<u32> {
3202 let mut i = 0;
3203 while i + 4 < data.len() {
3204 let (start_len, nal_byte) = if data[i] == 0 && data[i + 1] == 0 && data[i + 2] == 1 {
3205 (3usize, i + 3)
3206 } else if data[i] == 0 && data[i + 1] == 0 && data[i + 2] == 0 && data[i + 3] == 1 {
3207 (4usize, i + 4)
3208 } else {
3209 i += 1;
3210 continue;
3211 };
3212 if nal_byte + 1 >= data.len() {
3213 return None;
3214 }
3215 let t = (data[nal_byte] >> 1) & 0x3F;
3216 if (0..=9).contains(&t) || (16..=23).contains(&t) {
3217 return Some(nal_byte as u32);
3218 }
3219 i += start_len;
3220 }
3221 None
3222}
3223
3224pub fn h264_first_slice_nal_offset(data: &[u8]) -> Option<u32> {
3228 let mut i = 0;
3229 while i + 4 < data.len() {
3230 let (start_len, nal_byte) = if data[i] == 0 && data[i + 1] == 0 && data[i + 2] == 1 {
3231 (3usize, i + 3)
3232 } else if data[i] == 0 && data[i + 1] == 0 && data[i + 2] == 0 && data[i + 3] == 1 {
3233 (4usize, i + 4)
3234 } else {
3235 i += 1;
3236 continue;
3237 };
3238 if nal_byte >= data.len() {
3239 return None;
3240 }
3241 let t = data[nal_byte] & 0x1F;
3242 if matches!(t, 1 | 5 | 19) {
3243 return Some(nal_byte as u32);
3244 }
3245 i += start_len;
3246 }
3247 None
3248}
3249
3250fn find_hevc_slice_nal(data: &[u8]) -> Option<(u8, Vec<u8>)> {
3253 let mut i = 0;
3254 while i + 4 < data.len() {
3255 let (start_len, nal_byte) = if data[i] == 0 && data[i + 1] == 0 && data[i + 2] == 1 {
3256 (3, i + 3)
3257 } else if data[i] == 0 && data[i + 1] == 0 && data[i + 2] == 0 && data[i + 3] == 1 {
3258 (4, i + 4)
3259 } else {
3260 i += 1;
3261 continue;
3262 };
3263 if nal_byte + 1 >= data.len() {
3264 return None;
3265 }
3266 let t = (data[nal_byte] >> 1) & 0x3F;
3267 if (0..=9).contains(&t) || (16..=23).contains(&t) {
3268 let start = nal_byte + 2;
3269 let end = find_next_start_code(&data[start..])
3270 .map(|off| start + off)
3271 .unwrap_or(data.len());
3272 return Some((t, remove_h264_rbsp_stuffing(&data[start..end])));
3273 }
3274 i += start_len;
3275 }
3276 None
3277}
3278
3279pub fn parse_mpeg2_sequence_header(sample: &[u8]) -> Option<Mpeg2SeqInfo> {
3289 let seq_hdr_start = find_mpeg2_start_code(sample, 0xB3)?;
3292 let hdr_body_off = seq_hdr_start + 4;
3293 if hdr_body_off + 3 > sample.len() {
3294 return None;
3295 }
3296 let b = &sample[hdr_body_off..hdr_body_off + 3];
3297 let mut width = (((b[0] as u32) << 4) | ((b[1] as u32) >> 4)) & 0x0FFF;
3298 let mut height = (((b[1] as u32 & 0x0F) << 8) | (b[2] as u32)) & 0x0FFF;
3299
3300 let search_from = hdr_body_off + 3;
3305 if search_from < sample.len()
3306 && let Some(ext_start) = find_mpeg2_start_code(&sample[search_from..], 0xB5)
3307 {
3308 let ext_body_off = search_from + ext_start + 4;
3309 if ext_body_off + 3 <= sample.len() {
3310 let mut br = BitReader::new(&sample[ext_body_off..]);
3311 if let Some(id) = br.read_bits(4)
3312 && id == 1
3313 {
3314 let _profile_level = br.read_bits(8)?;
3322 let _progressive = br.read_bits(1)?;
3323 let _chroma = br.read_bits(2)?;
3324 let h_ext = br.read_bits(2)?;
3325 let v_ext = br.read_bits(2)?;
3326 width |= h_ext << 12;
3327 height |= v_ext << 12;
3328 }
3329 }
3330 }
3331
3332 if width == 0 || height == 0 {
3333 return None;
3334 }
3335 Some(Mpeg2SeqInfo { width, height })
3336}
3337
3338fn find_mpeg2_start_code(data: &[u8], target: u8) -> Option<usize> {
3341 let mut i = 0;
3342 while i + 4 <= data.len() {
3343 if data[i] == 0 && data[i + 1] == 0 && data[i + 2] == 1 && data[i + 3] == target {
3344 return Some(i);
3345 }
3346 i += 1;
3347 }
3348 None
3349}
3350
3351#[derive(Debug, Clone, Copy, PartialEq, Eq)]
3364pub struct H264PpsInfo {
3365 pub pic_parameter_set_id: u8,
3366 pub seq_parameter_set_id: u8,
3367 pub entropy_coding_mode_flag: bool,
3368 pub bottom_field_pic_order_in_frame_present_flag: bool,
3372 pub num_slice_groups_minus1: u8,
3373 pub num_ref_idx_l0_default_active_minus1: u8,
3374 pub num_ref_idx_l1_default_active_minus1: u8,
3375 pub weighted_pred_flag: bool,
3376 pub weighted_bipred_idc: u8,
3377 pub pic_init_qp_minus26: i8,
3378 pub pic_init_qs_minus26: i8,
3379 pub chroma_qp_index_offset: i8,
3380 pub deblocking_filter_control_present_flag: bool,
3381 pub constrained_intra_pred_flag: bool,
3382 pub redundant_pic_cnt_present_flag: bool,
3383 pub transform_8x8_mode_flag: Option<bool>,
3387 pub pic_scaling_matrix_present_flag: Option<bool>,
3388 pub second_chroma_qp_index_offset: Option<i8>,
3389}
3390
3391pub fn parse_h264_pps(sample: &[u8]) -> Option<H264PpsInfo> {
3402 let pps = find_h264_nal_by_type(sample, 8)?;
3403 let rbsp = remove_h264_rbsp_stuffing(pps);
3404 let mut br = BitReader::new(&rbsp);
3405
3406 let pic_parameter_set_id = br.read_ue()? as u8;
3407 let seq_parameter_set_id = br.read_ue()? as u8;
3408 let entropy_coding_mode_flag = br.read_bits(1)? == 1;
3409 let bottom_field_pic_order_in_frame_present_flag = br.read_bits(1)? == 1;
3410
3411 let num_slice_groups_minus1 = br.read_ue()?;
3412 if num_slice_groups_minus1 > 0 {
3413 let slice_group_map_type = br.read_ue()?;
3415 match slice_group_map_type {
3416 0 => {
3417 for _ in 0..=num_slice_groups_minus1 {
3418 let _run_length_minus1 = br.read_ue()?;
3419 }
3420 }
3421 2 => {
3422 for _ in 0..num_slice_groups_minus1 {
3423 let _top_left = br.read_ue()?;
3424 let _bottom_right = br.read_ue()?;
3425 }
3426 }
3427 3..=5 => {
3428 let _slice_group_change_direction_flag = br.read_bits(1)?;
3429 let _slice_group_change_rate_minus1 = br.read_ue()?;
3430 }
3431 6 => {
3432 let pic_size_in_map_units_minus1 = br.read_ue()?;
3433 let bits = ((num_slice_groups_minus1 + 1) as f64).log2().ceil() as usize;
3434 let bits = bits.max(1);
3435 for _ in 0..=pic_size_in_map_units_minus1 {
3436 let _slice_group_id = br.read_bits(bits)?;
3437 }
3438 }
3439 _ => {}
3440 }
3441 }
3442
3443 let num_ref_idx_l0_default_active_minus1 = br.read_ue()? as u8;
3444 let num_ref_idx_l1_default_active_minus1 = br.read_ue()? as u8;
3445 let weighted_pred_flag = br.read_bits(1)? == 1;
3446 let weighted_bipred_idc = br.read_bits(2)? as u8;
3447 let pic_init_qp_minus26 = clamp_to_i8(br.read_se()?);
3448 let pic_init_qs_minus26 = clamp_to_i8(br.read_se()?);
3449 let chroma_qp_index_offset = clamp_to_i8(br.read_se()?);
3450 let deblocking_filter_control_present_flag = br.read_bits(1)? == 1;
3451 let constrained_intra_pred_flag = br.read_bits(1)? == 1;
3452 let redundant_pic_cnt_present_flag = br.read_bits(1)? == 1;
3453
3454 let (transform_8x8_mode_flag, pic_scaling_matrix_present_flag, second_chroma_qp_index_offset) =
3460 if more_rbsp_data(&br, &rbsp) {
3461 let t8 = br.read_bits(1).map(|v| v == 1);
3462 let psm = br.read_bits(1).map(|v| v == 1);
3463 if let Some(true) = psm {
3467 let count = 6 + if let Some(true) = t8 { 2 } else { 0 };
3472 for i in 0..count {
3473 if br.read_bits(1) == Some(1) {
3474 let size = if i < 6 { 16 } else { 64 };
3475 let mut last_scale: i32 = 8;
3476 let mut next_scale: i32 = 8;
3477 for _ in 0..size {
3478 if next_scale != 0 {
3479 let delta = br.read_se().unwrap_or(0);
3480 next_scale = (last_scale + delta + 256).rem_euclid(256);
3481 }
3482 if next_scale != 0 {
3483 last_scale = next_scale;
3484 }
3485 }
3486 }
3487 }
3488 }
3489 let s2 = br.read_se().map(clamp_to_i8);
3490 (t8, psm, s2)
3491 } else {
3492 (None, None, None)
3493 };
3494
3495 Some(H264PpsInfo {
3496 pic_parameter_set_id,
3497 seq_parameter_set_id,
3498 entropy_coding_mode_flag,
3499 bottom_field_pic_order_in_frame_present_flag,
3500 num_slice_groups_minus1: num_slice_groups_minus1.min(u8::MAX as u32) as u8,
3501 num_ref_idx_l0_default_active_minus1,
3502 num_ref_idx_l1_default_active_minus1,
3503 weighted_pred_flag,
3504 weighted_bipred_idc,
3505 pic_init_qp_minus26,
3506 pic_init_qs_minus26,
3507 chroma_qp_index_offset,
3508 deblocking_filter_control_present_flag,
3509 constrained_intra_pred_flag,
3510 redundant_pic_cnt_present_flag,
3511 transform_8x8_mode_flag,
3512 pic_scaling_matrix_present_flag,
3513 second_chroma_qp_index_offset,
3514 })
3515}
3516
3517fn more_rbsp_data(br: &BitReader, rbsp: &[u8]) -> bool {
3525 let pos = br.pos;
3526 let total_bits = rbsp.len() * 8;
3527 total_bits.saturating_sub(pos) > 8
3530}
3531
3532fn clamp_to_i8(v: i32) -> i8 {
3533 v.clamp(i8::MIN as i32, i8::MAX as i32) as i8
3534}
3535
3536#[derive(Debug, Clone, Copy, PartialEq, Eq)]
3542pub enum H264SliceType {
3543 P,
3544 B,
3545 I,
3546 SP,
3547 SI,
3548}
3549
3550impl H264SliceType {
3551 fn from_ue(v: u32) -> Option<Self> {
3552 match v % 5 {
3553 0 => Some(Self::P),
3554 1 => Some(Self::B),
3555 2 => Some(Self::I),
3556 3 => Some(Self::SP),
3557 4 => Some(Self::SI),
3558 _ => None,
3559 }
3560 }
3561}
3562
3563#[derive(Debug, Clone, Copy, PartialEq, Eq)]
3570pub struct H264SliceHeader {
3571 pub first_mb_in_slice: u32,
3572 pub slice_type: H264SliceType,
3573 pub pic_parameter_set_id: u8,
3574 pub is_idr: bool,
3578 pub frame_num: u32,
3579 pub field_pic_flag: bool,
3583 pub bottom_field_flag: bool,
3584 pub colour_plane_id: Option<u8>,
3585 pub idr_pic_id: Option<u32>,
3587 pub pic_order_cnt_lsb: Option<u32>,
3589 pub delta_pic_order_cnt_bottom: Option<i32>,
3590 pub delta_pic_order_cnt: [Option<i32>; 2],
3596}
3597
3598pub fn parse_h264_slice_header(
3606 sample: &[u8],
3607 sps: &H264SpsInfo,
3608 pps: &H264PpsInfo,
3609) -> Option<H264SliceHeader> {
3610 let (nal_type, rbsp) = find_h264_slice_nal(sample)?;
3614 let is_idr = nal_type == 5;
3615
3616 let mut br = BitReader::new(&rbsp);
3617 let first_mb_in_slice = br.read_ue()?;
3618 let slice_type_code = br.read_ue()?;
3619 let slice_type = H264SliceType::from_ue(slice_type_code)?;
3620 let pic_parameter_set_id = br.read_ue()? as u8;
3621
3622 let colour_plane_id = if sps.separate_colour_plane_flag {
3623 Some(br.read_bits(2)? as u8)
3624 } else {
3625 None
3626 };
3627
3628 let frame_num_bits = (sps.log2_max_frame_num_minus4? as usize) + 4;
3629 let frame_num = br.read_bits(frame_num_bits)?;
3630
3631 let (field_pic_flag, bottom_field_flag) = if !sps.frame_mbs_only {
3632 let f = br.read_bits(1)? == 1;
3633 let b = if f { br.read_bits(1)? == 1 } else { false };
3634 (f, b)
3635 } else {
3636 (false, false)
3637 };
3638
3639 let idr_pic_id = if is_idr { Some(br.read_ue()?) } else { None };
3640
3641 let poc_type = sps.pic_order_cnt_type?;
3642 let mut pic_order_cnt_lsb = None;
3643 let mut delta_pic_order_cnt_bottom = None;
3644 let mut delta_pic_order_cnt: [Option<i32>; 2] = [None, None];
3645 match poc_type {
3646 0 => {
3647 let bits = (sps.log2_max_pic_order_cnt_lsb_minus4? as usize) + 4;
3648 pic_order_cnt_lsb = Some(br.read_bits(bits)?);
3649 if pps.bottom_field_pic_order_in_frame_present_flag && !field_pic_flag {
3650 delta_pic_order_cnt_bottom = Some(br.read_se()?);
3651 }
3652 }
3653 1 => {
3654 let always_zero = sps.delta_pic_order_always_zero_flag.unwrap_or(false);
3655 if !always_zero {
3656 delta_pic_order_cnt[0] = Some(br.read_se()?);
3657 if pps.bottom_field_pic_order_in_frame_present_flag && !field_pic_flag {
3658 delta_pic_order_cnt[1] = Some(br.read_se()?);
3659 }
3660 }
3661 }
3662 2 => { }
3663 _ => return None,
3664 }
3665
3666 Some(H264SliceHeader {
3667 first_mb_in_slice,
3668 slice_type,
3669 pic_parameter_set_id,
3670 is_idr,
3671 frame_num,
3672 field_pic_flag,
3673 bottom_field_flag,
3674 colour_plane_id,
3675 idr_pic_id,
3676 pic_order_cnt_lsb,
3677 delta_pic_order_cnt_bottom,
3678 delta_pic_order_cnt,
3679 })
3680}
3681
3682fn find_h264_slice_nal(data: &[u8]) -> Option<(u8, Vec<u8>)> {
3685 let mut i = 0;
3686 while i + 4 < data.len() {
3687 let (start_len, nal_byte) = if data[i] == 0 && data[i + 1] == 0 && data[i + 2] == 1 {
3688 (3, i + 3)
3689 } else if data[i] == 0 && data[i + 1] == 0 && data[i + 2] == 0 && data[i + 3] == 1 {
3690 (4, i + 4)
3691 } else {
3692 i += 1;
3693 continue;
3694 };
3695 if nal_byte >= data.len() {
3696 return None;
3697 }
3698 let nal_unit_type = data[nal_byte] & 0x1F;
3699 if matches!(nal_unit_type, 1 | 5 | 19) {
3700 let start = nal_byte + 1;
3701 let end = find_next_start_code(&data[start..])
3702 .map(|off| start + off)
3703 .unwrap_or(data.len());
3704 let rbsp = remove_h264_rbsp_stuffing(&data[start..end]);
3705 return Some((nal_unit_type, rbsp));
3706 }
3707 i += start_len;
3708 }
3709 None
3710}
3711
3712fn find_h264_nal_by_type(data: &[u8], target_type: u8) -> Option<&[u8]> {
3716 let mut i = 0;
3717 while i + 4 < data.len() {
3718 let (start_len, nal_byte) = if data[i] == 0 && data[i + 1] == 0 && data[i + 2] == 1 {
3719 (3, i + 3)
3720 } else if data[i] == 0 && data[i + 1] == 0 && data[i + 2] == 0 && data[i + 3] == 1 {
3721 (4, i + 4)
3722 } else {
3723 i += 1;
3724 continue;
3725 };
3726 if nal_byte >= data.len() {
3727 return None;
3728 }
3729 let nal_unit_type = data[nal_byte] & 0x1F;
3730 if nal_unit_type == target_type {
3731 let start = nal_byte + 1;
3732 let end = find_next_start_code(&data[start..])
3733 .map(|off| start + off)
3734 .unwrap_or(data.len());
3735 return Some(&data[start..end]);
3736 }
3737 i += start_len;
3738 }
3739 None
3740}
3741
3742#[cfg(test)]
3743mod tests {
3744 use super::*;
3745
3746 #[test]
3747 fn detects_h264_baseline_yuv420p() {
3748 let sps_rbsp = vec![
3750 66, 0, 30, 0b1000_0000,
3755 ];
3756 let mut sample = vec![0, 0, 0, 1, 0x27]; sample.extend_from_slice(&sps_rbsp);
3758 let pf = detect_h264(&sample).unwrap();
3759 assert_eq!(pf, PixelFormat::Yuv420p);
3760 }
3761
3762 #[test]
3763 fn empty_samples_returns_default() {
3764 let pf = detect("h264", &[]);
3765 assert_eq!(pf, PixelFormat::Yuv420p);
3766 }
3767
3768 #[test]
3769 fn unknown_codec_returns_default() {
3770 let pf = detect("prores", &[vec![1, 2, 3]]);
3771 assert_eq!(pf, PixelFormat::Yuv420p);
3772 }
3773
3774 #[test]
3775 fn from_chroma_and_depth_420_8bit() {
3776 assert_eq!(
3777 PixelFormat::from_chroma_and_depth(1, 8),
3778 PixelFormat::Yuv420p
3779 );
3780 assert_eq!(
3781 PixelFormat::from_chroma_and_depth(1, 10),
3782 PixelFormat::Yuv420p10le
3783 );
3784 assert_eq!(
3785 PixelFormat::from_chroma_and_depth(2, 8),
3786 PixelFormat::Yuv422p
3787 );
3788 assert_eq!(
3789 PixelFormat::from_chroma_and_depth(3, 8),
3790 PixelFormat::Yuv444p
3791 );
3792 }
3793
3794 #[test]
3795 fn as_ffmpeg_str_matches_python_names() {
3796 assert_eq!(PixelFormat::Yuv420p.as_ffmpeg_str(), "yuv420p");
3797 assert_eq!(PixelFormat::Yuv420p10le.as_ffmpeg_str(), "yuv420p10le");
3798 assert_eq!(PixelFormat::Yuv444p.as_ffmpeg_str(), "yuv444p");
3799 }
3800
3801 struct BitWriter {
3811 bytes: Vec<u8>,
3812 bit_pos: usize, }
3814
3815 impl BitWriter {
3816 fn new() -> Self {
3817 Self {
3818 bytes: Vec::new(),
3819 bit_pos: 8,
3820 }
3821 }
3822 fn write_bit(&mut self, b: u8) {
3823 if self.bit_pos == 8 {
3824 self.bytes.push(0);
3825 self.bit_pos = 0;
3826 }
3827 if b != 0 {
3828 let idx = self.bytes.len() - 1;
3829 self.bytes[idx] |= 1 << (7 - self.bit_pos);
3830 }
3831 self.bit_pos += 1;
3832 }
3833 fn write_bits(&mut self, val: u64, n: usize) {
3834 for i in 0..n {
3838 let bit = ((val >> (n - 1 - i)) & 1) as u8;
3839 self.write_bit(bit);
3840 }
3841 }
3842 fn write_ue(&mut self, v: u32) {
3843 let z = if v == 0 { 0 } else { (v + 1).ilog2() as usize };
3844 for _ in 0..z {
3845 self.write_bit(0);
3846 }
3847 self.write_bit(1);
3848 if z > 0 {
3849 let suffix = (v + 1) - (1u32 << z);
3850 self.write_bits(suffix as u64, z);
3851 }
3852 }
3853 fn bytes(self) -> Vec<u8> {
3854 self.bytes
3855 }
3856 }
3857
3858 fn build_h264_baseline_sps(width_in_mbs: u32, height_in_mbs: u32) -> Vec<u8> {
3866 let mut w = BitWriter::new();
3867 w.write_bits(66, 8); w.write_bits(0, 8); w.write_bits(30, 8); w.write_ue(0); w.write_ue(0); w.write_ue(0); w.write_ue(0); w.write_ue(1); w.write_bit(0); w.write_ue(width_in_mbs - 1); w.write_ue(height_in_mbs - 1); w.write_bit(1); w.write_bit(1); w.write_bit(0); w.write_bit(0); w.write_bit(1); let mut sample = vec![0x00, 0x00, 0x00, 0x01, 0x67]; sample.extend_from_slice(&w.bytes());
3886 sample
3887 }
3888
3889 #[test]
3890 fn parse_h264_sps_baseline_1280x720() {
3891 let sample = build_h264_baseline_sps(1280 / 16, 720 / 16);
3892 let info = parse_h264_sps(&sample).expect("parse");
3893 assert_eq!(info.profile_idc, 66);
3894 assert_eq!(info.chroma_format_idc, 1); assert_eq!(info.width, Some(1280));
3896 assert_eq!(info.height, Some(720));
3897 assert!(info.frame_mbs_only);
3898 }
3899
3900 #[test]
3901 fn parse_h264_sps_baseline_640x480() {
3902 let sample = build_h264_baseline_sps(640 / 16, 480 / 16);
3903 let info = parse_h264_sps(&sample).expect("parse");
3904 assert_eq!(info.width, Some(640));
3905 assert_eq!(info.height, Some(480));
3906 }
3907
3908 #[test]
3909 fn parse_h264_sps_with_cropping_1920x1080() {
3910 let mut w = BitWriter::new();
3913 w.write_bits(66, 8);
3914 w.write_bits(0, 8);
3915 w.write_bits(40, 8);
3916 w.write_ue(0);
3917 w.write_ue(0);
3918 w.write_ue(0);
3919 w.write_ue(0);
3920 w.write_ue(1);
3921 w.write_bit(0);
3922 w.write_ue(1920 / 16 - 1); w.write_ue(1088 / 16 - 1); w.write_bit(1); w.write_bit(1); w.write_bit(1); w.write_ue(0); w.write_ue(0); w.write_ue(0); w.write_ue(4); w.write_bit(0); w.write_bit(1); let mut sample = vec![0, 0, 0, 1, 0x67];
3934 sample.extend_from_slice(&w.bytes());
3935 let info = parse_h264_sps(&sample).expect("parse");
3936 assert_eq!(info.width, Some(1920));
3937 assert_eq!(info.height, Some(1080));
3938 }
3939
3940 #[test]
3941 fn parse_h264_sps_high_profile_422_returns_chroma_even_without_dims() {
3942 let mut w = BitWriter::new();
3948 w.write_bits(122, 8); w.write_bits(0, 8);
3950 w.write_bits(40, 8);
3951 w.write_ue(0); w.write_ue(2); w.write_ue(0); w.write_ue(0); w.write_bit(0); w.write_bit(0); let mut sample = vec![0, 0, 0, 1, 0x67];
3960 sample.extend_from_slice(&w.bytes());
3961 let info = parse_h264_sps(&sample).expect("parse");
3962 assert_eq!(info.profile_idc, 122);
3963 assert_eq!(info.chroma_format_idc, 2);
3964 }
3966
3967 fn build_hevc_sps(pic_width: u32, pic_height: u32) -> Vec<u8> {
3972 build_hevc_sps_full(pic_width, pic_height, false, 0, 0, 0, 0)
3973 }
3974
3975 fn build_hevc_sps_full(
3976 pic_width: u32,
3977 pic_height: u32,
3978 conformance_window: bool,
3979 cwl: u32,
3980 cwr: u32,
3981 cwt: u32,
3982 cwb: u32,
3983 ) -> Vec<u8> {
3984 let mut w = BitWriter::new();
3985 w.write_bits(0, 4); w.write_bits(0, 3); w.write_bits(1, 1); w.write_bits(0b0_0_00001, 8); w.write_bits(0x40000000, 32); w.write_bits(0, 48); w.write_bits(93, 8); w.write_ue(0); w.write_ue(1); w.write_ue(pic_width);
3996 w.write_ue(pic_height);
3997 if conformance_window {
3998 w.write_bit(1);
3999 w.write_ue(cwl);
4000 w.write_ue(cwr);
4001 w.write_ue(cwt);
4002 w.write_ue(cwb);
4003 } else {
4004 w.write_bit(0); }
4006 w.write_ue(0); w.write_ue(0); w.write_ue(4); w.write_bit(1); w.write_ue(4); w.write_ue(0); w.write_ue(0); w.write_ue(0); w.write_ue(3); w.write_ue(0); w.write_ue(3); w.write_ue(2); w.write_ue(2); w.write_bit(0); w.write_bit(1); w.write_bit(1); w.write_bit(0); w.write_ue(0); w.write_bit(0); w.write_bit(1); w.write_bit(0); w.write_bit(0); w.write_bit(0); w.write_bit(1); let mut sample = vec![0, 0, 0, 1, 0x42, 0x01];
4032 sample.extend_from_slice(&w.bytes());
4033 sample
4034 }
4035
4036 #[test]
4037 fn parse_hevc_sps_1920x1080_no_crop() {
4038 let sample = build_hevc_sps(1920, 1080);
4039 let info = parse_hevc_sps(&sample).expect("parse");
4040 assert_eq!(info.chroma_format_idc, 1);
4041 assert_eq!(info.bit_depth_luma, 8);
4042 assert_eq!(info.width, Some(1920));
4043 assert_eq!(info.height, Some(1080));
4044 }
4045
4046 #[test]
4047 fn parse_hevc_sps_with_conformance_window() {
4048 let sample = build_hevc_sps_full(1920, 1088, true, 0, 0, 0, 4);
4051 let info = parse_hevc_sps(&sample).expect("parse");
4052 assert_eq!(info.width, Some(1920));
4053 assert_eq!(info.height, Some(1080));
4054 }
4055
4056 #[test]
4057 fn parse_mpeg2_sequence_header_no_extension_640x480() {
4058 let sample = vec![0x00, 0x00, 0x01, 0xB3, 0x28, 0x01, 0xE0, 0x13, 0xFF, 0xFF];
4062 let info = parse_mpeg2_sequence_header(&sample).expect("parse");
4063 assert_eq!(info.width, 640);
4064 assert_eq!(info.height, 480);
4065 }
4066
4067 #[test]
4068 fn parse_mpeg2_sequence_header_with_extension_upgrades_to_14bit() {
4069 let mut bytes = vec![0x00, 0x00, 0x01, 0xB3, 0x78, 0x04, 0x38, 0x13, 0xFF, 0xFF];
4076 let mut w = BitWriter::new();
4082 w.write_bits(1, 4); w.write_bits(0, 8); w.write_bit(1); w.write_bits(1, 2); w.write_bits(1, 2); w.write_bits(2, 2); w.write_bits(0, 1); bytes.extend_from_slice(&[0x00, 0x00, 0x01, 0xB5]);
4090 bytes.extend_from_slice(&w.bytes());
4091 let info = parse_mpeg2_sequence_header(&bytes).expect("parse");
4092 assert_eq!(info.width, 1920 | (1 << 12)); assert_eq!(info.height, 1080 | (2 << 12)); }
4095
4096 #[test]
4097 fn parse_mpeg2_sequence_header_none_when_no_start_code() {
4098 let sample = vec![0xFFu8; 128];
4099 assert!(parse_mpeg2_sequence_header(&sample).is_none());
4100 }
4101
4102 #[test]
4103 fn detect_dims_dispatches_by_codec() {
4104 let h264 = build_h264_baseline_sps(1280 / 16, 720 / 16);
4105 let hevc = build_hevc_sps(1920, 1080);
4106 let mpeg2 = vec![0x00, 0x00, 0x01, 0xB3, 0x28, 0x01, 0xE0, 0x13, 0xFF, 0xFF];
4107 assert_eq!(detect_dims("h264", &[h264.clone()]), Some((1280, 720)));
4108 assert_eq!(detect_dims("avc1", &[h264]), Some((1280, 720)));
4109 assert_eq!(detect_dims("h265", &[hevc.clone()]), Some((1920, 1080)));
4110 assert_eq!(detect_dims("hevc", &[hevc]), Some((1920, 1080)));
4111 assert_eq!(detect_dims("mpeg2", &[mpeg2]), Some((640, 480)));
4112 assert_eq!(detect_dims("unknown", &[vec![0u8; 8]]), None);
4113 assert_eq!(detect_dims("h264", &[]), None);
4114 }
4115
4116 fn build_h264_baseline_pps(pps_id: u32, sps_id: u32) -> Vec<u8> {
4120 let mut w = BitWriter::new();
4121 w.write_ue(pps_id); w.write_ue(sps_id); w.write_bit(0); w.write_bit(0); w.write_ue(0); w.write_ue(0); w.write_ue(0); w.write_bit(0); w.write_bits(0, 2); w.write_ue(0); w.write_ue(0); w.write_ue(0); w.write_bit(1); w.write_bit(0); w.write_bit(0); w.write_bit(1); let mut sample = vec![0x00, 0x00, 0x00, 0x01, 0x68]; sample.extend_from_slice(&w.bytes());
4139 sample
4140 }
4141
4142 #[test]
4143 fn parse_h264_pps_baseline_roundtrip() {
4144 let sample = build_h264_baseline_pps(0, 0);
4145 let info = parse_h264_pps(&sample).expect("PPS parses");
4146 assert_eq!(info.pic_parameter_set_id, 0);
4147 assert_eq!(info.seq_parameter_set_id, 0);
4148 assert!(!info.entropy_coding_mode_flag);
4149 assert!(!info.bottom_field_pic_order_in_frame_present_flag);
4150 assert_eq!(info.num_slice_groups_minus1, 0);
4151 assert_eq!(info.num_ref_idx_l0_default_active_minus1, 0);
4152 assert_eq!(info.num_ref_idx_l1_default_active_minus1, 0);
4153 assert!(!info.weighted_pred_flag);
4154 assert_eq!(info.weighted_bipred_idc, 0);
4155 assert_eq!(info.pic_init_qp_minus26, 0);
4156 assert_eq!(info.pic_init_qs_minus26, 0);
4157 assert_eq!(info.chroma_qp_index_offset, 0);
4158 assert!(info.deblocking_filter_control_present_flag);
4159 assert!(!info.constrained_intra_pred_flag);
4160 assert!(!info.redundant_pic_cnt_present_flag);
4161 }
4162
4163 #[test]
4164 fn parse_h264_pps_nonzero_ids_and_flags() {
4165 let mut w = BitWriter::new();
4166 w.write_ue(3); w.write_ue(7); w.write_bit(1); w.write_bit(1); w.write_ue(0); w.write_ue(2); w.write_ue(1); w.write_bit(1); w.write_bits(2, 2); w.write_ue(10);
4177 w.write_ue(5);
4179 w.write_ue(0);
4181 w.write_bit(0); w.write_bit(1); w.write_bit(1); w.write_bit(1); let mut sample = vec![0x00, 0x00, 0x00, 0x01, 0x68];
4186 sample.extend_from_slice(&w.bytes());
4187 let info = parse_h264_pps(&sample).expect("parse");
4188 assert_eq!(info.pic_parameter_set_id, 3);
4189 assert_eq!(info.seq_parameter_set_id, 7);
4190 assert!(info.entropy_coding_mode_flag);
4191 assert!(info.bottom_field_pic_order_in_frame_present_flag);
4192 assert_eq!(info.num_ref_idx_l0_default_active_minus1, 2);
4193 assert_eq!(info.num_ref_idx_l1_default_active_minus1, 1);
4194 assert!(info.weighted_pred_flag);
4195 assert_eq!(info.weighted_bipred_idc, 2);
4196 assert_eq!(info.pic_init_qp_minus26, -5);
4197 assert_eq!(info.pic_init_qs_minus26, 3);
4198 assert!(!info.deblocking_filter_control_present_flag);
4199 assert!(info.constrained_intra_pred_flag);
4200 assert!(info.redundant_pic_cnt_present_flag);
4201 }
4202
4203 #[test]
4204 fn parse_h264_pps_returns_none_when_no_pps_in_sample() {
4205 let sample = build_h264_baseline_sps(80, 45); assert!(parse_h264_pps(&sample).is_none());
4208 }
4209
4210 fn build_h264_idr_slice_header_rbsp() -> Vec<u8> {
4218 let mut w = BitWriter::new();
4219 w.write_ue(0); w.write_ue(7); w.write_ue(0); w.write_bits(0, 4); w.write_ue(0); w.write_bits(0, 4); w.bytes()
4228 }
4229
4230 #[test]
4231 fn parse_h264_slice_header_idr_i_slice() {
4232 let sps = parse_h264_sps(&build_h264_baseline_sps(1280 / 16, 720 / 16)).expect("sps");
4233 let pps = parse_h264_pps(&build_h264_baseline_pps(0, 0)).expect("pps");
4234 let rbsp = build_h264_idr_slice_header_rbsp();
4235 let mut sample = vec![0x00, 0x00, 0x00, 0x01, 0x65];
4237 sample.extend_from_slice(&rbsp);
4238
4239 let sh = parse_h264_slice_header(&sample, &sps, &pps).expect("slice");
4240 assert_eq!(sh.first_mb_in_slice, 0);
4241 assert_eq!(sh.slice_type, H264SliceType::I);
4242 assert_eq!(sh.pic_parameter_set_id, 0);
4243 assert!(sh.is_idr);
4244 assert_eq!(sh.frame_num, 0);
4245 assert!(!sh.field_pic_flag);
4246 assert_eq!(sh.idr_pic_id, Some(0));
4247 assert_eq!(sh.pic_order_cnt_lsb, Some(0));
4248 }
4249
4250 #[test]
4251 fn parse_h264_slice_header_returns_none_without_sps_context() {
4252 let mut w = BitWriter::new();
4257 w.write_bits(122, 8);
4258 w.write_bits(0, 8);
4259 w.write_bits(40, 8);
4260 w.write_ue(0); w.write_ue(2); w.write_ue(0);
4263 w.write_ue(0);
4264 w.write_bit(0); w.write_bit(0); let mut sample = vec![0, 0, 0, 1, 0x67];
4267 sample.extend_from_slice(&w.bytes());
4268 let sps = parse_h264_sps(&sample).expect("sps parses");
4269 assert!(sps.pic_order_cnt_type.is_none());
4270
4271 let pps = parse_h264_pps(&build_h264_baseline_pps(0, 0)).expect("pps");
4272 let rbsp = build_h264_idr_slice_header_rbsp();
4273 let mut slice_sample = vec![0x00, 0x00, 0x00, 0x01, 0x65];
4274 slice_sample.extend_from_slice(&rbsp);
4275 assert!(parse_h264_slice_header(&slice_sample, &sps, &pps).is_none());
4279 }
4280
4281 #[test]
4282 fn parse_h264_slice_type_ue_mapping_covers_both_halves() {
4283 for (code, expected) in [
4286 (0, H264SliceType::P),
4287 (5, H264SliceType::P),
4288 (1, H264SliceType::B),
4289 (6, H264SliceType::B),
4290 (2, H264SliceType::I),
4291 (7, H264SliceType::I),
4292 (3, H264SliceType::SP),
4293 (8, H264SliceType::SP),
4294 (4, H264SliceType::SI),
4295 (9, H264SliceType::SI),
4296 ] {
4297 assert_eq!(
4298 H264SliceType::from_ue(code),
4299 Some(expected),
4300 "code {}",
4301 code
4302 );
4303 }
4304 }
4305
4306 #[test]
4307 fn bit_reader_read_se_exp_golomb_mapping() {
4308 for (code, expected) in [(0u32, 0i32), (1, 1), (2, -1), (3, 2), (4, -2), (5, 3)] {
4311 let mut w = BitWriter::new();
4312 w.write_ue(code);
4313 let bytes = w.bytes();
4314 let mut br = BitReader::new(&bytes);
4315 assert_eq!(
4316 br.read_se(),
4317 Some(expected),
4318 "codeNum={} expected={}",
4319 code,
4320 expected
4321 );
4322 }
4323 }
4324}