fix clippy warnings for update to rustc 1.46
[nihav.git] / nihav-registry / src / register.rs
1 //! Global registry of codec information.
2 //!
3 //! This module contains codec information from technical level that allows user to retrieve information about codec type and features without creating and invoking a decoder for such codec.
4 use std::fmt;
5
6 /// Codec types.
7 #[derive(Debug,Clone,Copy,PartialEq)]
8 #[allow(dead_code)]
9 pub enum CodecType {
10 /// Video codec.
11 Video,
12 /// Audio codec.
13 Audio,
14 /// Subtitle codec.
15 Subtitles,
16 /// Some special codec (e.g. some event stream or separate timecodes stream).
17 Data,
18 /// Dummy codec.
19 None,
20 }
21
22 impl fmt::Display for CodecType {
23 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
24 match *self {
25 CodecType::Video => write!(f, "Video"),
26 CodecType::Audio => write!(f, "Audio"),
27 CodecType::Subtitles => write!(f, "Subtitles"),
28 CodecType::Data => write!(f, "Data"),
29 CodecType::None => write!(f, "-"),
30 }
31 }
32 }
33
34 /// Codec capability flag for intra-only codecs.
35 pub const CODEC_CAP_INTRAONLY:u32 = 0x0001;
36 /// Codec capability flag for lossless codecs.
37 pub const CODEC_CAP_LOSSLESS:u32 = 0x0002;
38 /// Codec capability flag for codecs with frame reordering.
39 pub const CODEC_CAP_REORDER:u32 = 0x0004;
40 /// Codec capability flag for codecs that can be both lossy and lossless.
41 pub const CODEC_CAP_HYBRID:u32 = 0x0008;
42 /// Codec capability flag for codecs with scalability features.
43 pub const CODEC_CAP_SCALABLE:u32 = 0x0010;
44 /// Codec capability flag for codecs with complex frame reordering.
45 pub const CODEC_CAP_COMPLEX_REORDER:u32 = 0x0020;
46
47 /// Codec description structure.
48 #[derive(Clone)]
49 pub struct CodecDescription {
50 /// Short codec name.
51 ///
52 /// Short codec name is used inside NihAV as the unique identifier.
53 pub name: &'static str,
54 /// Full codec name.
55 pub fname: &'static str,
56 /// Codec type.
57 pub ctype: CodecType,
58 /// Codec capabilities.
59 pub caps: u32,
60 }
61
62 impl CodecDescription {
63 /// Returns short codec name.
64 pub fn get_name(&self) -> &'static str { self.name }
65 /// Returns full codec name.
66 pub fn get_full_name(&self) -> &'static str { self.fname }
67 /// Returns codec type.
68 pub fn get_codec_type(&self) -> CodecType { self.ctype }
69 /// Reports whether the codec has only intra frames or not.
70 pub fn is_intraonly(&self) -> bool { (self.caps & CODEC_CAP_INTRAONLY) != 0 }
71 /// Reports whether the codec is lossless.
72 pub fn is_lossless(&self) -> bool { (self.caps & CODEC_CAP_LOSSLESS) != 0 }
73 /// Reports whether the codec requires frame reordering.
74 pub fn has_reorder(&self) -> bool { (self.caps & CODEC_CAP_REORDER) != 0 }
75 /// Reports whether the codec can be either lossless or lossy.
76 pub fn is_hybrid(&self) -> bool { (self.caps & CODEC_CAP_HYBRID) != 0 }
77 /// Reports whether codec supports scalability.
78 ///
79 /// Scalability means that codec can be decoded in reduced resolution by design.
80 pub fn is_scalable(&self) -> bool { (self.caps & CODEC_CAP_SCALABLE) != 0 }
81 }
82
83 impl fmt::Display for CodecDescription {
84 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
85 let mut out = self.fname.to_string();
86 if self.caps != 0 {
87 let mut capfmt = "".to_string();
88 if (self.caps & CODEC_CAP_INTRAONLY) != 0 {
89 capfmt = format!("{} Intra-only", capfmt);
90 }
91 if (self.caps & CODEC_CAP_LOSSLESS) != 0 {
92 capfmt = format!("{} Lossless", capfmt);
93 }
94 if (self.caps & CODEC_CAP_REORDER) != 0 {
95 capfmt = format!("{} Frame reorder", capfmt);
96 }
97 if (self.caps & CODEC_CAP_HYBRID) != 0 {
98 capfmt = format!("{} Can be lossy and lossless", capfmt);
99 }
100 if (self.caps & CODEC_CAP_SCALABLE) != 0 {
101 capfmt = format!("{} Scalable", capfmt);
102 }
103 out = format!("{} ({})", out, capfmt);
104 }
105 write!(f, "{}", out)
106 }
107 }
108
109 macro_rules! desc {
110 (video; $n:expr, $fn:expr) => ({
111 CodecDescription{ name: $n, fname: $fn, ctype: CodecType::Video,
112 caps: 0 }
113 });
114 (video; $n:expr, $fn:expr, $c:expr) => ({
115 CodecDescription{ name: $n, fname: $fn, ctype: CodecType::Video,
116 caps: $c }
117 });
118 (video-ll; $n:expr, $fn:expr) => ({
119 CodecDescription{ name: $n, fname: $fn, ctype: CodecType::Video,
120 caps: CODEC_CAP_LOSSLESS | CODEC_CAP_INTRAONLY }
121 });
122 (video-llp; $n:expr, $fn:expr) => ({
123 CodecDescription{ name: $n, fname: $fn, ctype: CodecType::Video,
124 caps: CODEC_CAP_LOSSLESS }
125 });
126 (video-im; $n:expr, $fn:expr) => ({
127 CodecDescription{ name: $n, fname: $fn, ctype: CodecType::Video,
128 caps: CODEC_CAP_INTRAONLY }
129 });
130 (video-modern; $n:expr, $fn:expr) => ({
131 CodecDescription{ name: $n, fname: $fn, ctype: CodecType::Video,
132 caps: CODEC_CAP_REORDER | CODEC_CAP_HYBRID }
133 });
134 (audio; $n:expr, $fn:expr) => ({
135 CodecDescription{ name: $n, fname: $fn, ctype: CodecType::Audio,
136 caps: 0 }
137 });
138 (audio-ll; $n:expr, $fn:expr) => ({
139 CodecDescription{ name: $n, fname: $fn, ctype: CodecType::Audio,
140 caps: CODEC_CAP_LOSSLESS | CODEC_CAP_INTRAONLY }
141 });
142 (audio-hyb; $n:expr, $fn:expr) => ({
143 CodecDescription{ name: $n, fname: $fn, ctype: CodecType::Audio,
144 caps: CODEC_CAP_HYBRID }
145 });
146 }
147
148 /// Returns codec description for the provided codec short name if it is found.
149 pub fn get_codec_description(name: &str) -> Option<&'static CodecDescription> {
150 for reg in CODEC_REGISTER {
151 if reg.name == name {
152 return Some(reg);
153 }
154 }
155 None
156 }
157
158 static CODEC_REGISTER: &[CodecDescription] = &[
159 desc!(audio-ll; "pcm", "PCM"),
160 desc!(audio; "alaw", "A-law PCM"),
161 desc!(audio; "ulaw", "mu-law PCM"),
162
163 desc!(video-im; "indeo1", "Intel Raw IF09"),
164 desc!(video-im; "indeo2", "Intel Indeo 2"),
165 desc!(video; "indeo3", "Intel Indeo 3"),
166 desc!(video; "indeo4", "Intel Indeo 4", CODEC_CAP_REORDER | CODEC_CAP_SCALABLE),
167 desc!(video; "indeo5", "Intel Indeo 5", CODEC_CAP_REORDER | CODEC_CAP_SCALABLE),
168 desc!(video; "intel263", "Intel I263", CODEC_CAP_REORDER),
169 desc!(audio; "iac", "Intel Indeo audio"),
170 desc!(audio; "imc", "Intel Music Coder"),
171
172 desc!(video; "realvideo1", "Real Video 1"),
173 desc!(video; "realvideo2", "Real Video 2", CODEC_CAP_REORDER),
174 desc!(video; "realvideo3", "Real Video 3", CODEC_CAP_REORDER),
175 desc!(video; "realvideo4", "Real Video 4", CODEC_CAP_REORDER),
176 desc!(video; "realvideo6", "Real Video 6", CODEC_CAP_REORDER),
177 desc!(video; "clearvideo", "ClearVideo"),
178 desc!(video; "clearvideo_rm", "ClearVideo"),
179 desc!(audio; "ra14.4", "RealAudio 14.4"),
180 desc!(audio; "ra28.8", "RealAudio 28.8"),
181 desc!(audio; "cook", "RealAudio Cooker"),
182 desc!(audio; "ralf", "RealAudio Lossless"),
183 desc!(audio; "aac", "AAC"),
184 desc!(audio; "ac3", "ETSI TS 102 366"),
185 desc!(audio; "atrac3", "Sony Atrac3"),
186 desc!(audio; "sipro", "Sipro Labs ADPCM"),
187
188 desc!(video; "cinepak", "Cinepak"),
189
190 desc!(video; "msvideo1", "MS Video 1"),
191 desc!(video; "msrle", "MS RLE"),
192 desc!(audio; "ms-adpcm", "MS ADPCM"),
193 desc!(audio; "ima-adpcm-ms", "IMA ADPCM (MS variant)"),
194
195 desc!(video; "qt-smc", "Apple Graphics"),
196 desc!(video; "qt-rle", "Apple Animation"),
197 desc!(video; "apple-video", "Apple video"),
198 desc!(video; "sorenson-video", "Sorenson Video"),
199 desc!(video; "sorenson-video3", "Sorenson Video 3", CODEC_CAP_REORDER),
200 desc!(audio; "mace-3", "MACE 3:1"),
201 desc!(audio; "mace-6", "MACE 6:1"),
202 desc!(audio; "ima-adpcm-qt", "IMA ADPCM (Apple variant)"),
203 desc!(audio; "qdesign-music", "QDesign Music"),
204 desc!(audio; "qdesign-music2", "QDesign Music v2"),
205 desc!(audio; "qualcomm-purevoice", "Qualcomm PureVoice"),
206
207 desc!(video; "truemotion1", "TrueMotion 1"),
208 desc!(video-im; "truemotionrt", "TrueMotion RT"),
209 desc!(video; "truemotion2", "TrueMotion 2"),
210 desc!(video; "truemotion2x", "TrueMotion 2X"),
211 desc!(video; "vp3", "VP3"),
212 desc!(video; "vp4", "VP4"),
213 desc!(video; "vp5", "VP5"),
214 desc!(video; "vp6", "VP6"),
215 desc!(video; "vp6a", "VP6"),
216 desc!(video; "vp7", "VP7"),
217 desc!(video; "vp8", "VP8"),
218 desc!(video; "vp9", "VP9"),
219 desc!(audio; "adpcm-dk3", "Duck DK3 ADPCM"),
220 desc!(audio; "adpcm-dk4", "Duck DK4 ADPCM"),
221 desc!(audio; "on2avc-500", "On2 AVC"),
222 desc!(audio; "on2avc-501", "On2 AVC"),
223
224 desc!(video; "gdv-video", "Gremlin Digital Video - video"),
225 desc!(audio; "gdv-audio", "Gremlin Digital Video - audio"),
226 desc!(video; "bmv-video", "BMV video"),
227 desc!(audio; "bmv-audio", "BMV audio"),
228 desc!(video; "bmv3-video", "DW Noir BMV video"),
229 desc!(audio; "bmv3-audio", "DW Noir BMV audio"),
230 desc!(video; "fable-imax", "Fable IMAX video"),
231 desc!(video; "fst-video", "FutureVision video"),
232 desc!(audio; "fst-audio", "FutureVision audio"),
233 desc!(video; "midivid", "MidiVid"),
234 desc!(video; "midivid3", "MidiVid 3"),
235 desc!(video-ll; "midivid-ll", "MidiVid Lossless"),
236 desc!(video; "vmd-video", "VMD video"),
237 desc!(audio; "vmd-audio", "VMD audio"),
238 desc!(video; "vxvideo", "Actimagine Vx"),
239 desc!(audio; "vxaudio", "Actimagine Sx"),
240
241 desc!(video; "smacker-video", "Smacker video"),
242 desc!(audio; "smacker-audio", "Smacker audio"),
243 desc!(video; "bink-video", "Bink video"),
244 desc!(video; "bink2-video", "Bink2 video"),
245 desc!(audio; "bink-audio-dct", "Bink audio (DCT)"),
246 desc!(audio; "bink-audio-rdft", "Bink audio (RDFT)"),
247
248 desc!(audio; "lhst15f8", "L&H StreamTalk 15kbps at 8 kHz"),
249 desc!(audio; "lhst250f11", "L&H StreamTalk 25kbps at 11 kHz"),
250 desc!(audio; "lhst500f22", "L&H StreamTalk 50kpbs at 22 kHz"),
251 desc!(audio; "lhst48", "L&H StreamTalk CELP Codec 4.8kbps at 8 kHz"),
252
253 desc!(video; "vivo1", "VivoActive Video 1.0"),
254 desc!(video; "vivo2", "VivoActive Video 2.0", CODEC_CAP_REORDER),
255 desc!(audio; "g723.1", "ITU G.723.1"),
256 desc!(audio; "siren", "Polycom Siren"),
257
258 desc!(audio-ll; "ape", "Monkey's Audio"),
259 desc!(audio-ll; "flac", "Free Lossless Audio Codec"),
260 desc!(audio-ll; "tta", "True Audio codec"),
261 desc!(audio-hyb; "wavpack", "WavPack"),
262
263 desc!(video; "h264", "ITU H.264", CODEC_CAP_COMPLEX_REORDER | CODEC_CAP_HYBRID),
264 ];
265
266 static AVI_VIDEO_CODEC_REGISTER: &[(&[u8;4], &str)] = &[
267 (&[1, 0, 0, 0], "msrle"),
268 (&[2, 0, 0, 0], "msrle"),
269
270 (b"CRAM", "msvideo1"),
271 (b"MSVC", "msvideo1"),
272 (b"WHAM", "msvideo1"),
273
274 (b"IF09", "indeo1"),
275 (b"RT21", "indeo2"),
276 (b"IV31", "indeo3"),
277 (b"IV32", "indeo3"),
278 (b"IV41", "indeo4"),
279 (b"IV50", "indeo5"),
280 (b"I263", "intel263"),
281
282 (b"UCOD", "clearvideo"),
283 (b"cvid", "cinepak"),
284
285 (b"MVDV", "midivid"),
286 (b"MV30", "midivid3"),
287 (b"MVLZ", "midivid-ll"),
288
289 (b"DUCK", "truemotion1"),
290 (b"TR20", "truemotionrt"),
291 (b"TM20", "truemotion2"),
292 (b"TM2A", "truemotion2x"),
293 (b"TM2X", "truemotion2x"),
294 (b"VP30", "vp3"),
295 (b"VP31", "vp3"),
296 (b"VP40", "vp4"),
297 (b"VP50", "vp5"),
298 (b"VP60", "vp6"),
299 (b"VP61", "vp6"),
300 (b"VP62", "vp6"),
301 (b"VP6A", "vp6a"),
302 (b"VP70", "vp7"),
303 ];
304
305 static WAV_CODEC_REGISTER: &[(u16, &str)] = &[
306 (0x0000, "unknown"),
307 (0x0001, "pcm"),
308 (0x0002, "ms-adpcm"),
309 (0x0003, "pcm"),
310 (0x0011, "ima-adpcm-ms"),
311 (0x0061, "adpcm-dk4"),
312 (0x0062, "adpcm-dk3"),
313 (0x0401, "imc"),
314 (0x0402, "iac"),
315 (0x0500, "on2avc-500"),
316 (0x0501, "on2avc-501"),
317 ];
318
319 static MOV_VIDEO_CODEC_REGISTER: &[(&[u8;4], &str)] = &[
320 (b"cvid", "cinepak"),
321 (b"jpeg", "jpeg"),
322 //(b"raw ", "raw"),
323 //(b"Yuv2", "raw"),
324 (b"smc ", "qt-smc"),
325 (b"rle ", "qt-rle"),
326 (b"rpza", "apple-video"),
327 (b"kpcd", "kodak-photocd"),
328 //(b"mpeg", "mpeg-video"),
329 (b"mjpa", "mjpeg-a"),
330 (b"mjpb", "mjpeg-b"),
331 (b"svqi", "sorenson-video"),
332 (b"SVQ1", "sorenson-video"),
333 (b"svq3", "sorenson-video3"),
334 (b"SVQ3", "sorenson-video3"),
335
336 (b"IV31", "indeo3"),
337 (b"IV32", "indeo3"),
338
339 (b"UCOD", "clearvideo"),
340
341 (b"VP30", "vp3"),
342 (b"VP31", "vp3"),
343
344 (b"avc1", "h264"),
345 ];
346
347 static MOV_AUDIO_CODEC_REGISTER: &[(&[u8;4], &str)] = &[
348 (b"NONE", "pcm"),
349 (b"raw ", "pcm"),
350 (b"twos", "pcm"),
351 (b"sowt", "pcm"),
352 (b"fl32", "pcm"),
353 (b"fl64", "pcm"),
354 (b"in24", "pcm"),
355 (b"in32", "pcm"),
356 (b"MAC3", "mace-3"),
357 (b"MAC6", "mace-6"),
358 (b"ima4", "ima-adpcm-qt"),
359 (b"ulaw", "ulaw"),
360 (b"alaw", "alaw"),
361 (b"dvca", "dv-audio"),
362 (b"QDMC", "qdesign-music"),
363 (b"QDM2", "qdesign-music2"),
364 (b"Qclp", "qualcomm-purevoice"),
365 //(b".mp3", "mpeg-layer3"),
366
367 (b"mp4a", "aac"),
368 ];
369
370 /// Returns video codec short name for provided FOURCC (used in AVI format).
371 pub fn find_codec_from_avi_fourcc(fcc: &[u8;4]) -> Option<&'static str> {
372 for (fourcc, name) in AVI_VIDEO_CODEC_REGISTER.iter() {
373 if *fourcc == fcc { return Some(name); }
374 }
375 None
376 }
377
378 /// Returns FOURCC (used in AVI format) for provided codec name.
379 pub fn find_avi_fourcc(codecname: &str) -> Option<[u8; 4]> {
380 for (fourcc, name) in AVI_VIDEO_CODEC_REGISTER.iter() {
381 if *name == codecname { return Some(**fourcc); }
382 }
383 None
384 }
385
386 /// Returns known audio codec short name for provided TWOCC (used in WAV and AVI format).
387 pub fn find_codec_from_wav_twocc(tcc: u16) -> Option<&'static str> {
388 for (twocc, name) in WAV_CODEC_REGISTER.iter() {
389 if *twocc == tcc { return Some(name); }
390 }
391 None
392 }
393
394 /// Returns TWOCC (used in WAV and AVI format for provided codec name.
395 pub fn find_wav_twocc(codecname: &str) -> Option<u16> {
396 for (twocc, name) in WAV_CODEC_REGISTER.iter() {
397 if *name == codecname { return Some(*twocc); }
398 }
399 None
400 }
401
402 /// Returns video codec short name for provided FOURCC (used in MOV format).
403 pub fn find_codec_from_mov_video_fourcc(fcc: &[u8;4]) -> Option<&'static str> {
404 for (fourcc, name) in MOV_VIDEO_CODEC_REGISTER.iter() {
405 if *fourcc == fcc { return Some(name); }
406 }
407 None
408 }
409
410 /// Returns known audio codec short name for provided FOURCC (used in MOV format).
411 pub fn find_codec_from_mov_audio_fourcc(fcc: &[u8;4]) -> Option<&'static str> {
412 for (fourcc, name) in MOV_AUDIO_CODEC_REGISTER.iter() {
413 if *fourcc == fcc { return Some(name); }
414 }
415 None
416 }
417
418 #[cfg(test)]
419 mod test {
420 use super::*;
421
422 #[test]
423 fn test_register() {
424 let c1 = find_codec_from_avi_fourcc(b"IV41").unwrap();
425 let c2 = find_codec_from_wav_twocc(0x401).unwrap();
426 println!("found {} and {}", c1, c2);
427 let cd1 = get_codec_description(c1).unwrap();
428 let cd2 = get_codec_description(c2).unwrap();
429 println!("got {} and {}", cd1, cd2);
430 }
431 }