scuffle_mp4/boxes/types/
avc1.rs

1use std::io;
2
3use bytes::{Buf, Bytes};
4
5use super::avcc::AvcC;
6use super::btrt::Btrt;
7use super::stsd::{SampleEntry, VisualSampleEntry};
8use crate::boxes::DynBox;
9use crate::boxes::header::BoxHeader;
10use crate::boxes::traits::BoxType;
11use crate::codec::VideoCodec;
12
13#[derive(Debug, Clone, PartialEq)]
14/// AVC Codec Box
15/// ISO/IEC 14496-15:2022(E) - 6.5.3
16pub struct Avc1 {
17    pub header: BoxHeader,
18    pub visual_sample_entry: SampleEntry<VisualSampleEntry>,
19    pub avcc: AvcC,
20    pub btrt: Option<Btrt>,
21    pub unknown: Vec<DynBox>,
22}
23
24impl Avc1 {
25    pub fn new(visual_sample_entry: SampleEntry<VisualSampleEntry>, avcc: AvcC, btrt: Option<Btrt>) -> Self {
26        Self {
27            header: BoxHeader::new(Self::NAME),
28            visual_sample_entry,
29            avcc,
30            btrt,
31            unknown: Vec::new(),
32        }
33    }
34
35    pub fn codec(&self) -> io::Result<VideoCodec> {
36        Ok(VideoCodec::Avc {
37            constraint_set: self.avcc.avc_decoder_configuration_record.profile_compatibility,
38            level: self.avcc.avc_decoder_configuration_record.level_indication,
39            profile: self.avcc.avc_decoder_configuration_record.profile_indication,
40        })
41    }
42}
43
44impl BoxType for Avc1 {
45    const NAME: [u8; 4] = *b"avc1";
46
47    fn demux(header: BoxHeader, data: Bytes) -> io::Result<Self> {
48        let mut reader = io::Cursor::new(data);
49
50        let mut visual_sample_entry = SampleEntry::<VisualSampleEntry>::demux(&mut reader)?;
51
52        let mut avcc = None;
53        let mut btrt = None;
54        let mut unknown = Vec::new();
55
56        while reader.has_remaining() {
57            let dyn_box = DynBox::demux(&mut reader)?;
58            match dyn_box {
59                DynBox::AvcC(b) => {
60                    avcc = Some(*b);
61                }
62                DynBox::Btrt(b) => {
63                    btrt = Some(*b);
64                }
65                DynBox::Clap(b) => {
66                    visual_sample_entry.extension.clap = Some(*b);
67                }
68                DynBox::Pasp(b) => {
69                    visual_sample_entry.extension.pasp = Some(*b);
70                }
71                DynBox::Colr(b) => {
72                    visual_sample_entry.extension.colr = Some(*b);
73                }
74                _ => {
75                    unknown.push(dyn_box);
76                }
77            }
78        }
79
80        let avcc = avcc.ok_or_else(|| io::Error::new(io::ErrorKind::InvalidData, "trak box is missing tkhd box"))?;
81
82        Ok(Self {
83            header,
84            visual_sample_entry,
85            avcc,
86            btrt,
87            unknown,
88        })
89    }
90
91    fn primitive_size(&self) -> u64 {
92        self.visual_sample_entry.size()
93            + self.avcc.size()
94            + self.btrt.as_ref().map(|b| b.size()).unwrap_or(0)
95            + self.unknown.iter().map(|b| b.size()).sum::<u64>()
96    }
97
98    fn primitive_mux<T: io::Write>(&self, writer: &mut T) -> io::Result<()> {
99        self.visual_sample_entry.mux(writer)?;
100        self.avcc.mux(writer)?;
101        if let Some(btrt) = &self.btrt {
102            btrt.mux(writer)?;
103        }
104        for unknown in &self.unknown {
105            unknown.mux(writer)?;
106        }
107        Ok(())
108    }
109}