Skip to main content

vsd_mp4/boxes/
trun.rs

1use crate::{ParsedBox, Result};
2
3/// Sample data entry within a track fragment run.
4#[derive(Debug, Clone)]
5pub struct TrunSample {
6    /// The length of the sample in timescale units.
7    pub sample_duration: Option<u32>,
8    /// The size of the sample in bytes.
9    pub sample_size: Option<u32>,
10    /// The composition time offset of the sample (difference between composition time and decode time), in timescale units.
11    pub sample_composition_time_offset: Option<i32>,
12}
13
14/// Track Fragment Run Box (trun) - provides details for each sample in a movie fragment.
15#[derive(Debug, Clone)]
16pub struct TrunBox {
17    /// The number of samples being added in this run.
18    pub sample_count: u32,
19    /// An array containing data for each sample in the run.
20    pub sample_data: Vec<TrunSample>,
21    /// If specified via flags, this indicates the offset of the first sample's data in bytes.
22    pub data_offset: Option<u32>,
23}
24
25impl TrunBox {
26    /// Parses a `trun` box from a `ParsedBox`.
27    pub fn new(box_: &mut ParsedBox) -> Result<Self> {
28        let reader = &mut box_.reader;
29        let version = box_.version.unwrap();
30        let flags = box_.flags.unwrap();
31
32        let sample_count = reader.read_u32()?;
33        let mut sample_data = vec![];
34        let mut data_offset = None;
35
36        // "data_offset"
37        if (flags & 0x000001) != 0 {
38            data_offset = Some(reader.read_u32()?);
39        }
40
41        // Skip "first_sample_flags" if present.
42        if (flags & 0x000004) != 0 {
43            reader.skip(4)?;
44        }
45
46        for _ in 0..sample_count {
47            let mut sample = TrunSample {
48                sample_duration: None,
49                sample_size: None,
50                sample_composition_time_offset: None,
51            };
52
53            // Read "sample duration" if present.
54            if (flags & 0x000100) != 0 {
55                sample.sample_duration = Some(reader.read_u32()?);
56            }
57
58            // Read "sample_size" if present.
59            if (flags & 0x000200) != 0 {
60                sample.sample_size = Some(reader.read_u32()?);
61            }
62
63            // Skip "sample_flags" if present.
64            if (flags & 0x000400) != 0 {
65                reader.skip(4)?;
66            }
67
68            // Read "sample_time_offset" if present.
69            if (flags & 0x000800) != 0 {
70                sample.sample_composition_time_offset = Some(if version == 0 {
71                    reader.read_u32()? as i32
72                } else {
73                    reader.read_i32()?
74                });
75            }
76
77            sample_data.push(sample);
78        }
79
80        Ok(Self {
81            sample_count,
82            sample_data,
83            data_offset,
84        })
85    }
86}