1use std::io::SeekFrom;
2use futures::{AsyncSeekExt};
3use crate::bytes_read::ReadMp4;
4use crate::bytes_write::{Mp4Writable, WriteMp4};
5use crate::error::MP4Error;
6use crate::header::BoxHeader;
7use crate::id::BoxId;
8use crate::mp4box::box_trait::{BoxRead, BoxWrite, IBox};
9use crate::r#type::BoxType;
10
11pub type FtypBox = Ftyp;
12
13#[derive(Debug, Clone, Eq, PartialEq, Hash)]
14pub struct Ftyp {
15 pub major_brand: [u8; 4],
16 pub minor_version: u32,
17 pub compatible_brands: Vec<[u8; 4]>
18}
19
20impl Ftyp {
21 fn inner_byte_size(&self) -> usize {
22 self.major_brand.byte_size() + self.minor_version.byte_size() + self.compatible_brands.iter().map(Mp4Writable::byte_size).sum::<usize>()
23 }
24
25 fn header(&self) -> BoxHeader {
26 BoxHeader::from_id_and_inner_size(Self::ID, self.inner_byte_size())
27 }
28}
29
30impl IBox for Ftyp {
31 fn byte_size(&self) -> usize {
32 self.header().byte_size() + self.inner_byte_size()
33 }
34
35 const ID: BoxType = BoxType::Id(BoxId(*b"ftyp"));
36}
37
38#[async_trait::async_trait]
39impl BoxRead for Ftyp {
40 async fn read<R: ReadMp4>(header: BoxHeader, reader: &mut R) -> Result<Self, MP4Error> {
41 let start = reader.seek(SeekFrom::Current(0)).await?;
42 let size = header.size_minus_self();
43 let major_brand = reader.read().await?;
44 let minor_version = reader.read().await?;
45 let mut compatible_brands = vec![];
46 while !size.ended(start, reader).await? {
47 compatible_brands.push(reader.read().await?);
48 }
49 Ok(Self {
50 major_brand,
51 minor_version,
52 compatible_brands
53 })
54 }
55}
56
57impl BoxWrite for Ftyp {
58
59 fn write<W: WriteMp4>(&self, writer: &mut W) -> Result<usize, MP4Error> {
60 let mut count = 0;
61 count += self.header().write(writer)?;
62 count += self.major_brand.write(writer)?;
63 count += self.minor_version.write(writer)?;
64 count += self.compatible_brands.write(writer)?;
65 Ok(count)
66 }
67}