mp4_atom/moov/trak/mdia/minf/stbl/stsd/
colr.rs1use crate::*;
2
3#[derive(Debug, Clone, PartialEq, Eq)]
4#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
5pub enum Colr {
6 Nclx {
7 colour_primaries: u16,
8 transfer_characteristics: u16,
9 matrix_coefficients: u16,
10 full_range_flag: bool,
11 },
12 Ricc {
13 profile: Vec<u8>,
14 },
15 Prof {
16 profile: Vec<u8>,
17 },
18}
19
20impl Colr {
21 pub fn new(
22 colour_primaries: u16,
23 transfer_characteristics: u16,
24 matrix_coefficients: u16,
25 full_range_flag: bool,
26 ) -> Result<Self> {
27 Ok(Colr::Nclx {
28 colour_primaries,
29 transfer_characteristics,
30 matrix_coefficients,
31 full_range_flag,
32 })
33 }
34}
35
36impl Atom for Colr {
37 const KIND: FourCC = FourCC::new(b"colr");
38
39 fn decode_body<B: Buf>(buf: &mut B) -> Result<Self> {
40 let colour_type = FourCC::decode(buf)?;
41 if colour_type == FourCC::new(b"nclx") {
42 let colour_primaries = u16::decode(buf)?;
43 let transfer_characteristics = u16::decode(buf)?;
44 let matrix_coefficients = u16::decode(buf)?;
45 let full_range_flag = u8::decode(buf)? == 0x80;
46 Ok(Colr::Nclx {
47 colour_primaries,
48 transfer_characteristics,
49 matrix_coefficients,
50 full_range_flag,
51 })
52 } else if colour_type == FourCC::new(b"prof") {
53 let profile_len = buf.remaining();
54 let profile = buf.slice(profile_len).to_vec();
55 Ok(Colr::Prof { profile })
56 } else if colour_type == FourCC::new(b"rICC") {
57 let profile_len = buf.remaining();
58 let profile = buf.slice(profile_len).to_vec();
59 Ok(Colr::Ricc { profile })
60 } else {
61 Err(Error::UnexpectedBox(colour_type))
62 }
63 }
64
65 fn encode_body<B: BufMut>(&self, buf: &mut B) -> Result<()> {
66 match self {
67 Colr::Nclx {
68 colour_primaries,
69 transfer_characteristics,
70 matrix_coefficients,
71 full_range_flag,
72 } => {
73 b"nclx".encode(buf)?;
74 colour_primaries.encode(buf)?;
75 transfer_characteristics.encode(buf)?;
76 matrix_coefficients.encode(buf)?;
77 if *full_range_flag {
78 0x80u8.encode(buf)?;
79 } else {
80 0x00u8.encode(buf)?;
81 }
82 }
83 Colr::Ricc { profile } => {
84 b"rICC".encode(buf)?;
85 profile.encode(buf)?;
86 }
87 Colr::Prof { profile } => {
88 b"prof".encode(buf)?;
89 profile.encode(buf)?;
90 }
91 }
92 Ok(())
93 }
94}
95
96impl Default for Colr {
97 fn default() -> Self {
98 Colr::Nclx {
99 colour_primaries: 1,
101 transfer_characteristics: 13,
102 matrix_coefficients: 5,
103 full_range_flag: true,
104 }
105 }
106}
107
108#[cfg(test)]
109mod tests {
110 use super::*;
111
112 #[test]
113 fn test_nclx_decode() {
114 const ENCODED: &[u8] = &[
115 0x00, 0x00, 0x00, 0x13, 0x63, 0x6f, 0x6c, 0x72, 0x6e, 0x63, 0x6c, 0x78, 0x00, 0x01,
116 0x00, 0x01, 0x00, 0x01, 0x00,
117 ];
118
119 let buf = &mut std::io::Cursor::new(&ENCODED);
120
121 let colr = Colr::decode(buf).expect("failed to decode colr");
122
123 assert_eq!(
124 colr,
125 Colr::Nclx {
126 colour_primaries: 1,
127 transfer_characteristics: 1,
128 matrix_coefficients: 1,
129 full_range_flag: false
130 }
131 );
132 }
133
134 #[test]
135 fn test_nclx_encode() {
136 const ENCODED: &[u8] = &[
137 0x00, 0x00, 0x00, 0x13, 0x63, 0x6f, 0x6c, 0x72, 0x6e, 0x63, 0x6c, 0x78, 0x00, 0x01,
138 0x00, 0x0d, 0x00, 0x06, 0x80,
139 ];
140
141 let colr = Colr::Nclx {
142 colour_primaries: 1,
143 transfer_characteristics: 13,
144 matrix_coefficients: 6,
145 full_range_flag: true,
146 };
147
148 let mut buf = Vec::new();
149 colr.encode(&mut buf).unwrap();
150
151 assert_eq!(buf.as_slice(), ENCODED);
152 }
153}