]> git.nihav.org Git - nihav.git/blame_incremental - nihav-registry/src/register.rs
smacker: fix version 4 support
[nihav.git] / nihav-registry / src / register.rs
... / ...
CommitLineData
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.
4use std::fmt;
5
6/// Codec types.
7#[derive(Debug,Clone,Copy,PartialEq)]
8#[allow(dead_code)]
9pub 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
22impl 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.
35pub const CODEC_CAP_INTRAONLY:u32 = 0x0001;
36/// Codec capability flag for lossless codecs.
37pub const CODEC_CAP_LOSSLESS:u32 = 0x0002;
38/// Codec capability flag for codecs with frame reordering.
39pub const CODEC_CAP_REORDER:u32 = 0x0004;
40/// Codec capability flag for codecs that can be both lossy and lossless.
41pub const CODEC_CAP_HYBRID:u32 = 0x0008;
42/// Codec capability flag for codecs with scalability features.
43pub const CODEC_CAP_SCALABLE:u32 = 0x0010;
44/// Codec capability flag for codecs with complex frame reordering.
45pub const CODEC_CAP_COMPLEX_REORDER:u32 = 0x0020;
46
47/// Codec description structure.
48#[derive(Clone)]
49pub 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
62impl 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
83impl 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
109macro_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.
149pub fn get_codec_description(name: &str) -> Option<&'static CodecDescription> {
150 CODEC_REGISTER.iter().find(|&reg| reg.name == name)
151}
152
153static CODEC_REGISTER: &[CodecDescription] = &[
154 desc!(audio-ll; "pcm", "PCM"),
155 desc!(audio; "alaw", "A-law PCM"),
156 desc!(audio; "ulaw", "mu-law PCM"),
157
158 desc!(video-im; "indeo1", "Intel Raw IF09"),
159 desc!(video; "indeo2", "Intel Indeo 2"),
160 desc!(video; "ima-rtv2", "Intel RTV 2 (Indeo 2)"),
161 desc!(video; "indeo3", "Intel Indeo 3"),
162 desc!(video; "indeo4", "Intel Indeo 4", CODEC_CAP_REORDER | CODEC_CAP_SCALABLE),
163 desc!(video; "indeo5", "Intel Indeo 5", CODEC_CAP_REORDER | CODEC_CAP_SCALABLE),
164 desc!(video; "indeo5s", "Intel Indeo 5 Scalable", CODEC_CAP_SCALABLE),
165 desc!(video; "intel263", "Intel I263", CODEC_CAP_REORDER),
166 desc!(audio; "iac", "Intel Indeo audio"),
167 desc!(audio; "imc", "Intel Music Coder"),
168
169 desc!(video; "realvideo1", "Real Video 1"),
170 desc!(video; "realvideo2", "Real Video 2", CODEC_CAP_REORDER),
171 desc!(video; "realvideo3", "Real Video 3", CODEC_CAP_REORDER),
172 desc!(video; "realvideo4", "Real Video 4", CODEC_CAP_REORDER),
173 desc!(video; "realvideo6", "Real Video 6", CODEC_CAP_REORDER),
174 desc!(video; "clearvideo", "ClearVideo"),
175 desc!(video; "clearvideo_rm", "ClearVideo"),
176 desc!(audio; "ra14.4", "RealAudio 14.4"),
177 desc!(audio; "ra28.8", "RealAudio 28.8"),
178 desc!(audio; "cook", "RealAudio Cooker"),
179 desc!(audio; "ralf", "RealAudio Lossless"),
180 desc!(audio; "aac", "AAC"),
181 desc!(audio; "ac3", "ETSI TS 102 366"),
182 desc!(audio; "atrac3", "Sony Atrac3"),
183 desc!(audio; "sipro", "Sipro Labs ADPCM"),
184
185
186 desc!(video-ll; "rawvideo", "Raw video data"),
187 desc!(video-ll; "rawvideo-ms", "Raw video data"),
188
189 desc!(video; "cinepak", "Cinepak"),
190
191 desc!(video-llp; "zmbv", "Zip Motion Blocks Video"),
192
193 desc!(video; "msvideo1", "MS Video 1"),
194 desc!(video; "msrle", "MS RLE"),
195 desc!(audio; "ms-adpcm", "MS ADPCM"),
196 desc!(audio; "ima-adpcm-ms", "IMA ADPCM (MS variant)"),
197
198 desc!(video; "qt-smc", "Apple Graphics"),
199 desc!(video; "qt-rle", "Apple Animation"),
200 desc!(video; "apple-video", "Apple video"),
201 desc!(video; "sorenson-video", "Sorenson Video"),
202 desc!(video; "sorenson-video3", "Sorenson Video 3", CODEC_CAP_REORDER),
203 desc!(audio-ll; "alac", "Apple Lossless Audio Codec"),
204 desc!(audio; "mace-3", "MACE 3:1"),
205 desc!(audio; "mace-6", "MACE 6:1"),
206 desc!(audio; "ima-adpcm-qt", "IMA ADPCM (Apple variant)"),
207 desc!(audio; "qdesign-music", "QDesign Music"),
208 desc!(audio; "qdesign-music2", "QDesign Music v2"),
209 desc!(audio; "qualcomm-purevoice", "Qualcomm PureVoice"),
210
211 desc!(video-ll; "arm_rawvideo", "Acorn Replay Movie raw video formats"),
212 desc!(audio; "arm_rawaudio", "Acorn Replay Movie raw audio formats"),
213 desc!(video; "movinglines", "Acorn Moving Lines"),
214 desc!(video; "movingblocks", "Acorn Moving Blocks"),
215 desc!(video; "movingblockshq", "Acorn Moving Blocks HQ"),
216 desc!(video; "supermovingblocks", "Acorn Super Moving Blocks"),
217 desc!(video; "linepack", "Henrik Pedersen's LinePack"),
218 desc!(video; "movie16_3", "Henrik Pedersen's Movie 16:3"),
219 desc!(video; "escape100", "Eidos Escape 100"),
220 desc!(video; "escape102", "Eidos Escape 102"),
221 desc!(video; "escape122", "Eidos Escape 122"),
222 desc!(video; "escape124", "Eidos Escape 124"),
223 desc!(video; "escape130", "Eidos Escape 130"),
224
225 desc!(video; "truemotion1", "TrueMotion 1"),
226 desc!(video-im; "truemotionrt", "TrueMotion RT"),
227 desc!(video; "truemotion2", "TrueMotion 2"),
228 desc!(video; "truemotion2x", "TrueMotion 2X"),
229 desc!(video; "vp3", "VP3"),
230 desc!(video; "vp4", "VP4"),
231 desc!(video; "vp5", "VP5"),
232 desc!(video; "vp6", "VP6"),
233 desc!(video; "vp6f", "VP6 (in Flash)"),
234 desc!(video; "vp6a", "VP6 with alpha"),
235 desc!(video; "vp7", "VP7"),
236 desc!(video; "vp8", "VP8"),
237 desc!(video; "vp9", "VP9"),
238 desc!(audio; "adpcm-dk3", "Duck DK3 ADPCM"),
239 desc!(audio; "adpcm-dk4", "Duck DK4 ADPCM"),
240 desc!(audio; "on2avc-500", "On2 AVC"),
241 desc!(audio; "on2avc-501", "On2 AVC"),
242
243 desc!(video; "flv263", "Sorenson H.263"),
244 desc!(video-llp; "flashsv", "Flash Screen Video"),
245 desc!(video-llp; "flashsv2", "Flash Screen Video 2"),
246 desc!(audio; "asao", "N*llym*s*r ASAO"),
247 desc!(audio; "flv-adpcm", "Flash ADPCM"),
248
249 desc!(audio; "mp1", "MPEG Audio Layer I"),
250 desc!(audio; "mp2", "MPEG Audio Layer II"),
251 desc!(audio; "mp3", "MPEG Audio Layer III"),
252 desc!(audio; "speex", "Speex"),
253
254 desc!(video; "gdv-video", "Gremlin Digital Video - video"),
255 desc!(audio; "gdv-audio", "Gremlin Digital Video - audio"),
256 desc!(video-im; "arxel-video", "Arxel Tribe Video"),
257 desc!(video; "beam-fcp", "Beam Software Animation"),
258 desc!(video; "beam-video", "Beam Software Video"),
259 desc!(video; "bmv-video", "BMV video"),
260 desc!(audio; "bmv-audio", "BMV audio"),
261 desc!(video; "bmv3-video", "DW Noir BMV video"),
262 desc!(audio; "bmv3-audio", "DW Noir BMV audio"),
263 desc!(video; "dp-sga", "Digital Pictures SGA video"),
264 desc!(video; "fable-imax", "Fable IMAX video"),
265 desc!(video; "fst-video", "FutureVision video"),
266 desc!(audio; "fst-audio", "FutureVision audio"),
267 desc!(video; "hl-fmv-video", "Highlander FMV video"),
268 desc!(video-llp; "ipma", "Imagination Pilots Matte Animation"),
269 desc!(video-llp; "ipma2", "Imagination Pilots Matte Animation v2"),
270 desc!(video; "kmvc", "Karl Morton's Video Codec"),
271 desc!(video; "legend-q-video", "Legend Entertainment Q video"),
272 desc!(video; "midivid", "MidiVid"),
273 desc!(video; "midivid3", "MidiVid 3"),
274 desc!(video-ll; "midivid-ll", "MidiVid Lossless"),
275 desc!(video-ll; "rbt-video", "Sierra Robot video"),
276 desc!(audio; "rbt-audio", "Sierra Robot audio"),
277 desc!(video; "seq-video", "Sierra Sequence video"),
278 desc!(video; "smushv1", "SMUSH Video paletted"),
279 desc!(video; "smushv2", "SMUSH Video 16-bit"),
280 desc!(video; "smush-iact", "SMUSH IACT Audio"),
281 desc!(video; "smush-vima", "SMUSH VIMA Audio"),
282 desc!(video; "vmd-video", "VMD video"),
283 desc!(audio; "vmd-audio", "VMD audio"),
284 desc!(video; "vxvideo", "Actimagine Vx"),
285 desc!(audio; "vxaudio", "Actimagine Sx"),
286
287 desc!(video; "smacker-video", "Smacker video"),
288 desc!(audio; "smacker-audio", "Smacker audio"),
289 desc!(video; "bink-video", "Bink video"),
290 desc!(video; "bink2-video", "Bink2 video"),
291 desc!(audio; "bink-audio-dct", "Bink audio (DCT)"),
292 desc!(audio; "bink-audio-rdft", "Bink audio (RDFT)"),
293
294 desc!(audio; "lhst15f8", "L&H StreamTalk 15kbps at 8 kHz"),
295 desc!(audio; "lhst250f11", "L&H StreamTalk 25kbps at 11 kHz"),
296 desc!(audio; "lhst500f22", "L&H StreamTalk 50kpbs at 22 kHz"),
297 desc!(audio; "lhst48", "L&H StreamTalk CELP Codec 4.8kbps at 8 kHz"),
298
299 desc!(video; "vivo1", "VivoActive Video 1.0"),
300 desc!(video; "vivo2", "VivoActive Video 2.0", CODEC_CAP_REORDER),
301 desc!(audio; "g723.1", "ITU G.723.1"),
302 desc!(audio; "siren", "Polycom Siren"),
303
304 desc!(audio-ll; "ape", "Monkey's Audio"),
305 desc!(audio-ll; "flac", "Free Lossless Audio Codec"),
306 desc!(audio-ll; "tta", "True Audio codec"),
307 desc!(audio-hyb; "wavpack", "WavPack"),
308
309 desc!(video-ll; "gif", "GIF"),
310 desc!(video-im; "jpeg", "JPEG"),
311 desc!(video; "h264", "ITU H.264", CODEC_CAP_COMPLEX_REORDER | CODEC_CAP_HYBRID),
312 desc!(video-modern; "mpeg4asp", "MPEG-4 ASP"),
313
314 desc!(video-im; "mwv1", "Aware MotionWavelets"),
315
316 desc!(video-im; "pgvv", "Radius Studio Video"),
317];
318
319static AVI_VIDEO_CODEC_REGISTER: &[(&[u8;4], &str)] = &[
320 (&[1, 0, 0, 0], "msrle"),
321 (&[2, 0, 0, 0], "msrle"),
322
323 (b"CRAM", "msvideo1"),
324 (b"MSVC", "msvideo1"),
325 (b"WHAM", "msvideo1"),
326
327 (b"MJPG", "jpeg"),
328
329 (b"IF09", "indeo1"),
330 (b"RT21", "indeo2"),
331 (b"IV31", "indeo3"),
332 (b"IV32", "indeo3"),
333 (b"IV41", "indeo4"),
334 (b"IV50", "indeo5"),
335 (b"I263", "intel263"),
336
337 (b"UCOD", "clearvideo"),
338 (b"cvid", "cinepak"),
339 (b"ZMBV", "zmbv"),
340
341 (b"Ipma", "ipma"),
342 (b"Ip20", "ipma2"),
343 (b"KMVC", "kmvc"),
344
345 (b"MVDV", "midivid"),
346 (b"MV30", "midivid3"),
347 (b"MVLZ", "midivid-ll"),
348
349 (b"tmot", "truemotion1"),
350 (b"DUCK", "truemotion1"),
351 (b"TR20", "truemotionrt"),
352 (b"TM20", "truemotion2"),
353 (b"TM2A", "truemotion2x"),
354 (b"TM2X", "truemotion2x"),
355 (b"VP30", "vp3"),
356 (b"VP31", "vp3"),
357 (b"VP40", "vp4"),
358 (b"VP50", "vp5"),
359 (b"VP60", "vp6"),
360 (b"VP61", "vp6"),
361 (b"VP62", "vp6"),
362 (b"VP6A", "vp6a"),
363 (b"VP70", "vp7"),
364
365 (b"MWV1", "mwv1"),
366
367 (b"azpr", "apple-video"),
368 (b"PGVV", "pgvv"),
369
370 (b"VXS1", "vxvideo"),
371
372 (b"DX50", "mpeg4asp"),
373 (b"DIVX", "mpeg4asp"),
374 (b"XVID", "mpeg4asp"),
375];
376
377static WAV_CODEC_REGISTER: &[(u16, &str)] = &[
378 (0x0000, "unknown"),
379 (0x0001, "pcm"),
380 (0x0002, "ms-adpcm"),
381 (0x0003, "pcm"),
382 (0x0011, "ima-adpcm-ms"),
383 (0x0055, "mp3"),
384 (0x0061, "adpcm-dk4"),
385 (0x0062, "adpcm-dk3"),
386 (0x0401, "imc"),
387 (0x0402, "iac"),
388 (0x0500, "on2avc-500"),
389 (0x0501, "on2avc-501"),
390];
391
392static MOV_VIDEO_CODEC_REGISTER: &[(&[u8;4], &str)] = &[
393 (b"cvid", "cinepak"),
394 (b"jpeg", "jpeg"),
395 //(b"raw ", "raw"),
396 //(b"Yuv2", "raw"),
397 (b"smc ", "qt-smc"),
398 (b"rle ", "qt-rle"),
399 (b"rpza", "apple-video"),
400 (b"kpcd", "kodak-photocd"),
401 //(b"mpeg", "mpeg-video"),
402 (b"mjpa", "mjpeg-a"),
403 (b"mjpb", "mjpeg-b"),
404 (b"svqi", "sorenson-video"),
405 (b"SVQ1", "sorenson-video"),
406 (b"svq3", "sorenson-video3"),
407 (b"SVQ3", "sorenson-video3"),
408
409 (b"IV31", "indeo3"),
410 (b"IV32", "indeo3"),
411
412 (b"UCOD", "clearvideo"),
413
414 (b"VP30", "vp3"),
415 (b"VP31", "vp3"),
416
417 (b"mp4v", "mpeg4asp"),
418 (b"avc1", "h264"),
419];
420
421static MOV_AUDIO_CODEC_REGISTER: &[(&[u8;4], &str)] = &[
422 (b"NONE", "pcm"),
423 (b"raw ", "pcm"),
424 (b"twos", "pcm"),
425 (b"sowt", "pcm"),
426 (b"fl32", "pcm"),
427 (b"fl64", "pcm"),
428 (b"in24", "pcm"),
429 (b"in32", "pcm"),
430 (b"MAC3", "mace-3"),
431 (b"MAC6", "mace-6"),
432 (b"ima4", "ima-adpcm-qt"),
433 (b"ulaw", "ulaw"),
434 (b"alaw", "alaw"),
435 (b"dvca", "dv-audio"),
436 (b"QDMC", "qdesign-music"),
437 (b"QDM2", "qdesign-music2"),
438 (b"Qclp", "qualcomm-purevoice"),
439 //(b".mp3", "mpeg-layer3"),
440
441 (b"mp4a", "aac"),
442
443 (b"alac", "alac"),
444];
445
446/// Returns video codec short name for provided FOURCC (used in AVI format).
447pub fn find_codec_from_avi_fourcc(fcc: &[u8;4]) -> Option<&'static str> {
448 for (fourcc, name) in AVI_VIDEO_CODEC_REGISTER.iter() {
449 if *fourcc == fcc { return Some(name); }
450 }
451 None
452}
453
454/// Returns FOURCC (used in AVI format) for provided codec name.
455pub fn find_avi_fourcc(codecname: &str) -> Option<[u8; 4]> {
456 for (fourcc, name) in AVI_VIDEO_CODEC_REGISTER.iter() {
457 if *name == codecname { return Some(**fourcc); }
458 }
459 None
460}
461
462/// Returns known audio codec short name for provided TWOCC (used in WAV and AVI format).
463pub fn find_codec_from_wav_twocc(tcc: u16) -> Option<&'static str> {
464 for (twocc, name) in WAV_CODEC_REGISTER.iter() {
465 if *twocc == tcc { return Some(name); }
466 }
467 None
468}
469
470/// Returns TWOCC (used in WAV and AVI format for provided codec name.
471pub fn find_wav_twocc(codecname: &str) -> Option<u16> {
472 for (twocc, name) in WAV_CODEC_REGISTER.iter() {
473 if *name == codecname { return Some(*twocc); }
474 }
475 None
476}
477
478/// Returns video codec short name for provided FOURCC (used in MOV format).
479pub fn find_codec_from_mov_video_fourcc(fcc: &[u8;4]) -> Option<&'static str> {
480 for (fourcc, name) in MOV_VIDEO_CODEC_REGISTER.iter() {
481 if *fourcc == fcc { return Some(name); }
482 }
483 None
484}
485
486/// Returns known audio codec short name for provided FOURCC (used in MOV format).
487pub fn find_codec_from_mov_audio_fourcc(fcc: &[u8;4]) -> Option<&'static str> {
488 for (fourcc, name) in MOV_AUDIO_CODEC_REGISTER.iter() {
489 if *fourcc == fcc { return Some(name); }
490 }
491 None
492}
493
494#[cfg(test)]
495mod test {
496 use super::*;
497
498 #[test]
499 fn test_register() {
500 let c1 = find_codec_from_avi_fourcc(b"IV41").unwrap();
501 let c2 = find_codec_from_wav_twocc(0x401).unwrap();
502 println!("found {} and {}", c1, c2);
503 let cd1 = get_codec_description(c1).unwrap();
504 let cd2 = get_codec_description(c2).unwrap();
505 println!("got {} and {}", cd1, cd2);
506 }
507}