mp4_atom/moov/trak/mdia/minf/stbl/stsd/
wvtt.rs1use crate::*;
2
3#[derive(Debug, Clone, PartialEq, Eq)]
5#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
6pub struct VttC {
7 pub config: String,
8}
9
10impl Atom for VttC {
11 const KIND: FourCC = FourCC::new(b"vttC");
12
13 fn decode_body<B: Buf>(buf: &mut B) -> Result<Self> {
14 Ok(Self {
15 config: decode_boxstring(buf)?,
16 })
17 }
18
19 fn encode_body<B: BufMut>(&self, buf: &mut B) -> Result<()> {
20 self.config.as_bytes().encode(buf)
21 }
22}
23
24#[derive(Debug, Clone, PartialEq, Eq)]
26#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
27pub struct Vlab {
28 pub source_label: String,
29}
30
31impl Atom for Vlab {
32 const KIND: FourCC = FourCC::new(b"vlab");
33
34 fn decode_body<B: Buf>(buf: &mut B) -> Result<Self> {
35 Ok(Self {
36 source_label: decode_boxstring(buf)?,
37 })
38 }
39
40 fn encode_body<B: BufMut>(&self, buf: &mut B) -> Result<()> {
41 self.source_label.as_bytes().encode(buf)
43 }
44}
45
46#[derive(Debug, Clone, PartialEq, Eq)]
47#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
48pub struct Wvtt {
49 pub plaintext: PlainText,
50 pub config: VttC,
51 pub label: Option<Vlab>,
52 pub btrt: Option<Btrt>,
53}
54
55impl Atom for Wvtt {
56 const KIND: FourCC = FourCC::new(b"wvtt");
57
58 fn decode_body<B: Buf>(buf: &mut B) -> Result<Self> {
59 let plaintext = PlainText::decode(buf)?;
60
61 let mut vtcc = None;
62 let mut vlab = None;
63 let mut btrt = None;
64
65 while let Some(atom) = Any::decode_maybe(buf)? {
66 match atom {
67 Any::VttC(atom) => vtcc = atom.into(),
68 Any::Vlab(atom) => vlab = atom.into(),
69 Any::Btrt(atom) => btrt = atom.into(),
70 unknown => Self::decode_unknown(&unknown)?,
71 }
72 }
73 skip_trailing_padding(buf);
74
75 Ok(Self {
76 plaintext,
77 config: vtcc.ok_or(Error::MissingBox(VttC::KIND))?,
78 label: vlab,
79 btrt,
80 })
81 }
82
83 fn encode_body<B: BufMut>(&self, buf: &mut B) -> Result<()> {
84 self.plaintext.encode(buf)?;
85 self.config.encode(buf)?;
86 self.label.encode(buf)?;
87 self.btrt.encode(buf)?;
88 Ok(())
89 }
90}
91
92fn decode_boxstring<B: Buf>(buf: &mut B) -> Result<String> {
93 let remaining_bytes = buf.remaining();
94 let body = &mut buf.slice(remaining_bytes);
95 let text = String::from_utf8(body.to_vec()).map_err(|_| Error::InvalidSize)?;
96 buf.advance(remaining_bytes);
97 Ok(text)
98}
99
100#[cfg(test)]
101mod tests {
102 use super::*;
103
104 const ENCODED_WVTT: &[u8] = &[
106 0x00, 0x00, 0x00, 0x3d, 0x77, 0x76, 0x74, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
107 0x01, 0x00, 0x00, 0x00, 0x2d, 0x76, 0x74, 0x74, 0x43, 0x57, 0x45, 0x42, 0x56, 0x54, 0x54,
108 0x0a, 0x53, 0x6f, 0x6d, 0x65, 0x20, 0x64, 0x75, 0x6d, 0x6d, 0x79, 0x20, 0x68, 0x65, 0x61,
109 0x64, 0x65, 0x72, 0x20, 0x69, 0x6e, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e,
110 0x0a,
111 ];
112
113 #[test]
114 fn test_wvtt_decode() {
115 let buf: &mut std::io::Cursor<&[u8]> = &mut std::io::Cursor::new(ENCODED_WVTT);
116
117 let wvtt = Wvtt::decode(buf).expect("failed to decode wvtt");
118
119 assert_eq!(
120 wvtt,
121 Wvtt {
122 plaintext: PlainText {
123 data_reference_index: 1
124 },
125 config: VttC {
126 config: "WEBVTT\nSome dummy header information\n".into()
127 },
128 label: None,
129 btrt: None,
130 }
131 );
132 }
133
134 #[test]
135 fn test_wvtt_encode() {
136 let wvtt = Wvtt {
137 plaintext: PlainText {
138 data_reference_index: 1,
139 },
140 config: VttC {
141 config: "WEBVTT\nSome dummy header information\n".into(),
142 },
143 label: None,
144 btrt: None,
145 };
146
147 let mut buf = Vec::new();
148 wvtt.encode(&mut buf).unwrap();
149
150 assert_eq!(buf.as_slice(), ENCODED_WVTT);
151 }
152
153 #[test]
154 fn test_round_trip_with_label() {
155 let wvtt = Wvtt {
156 plaintext: PlainText {
157 data_reference_index: 1,
158 },
159 config: VttC {
160 config: "WEBVTT\nSome dummy header information\n".into(),
161 },
162 label: Some(Vlab {
163 source_label: "uri://dummy/label".into(),
164 }),
165 btrt: Some(Btrt {
166 buffer_size_db: 1,
167 max_bitrate: 2000,
168 avg_bitrate: 400,
169 }),
170 };
171
172 let mut buf = Vec::new();
173 wvtt.encode(&mut buf).unwrap();
174 let decoded = Wvtt::decode(&mut buf.as_ref()).expect("failed to decode wvtt");
175
176 assert_eq!(decoded, wvtt,);
177 }
178}