moq_karp/video/
h264.rs

1use std::{fmt, str::FromStr};
2
3use serde::{Deserialize, Serialize};
4
5use crate::Error;
6
7#[serde_with::serde_as]
8#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
9pub struct H264 {
10	pub profile: u8,
11	pub constraints: u8,
12	pub level: u8,
13}
14
15impl fmt::Display for H264 {
16	fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
17		write!(f, "avc1.{:02x}{:02x}{:02x}", self.profile, self.constraints, self.level)
18	}
19}
20
21impl FromStr for H264 {
22	type Err = Error;
23
24	fn from_str(s: &str) -> Result<Self, Self::Err> {
25		let mut parts = s.split('.');
26		if parts.next() != Some("avc1") {
27			return Err(Error::InvalidCodec);
28		}
29
30		let part = parts.next().ok_or(Error::InvalidCodec)?;
31		if part.len() != 6 {
32			return Err(Error::InvalidCodec);
33		}
34
35		Ok(Self {
36			profile: u8::from_str_radix(&part[0..2], 16)?,
37			constraints: u8::from_str_radix(&part[2..4], 16)?,
38			level: u8::from_str_radix(&part[4..6], 16)?,
39		})
40	}
41}
42
43#[cfg(test)]
44mod tests {
45	use std::str::FromStr;
46
47	use super::*;
48
49	#[test]
50	fn test_h264() {
51		let encoded = "avc1.42c01e";
52		let decoded = H264 {
53			profile: 0x42,
54			constraints: 0xc0,
55			level: 0x1e,
56		};
57
58		let output = H264::from_str(encoded).expect("failed to parse");
59		assert_eq!(output, decoded);
60
61		let output = decoded.to_string();
62		assert_eq!(output, encoded);
63	}
64}