scuffle_mp4/boxes/types/
hev1.rs1use std::io;
2
3use bytes::{Buf, Bytes};
4
5use super::btrt::Btrt;
6use super::hvcc::HvcC;
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)]
14pub struct Hev1 {
17 pub header: BoxHeader,
18 pub visual_sample_entry: SampleEntry<VisualSampleEntry>,
19 pub hvcc: HvcC,
20 pub btrt: Option<Btrt>,
21 pub unknown: Vec<DynBox>,
22}
23
24impl Hev1 {
25 pub fn new(visual_sample_entry: SampleEntry<VisualSampleEntry>, hvcc: HvcC, btrt: Option<Btrt>) -> Self {
26 Self {
27 header: BoxHeader::new(Self::NAME),
28 visual_sample_entry,
29 hvcc,
30 btrt,
31 unknown: Vec::new(),
32 }
33 }
34
35 pub fn codec(&self) -> io::Result<VideoCodec> {
36 Ok(VideoCodec::Hevc {
37 constraint_indicator: self.hvcc.hevc_config.general_constraint_indicator_flags,
38 level: self.hvcc.hevc_config.general_level_idc,
39 profile: self.hvcc.hevc_config.general_profile_idc,
40 profile_compatibility: self.hvcc.hevc_config.general_profile_compatibility_flags,
41 tier: self.hvcc.hevc_config.general_tier_flag,
42 general_profile_space: self.hvcc.hevc_config.general_profile_space,
43 })
44 }
45}
46
47impl BoxType for Hev1 {
48 const NAME: [u8; 4] = *b"hev1";
49
50 fn demux(header: BoxHeader, data: Bytes) -> io::Result<Self> {
51 let mut reader = io::Cursor::new(data);
52
53 let mut visual_sample_entry = SampleEntry::<VisualSampleEntry>::demux(&mut reader)?;
54
55 let mut hvcc = None;
56 let mut btrt = None;
57 let mut unknown = Vec::new();
58
59 while reader.has_remaining() {
60 let dyn_box = DynBox::demux(&mut reader)?;
61 match dyn_box {
62 DynBox::HvcC(b) => {
63 hvcc = Some(*b);
64 }
65 DynBox::Btrt(b) => {
66 btrt = Some(*b);
67 }
68 DynBox::Clap(b) => {
69 visual_sample_entry.extension.clap = Some(*b);
70 }
71 DynBox::Pasp(b) => {
72 visual_sample_entry.extension.pasp = Some(*b);
73 }
74 DynBox::Colr(b) => {
75 visual_sample_entry.extension.colr = Some(*b);
76 }
77 _ => {
78 unknown.push(dyn_box);
79 }
80 }
81 }
82
83 let hvcc = hvcc.ok_or_else(|| io::Error::new(io::ErrorKind::InvalidData, "trak box is missing tkhd box"))?;
84
85 Ok(Self {
86 header,
87 visual_sample_entry,
88 hvcc,
89 btrt,
90 unknown,
91 })
92 }
93
94 fn primitive_size(&self) -> u64 {
95 self.visual_sample_entry.size()
96 + self.hvcc.size()
97 + self.btrt.as_ref().map(|b| b.size()).unwrap_or(0)
98 + self.unknown.iter().map(|b| b.size()).sum::<u64>()
99 }
100
101 fn primitive_mux<T: io::Write>(&self, writer: &mut T) -> io::Result<()> {
102 self.visual_sample_entry.mux(writer)?;
103 self.hvcc.mux(writer)?;
104 if let Some(btrt) = &self.btrt {
105 btrt.mux(writer)?;
106 }
107 for unknown in &self.unknown {
108 unknown.mux(writer)?;
109 }
110 Ok(())
111 }
112}