mp4_atom/moov/trak/mdia/minf/stbl/stsd/
vp09.rs1use crate::*;
2
3#[derive(Debug, Clone, PartialEq, Eq, Default)]
5#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
6pub struct Vp09 {
7 pub visual: Visual,
8 pub vpcc: VpcC,
9}
10
11impl Atom for Vp09 {
12 const KIND: FourCC = FourCC::new(b"vp09");
13
14 fn decode_body<B: Buf>(buf: &mut B) -> Result<Self> {
15 let visual = Visual::decode(buf)?;
16
17 let mut vpcc = None;
18 while let Some(atom) = Any::decode_maybe(buf)? {
19 match atom {
20 Any::VpcC(atom) => vpcc = atom.into(),
21 _ => tracing::warn!("unknown atom: {:?}", atom),
22 }
23 }
24
25 Ok(Self {
26 visual,
27 vpcc: vpcc.ok_or(Error::MissingBox(VpcC::KIND))?,
28 })
29 }
30
31 fn encode_body<B: BufMut>(&self, buf: &mut B) -> Result<()> {
32 self.visual.encode(buf)?;
33 self.vpcc.encode(buf)?;
34
35 Ok(())
36 }
37}
38
39ext! {
40 name: Vpcc,
41 versions: [1],
42 flags: {}
43}
44
45#[derive(Debug, Clone, PartialEq, Eq, Default)]
46#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
47pub struct VpcC {
48 pub profile: u8,
49 pub level: u8,
50 pub bit_depth: u8,
51 pub chroma_subsampling: u8,
52 pub video_full_range_flag: bool,
53 pub color_primaries: u8,
54 pub transfer_characteristics: u8,
55 pub matrix_coefficients: u8,
56 pub codec_initialization_data: Vec<u8>,
57}
58
59impl AtomExt for VpcC {
60 const KIND_EXT: FourCC = FourCC::new(b"vpcC");
61
62 type Ext = VpccExt;
63
64 fn decode_body_ext<B: Buf>(buf: &mut B, _ext: VpccExt) -> Result<Self> {
65 let profile = u8::decode(buf)?;
66 let level = u8::decode(buf)?;
67 let (bit_depth, chroma_subsampling, video_full_range_flag) = {
68 let b = u8::decode(buf)?;
69 (b >> 4, (b >> 1) & 0x01, b & 0x01 == 1)
70 };
71 let color_primaries = u8::decode(buf)?;
72 let transfer_characteristics = u8::decode(buf)?;
73 let matrix_coefficients = u8::decode(buf)?;
74 let _codec_initialization_data_size = u16::decode(buf)?;
75 let codec_initialization_data = Vec::decode(buf)?; Ok(Self {
78 profile,
79 level,
80 bit_depth,
81 chroma_subsampling,
82 video_full_range_flag,
83 color_primaries,
84 transfer_characteristics,
85 matrix_coefficients,
86 codec_initialization_data,
87 })
88 }
89
90 fn encode_body_ext<B: BufMut>(&self, buf: &mut B) -> Result<VpccExt> {
91 self.profile.encode(buf)?;
92 self.level.encode(buf)?;
93 ((self.bit_depth << 4)
94 | (self.chroma_subsampling << 1)
95 | (self.video_full_range_flag as u8))
96 .encode(buf)?;
97 self.color_primaries.encode(buf)?;
98 self.transfer_characteristics.encode(buf)?;
99 self.matrix_coefficients.encode(buf)?;
100 (self.codec_initialization_data.len() as u16).encode(buf)?;
101 self.codec_initialization_data.encode(buf)?;
102
103 Ok(VpccVersion::V1.into())
104 }
105}
106
107#[cfg(test)]
108mod tests {
109 use super::*;
110
111 #[test]
112 fn test_vpcc() {
113 let expected = VpcC {
114 profile: 0,
115 level: 0x1F,
116 bit_depth: 8,
117 chroma_subsampling: 0,
118 video_full_range_flag: false,
119 color_primaries: 0,
120 transfer_characteristics: 0,
121 matrix_coefficients: 0,
122 codec_initialization_data: vec![],
123 };
124 let mut buf = Vec::new();
125 expected.encode(&mut buf).unwrap();
126
127 let mut buf = buf.as_ref();
128 let decoded = VpcC::decode(&mut buf).unwrap();
129 assert_eq!(decoded, expected);
130 }
131
132 #[test]
133 fn test_vp09() {
134 let expected = Vp09 {
135 visual: Visual {
136 width: 1920,
137 height: 1080,
138 ..Default::default()
139 },
140 vpcc: VpcC::default(),
141 };
142 let mut buf = Vec::new();
143 expected.encode(&mut buf).unwrap();
144
145 let mut buf = buf.as_ref();
146 let decoded = Vp09::decode(&mut buf).unwrap();
147 assert_eq!(decoded, expected);
148 }
149}