scuffle_mp4/boxes/types/
stz2.rs1use std::io;
2
3use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};
4use bytes::Bytes;
5
6use crate::boxes::header::{BoxHeader, FullBoxHeader};
7use crate::boxes::traits::BoxType;
8
9#[derive(Debug, Clone, PartialEq)]
10pub struct Stz2 {
13 pub header: FullBoxHeader,
14 pub reserved: u32,
15 pub field_size: u8,
16 pub samples: Vec<u16>,
17}
18
19impl BoxType for Stz2 {
20 const NAME: [u8; 4] = *b"stz2";
21
22 fn demux(header: BoxHeader, data: Bytes) -> io::Result<Self> {
23 let mut reader = io::Cursor::new(data);
24
25 let header = FullBoxHeader::demux(header, &mut reader)?;
26
27 let reserved = reader.read_u24::<BigEndian>()?;
28
29 let field_size = reader.read_u8()?;
30 let sample_count = reader.read_u32::<BigEndian>()?;
31
32 let mut samples = Vec::with_capacity(sample_count as usize);
33
34 let mut sample_idx = 0;
35 while sample_idx < sample_count {
36 let sample = match field_size {
37 4 => {
38 let byte = reader.read_u8()?;
39 samples.push((byte >> 4) as u16);
40 sample_idx += 1;
41 if sample_idx >= sample_count {
42 break;
43 }
44
45 (byte & 0x0F) as u16
46 }
47 8 => reader.read_u8()? as u16,
48 16 => reader.read_u16::<BigEndian>()?,
49 _ => {
50 return Err(io::Error::new(io::ErrorKind::InvalidData, "Invalid field size"));
51 }
52 };
53
54 sample_idx += 1;
55 samples.push(sample);
56 }
57
58 Ok(Self {
59 header,
60 reserved,
61 field_size,
62 samples,
63 })
64 }
65
66 fn primitive_size(&self) -> u64 {
67 let size = self.header.size();
68 let size = size + 8; size + (self.samples.len() as u64 * self.field_size as u64)
71 }
72
73 fn primitive_mux<T: io::Write>(&self, writer: &mut T) -> io::Result<()> {
74 self.header.mux(writer)?;
75
76 writer.write_u24::<BigEndian>(self.reserved)?;
77 writer.write_u8(self.field_size)?;
78 writer.write_u32::<BigEndian>(self.samples.len() as u32)?;
79
80 let mut sample_idx = 0;
81 while sample_idx < self.samples.len() {
82 let sample = self.samples[sample_idx];
83 match self.field_size {
84 4 => {
85 let byte = (sample << 4) as u8;
86 sample_idx += 1;
87 if sample_idx >= self.samples.len() {
88 writer.write_u8(byte)?;
89 break;
90 }
91
92 let sample = self.samples[sample_idx];
93 let byte = byte | (sample & 0x0F) as u8;
94 writer.write_u8(byte)?;
95 }
96 8 => writer.write_u8(sample as u8)?,
97 16 => writer.write_u16::<BigEndian>(sample)?,
98 _ => {
99 return Err(io::Error::new(io::ErrorKind::InvalidData, "Invalid field size"));
100 }
101 };
102
103 sample_idx += 1;
104 }
105
106 Ok(())
107 }
108
109 fn validate(&self) -> io::Result<()> {
110 if self.header.version != 0 {
111 return Err(io::Error::new(io::ErrorKind::InvalidData, "stz2 version must be 0"));
112 }
113
114 if self.reserved != 0 {
115 return Err(io::Error::new(io::ErrorKind::InvalidData, "stz2 reserved must be 0"));
116 }
117
118 if self.field_size != 4 && self.field_size != 8 && self.field_size != 16 {
119 return Err(io::Error::new(
120 io::ErrorKind::InvalidData,
121 "stz2 field_size must be 4, 8 or 16",
122 ));
123 }
124
125 if self.field_size != 16 {
126 for sample in &self.samples {
127 if self.field_size == 4 {
128 if *sample > 0x0F {
129 return Err(io::Error::new(io::ErrorKind::InvalidData, "stz2 sample value must be 4 bits"));
130 }
131 } else if self.field_size == 8 && *sample > 0xFF {
132 return Err(io::Error::new(io::ErrorKind::InvalidData, "stz2 sample value must be 8 bits"));
133 }
134 }
135 }
136
137 Ok(())
138 }
139}