scuffle_h265/sps/
pcm.rs

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