scuffle_h265/sps/pcm.rs
1use std::io;
2
3use scuffle_bytes_util::BitReader;
4use scuffle_expgolomb::BitReaderExpGolombExt;
5
6use crate::range_check::range_check;
7
8/// Directly part of [SPS RBSP](crate::SpsRbsp).
9#[derive(Debug, Clone, PartialEq)]
10pub struct Pcm {
11 /// Defines [`PcmBitDepth_Y`](Pcm::pcm_bit_depth_y).
12 pub pcm_sample_bit_depth_luma_minus1: u8,
13 /// Defines [`PcmBitDepth_C`](Pcm::pcm_bit_depth_c).
14 pub pcm_sample_bit_depth_chroma_minus1: u8,
15 /// This value plus 3 specifies the minimum size of coding blocks with `pcm_flag` equal to `true`.
16 ///
17 /// Defines [`Log2MinIpcmCbSizeY`](Pcm::log2_min_ipcm_cb_size_y).
18 pub log2_min_pcm_luma_coding_block_size_minus3: u64,
19 /// Specifies the difference between the maximum and minimum size of coding blocks with `pcm_flag` equal to `true`.
20 ///
21 /// Defines [`Log2MaxIpcmCbSizeY`](Pcm::log2_max_ipcm_cb_size_y).
22 pub log2_diff_max_min_pcm_luma_coding_block_size: u64,
23 /// Specifies whether the loop filter process is disabled on reconstructed
24 /// samples in a coding unit with `pcm_flag` equal to `true`.
25 pub pcm_loop_filter_disabled_flag: bool,
26}
27
28impl Pcm {
29 pub(crate) fn parse<R: io::Read>(
30 bit_reader: &mut BitReader<R>,
31 bit_depth_y: u8,
32 bit_depth_c: u8,
33 min_cb_log2_size_y: u64,
34 ctb_log2_size_y: u64,
35 ) -> io::Result<Self> {
36 let pcm_sample_bit_depth_luma_minus1 = bit_reader.read_bits(4)? as u8;
37 if pcm_sample_bit_depth_luma_minus1 + 1 > bit_depth_y {
38 return Err(io::Error::new(
39 io::ErrorKind::InvalidData,
40 "PcmBitDepth_Y must be less than or equal to BitDepth_Y",
41 ));
42 }
43
44 let pcm_sample_bit_depth_chroma_minus1 = bit_reader.read_bits(4)? as u8;
45 if pcm_sample_bit_depth_chroma_minus1 + 1 > bit_depth_c {
46 return Err(io::Error::new(
47 io::ErrorKind::InvalidData,
48 "PcmBitDepth_C must be less than or equal to BitDepth_C",
49 ));
50 }
51
52 let log2_min_pcm_luma_coding_block_size_minus3 = bit_reader.read_exp_golomb()?;
53 let log2_min_ipcm_cb_size_y = log2_min_pcm_luma_coding_block_size_minus3 + 3;
54 range_check!(log2_min_ipcm_cb_size_y, min_cb_log2_size_y.min(5), ctb_log2_size_y.min(5))?;
55
56 let log2_diff_max_min_pcm_luma_coding_block_size = bit_reader.read_exp_golomb()?;
57 let log2_max_ipcm_cb_size_y = log2_diff_max_min_pcm_luma_coding_block_size + log2_min_ipcm_cb_size_y;
58 if log2_max_ipcm_cb_size_y > ctb_log2_size_y.min(5) {
59 return Err(io::Error::new(
60 io::ErrorKind::InvalidData,
61 "Log2MaxIpcmCbSizeY must be less than or equal to Min(CtbLog2SizeY, 5)",
62 ));
63 }
64
65 Ok(Self {
66 pcm_sample_bit_depth_luma_minus1,
67 pcm_sample_bit_depth_chroma_minus1,
68 log2_min_pcm_luma_coding_block_size_minus3,
69 log2_diff_max_min_pcm_luma_coding_block_size,
70 pcm_loop_filter_disabled_flag: bit_reader.read_bit()?,
71 })
72 }
73
74 /// Specifies the number of bits used to represent each of PCM sample values of the luma component.
75 ///
76 /// The value of `PcmBitDepthY` is less than or equal to the value of [`BitDepthY`](crate::SpsRbsp::bit_depth_y).
77 ///
78 /// `PcmBitDepthY = pcm_sample_bit_depth_luma_minus1 + 1` (7-25)
79 ///
80 /// ISO/IEC 23008-2 - 7.4.3.2.1
81 pub fn pcm_bit_depth_y(&self) -> u8 {
82 self.pcm_sample_bit_depth_luma_minus1 + 1
83 }
84
85 /// Specifies the number of bits used to represent each of PCM sample values of the chroma components.
86 ///
87 /// The value of `PcmBitDepthC` is less than or equal to the value of [`BitDepthC`](crate::SpsRbsp::bit_depth_c).
88 /// When [`ChromaArrayType`](crate::SpsRbsp::chroma_array_type) is equal to 0, decoders shall ignore its value.
89 ///
90 /// `PcmBitDepthC = pcm_sample_bit_depth_chroma_minus1 + 1` (7-26)
91 ///
92 /// ISO/IEC 23008-2 - 7.4.3.2.1
93 pub fn pcm_bit_depth_c(&self) -> u8 {
94 self.pcm_sample_bit_depth_chroma_minus1 + 1
95 }
96
97 /// The value is range
98 /// \[[`Min(MinCbLog2SizeY, 5)`](crate::SpsRbsp::min_cb_log2_size_y), [`Min(CtbLog2SizeY, 5)`](crate::SpsRbsp::ctb_log2_size_y)\].
99 ///
100 /// `Log2MinIpcmCbSizeY = log2_min_pcm_luma_coding_block_size_minus3 + 3`
101 ///
102 /// ISO/IEC 23008-2 - 7.4.3.2.1
103 pub fn log2_min_ipcm_cb_size_y(&self) -> u64 {
104 self.log2_min_pcm_luma_coding_block_size_minus3 + 3
105 }
106
107 /// The value is less than or equal to [`Min(CtbLog2SizeY, 5)`](crate::SpsRbsp::ctb_log2_size_y).
108 ///
109 /// `Log2MaxIpcmCbSizeY = log2_diff_max_min_pcm_luma_coding_block_size + Log2MinIpcmCbSizeY`
110 ///
111 /// ISO/IEC 23008-2 - 7.4.3.2.1
112 pub fn log2_max_ipcm_cb_size_y(&self) -> u64 {
113 self.log2_diff_max_min_pcm_luma_coding_block_size + self.log2_min_ipcm_cb_size_y()
114 }
115}