scuffle_mp4/boxes/types/
ftyp.rs1use std::io;
2
3use byteorder::{ReadBytesExt, WriteBytesExt};
4use bytes::Bytes;
5
6use crate::boxes::header::BoxHeader;
7use crate::boxes::traits::BoxType;
8
9#[derive(Debug, Clone, PartialEq)]
10pub struct Ftyp {
13 pub header: BoxHeader,
14 pub major_brand: FourCC,
15 pub minor_version: u32,
16 pub compatible_brands: Vec<FourCC>,
17}
18
19impl Ftyp {
20 pub fn new(major_brand: FourCC, minor_version: u32, compatible_brands: Vec<FourCC>) -> Self {
21 Self {
22 header: BoxHeader::new(Self::NAME),
23 major_brand,
24 minor_version,
25 compatible_brands,
26 }
27 }
28}
29
30impl BoxType for Ftyp {
31 const NAME: [u8; 4] = *b"ftyp";
32
33 fn demux(header: BoxHeader, data: Bytes) -> io::Result<Self> {
34 let major_brand =
35 FourCC::from(TryInto::<[u8; 4]>::try_into(data.slice(0..4).as_ref()).expect("slice is 4 bytes long"));
36 let minor_version = data.slice(4..8).as_ref().read_u32::<byteorder::BigEndian>()?;
37 let compatible_brands = {
38 let mut compatible_brands = Vec::new();
39 let mut data = data.slice(8..);
40 while data.len() >= 4 {
41 compatible_brands.push(FourCC::from(
42 TryInto::<[u8; 4]>::try_into(data.slice(0..4).as_ref()).expect("slice is 4 bytes long"),
43 ));
44 data = data.slice(4..);
45 }
46 compatible_brands
47 };
48
49 Ok(Self {
50 header,
51 major_brand,
52 minor_version,
53 compatible_brands,
54 })
55 }
56
57 fn primitive_size(&self) -> u64 {
58 4 + 4 + (self.compatible_brands.len() * 4) as u64
59 }
60
61 fn primitive_mux<T: io::Write>(&self, writer: &mut T) -> io::Result<()> {
62 writer.write_all(&self.major_brand.to_bytes())?;
63 writer.write_u32::<byteorder::BigEndian>(self.minor_version)?;
64 for compatible_brand in &self.compatible_brands {
65 writer.write_all(&compatible_brand.to_bytes())?;
66 }
67 Ok(())
68 }
69}
70
71#[derive(Debug, Clone, PartialEq)]
72pub enum FourCC {
74 Iso5,
75 Iso6,
76 Mp41,
77 Avc1,
78 Av01,
79 Hev1,
80 Unknown([u8; 4]),
81}
82
83impl FourCC {
84 pub fn to_bytes(&self) -> [u8; 4] {
85 match self {
86 Self::Iso5 => *b"iso5",
87 Self::Iso6 => *b"iso6",
88 Self::Mp41 => *b"mp41",
89 Self::Avc1 => *b"avc1",
90 Self::Av01 => *b"av01",
91 Self::Hev1 => *b"hev1",
92 Self::Unknown(bytes) => *bytes,
93 }
94 }
95}
96
97impl From<[u8; 4]> for FourCC {
98 fn from(bytes: [u8; 4]) -> Self {
99 match &bytes {
100 b"iso5" => Self::Iso5,
101 b"iso6" => Self::Iso6,
102 b"mp41" => Self::Mp41,
103 b"avc1" => Self::Avc1,
104 b"av01" => Self::Av01,
105 b"hev1" => Self::Hev1,
106 _ => Self::Unknown(bytes),
107 }
108 }
109}