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}