scuffle_mp4/boxes/types/
colr.rs1use std::io::{
2 Read, {self},
3};
4
5use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};
6use bytes::Bytes;
7
8use crate::boxes::header::BoxHeader;
9use crate::boxes::traits::BoxType;
10
11#[derive(Debug, Clone, PartialEq)]
12pub struct Colr {
15 pub header: BoxHeader,
16 pub color_type: ColorType,
17}
18
19#[derive(Debug, Clone, PartialEq)]
20pub enum ColorType {
21 Nclx {
22 color_primaries: u16,
23 transfer_characteristics: u16,
24 matrix_coefficients: u16,
25 full_range_flag: bool,
26 },
27 Unknown(([u8; 4], Bytes)),
28}
29
30impl Colr {
31 pub fn new(color_type: ColorType) -> Self {
32 Self {
33 header: BoxHeader::new(Self::NAME),
34 color_type,
35 }
36 }
37}
38
39impl BoxType for Colr {
40 const NAME: [u8; 4] = *b"colr";
41
42 fn demux(header: BoxHeader, data: Bytes) -> io::Result<Self> {
43 let mut reader = io::Cursor::new(data);
44
45 let mut color_type = [0; 4];
46 reader.read_exact(&mut color_type)?;
47
48 let color_type = match &color_type {
49 b"nclx" => {
50 let color_primaries = reader.read_u16::<BigEndian>()?;
51 let transfer_characteristics = reader.read_u16::<BigEndian>()?;
52 let matrix_coefficients = reader.read_u16::<BigEndian>()?;
53 let full_range_flag = (reader.read_u8()? >> 7) == 1;
54
55 ColorType::Nclx {
56 color_primaries,
57 transfer_characteristics,
58 matrix_coefficients,
59 full_range_flag,
60 }
61 }
62 _ => {
63 let pos = reader.position() as usize;
64 let data = reader.into_inner().slice(pos..);
65 ColorType::Unknown((color_type, data))
66 }
67 };
68
69 Ok(Self { header, color_type })
70 }
71
72 fn primitive_size(&self) -> u64 {
73 let size = match &self.color_type {
74 ColorType::Nclx { .. } => 2 + 2 + 2 + 1, ColorType::Unknown((_, data)) => data.len() as u64, };
77
78 size + 4 }
80
81 fn primitive_mux<T: io::Write>(&self, writer: &mut T) -> io::Result<()> {
82 match &self.color_type {
83 ColorType::Nclx {
84 color_primaries,
85 transfer_characteristics,
86 matrix_coefficients,
87 full_range_flag,
88 } => {
89 writer.write_all(b"nclx")?;
90 writer.write_u16::<BigEndian>(*color_primaries)?;
91 writer.write_u16::<BigEndian>(*transfer_characteristics)?;
92 writer.write_u16::<BigEndian>(*matrix_coefficients)?;
93 writer.write_u8(if *full_range_flag { 0x80 } else { 0x00 })?;
94 }
95 ColorType::Unknown((color_type, data)) => {
96 writer.write_all(color_type)?;
97 writer.write_all(data)?;
98 }
99 }
100
101 Ok(())
102 }
103}