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
74 Ok(Self {
75 plaintext,
76 config: vtcc.ok_or(Error::MissingBox(VttC::KIND))?,
77 label: vlab,
78 btrt,
79 })
80 }
81
82 fn encode_body<B: BufMut>(&self, buf: &mut B) -> Result<()> {
83 self.plaintext.encode(buf)?;
84 self.config.encode(buf)?;
85 self.label.encode(buf)?;
86 self.btrt.encode(buf)?;
87 Ok(())
88 }
89}
90
91fn decode_boxstring<B: Buf>(buf: &mut B) -> Result<String> {
92 let remaining_bytes = buf.remaining();
93 let body = &mut buf.slice(remaining_bytes);
94 let text = String::from_utf8(body.to_vec()).map_err(|_| Error::InvalidSize)?;
95 buf.advance(remaining_bytes);
96 Ok(text)
97}
98
99#[cfg(test)]
100mod tests {
101 use super::*;
102
103 const ENCODED_WVTT: &[u8] = &[
105 0x00, 0x00, 0x00, 0x3d, 0x77, 0x76, 0x74, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
106 0x01, 0x00, 0x00, 0x00, 0x2d, 0x76, 0x74, 0x74, 0x43, 0x57, 0x45, 0x42, 0x56, 0x54, 0x54,
107 0x0a, 0x53, 0x6f, 0x6d, 0x65, 0x20, 0x64, 0x75, 0x6d, 0x6d, 0x79, 0x20, 0x68, 0x65, 0x61,
108 0x64, 0x65, 0x72, 0x20, 0x69, 0x6e, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e,
109 0x0a,
110 ];
111
112 #[test]
113 fn test_wvtt_decode() {
114 let buf: &mut std::io::Cursor<&[u8]> = &mut std::io::Cursor::new(ENCODED_WVTT);
115
116 let wvtt = Wvtt::decode(buf).expect("failed to decode wvtt");
117
118 assert_eq!(
119 wvtt,
120 Wvtt {
121 plaintext: PlainText {
122 data_reference_index: 1
123 },
124 config: VttC {
125 config: "WEBVTT\nSome dummy header information\n".into()
126 },
127 label: None,
128 btrt: None,
129 }
130 );
131 }
132
133 #[test]
134 fn test_wvtt_encode() {
135 let wvtt = Wvtt {
136 plaintext: PlainText {
137 data_reference_index: 1,
138 },
139 config: VttC {
140 config: "WEBVTT\nSome dummy header information\n".into(),
141 },
142 label: None,
143 btrt: None,
144 };
145
146 let mut buf = Vec::new();
147 wvtt.encode(&mut buf).unwrap();
148
149 assert_eq!(buf.as_slice(), ENCODED_WVTT);
150 }
151
152 #[test]
153 fn test_round_trip_with_label() {
154 let wvtt = Wvtt {
155 plaintext: PlainText {
156 data_reference_index: 1,
157 },
158 config: VttC {
159 config: "WEBVTT\nSome dummy header information\n".into(),
160 },
161 label: Some(Vlab {
162 source_label: "uri://dummy/label".into(),
163 }),
164 btrt: Some(Btrt {
165 buffer_size_db: 1,
166 max_bitrate: 2000,
167 avg_bitrate: 400,
168 }),
169 };
170
171 let mut buf = Vec::new();
172 wvtt.encode(&mut buf).unwrap();
173 let decoded = Wvtt::decode(&mut buf.as_ref()).expect("failed to decode wvtt");
174
175 assert_eq!(decoded, wvtt,);
176 }
177}