flowly_mp4/mp4box/
smhd.rs

1use byteorder::{BigEndian, WriteBytesExt};
2use serde::Serialize;
3use std::io::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    const TYPE: BoxType = BoxType::SmhdBox;
38
39    fn box_size(&self) -> u64 {
40        self.get_size()
41    }
42
43    fn to_json(&self) -> Result<String, Error> {
44        Ok(serde_json::to_string(&self).unwrap())
45    }
46
47    fn summary(&self) -> Result<String, Error> {
48        let s = format!("balance={}", self.balance.value());
49        Ok(s)
50    }
51}
52
53impl BlockReader for SmhdBox {
54    fn read_block<'a>(reader: &mut impl Reader<'a>) -> Result<Self, Error> {
55        let (version, flags) = read_box_header_ext(reader);
56
57        Ok(SmhdBox {
58            version,
59            flags,
60            balance: FixedPointI8::new_raw(reader.get_i16()),
61        })
62    }
63
64    fn size_hint() -> usize {
65        6
66    }
67}
68
69impl<W: Write> WriteBox<&mut W> for SmhdBox {
70    fn write_box(&self, writer: &mut W) -> Result<u64, Error> {
71        let size = self.box_size();
72        BoxHeader::new(Self::TYPE, size).write(writer)?;
73
74        write_box_header_ext(writer, self.version, self.flags)?;
75
76        writer.write_i16::<BigEndian>(self.balance.raw_value())?;
77        writer.write_u16::<BigEndian>(0)?; // reserved
78
79        Ok(size)
80    }
81}
82
83#[cfg(test)]
84mod tests {
85    use super::*;
86    use crate::mp4box::BoxHeader;
87
88    #[tokio::test]
89    async fn test_smhd() {
90        let src_box = SmhdBox {
91            version: 0,
92            flags: 0,
93            balance: FixedPointI8::new_raw(-1),
94        };
95        let mut buf = Vec::new();
96        src_box.write_box(&mut buf).unwrap();
97        assert_eq!(buf.len(), src_box.box_size() as usize);
98
99        let mut reader = buf.as_slice();
100        let header = BoxHeader::read(&mut reader, &mut 0).await.unwrap().unwrap();
101        assert_eq!(header.kind, BoxType::SmhdBox);
102        assert_eq!(src_box.box_size(), header.size);
103
104        let dst_box = SmhdBox::read_block(&mut reader).unwrap();
105        assert_eq!(src_box, dst_box);
106    }
107}