ff_format/stream/
subtitle.rs1use std::time::Duration;
4
5use crate::codec::SubtitleCodec;
6
7#[derive(Debug, Clone)]
28pub struct SubtitleStreamInfo {
29 index: u32,
31 codec: SubtitleCodec,
33 codec_name: String,
35 language: Option<String>,
37 title: Option<String>,
39 duration: Option<Duration>,
41 forced: bool,
43}
44
45impl SubtitleStreamInfo {
46 #[must_use]
48 pub fn builder() -> SubtitleStreamInfoBuilder {
49 SubtitleStreamInfoBuilder::default()
50 }
51
52 #[must_use]
54 #[inline]
55 pub const fn index(&self) -> u32 {
56 self.index
57 }
58
59 #[must_use]
61 #[inline]
62 pub fn codec(&self) -> &SubtitleCodec {
63 &self.codec
64 }
65
66 #[must_use]
68 #[inline]
69 pub fn codec_name(&self) -> &str {
70 &self.codec_name
71 }
72
73 #[must_use]
75 #[inline]
76 pub fn language(&self) -> Option<&str> {
77 self.language.as_deref()
78 }
79
80 #[must_use]
82 #[inline]
83 pub fn title(&self) -> Option<&str> {
84 self.title.as_deref()
85 }
86
87 #[must_use]
89 #[inline]
90 pub const fn duration(&self) -> Option<Duration> {
91 self.duration
92 }
93
94 #[must_use]
96 #[inline]
97 pub const fn is_forced(&self) -> bool {
98 self.forced
99 }
100
101 #[must_use]
103 #[inline]
104 pub fn is_text_based(&self) -> bool {
105 self.codec.is_text_based()
106 }
107}
108
109#[derive(Debug, Clone)]
111pub struct SubtitleStreamInfoBuilder {
112 index: u32,
113 codec: SubtitleCodec,
114 codec_name: String,
115 language: Option<String>,
116 title: Option<String>,
117 duration: Option<Duration>,
118 forced: bool,
119}
120
121impl Default for SubtitleStreamInfoBuilder {
122 fn default() -> Self {
123 Self {
124 index: 0,
125 codec: SubtitleCodec::Other(String::new()),
126 codec_name: String::new(),
127 language: None,
128 title: None,
129 duration: None,
130 forced: false,
131 }
132 }
133}
134
135impl SubtitleStreamInfoBuilder {
136 #[must_use]
138 pub fn index(mut self, index: u32) -> Self {
139 self.index = index;
140 self
141 }
142
143 #[must_use]
145 pub fn codec(mut self, codec: SubtitleCodec) -> Self {
146 self.codec = codec;
147 self
148 }
149
150 #[must_use]
152 pub fn codec_name(mut self, name: impl Into<String>) -> Self {
153 self.codec_name = name.into();
154 self
155 }
156
157 #[must_use]
159 pub fn language(mut self, lang: impl Into<String>) -> Self {
160 self.language = Some(lang.into());
161 self
162 }
163
164 #[must_use]
166 pub fn title(mut self, title: impl Into<String>) -> Self {
167 self.title = Some(title.into());
168 self
169 }
170
171 #[must_use]
173 pub fn duration(mut self, duration: Duration) -> Self {
174 self.duration = Some(duration);
175 self
176 }
177
178 #[must_use]
180 pub fn forced(mut self, forced: bool) -> Self {
181 self.forced = forced;
182 self
183 }
184
185 #[must_use]
187 pub fn build(self) -> SubtitleStreamInfo {
188 SubtitleStreamInfo {
189 index: self.index,
190 codec: self.codec,
191 codec_name: self.codec_name,
192 language: self.language,
193 title: self.title,
194 duration: self.duration,
195 forced: self.forced,
196 }
197 }
198}
199
200#[cfg(test)]
201mod tests {
202 use super::*;
203
204 #[test]
205 fn builder_should_store_all_fields() {
206 let info = SubtitleStreamInfo::builder()
207 .index(2)
208 .codec(SubtitleCodec::Srt)
209 .codec_name("srt")
210 .language("eng")
211 .title("English")
212 .duration(Duration::from_secs(120))
213 .forced(true)
214 .build();
215
216 assert_eq!(info.index(), 2);
217 assert_eq!(info.codec(), &SubtitleCodec::Srt);
218 assert_eq!(info.codec_name(), "srt");
219 assert_eq!(info.language(), Some("eng"));
220 assert_eq!(info.title(), Some("English"));
221 assert_eq!(info.duration(), Some(Duration::from_secs(120)));
222 assert!(info.is_forced());
223 }
224
225 #[test]
226 fn is_forced_should_default_to_false() {
227 let info = SubtitleStreamInfo::builder()
228 .codec(SubtitleCodec::Ass)
229 .build();
230 assert!(!info.is_forced());
231 }
232
233 #[test]
234 fn is_text_based_should_delegate_to_codec() {
235 let text = SubtitleStreamInfo::builder()
236 .codec(SubtitleCodec::Srt)
237 .build();
238 assert!(text.is_text_based());
239
240 let bitmap = SubtitleStreamInfo::builder()
241 .codec(SubtitleCodec::Hdmv)
242 .build();
243 assert!(!bitmap.is_text_based());
244 }
245
246 #[test]
247 fn optional_fields_should_default_to_none() {
248 let info = SubtitleStreamInfo::builder().build();
249 assert!(info.language().is_none());
250 assert!(info.title().is_none());
251 assert!(info.duration().is_none());
252 }
253}