Skip to main content

mp4/mp4box/
smhd.rs

1use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};
2use serde::Serialize;
3use std::io::{Read, Seek, Write};
4
5use crate::mp4box::*;
6
7#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
8pub struct SmhdBox {
9    pub version: u8,
10    pub flags: u32,
11
12    #[serde(with = "value_i16")]
13    pub balance: FixedPointI8,
14}
15
16impl SmhdBox {
17    pub fn get_type(&self) -> BoxType {
18        BoxType::SmhdBox
19    }
20
21    pub fn get_size(&self) -> u64 {
22        HEADER_SIZE + HEADER_EXT_SIZE + 4
23    }
24}
25
26impl Default for SmhdBox {
27    fn default() -> Self {
28        SmhdBox {
29            version: 0,
30            flags: 0,
31            balance: FixedPointI8::new_raw(0),
32        }
33    }
34}
35
36impl Mp4Box for SmhdBox {
37    fn box_type(&self) -> BoxType {
38        self.get_type()
39    }
40
41    fn box_size(&self) -> u64 {
42        self.get_size()
43    }
44
45    fn to_json(&self) -> Result<String> {
46        Ok(serde_json::to_string(&self).unwrap())
47    }
48
49    fn summary(&self) -> Result<String> {
50        let s = format!("balance={}", self.balance.value());
51        Ok(s)
52    }
53}
54
55impl<R: Read + Seek> ReadBox<&mut R> for SmhdBox {
56    fn read_box(reader: &mut R, size: u64) -> Result<Self> {
57        let start = box_start(reader)?;
58
59        let (version, flags) = read_box_header_ext(reader)?;
60
61        let balance = FixedPointI8::new_raw(reader.read_i16::<BigEndian>()?);
62
63        skip_bytes_to(reader, start + size)?;
64
65        Ok(SmhdBox {
66            version,
67            flags,
68            balance,
69        })
70    }
71}
72
73impl<W: Write> WriteBox<&mut W> for SmhdBox {
74    fn write_box(&self, writer: &mut W) -> Result<u64> {
75        let size = self.box_size();
76        BoxHeader::new(self.box_type(), size).write(writer)?;
77
78        write_box_header_ext(writer, self.version, self.flags)?;
79
80        writer.write_i16::<BigEndian>(self.balance.raw_value())?;
81        writer.write_u16::<BigEndian>(0)?; // reserved
82
83        Ok(size)
84    }
85}
86
87#[cfg(test)]
88mod tests {
89    use super::*;
90    use crate::mp4box::BoxHeader;
91    use std::io::Cursor;
92
93    #[test]
94    fn test_smhd() {
95        let src_box = SmhdBox {
96            version: 0,
97            flags: 0,
98            balance: FixedPointI8::new_raw(-1),
99        };
100        let mut buf = Vec::new();
101        src_box.write_box(&mut buf).unwrap();
102        assert_eq!(buf.len(), src_box.box_size() as usize);
103
104        let mut reader = Cursor::new(&buf);
105        let header = BoxHeader::read(&mut reader).unwrap();
106        assert_eq!(header.name, BoxType::SmhdBox);
107        assert_eq!(src_box.box_size(), header.size);
108
109        let dst_box = SmhdBox::read_box(&mut reader, header.size).unwrap();
110        assert_eq!(src_box, dst_box);
111    }
112}