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