add Arxel Tribe video support
[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; "indeo5s", "Intel Indeo 5 Scalable", CODEC_CAP_SCALABLE),
169 desc!(video; "intel263", "Intel I263", CODEC_CAP_REORDER),
170 desc!(audio; "iac", "Intel Indeo audio"),
171 desc!(audio; "imc", "Intel Music Coder"),
172
173 desc!(video; "realvideo1", "Real Video 1"),
174 desc!(video; "realvideo2", "Real Video 2", CODEC_CAP_REORDER),
175 desc!(video; "realvideo3", "Real Video 3", CODEC_CAP_REORDER),
176 desc!(video; "realvideo4", "Real Video 4", CODEC_CAP_REORDER),
177 desc!(video; "realvideo6", "Real Video 6", CODEC_CAP_REORDER),
178 desc!(video; "clearvideo", "ClearVideo"),
179 desc!(video; "clearvideo_rm", "ClearVideo"),
180 desc!(audio; "ra14.4", "RealAudio 14.4"),
181 desc!(audio; "ra28.8", "RealAudio 28.8"),
182 desc!(audio; "cook", "RealAudio Cooker"),
183 desc!(audio; "ralf", "RealAudio Lossless"),
184 desc!(audio; "aac", "AAC"),
185 desc!(audio; "ac3", "ETSI TS 102 366"),
186 desc!(audio; "atrac3", "Sony Atrac3"),
187 desc!(audio; "sipro", "Sipro Labs ADPCM"),
188
189
190 desc!(video-ll; "rawvideo", "Raw video data"),
191 desc!(video-ll; "rawvideo-ms", "Raw video data"),
192
193 desc!(video; "cinepak", "Cinepak"),
194
195 desc!(video-llp; "zmbv", "Zip Motion Blocks Video"),
196
197 desc!(video; "msvideo1", "MS Video 1"),
198 desc!(video; "msrle", "MS RLE"),
199 desc!(audio; "ms-adpcm", "MS ADPCM"),
200 desc!(audio; "ima-adpcm-ms", "IMA ADPCM (MS variant)"),
201
202 desc!(video; "qt-smc", "Apple Graphics"),
203 desc!(video; "qt-rle", "Apple Animation"),
204 desc!(video; "apple-video", "Apple video"),
205 desc!(video; "sorenson-video", "Sorenson Video"),
206 desc!(video; "sorenson-video3", "Sorenson Video 3", CODEC_CAP_REORDER),
207 desc!(audio-ll; "alac", "Apple Lossless Audio Codec"),
208 desc!(audio; "mace-3", "MACE 3:1"),
209 desc!(audio; "mace-6", "MACE 6:1"),
210 desc!(audio; "ima-adpcm-qt", "IMA ADPCM (Apple variant)"),
211 desc!(audio; "qdesign-music", "QDesign Music"),
212 desc!(audio; "qdesign-music2", "QDesign Music v2"),
213 desc!(audio; "qualcomm-purevoice", "Qualcomm PureVoice"),
214
215 desc!(video; "truemotion1", "TrueMotion 1"),
216 desc!(video-im; "truemotionrt", "TrueMotion RT"),
217 desc!(video; "truemotion2", "TrueMotion 2"),
218 desc!(video; "truemotion2x", "TrueMotion 2X"),
219 desc!(video; "vp3", "VP3"),
220 desc!(video; "vp4", "VP4"),
221 desc!(video; "vp5", "VP5"),
222 desc!(video; "vp6", "VP6"),
223 desc!(video; "vp6f", "VP6 (in Flash)"),
224 desc!(video; "vp6a", "VP6 with alpha"),
225 desc!(video; "vp7", "VP7"),
226 desc!(video; "vp8", "VP8"),
227 desc!(video; "vp9", "VP9"),
228 desc!(audio; "adpcm-dk3", "Duck DK3 ADPCM"),
229 desc!(audio; "adpcm-dk4", "Duck DK4 ADPCM"),
230 desc!(audio; "on2avc-500", "On2 AVC"),
231 desc!(audio; "on2avc-501", "On2 AVC"),
232
233 desc!(video; "flv263", "Sorenson H.263"),
234 desc!(video-llp; "flashsv", "Flash Screen Video"),
235 desc!(video-llp; "flashsv2", "Flash Screen Video 2"),
236 desc!(audio; "asao", "N*llym*s*r ASAO"),
237 desc!(audio; "flv-adpcm", "Flash ADPCM"),
238
239 desc!(audio; "mp1", "MPEG Audio Layer I"),
240 desc!(audio; "mp2", "MPEG Audio Layer II"),
241 desc!(audio; "mp3", "MPEG Audio Layer III"),
242 desc!(audio; "speex", "Speex"),
243
244 desc!(video; "gdv-video", "Gremlin Digital Video - video"),
245 desc!(audio; "gdv-audio", "Gremlin Digital Video - audio"),
246 desc!(video-im; "arxel-video", "Arxel Tribe Video"),
247 desc!(video; "beam-fcp", "Beam Software Animation"),
248 desc!(video; "beam-video", "Beam Software Video"),
249 desc!(video; "bmv-video", "BMV video"),
250 desc!(audio; "bmv-audio", "BMV audio"),
251 desc!(video; "bmv3-video", "DW Noir BMV video"),
252 desc!(audio; "bmv3-audio", "DW Noir BMV audio"),
253 desc!(video; "fable-imax", "Fable IMAX video"),
254 desc!(video; "fst-video", "FutureVision video"),
255 desc!(audio; "fst-audio", "FutureVision audio"),
256 desc!(video; "hl-fmv-video", "Highlander FMV video"),
257 desc!(video-llp; "ipma", "Imagination Pilots Matte Animation"),
258 desc!(video-llp; "ipma2", "Imagination Pilots Matte Animation v2"),
259 desc!(video; "legend-q-video", "Legend Entertainment Q video"),
260 desc!(video; "midivid", "MidiVid"),
261 desc!(video; "midivid3", "MidiVid 3"),
262 desc!(video-ll; "midivid-ll", "MidiVid Lossless"),
263 desc!(video; "smushv1", "SMUSH Video paletted"),
264 desc!(video; "smushv2", "SMUSH Video 16-bit"),
265 desc!(video; "smush-iact", "SMUSH IACT Audio"),
266 desc!(video; "smush-vima", "SMUSH VIMA Audio"),
267 desc!(video; "vmd-video", "VMD video"),
268 desc!(audio; "vmd-audio", "VMD audio"),
269 desc!(video; "vxvideo", "Actimagine Vx"),
270 desc!(audio; "vxaudio", "Actimagine Sx"),
271
272 desc!(video; "smacker-video", "Smacker video"),
273 desc!(audio; "smacker-audio", "Smacker audio"),
274 desc!(video; "bink-video", "Bink video"),
275 desc!(video; "bink2-video", "Bink2 video"),
276 desc!(audio; "bink-audio-dct", "Bink audio (DCT)"),
277 desc!(audio; "bink-audio-rdft", "Bink audio (RDFT)"),
278
279 desc!(audio; "lhst15f8", "L&H StreamTalk 15kbps at 8 kHz"),
280 desc!(audio; "lhst250f11", "L&H StreamTalk 25kbps at 11 kHz"),
281 desc!(audio; "lhst500f22", "L&H StreamTalk 50kpbs at 22 kHz"),
282 desc!(audio; "lhst48", "L&H StreamTalk CELP Codec 4.8kbps at 8 kHz"),
283
284 desc!(video; "vivo1", "VivoActive Video 1.0"),
285 desc!(video; "vivo2", "VivoActive Video 2.0", CODEC_CAP_REORDER),
286 desc!(audio; "g723.1", "ITU G.723.1"),
287 desc!(audio; "siren", "Polycom Siren"),
288
289 desc!(audio-ll; "ape", "Monkey's Audio"),
290 desc!(audio-ll; "flac", "Free Lossless Audio Codec"),
291 desc!(audio-ll; "tta", "True Audio codec"),
292 desc!(audio-hyb; "wavpack", "WavPack"),
293
294 desc!(video-im; "jpeg", "JPEG"),
295 desc!(video; "h264", "ITU H.264", CODEC_CAP_COMPLEX_REORDER | CODEC_CAP_HYBRID),
296
297 desc!(video-im; "mwv1", "Aware MotionWavelets"),
298 ];
299
300 static AVI_VIDEO_CODEC_REGISTER: &[(&[u8;4], &str)] = &[
301 (&[1, 0, 0, 0], "msrle"),
302 (&[2, 0, 0, 0], "msrle"),
303
304 (b"CRAM", "msvideo1"),
305 (b"MSVC", "msvideo1"),
306 (b"WHAM", "msvideo1"),
307
308 (b"MJPG", "jpeg"),
309
310 (b"IF09", "indeo1"),
311 (b"RT21", "indeo2"),
312 (b"IV31", "indeo3"),
313 (b"IV32", "indeo3"),
314 (b"IV41", "indeo4"),
315 (b"IV50", "indeo5"),
316 (b"I263", "intel263"),
317
318 (b"UCOD", "clearvideo"),
319 (b"cvid", "cinepak"),
320 (b"ZMBV", "zmbv"),
321
322 (b"Ipma", "ipma"),
323 (b"Ip20", "ipma2"),
324
325 (b"MVDV", "midivid"),
326 (b"MV30", "midivid3"),
327 (b"MVLZ", "midivid-ll"),
328
329 (b"DUCK", "truemotion1"),
330 (b"TR20", "truemotionrt"),
331 (b"TM20", "truemotion2"),
332 (b"TM2A", "truemotion2x"),
333 (b"TM2X", "truemotion2x"),
334 (b"VP30", "vp3"),
335 (b"VP31", "vp3"),
336 (b"VP40", "vp4"),
337 (b"VP50", "vp5"),
338 (b"VP60", "vp6"),
339 (b"VP61", "vp6"),
340 (b"VP62", "vp6"),
341 (b"VP6A", "vp6a"),
342 (b"VP70", "vp7"),
343
344 (b"MWV1", "mwv1"),
345 ];
346
347 static WAV_CODEC_REGISTER: &[(u16, &str)] = &[
348 (0x0000, "unknown"),
349 (0x0001, "pcm"),
350 (0x0002, "ms-adpcm"),
351 (0x0003, "pcm"),
352 (0x0011, "ima-adpcm-ms"),
353 (0x0061, "adpcm-dk4"),
354 (0x0062, "adpcm-dk3"),
355 (0x0401, "imc"),
356 (0x0402, "iac"),
357 (0x0500, "on2avc-500"),
358 (0x0501, "on2avc-501"),
359 ];
360
361 static MOV_VIDEO_CODEC_REGISTER: &[(&[u8;4], &str)] = &[
362 (b"cvid", "cinepak"),
363 (b"jpeg", "jpeg"),
364 //(b"raw ", "raw"),
365 //(b"Yuv2", "raw"),
366 (b"smc ", "qt-smc"),
367 (b"rle ", "qt-rle"),
368 (b"rpza", "apple-video"),
369 (b"kpcd", "kodak-photocd"),
370 //(b"mpeg", "mpeg-video"),
371 (b"mjpa", "mjpeg-a"),
372 (b"mjpb", "mjpeg-b"),
373 (b"svqi", "sorenson-video"),
374 (b"SVQ1", "sorenson-video"),
375 (b"svq3", "sorenson-video3"),
376 (b"SVQ3", "sorenson-video3"),
377
378 (b"IV31", "indeo3"),
379 (b"IV32", "indeo3"),
380
381 (b"UCOD", "clearvideo"),
382
383 (b"VP30", "vp3"),
384 (b"VP31", "vp3"),
385
386 (b"avc1", "h264"),
387 ];
388
389 static MOV_AUDIO_CODEC_REGISTER: &[(&[u8;4], &str)] = &[
390 (b"NONE", "pcm"),
391 (b"raw ", "pcm"),
392 (b"twos", "pcm"),
393 (b"sowt", "pcm"),
394 (b"fl32", "pcm"),
395 (b"fl64", "pcm"),
396 (b"in24", "pcm"),
397 (b"in32", "pcm"),
398 (b"MAC3", "mace-3"),
399 (b"MAC6", "mace-6"),
400 (b"ima4", "ima-adpcm-qt"),
401 (b"ulaw", "ulaw"),
402 (b"alaw", "alaw"),
403 (b"dvca", "dv-audio"),
404 (b"QDMC", "qdesign-music"),
405 (b"QDM2", "qdesign-music2"),
406 (b"Qclp", "qualcomm-purevoice"),
407 //(b".mp3", "mpeg-layer3"),
408
409 (b"mp4a", "aac"),
410
411 (b"alac", "alac"),
412 ];
413
414 /// Returns video codec short name for provided FOURCC (used in AVI format).
415 pub fn find_codec_from_avi_fourcc(fcc: &[u8;4]) -> Option<&'static str> {
416 for (fourcc, name) in AVI_VIDEO_CODEC_REGISTER.iter() {
417 if *fourcc == fcc { return Some(name); }
418 }
419 None
420 }
421
422 /// Returns FOURCC (used in AVI format) for provided codec name.
423 pub fn find_avi_fourcc(codecname: &str) -> Option<[u8; 4]> {
424 for (fourcc, name) in AVI_VIDEO_CODEC_REGISTER.iter() {
425 if *name == codecname { return Some(**fourcc); }
426 }
427 None
428 }
429
430 /// Returns known audio codec short name for provided TWOCC (used in WAV and AVI format).
431 pub fn find_codec_from_wav_twocc(tcc: u16) -> Option<&'static str> {
432 for (twocc, name) in WAV_CODEC_REGISTER.iter() {
433 if *twocc == tcc { return Some(name); }
434 }
435 None
436 }
437
438 /// Returns TWOCC (used in WAV and AVI format for provided codec name.
439 pub fn find_wav_twocc(codecname: &str) -> Option<u16> {
440 for (twocc, name) in WAV_CODEC_REGISTER.iter() {
441 if *name == codecname { return Some(*twocc); }
442 }
443 None
444 }
445
446 /// Returns video codec short name for provided FOURCC (used in MOV format).
447 pub fn find_codec_from_mov_video_fourcc(fcc: &[u8;4]) -> Option<&'static str> {
448 for (fourcc, name) in MOV_VIDEO_CODEC_REGISTER.iter() {
449 if *fourcc == fcc { return Some(name); }
450 }
451 None
452 }
453
454 /// Returns known audio codec short name for provided FOURCC (used in MOV format).
455 pub fn find_codec_from_mov_audio_fourcc(fcc: &[u8;4]) -> Option<&'static str> {
456 for (fourcc, name) in MOV_AUDIO_CODEC_REGISTER.iter() {
457 if *fourcc == fcc { return Some(name); }
458 }
459 None
460 }
461
462 #[cfg(test)]
463 mod test {
464 use super::*;
465
466 #[test]
467 fn test_register() {
468 let c1 = find_codec_from_avi_fourcc(b"IV41").unwrap();
469 let c2 = find_codec_from_wav_twocc(0x401).unwrap();
470 println!("found {} and {}", c1, c2);
471 let cd1 = get_codec_description(c1).unwrap();
472 let cd2 = get_codec_description(c2).unwrap();
473 println!("got {} and {}", cd1, cd2);
474 }
475 }