mp4_atom/moof/traf/
trun.rs1use crate::*;
2
3ext! {
4 name: Trun,
5 versions: [0, 1],
6 flags: {
7 data_offset = 0,
8 first_sample_flags = 2,
9 sample_duration = 8,
10 sample_size = 9,
11 sample_flags = 10,
12 sample_cts = 11,
13 }
14}
15
16#[derive(Debug, Clone, PartialEq, Eq, Default)]
17#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
18pub struct Trun {
19 pub data_offset: Option<i32>,
20 pub entries: Vec<TrunEntry>,
21}
22
23#[derive(Debug, Clone, PartialEq, Eq, Default)]
24#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
25pub struct TrunEntry {
26 pub duration: Option<u32>,
27 pub size: Option<u32>,
28 pub flags: Option<u32>,
29 pub cts: Option<i32>,
30}
31
32impl AtomExt for Trun {
33 const KIND_EXT: FourCC = FourCC::new(b"trun");
34
35 type Ext = TrunExt;
36
37 fn decode_body_ext<B: Buf>(buf: &mut B, ext: TrunExt) -> Result<Self> {
38 let sample_count = u32::decode(buf)?;
39 let data_offset = match ext.data_offset {
40 true => i32::decode(buf)?.into(),
41 false => None,
42 };
43
44 let mut first_sample_flags = match ext.first_sample_flags {
45 true => u32::decode(buf)?.into(),
46 false => None,
47 };
48
49 if !(ext.sample_duration
53 || ext.sample_size
54 || ext.sample_flags
55 || ext.sample_cts
56 || sample_count <= 4096)
57 {
58 return Err(Error::OutOfMemory);
59 }
60
61 let mut entries = Vec::with_capacity(sample_count.min(4096) as _);
62
63 for _ in 0..sample_count {
64 let duration = match ext.sample_duration {
65 true => u32::decode(buf)?.into(),
66 false => None,
67 };
68 let size = match ext.sample_size {
69 true => u32::decode(buf)?.into(),
70 false => None,
71 };
72 let sample_flags = match first_sample_flags.take() {
73 Some(flags) => Some(flags),
74 None => match ext.sample_flags {
75 true => u32::decode(buf)?.into(),
76 false => None,
77 },
78 };
79 let cts = match ext.sample_cts {
80 true => i32::decode(buf)?.into(),
81 false => None,
82 };
83
84 entries.push(TrunEntry {
85 duration,
86 size,
87 flags: sample_flags,
88 cts,
89 });
90 }
91
92 Ok(Trun {
93 data_offset,
94 entries,
95 })
96 }
97
98 fn encode_body_ext<B: BufMut>(&self, buf: &mut B) -> Result<TrunExt> {
99 let ext = TrunExt {
100 version: TrunVersion::V1,
101 data_offset: self.data_offset.is_some(),
102 first_sample_flags: false,
103
104 sample_duration: self.entries.iter().all(|s| s.duration.is_some()),
106 sample_size: self.entries.iter().all(|s| s.size.is_some()),
107 sample_flags: self.entries.iter().all(|s| s.flags.is_some()),
108 sample_cts: self.entries.iter().all(|s| s.cts.is_some()),
109 };
110
111 (self.entries.len() as u32).encode(buf)?;
112
113 self.data_offset.encode(buf)?;
114 0u32.encode(buf)?; for entry in &self.entries {
117 ext.sample_duration.then_some(entry.duration).encode(buf)?;
118 ext.sample_size.then_some(entry.size).encode(buf)?;
119 ext.sample_flags.then_some(entry.flags).encode(buf)?;
120 ext.sample_cts.then_some(entry.cts).encode(buf)?;
121 }
122
123 Ok(ext)
124 }
125}