1use super::bitreader::{BitReader, find_next_start_code, remove_h264_rbsp_stuffing, clamp_to_i8};
5
6pub(super) fn detect_hevc(sample: &[u8]) -> Option<crate::frame::PixelFormat> {
10 let sps = find_hevc_sps(sample)?;
11 let rbsp = remove_h264_rbsp_stuffing(sps);
12 let mut br = BitReader::new(&rbsp);
13
14 let _sps_video_parameter_set_id = br.read_bits(4)?;
15 let sps_max_sub_layers_minus1 = br.read_bits(3)? as usize;
16 let _sps_temporal_id_nesting_flag = br.read_bits(1)?;
17
18 skip_hevc_profile_tier_level(&mut br, sps_max_sub_layers_minus1)?;
22
23 let _sps_seq_parameter_set_id = br.read_ue()?;
24 let chroma_format_idc = br.read_ue()? as u8;
25 if chroma_format_idc == 3 {
26 let _separate_colour_plane_flag = br.read_bits(1)?;
27 }
28 let _pic_width = br.read_ue()?;
29 let _pic_height = br.read_ue()?;
30 let conformance_window_flag = br.read_bits(1)?;
31 if conformance_window_flag == 1 {
32 let _ = br.read_ue()?;
33 let _ = br.read_ue()?;
34 let _ = br.read_ue()?;
35 let _ = br.read_ue()?;
36 }
37 let bit_depth_luma = br.read_ue()? as u8 + 8;
38 let _bit_depth_chroma_minus8 = br.read_ue()?;
39
40 Some(crate::frame::PixelFormat::from_chroma_and_depth(
41 chroma_format_idc,
42 bit_depth_luma,
43 ))
44}
45
46fn find_hevc_sps(data: &[u8]) -> Option<&[u8]> {
47 let mut i = 0;
48 while i + 4 < data.len() {
49 let (start_len, nal_byte) = if data[i] == 0 && data[i + 1] == 0 && data[i + 2] == 1 {
50 (3, i + 3)
51 } else if data[i] == 0 && data[i + 1] == 0 && data[i + 2] == 0 && data[i + 3] == 1 {
52 (4, i + 4)
53 } else {
54 i += 1;
55 continue;
56 };
57 if nal_byte + 1 >= data.len() {
58 return None;
59 }
60 let nal_unit_type = (data[nal_byte] >> 1) & 0x3F;
62 if nal_unit_type == 33 {
63 let start = nal_byte + 2;
65 let end = find_next_start_code(&data[start..])
66 .map(|off| start + off)
67 .unwrap_or(data.len());
68 return Some(&data[start..end]);
69 }
70 i += start_len;
71 }
72 None
73}
74
75pub(super) fn skip_hevc_profile_tier_level(
76 br: &mut BitReader,
77 max_sub_layers_minus1: usize,
78) -> Option<()> {
79 let _ = br.read_bits(8)?;
81 let _ = br.read_bits(32)?;
83 let _ = br.read_bits(48)?;
86 let _ = br.read_bits(8)?;
87
88 let mut sub_layer_profile_present = Vec::with_capacity(max_sub_layers_minus1);
90 let mut sub_layer_level_present = Vec::with_capacity(max_sub_layers_minus1);
91 for _ in 0..max_sub_layers_minus1 {
92 sub_layer_profile_present.push(br.read_bits(1)?);
93 sub_layer_level_present.push(br.read_bits(1)?);
94 }
95 if max_sub_layers_minus1 > 0 {
96 for _ in max_sub_layers_minus1..8 {
98 let _ = br.read_bits(2)?;
99 }
100 }
101 for i in 0..max_sub_layers_minus1 {
102 if sub_layer_profile_present[i] == 1 {
103 let _ = br.read_bits(8)?;
104 let _ = br.read_bits(32)?;
105 let _ = br.read_bits(48)?;
106 }
107 if sub_layer_level_present[i] == 1 {
108 let _ = br.read_bits(8)?;
109 }
110 }
111 Some(())
112}
113
114#[derive(Debug, Clone, PartialEq, Eq, Default)]
122pub struct HevcSpsInfo {
123 pub sps_video_parameter_set_id: u8,
124 pub sps_seq_parameter_set_id: u8,
125 pub sps_max_sub_layers_minus1: u8,
126 pub sps_temporal_id_nesting_flag: bool,
127 pub chroma_format_idc: u8,
128 pub separate_colour_plane_flag: bool,
129 pub bit_depth_luma: u8,
130 pub bit_depth_chroma: u8,
131 pub width: Option<u32>,
132 pub height: Option<u32>,
133 pub conf_win_left_offset: u32,
135 pub conf_win_right_offset: u32,
136 pub conf_win_top_offset: u32,
137 pub conf_win_bottom_offset: u32,
138 pub log2_max_pic_order_cnt_lsb_minus4: u8,
139 pub log2_min_luma_coding_block_size_minus3: u8,
140 pub log2_diff_max_min_luma_coding_block_size: u8,
141 pub log2_min_luma_transform_block_size_minus2: u8,
142 pub log2_diff_max_min_luma_transform_block_size: u8,
143 pub max_transform_hierarchy_depth_inter: u8,
144 pub max_transform_hierarchy_depth_intra: u8,
145 pub scaling_list_enabled_flag: bool,
146 pub sps_sub_layer_ordering_info_present_flag: bool,
147 pub amp_enabled_flag: bool,
148 pub sample_adaptive_offset_enabled_flag: bool,
149 pub pcm_enabled_flag: bool,
150 pub pcm_loop_filter_disabled_flag: bool,
152 pub num_short_term_ref_pic_sets: u8,
153 pub long_term_ref_pics_present_flag: bool,
154 pub sps_temporal_mvp_enabled_flag: bool,
155 pub strong_intra_smoothing_enabled_flag: bool,
156 pub profile_idc: u8,
157 pub level_idc: u8,
158 pub tier_flag: bool,
159 pub max_dec_pic_buffering_minus1: [u8; 7],
163 pub max_num_reorder_pics: [u8; 7],
164 pub max_latency_increase_plus1: [u32; 7],
165 pub profile_compatibility_flags: u32,
168 pub general_profile_space: u8,
171 pub general_constraint_flags: u64,
175}
176
177#[derive(Debug, Clone, Copy, PartialEq, Eq)]
179pub struct H265VpsInfo {
180 pub vps_video_parameter_set_id: u8,
181 pub vps_max_sub_layers_minus1: u8,
182 pub vps_temporal_id_nesting_flag: bool,
183 pub profile_idc: u8,
184 pub level_idc: u8,
185 pub tier_flag: bool,
186}
187
188#[derive(Debug, Clone, Copy, PartialEq, Eq)]
190pub struct H265PpsInfo {
191 pub pps_pic_parameter_set_id: u8,
192 pub pps_seq_parameter_set_id: u8,
193 pub dependent_slice_segments_enabled_flag: bool,
194 pub output_flag_present_flag: bool,
195 pub num_extra_slice_header_bits: u8,
196 pub sign_data_hiding_enabled_flag: bool,
197 pub cabac_init_present_flag: bool,
198 pub num_ref_idx_l0_default_active_minus1: u8,
199 pub num_ref_idx_l1_default_active_minus1: u8,
200 pub init_qp_minus26: i8,
201 pub constrained_intra_pred_flag: bool,
202 pub transform_skip_enabled_flag: bool,
203 pub cu_qp_delta_enabled_flag: bool,
204 pub diff_cu_qp_delta_depth: u8,
205 pub pps_cb_qp_offset: i8,
206 pub pps_cr_qp_offset: i8,
207 pub pps_slice_chroma_qp_offsets_present_flag: bool,
208 pub weighted_pred_flag: bool,
209 pub weighted_bipred_flag: bool,
210 pub transquant_bypass_enabled_flag: bool,
211 pub tiles_enabled_flag: bool,
212 pub entropy_coding_sync_enabled_flag: bool,
213 pub num_tile_columns_minus1: u8,
216 pub num_tile_rows_minus1: u8,
217 pub uniform_spacing_flag: bool,
218 pub loop_filter_across_tiles_enabled_flag: bool,
219 pub pps_loop_filter_across_slices_enabled_flag: bool,
221 pub deblocking_filter_control_present_flag: bool,
222 pub deblocking_filter_override_enabled_flag: bool,
223 pub pps_deblocking_filter_disabled_flag: bool,
224 pub pps_beta_offset_div2: i8,
225 pub pps_tc_offset_div2: i8,
226 pub pps_scaling_list_data_present_flag: bool,
227 pub lists_modification_present_flag: bool,
228 pub log2_parallel_merge_level_minus2: u8,
229 pub slice_segment_header_extension_present_flag: bool,
230 pub pps_extension_present_flag: bool,
231}
232
233#[derive(Debug, Clone, Copy, PartialEq, Eq)]
235pub struct H265SliceHeader {
236 pub first_slice_segment_in_pic_flag: bool,
237 pub nal_unit_type: u8,
238 pub slice_pic_parameter_set_id: u8,
239 pub slice_type: H265SliceType,
240 pub pic_order_cnt_lsb: u32,
241 pub short_term_ref_pic_set_sps_flag: bool,
242 pub short_term_ref_pic_set_idx: Option<u8>,
243 pub is_irap: bool,
245 pub is_idr: bool,
247}
248
249#[derive(Debug, Clone, Copy, PartialEq, Eq)]
250pub enum H265SliceType {
251 B,
252 P,
253 I,
254}
255
256impl H265SliceType {
257 fn from_ue(v: u32) -> Option<Self> {
258 match v {
259 0 => Some(Self::B),
260 1 => Some(Self::P),
261 2 => Some(Self::I),
262 _ => None,
263 }
264 }
265}
266
267pub fn parse_hevc_sps(sample: &[u8]) -> Option<HevcSpsInfo> {
274 let sps = find_hevc_sps(sample)?;
275 let rbsp = remove_h264_rbsp_stuffing(sps);
276 let mut br = BitReader::new(&rbsp);
277
278 let sps_video_parameter_set_id = br.read_bits(4)? as u8;
279 let sps_max_sub_layers_minus1 = br.read_bits(3)? as u8;
280 let sps_temporal_id_nesting_flag = br.read_bits(1)? == 1;
281 let general_profile_space = br.read_bits(2)? as u8;
285 let tier_flag = br.read_bits(1)? == 1;
286 let profile_idc = br.read_bits(5)? as u8;
287 let profile_compatibility_flags = br.read_bits(32)?;
289 let constraint_hi = br.read_bits(24)? as u64;
293 let constraint_lo = br.read_bits(24)? as u64;
294 let general_constraint_flags = (constraint_hi << 24) | constraint_lo;
295 let level_idc = br.read_bits(8)? as u8;
296 let mut spl = Vec::with_capacity(sps_max_sub_layers_minus1 as usize);
299 let mut sll = Vec::with_capacity(sps_max_sub_layers_minus1 as usize);
300 for _ in 0..sps_max_sub_layers_minus1 {
301 spl.push(br.read_bits(1)?);
302 sll.push(br.read_bits(1)?);
303 }
304 if sps_max_sub_layers_minus1 > 0 {
305 for _ in sps_max_sub_layers_minus1 as usize..8 {
306 let _ = br.read_bits(2)?;
307 }
308 }
309 for i in 0..sps_max_sub_layers_minus1 as usize {
310 if spl[i] == 1 {
311 let _ = br.read_bits(8)?;
312 let _ = br.read_bits(32)?;
313 let _ = br.read_bits(48)?;
314 }
315 if sll[i] == 1 {
316 let _ = br.read_bits(8)?;
317 }
318 }
319
320 let sps_seq_parameter_set_id = br.read_ue()? as u8;
321 let chroma_format_idc = br.read_ue()? as u8;
322 let separate_colour_plane_flag = if chroma_format_idc == 3 {
323 br.read_bits(1)? == 1
324 } else {
325 false
326 };
327 let pic_width = br.read_ue()?;
328 let pic_height = br.read_ue()?;
329 let conformance_window_flag = br.read_bits(1)?;
330 let (cl, cr, ct, cb) = if conformance_window_flag == 1 {
331 (br.read_ue()?, br.read_ue()?, br.read_ue()?, br.read_ue()?)
332 } else {
333 (0u32, 0u32, 0u32, 0u32)
334 };
335 let bit_depth_luma_m8 = br.read_ue()?;
336 let bit_depth_chroma_m8 = br.read_ue()?;
337 let log2_max_pic_order_cnt_lsb_minus4 = br.read_ue()? as u8;
338
339 let sps_sub_layer_ordering_info_present_flag = br.read_bits(1)? == 1;
346 let mut max_dec_pic_buffering_minus1 = [0u8; 7];
347 let mut max_num_reorder_pics = [0u8; 7];
348 let mut max_latency_increase_plus1 = [0u32; 7];
349 let start = if sps_sub_layer_ordering_info_present_flag {
350 0
351 } else {
352 sps_max_sub_layers_minus1
353 };
354 for i in start..=sps_max_sub_layers_minus1 {
355 let dec = br.read_ue()?;
356 let nro = br.read_ue()?;
357 let latency = br.read_ue()?;
358 let idx = (i as usize).min(6);
359 max_dec_pic_buffering_minus1[idx] = dec.min(u8::MAX as u32) as u8;
360 max_num_reorder_pics[idx] = nro.min(u8::MAX as u32) as u8;
361 max_latency_increase_plus1[idx] = latency;
362 }
363 if !sps_sub_layer_ordering_info_present_flag {
365 let top = sps_max_sub_layers_minus1 as usize;
366 for i in 0..top {
367 max_dec_pic_buffering_minus1[i] = max_dec_pic_buffering_minus1[top];
368 max_num_reorder_pics[i] = max_num_reorder_pics[top];
369 max_latency_increase_plus1[i] = max_latency_increase_plus1[top];
370 }
371 }
372
373 let log2_min_luma_coding_block_size_minus3 = br.read_ue()? as u8;
374 let log2_diff_max_min_luma_coding_block_size = br.read_ue()? as u8;
375 let log2_min_luma_transform_block_size_minus2 = br.read_ue()? as u8;
376 let log2_diff_max_min_luma_transform_block_size = br.read_ue()? as u8;
377 let max_transform_hierarchy_depth_inter = br.read_ue()? as u8;
378 let max_transform_hierarchy_depth_intra = br.read_ue()? as u8;
379
380 let scaling_list_enabled_flag = br.read_bits(1)? == 1;
381 if scaling_list_enabled_flag {
382 let sps_scaling_list_data_present_flag = br.read_bits(1)? == 1;
383 if sps_scaling_list_data_present_flag {
384 skip_hevc_scaling_list_data(&mut br)?;
385 }
386 }
387 let amp_enabled_flag = br.read_bits(1)? == 1;
388 let sample_adaptive_offset_enabled_flag = br.read_bits(1)? == 1;
389 let pcm_enabled_flag = br.read_bits(1)? == 1;
390 let mut pcm_loop_filter_disabled_flag = false;
391 if pcm_enabled_flag {
392 let _pcm_sample_bit_depth_luma_minus1 = br.read_bits(4)?;
393 let _pcm_sample_bit_depth_chroma_minus1 = br.read_bits(4)?;
394 let _log2_min_pcm_luma_cb_size_minus3 = br.read_ue()?;
395 let _log2_diff_max_min_pcm_luma_cb_size = br.read_ue()?;
396 pcm_loop_filter_disabled_flag = br.read_bits(1)? == 1;
397 }
398 let num_short_term_ref_pic_sets = br.read_ue()? as u8;
399 let mut st_rps_offsets: Vec<()> = Vec::with_capacity(num_short_term_ref_pic_sets as usize);
405 for rps_idx in 0..num_short_term_ref_pic_sets {
406 skip_hevc_short_term_rps(&mut br, rps_idx, num_short_term_ref_pic_sets)?;
407 st_rps_offsets.push(());
408 }
409 let long_term_ref_pics_present_flag = br.read_bits(1)? == 1;
410 if long_term_ref_pics_present_flag {
411 let num_long_term_ref_pics_sps = br.read_ue()?;
412 let lsb_bits = (log2_max_pic_order_cnt_lsb_minus4 as usize) + 4;
413 for _ in 0..num_long_term_ref_pics_sps {
414 let _lt_ref_pic_poc_lsb_sps = br.read_bits(lsb_bits)?;
415 let _used_by_curr_pic_lt_sps_flag = br.read_bits(1)?;
416 }
417 }
418 let sps_temporal_mvp_enabled_flag = br.read_bits(1)? == 1;
419 let strong_intra_smoothing_enabled_flag = br.read_bits(1)? == 1;
420 let chroma_array_type = if separate_colour_plane_flag {
423 0
424 } else {
425 chroma_format_idc
426 };
427 let (sub_w, sub_h) = match chroma_array_type {
428 0 => (1u32, 1u32),
429 1 => (2, 2),
430 2 => (2, 1),
431 3 => (1, 1),
432 _ => (1, 1),
433 };
434 let width = pic_width.saturating_sub(sub_w.saturating_mul(cl.saturating_add(cr)));
435 let height = pic_height.saturating_sub(sub_h.saturating_mul(ct.saturating_add(cb)));
436
437 Some(HevcSpsInfo {
438 sps_video_parameter_set_id,
439 sps_seq_parameter_set_id,
440 sps_max_sub_layers_minus1,
441 sps_temporal_id_nesting_flag,
442 chroma_format_idc,
443 separate_colour_plane_flag,
444 bit_depth_luma: bit_depth_luma_m8 as u8 + 8,
445 bit_depth_chroma: bit_depth_chroma_m8 as u8 + 8,
446 width: Some(width),
447 height: Some(height),
448 conf_win_left_offset: cl,
449 conf_win_right_offset: cr,
450 conf_win_top_offset: ct,
451 conf_win_bottom_offset: cb,
452 log2_max_pic_order_cnt_lsb_minus4,
453 log2_min_luma_coding_block_size_minus3,
454 log2_diff_max_min_luma_coding_block_size,
455 log2_min_luma_transform_block_size_minus2,
456 log2_diff_max_min_luma_transform_block_size,
457 max_transform_hierarchy_depth_inter,
458 max_transform_hierarchy_depth_intra,
459 scaling_list_enabled_flag,
460 sps_sub_layer_ordering_info_present_flag,
461 amp_enabled_flag,
462 sample_adaptive_offset_enabled_flag,
463 pcm_enabled_flag,
464 pcm_loop_filter_disabled_flag,
465 num_short_term_ref_pic_sets,
466 long_term_ref_pics_present_flag,
467 sps_temporal_mvp_enabled_flag,
468 strong_intra_smoothing_enabled_flag,
469 profile_idc,
470 level_idc,
471 tier_flag,
472 max_dec_pic_buffering_minus1,
473 max_num_reorder_pics,
474 max_latency_increase_plus1,
475 profile_compatibility_flags,
476 general_profile_space,
477 general_constraint_flags,
478 })
479}
480
481fn skip_hevc_scaling_list_data(br: &mut BitReader) -> Option<()> {
486 for size_id in 0..4 {
487 let matrix_count = if size_id == 3 { 2 } else { 6 };
488 for _matrix_id in 0..matrix_count {
489 let scaling_list_pred_mode_flag = br.read_bits(1)? == 1;
490 if !scaling_list_pred_mode_flag {
491 let _scaling_list_pred_matrix_id_delta = br.read_ue()?;
492 } else {
493 let coef_num: usize = (1 << (4 + (size_id << 1))).min(64);
494 if size_id > 1 {
495 let _scaling_list_dc_coef_minus8 = br.read_se()?;
496 }
497 for _ in 0..coef_num {
498 let _scaling_list_delta_coef = br.read_se()?;
499 }
500 }
501 }
502 }
503 Some(())
504}
505
506fn skip_hevc_short_term_rps(br: &mut BitReader, st_rps_idx: u8, num_st_rps: u8) -> Option<()> {
510 let inter_ref_pic_set_prediction_flag = if st_rps_idx != 0 {
511 br.read_bits(1)? == 1
512 } else {
513 false
514 };
515 if inter_ref_pic_set_prediction_flag {
516 if st_rps_idx == num_st_rps {
517 let _delta_idx_minus1 = br.read_ue()?;
518 }
519 let _delta_rps_sign = br.read_bits(1)?;
520 let _abs_delta_rps_minus1 = br.read_ue()?;
521 for _ in 0..16 {
526 let used = br.read_bits(1)?;
527 if used == 0 {
528 let _use_delta_flag = br.read_bits(1)?;
529 }
530 }
531 } else {
532 let num_negative_pics = br.read_ue()?;
533 let num_positive_pics = br.read_ue()?;
534 for _ in 0..num_negative_pics {
535 let _delta_poc_s0_minus1 = br.read_ue()?;
536 let _used_by_curr_pic_s0_flag = br.read_bits(1)?;
537 }
538 for _ in 0..num_positive_pics {
539 let _delta_poc_s1_minus1 = br.read_ue()?;
540 let _used_by_curr_pic_s1_flag = br.read_bits(1)?;
541 }
542 }
543 Some(())
544}
545
546pub fn parse_h265_vps(sample: &[u8]) -> Option<H265VpsInfo> {
550 let nal = find_hevc_nal_by_type(sample, 32)?;
551 let rbsp = remove_h264_rbsp_stuffing(nal);
552 let mut br = BitReader::new(&rbsp);
553 let vps_video_parameter_set_id = br.read_bits(4)? as u8;
554 let _vps_base_layer_internal_flag = br.read_bits(1)?;
555 let _vps_base_layer_available_flag = br.read_bits(1)?;
556 let _vps_max_layers_minus1 = br.read_bits(6)?;
557 let vps_max_sub_layers_minus1 = br.read_bits(3)? as u8;
558 let vps_temporal_id_nesting_flag = br.read_bits(1)? == 1;
559 let _vps_reserved_0xffff_16bits = br.read_bits(16)?;
560 let _gp_space = br.read_bits(2)?;
563 let tier_flag = br.read_bits(1)? == 1;
564 let profile_idc = br.read_bits(5)? as u8;
565 let _ = br.read_bits(32)?; let _ = br.read_bits(48)?; let level_idc = br.read_bits(8)? as u8;
568 Some(H265VpsInfo {
569 vps_video_parameter_set_id,
570 vps_max_sub_layers_minus1,
571 vps_temporal_id_nesting_flag,
572 profile_idc,
573 level_idc,
574 tier_flag,
575 })
576}
577
578pub fn parse_h265_pps(sample: &[u8]) -> Option<H265PpsInfo> {
582 let nal = find_hevc_nal_by_type(sample, 34)?;
583 let rbsp = remove_h264_rbsp_stuffing(nal);
584 let mut br = BitReader::new(&rbsp);
585 let pps_pic_parameter_set_id = br.read_ue()? as u8;
586 let pps_seq_parameter_set_id = br.read_ue()? as u8;
587 let dependent_slice_segments_enabled_flag = br.read_bits(1)? == 1;
588 let output_flag_present_flag = br.read_bits(1)? == 1;
589 let num_extra_slice_header_bits = br.read_bits(3)? as u8;
590 let sign_data_hiding_enabled_flag = br.read_bits(1)? == 1;
591 let cabac_init_present_flag = br.read_bits(1)? == 1;
592 let num_ref_idx_l0_default_active_minus1 = br.read_ue()? as u8;
593 let num_ref_idx_l1_default_active_minus1 = br.read_ue()? as u8;
594 let init_qp_minus26 = clamp_to_i8(br.read_se()?);
595 let constrained_intra_pred_flag = br.read_bits(1)? == 1;
596 let transform_skip_enabled_flag = br.read_bits(1)? == 1;
597 let cu_qp_delta_enabled_flag = br.read_bits(1)? == 1;
598 let diff_cu_qp_delta_depth = if cu_qp_delta_enabled_flag {
599 br.read_ue()? as u8
600 } else {
601 0
602 };
603 let pps_cb_qp_offset = clamp_to_i8(br.read_se()?);
604 let pps_cr_qp_offset = clamp_to_i8(br.read_se()?);
605 let pps_slice_chroma_qp_offsets_present_flag = br.read_bits(1)? == 1;
606 let weighted_pred_flag = br.read_bits(1)? == 1;
607 let weighted_bipred_flag = br.read_bits(1)? == 1;
608 let transquant_bypass_enabled_flag = br.read_bits(1)? == 1;
609 let tiles_enabled_flag = br.read_bits(1)? == 1;
610 let entropy_coding_sync_enabled_flag = br.read_bits(1)? == 1;
611
612 let mut num_tile_columns_minus1 = 0u8;
617 let mut num_tile_rows_minus1 = 0u8;
618 let mut uniform_spacing_flag = true;
619 let mut loop_filter_across_tiles_enabled_flag = true;
620 if tiles_enabled_flag {
621 num_tile_columns_minus1 = br.read_ue().unwrap_or(0) as u8;
622 num_tile_rows_minus1 = br.read_ue().unwrap_or(0) as u8;
623 uniform_spacing_flag = br.read_bits(1).unwrap_or(1) == 1;
624 if !uniform_spacing_flag {
625 for _ in 0..num_tile_columns_minus1 {
628 let _ = br.read_ue();
629 }
630 for _ in 0..num_tile_rows_minus1 {
631 let _ = br.read_ue();
632 }
633 }
634 loop_filter_across_tiles_enabled_flag = br.read_bits(1).unwrap_or(1) == 1;
635 }
636 let pps_loop_filter_across_slices_enabled_flag = br.read_bits(1)? == 1;
637
638 let deblocking_filter_control_present_flag = br.read_bits(1)? == 1;
640 let mut deblocking_filter_override_enabled_flag = false;
641 let mut pps_deblocking_filter_disabled_flag = false;
642 let mut pps_beta_offset_div2 = 0i8;
643 let mut pps_tc_offset_div2 = 0i8;
644 if deblocking_filter_control_present_flag {
645 deblocking_filter_override_enabled_flag = br.read_bits(1)? == 1;
646 pps_deblocking_filter_disabled_flag = br.read_bits(1)? == 1;
647 if !pps_deblocking_filter_disabled_flag {
648 pps_beta_offset_div2 = clamp_to_i8(br.read_se()?);
649 pps_tc_offset_div2 = clamp_to_i8(br.read_se()?);
650 }
651 }
652
653 let pps_scaling_list_data_present_flag = br.read_bits(1)? == 1;
655 let lists_modification_present_flag = br.read_bits(1)? == 1;
662 let log2_parallel_merge_level_minus2 = br.read_ue().unwrap_or(0) as u8;
663 let slice_segment_header_extension_present_flag = br.read_bits(1)? == 1;
664 let pps_extension_present_flag = br.read_bits(1).unwrap_or(0) == 1;
665
666 Some(H265PpsInfo {
667 pps_pic_parameter_set_id,
668 pps_seq_parameter_set_id,
669 dependent_slice_segments_enabled_flag,
670 output_flag_present_flag,
671 num_extra_slice_header_bits,
672 sign_data_hiding_enabled_flag,
673 cabac_init_present_flag,
674 num_ref_idx_l0_default_active_minus1,
675 num_ref_idx_l1_default_active_minus1,
676 init_qp_minus26,
677 constrained_intra_pred_flag,
678 transform_skip_enabled_flag,
679 cu_qp_delta_enabled_flag,
680 diff_cu_qp_delta_depth,
681 pps_cb_qp_offset,
682 pps_cr_qp_offset,
683 pps_slice_chroma_qp_offsets_present_flag,
684 weighted_pred_flag,
685 weighted_bipred_flag,
686 transquant_bypass_enabled_flag,
687 tiles_enabled_flag,
688 entropy_coding_sync_enabled_flag,
689 num_tile_columns_minus1,
690 num_tile_rows_minus1,
691 uniform_spacing_flag,
692 loop_filter_across_tiles_enabled_flag,
693 pps_loop_filter_across_slices_enabled_flag,
694 deblocking_filter_control_present_flag,
695 deblocking_filter_override_enabled_flag,
696 pps_deblocking_filter_disabled_flag,
697 pps_beta_offset_div2,
698 pps_tc_offset_div2,
699 pps_scaling_list_data_present_flag,
700 lists_modification_present_flag,
701 log2_parallel_merge_level_minus2,
702 slice_segment_header_extension_present_flag,
703 pps_extension_present_flag,
704 })
705}
706
707pub fn parse_h265_slice_header(
713 sample: &[u8],
714 sps: &HevcSpsInfo,
715 pps: &H265PpsInfo,
716) -> Option<H265SliceHeader> {
717 let (nal_unit_type, rbsp) = find_hevc_slice_nal(sample)?;
718 let mut br = BitReader::new(&rbsp);
719 let first_slice_segment_in_pic_flag = br.read_bits(1)? == 1;
720 let is_irap = (16..=23).contains(&nal_unit_type);
721 let is_idr = matches!(nal_unit_type, 19 | 20);
722 if is_irap {
723 let _no_output_of_prior_pics_flag = br.read_bits(1)?;
724 }
725 let slice_pic_parameter_set_id = br.read_ue()? as u8;
726 let dependent_slice_segment_flag =
727 if !first_slice_segment_in_pic_flag && pps.dependent_slice_segments_enabled_flag {
728 br.read_bits(1)? == 1
729 } else {
730 false
731 };
732 if !first_slice_segment_in_pic_flag {
733 return None;
740 }
741 let _ = dependent_slice_segment_flag;
742 for _ in 0..pps.num_extra_slice_header_bits {
744 let _ = br.read_bits(1)?;
745 }
746 let slice_type_code = br.read_ue()?;
747 let slice_type = H265SliceType::from_ue(slice_type_code)?;
748 if pps.output_flag_present_flag {
749 let _pic_output_flag = br.read_bits(1)?;
750 }
751 if sps.separate_colour_plane_flag {
752 let _colour_plane_id = br.read_bits(2)?;
753 }
754
755 let (pic_order_cnt_lsb, short_term_ref_pic_set_sps_flag, short_term_ref_pic_set_idx) =
756 if !is_idr {
757 let lsb_bits = (sps.log2_max_pic_order_cnt_lsb_minus4 as usize) + 4;
758 let lsb = br.read_bits(lsb_bits)?;
759 let sps_flag = br.read_bits(1)? == 1;
760 let idx = if sps_flag {
761 if sps.num_short_term_ref_pic_sets > 1 {
762 let bits =
763 ((sps.num_short_term_ref_pic_sets as f64).log2().ceil() as usize).max(1);
764 Some(br.read_bits(bits)? as u8)
765 } else {
766 Some(0)
767 }
768 } else {
769 None
770 };
771 (lsb, sps_flag, idx)
772 } else {
773 (0, false, None)
774 };
775
776 Some(H265SliceHeader {
777 first_slice_segment_in_pic_flag,
778 nal_unit_type,
779 slice_pic_parameter_set_id,
780 slice_type,
781 pic_order_cnt_lsb,
782 short_term_ref_pic_set_sps_flag,
783 short_term_ref_pic_set_idx,
784 is_irap,
785 is_idr,
786 })
787}
788
789fn find_hevc_nal_by_type(data: &[u8], target: u8) -> Option<&[u8]> {
793 let mut i = 0;
794 while i + 4 < data.len() {
795 let (start_len, nal_byte) = if data[i] == 0 && data[i + 1] == 0 && data[i + 2] == 1 {
796 (3, i + 3)
797 } else if data[i] == 0 && data[i + 1] == 0 && data[i + 2] == 0 && data[i + 3] == 1 {
798 (4, i + 4)
799 } else {
800 i += 1;
801 continue;
802 };
803 if nal_byte + 1 >= data.len() {
804 return None;
805 }
806 let nal_unit_type = (data[nal_byte] >> 1) & 0x3F;
807 if nal_unit_type == target {
808 let start = nal_byte + 2; let end = find_next_start_code(&data[start..])
810 .map(|off| start + off)
811 .unwrap_or(data.len());
812 return Some(&data[start..end]);
813 }
814 i += start_len;
815 }
816 None
817}
818
819pub fn hevc_first_slice_nal_offset(data: &[u8]) -> Option<u32> {
824 let mut i = 0;
825 while i + 4 < data.len() {
826 let (start_len, nal_byte) = if data[i] == 0 && data[i + 1] == 0 && data[i + 2] == 1 {
827 (3usize, i + 3)
828 } else if data[i] == 0 && data[i + 1] == 0 && data[i + 2] == 0 && data[i + 3] == 1 {
829 (4usize, i + 4)
830 } else {
831 i += 1;
832 continue;
833 };
834 if nal_byte + 1 >= data.len() {
835 return None;
836 }
837 let t = (data[nal_byte] >> 1) & 0x3F;
838 if (0..=9).contains(&t) || (16..=23).contains(&t) {
839 return Some(nal_byte as u32);
840 }
841 i += start_len;
842 }
843 None
844}
845
846fn find_hevc_slice_nal(data: &[u8]) -> Option<(u8, Vec<u8>)> {
849 let mut i = 0;
850 while i + 4 < data.len() {
851 let (start_len, nal_byte) = if data[i] == 0 && data[i + 1] == 0 && data[i + 2] == 1 {
852 (3, i + 3)
853 } else if data[i] == 0 && data[i + 1] == 0 && data[i + 2] == 0 && data[i + 3] == 1 {
854 (4, i + 4)
855 } else {
856 i += 1;
857 continue;
858 };
859 if nal_byte + 1 >= data.len() {
860 return None;
861 }
862 let t = (data[nal_byte] >> 1) & 0x3F;
863 if (0..=9).contains(&t) || (16..=23).contains(&t) {
864 let start = nal_byte + 2;
865 let end = find_next_start_code(&data[start..])
866 .map(|off| start + off)
867 .unwrap_or(data.len());
868 return Some((t, remove_h264_rbsp_stuffing(&data[start..end])));
869 }
870 i += start_len;
871 }
872 None
873}