1use serde::{Deserialize, Serialize};
2
3use crate::Error;
4
5#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
6pub struct VP9 {
7 pub profile: u8,
8 pub level: u8,
9 pub bit_depth: u8,
10 pub chroma_subsampling: u8,
11 pub color_primaries: u8,
12 pub transfer_characteristics: u8,
13 pub matrix_coefficients: u8,
14 pub full_range: bool,
15}
16
17impl std::fmt::Display for VP9 {
20 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
21 write!(f, "vp09.{:02}.{:02}.{:02}", self.profile, self.level, self.bit_depth)?;
22
23 let short = VP9 {
24 profile: self.profile,
25 level: self.level,
26 bit_depth: self.bit_depth,
27 ..Default::default()
28 };
29
30 if self == &short {
31 return Ok(());
32 }
33
34 write!(
35 f,
36 ".{:02}.{:02}.{:02}.{:02}.{:02}",
37 self.chroma_subsampling,
38 self.color_primaries,
39 self.transfer_characteristics,
40 self.matrix_coefficients,
41 self.full_range as u8,
42 )
43 }
44}
45
46impl std::str::FromStr for VP9 {
47 type Err = Error;
48
49 fn from_str(s: &str) -> Result<Self, Self::Err> {
50 let parts = s
51 .strip_prefix("vp09.")
52 .ok_or(Error::InvalidCodec)?
53 .split('.')
54 .map(u8::from_str)
55 .collect::<Result<Vec<_>, _>>()?;
56
57 if parts.len() < 3 {
58 return Err(Error::InvalidCodec);
59 }
60
61 let mut vp9 = VP9 {
62 profile: parts[0],
63 level: parts[1],
64 bit_depth: parts[2],
65 ..Default::default()
66 };
67
68 if parts.len() == 3 {
69 return Ok(vp9);
70 } else if parts.len() != 8 {
71 return Err(Error::InvalidCodec);
72 }
73
74 vp9.chroma_subsampling = parts[3];
75 vp9.color_primaries = parts[4];
76 vp9.transfer_characteristics = parts[5];
77 vp9.matrix_coefficients = parts[6];
78 vp9.full_range = parts[7] == 1;
79
80 Ok(vp9)
81 }
82}
83
84impl Default for VP9 {
85 fn default() -> Self {
86 Self {
87 profile: 0,
88 level: 0,
89 bit_depth: 0,
90 chroma_subsampling: 1,
91 color_primaries: 1,
92 transfer_characteristics: 1,
93 matrix_coefficients: 1,
94 full_range: false,
95 }
96 }
97}
98
99#[cfg(test)]
100mod test {
101 use std::str::FromStr;
102
103 use super::*;
104
105 #[test]
106 fn test_vp9() {
107 let encoded = "vp09.02.10.10.01.09.16.09.01";
108 let decoded = VP9 {
109 profile: 2,
110 level: 10,
111 bit_depth: 10,
112 chroma_subsampling: 1,
113 color_primaries: 9,
114 transfer_characteristics: 16,
115 matrix_coefficients: 9,
116 full_range: true,
117 };
118
119 let output = VP9::from_str(encoded).expect("failed to parse");
120 assert_eq!(output, decoded);
121
122 let output = decoded.to_string();
123 assert_eq!(output, encoded);
124 }
125
126 #[test]
127 fn test_vp9_short() {
128 let encoded = "vp09.00.41.08";
129 let decoded = VP9 {
130 profile: 0,
131 level: 41,
132 bit_depth: 8,
133 ..Default::default()
134 };
135
136 let output = VP9::from_str(encoded).expect("failed to parse");
137 assert_eq!(output, decoded);
138
139 let output = decoded.to_string();
140 assert_eq!(output, encoded);
141 }
142}