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}