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