scuffle_h264/sps/
color_config.rs1use std::io;
2
3use byteorder::ReadBytesExt;
4use scuffle_bytes_util::{BitReader, BitWriter};
5
6use crate::VideoFormat;
7
8#[derive(Debug, Clone, PartialEq)]
10pub struct ColorConfig {
11 pub video_format: VideoFormat,
17
18 pub video_full_range_flag: bool,
24
25 pub color_primaries: u8,
28
29 pub transfer_characteristics: u8,
32
33 pub matrix_coefficients: u8,
36}
37
38impl ColorConfig {
39 pub fn parse<T: io::Read>(reader: &mut BitReader<T>) -> io::Result<Self> {
42 let video_format = reader.read_bits(3)? as u8;
43 let video_full_range_flag = reader.read_bit()?;
44
45 let color_primaries;
46 let transfer_characteristics;
47 let matrix_coefficients;
48
49 let color_description_present_flag = reader.read_bit()?;
50 if color_description_present_flag {
51 color_primaries = reader.read_u8()?;
52 transfer_characteristics = reader.read_u8()?;
53 matrix_coefficients = reader.read_u8()?;
54 } else {
55 color_primaries = 2; transfer_characteristics = 2; matrix_coefficients = 2; }
59
60 Ok(ColorConfig {
61 video_format: VideoFormat(video_format), video_full_range_flag,
63 color_primaries,
64 transfer_characteristics,
65 matrix_coefficients,
66 })
67 }
68
69 pub fn build<T: io::Write>(&self, writer: &mut BitWriter<T>) -> io::Result<()> {
72 writer.write_bits(self.video_format.0 as u64, 3)?;
73 writer.write_bit(self.video_full_range_flag)?;
74
75 match (self.color_primaries, self.transfer_characteristics, self.matrix_coefficients) {
76 (2, 2, 2) => {
77 writer.write_bit(false)?;
78 }
79 (color_priamries, transfer_characteristics, matrix_coefficients) => {
80 writer.write_bit(true)?;
81 writer.write_bits(color_priamries as u64, 8)?;
82 writer.write_bits(transfer_characteristics as u64, 8)?;
83 writer.write_bits(matrix_coefficients as u64, 8)?;
84 }
85 }
86 Ok(())
87 }
88
89 pub fn bitsize(&self) -> u64 {
93 3 + 1 + 1 + match (self.color_primaries, self.transfer_characteristics, self.matrix_coefficients) {
97 (2, 2, 2) => 0,
98 _ => 24
99 }
100 }
101
102 pub fn bytesize(&self) -> u64 {
107 self.bitsize().div_ceil(8)
108 }
109}
110
111#[cfg(test)]
112#[cfg_attr(all(test, coverage_nightly), coverage(off))]
113mod tests {
114 use scuffle_bytes_util::{BitReader, BitWriter};
115
116 use crate::sps::ColorConfig;
117
118 #[test]
119 fn test_build_size_color_config() {
120 let mut data = Vec::new();
122 let mut writer = BitWriter::new(&mut data);
123
124 writer.write_bits(4, 3).unwrap();
125 writer.write_bit(true).unwrap();
126
127 writer.write_bit(true).unwrap();
129 writer.write_bits(2, 8).unwrap();
130 writer.write_bits(6, 8).unwrap();
131 writer.write_bits(1, 8).unwrap();
132 writer.finish().unwrap();
133
134 let mut reader = BitReader::new_from_slice(&mut data);
136 let color_config = ColorConfig::parse(&mut reader).unwrap();
137
138 let mut buf = Vec::new();
140 let mut writer2 = BitWriter::new(&mut buf);
141
142 color_config.build(&mut writer2).unwrap();
144 writer2.finish().unwrap();
145
146 assert_eq!(buf, data);
147 let mut reader2 = BitReader::new_from_slice(buf);
150 let rebuilt_color_config = ColorConfig::parse(&mut reader2).unwrap();
151
152 assert_eq!(rebuilt_color_config.bitsize(), color_config.bitsize());
154 assert_eq!(rebuilt_color_config.bytesize(), color_config.bytesize());
155 }
156
157 #[test]
158 fn test_build_size_color_config_no_desc() {
159 let mut data = Vec::new();
161 let mut writer = BitWriter::new(&mut data);
162
163 writer.write_bits(4, 3).unwrap();
164 writer.write_bit(true).unwrap();
165
166 writer.write_bit(false).unwrap();
168 writer.finish().unwrap();
169
170 let mut reader = BitReader::new_from_slice(&mut data);
172 let color_config = ColorConfig::parse(&mut reader).unwrap();
173
174 let mut buf = Vec::new();
176 let mut writer2 = BitWriter::new(&mut buf);
177
178 color_config.build(&mut writer2).unwrap();
180 writer2.finish().unwrap();
181
182 assert_eq!(buf, data);
183
184 let mut reader2 = BitReader::new_from_slice(buf);
187 let rebuilt_color_config = ColorConfig::parse(&mut reader2).unwrap();
188
189 assert_eq!(rebuilt_color_config.bitsize(), color_config.bitsize());
191 assert_eq!(rebuilt_color_config.bytesize(), color_config.bytesize());
192 }
193}