Skip to main content

vsd_mp4/boxes/
senc.rs

1use crate::{ParsedBox, Result};
2
3/// A subsample encryption entry, dividing a sample into clear (unencrypted) and encrypted bytes.
4#[derive(Debug, Clone)]
5pub struct SencSubsample {
6    /// Number of clear (unencrypted) bytes in this subsample.
7    pub bytes_of_clear_data: u16,
8    /// Number of encrypted bytes in this subsample.
9    pub bytes_of_encrypted_data: u32,
10}
11
12/// Encryption parameters for a single media sample.
13#[derive(Debug, Clone)]
14pub struct SencSample {
15    /// The initialization vector (IV) for this sample. Shorter IVs (e.g. 8 bytes) are zero-padded to 16 bytes.
16    pub iv: [u8; 16],
17    /// The list of subsample encryption entries if subsample-level encryption is active.
18    pub subsamples: Vec<SencSubsample>,
19}
20
21/// Sample Encryption Box (senc) - contains initialization vectors and subsample maps for all samples in a movie fragment.
22#[derive(Debug, Clone)]
23pub struct SencBox {
24    /// The flags from the box header (typically indicating whether subsamples are present).
25    pub flags: u32,
26    /// Per-sample encryption parameters.
27    pub samples: Vec<SencSample>,
28}
29
30impl SencBox {
31    /// Parses a `senc` box from a `ParsedBox`.
32    ///
33    /// # Arguments
34    /// * `box_` - The parsed box to read from.
35    /// * `iv_size` - The IV size in bytes (from `tenc` default or per-sample IV size).
36    /// * `constant_iv` - An optional constant IV to use if `iv_size` is zero.
37    pub fn new(box_: &mut ParsedBox, iv_size: u8, constant_iv: Option<&[u8; 16]>) -> Result<Self> {
38        let reader = &mut box_.reader;
39        let flags = box_.flags.unwrap_or(0);
40
41        let sample_count = reader.read_u32()?;
42        let has_subsamples = flags & 0x02 != 0;
43
44        let mut samples = Vec::with_capacity(sample_count as usize);
45
46        for _ in 0..sample_count {
47            let iv = if iv_size > 0 && iv_size <= 16 {
48                let bytes = reader.read_bytes_u8(iv_size as usize)?;
49                let mut iv = [0u8; 16];
50                iv[..bytes.len()].copy_from_slice(&bytes);
51                iv
52            } else if let Some(civ) = constant_iv {
53                *civ
54            } else {
55                [0u8; 16]
56            };
57
58            let subsamples = if has_subsamples {
59                let subsample_count = reader.read_u16()?;
60                let mut subs = Vec::with_capacity(subsample_count as usize);
61                for _ in 0..subsample_count {
62                    let bytes_of_clear_data = reader.read_u16()?;
63                    let bytes_of_encrypted_data = reader.read_u32()?;
64                    subs.push(SencSubsample {
65                        bytes_of_clear_data,
66                        bytes_of_encrypted_data,
67                    });
68                }
69                subs
70            } else {
71                Vec::new()
72            };
73
74            samples.push(SencSample { iv, subsamples });
75        }
76
77        Ok(Self { flags, samples })
78    }
79}