move LH codec into audio section
[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 });
140}
141
285f4c72 142/// Returns codec description for the provided codec short name if it is found.
d48ee414 143pub fn get_codec_description(name: &str) -> Option<&'static CodecDescription> {
34829caa
KS
144 for reg in CODEC_REGISTER {
145 if reg.name == name {
146 return Some(reg);
d48ee414
KS
147 }
148 }
149 None
150}
151
152static CODEC_REGISTER: &'static [CodecDescription] = &[
e8e022f4 153 desc!(audio-ll; "pcm", "PCM"),
3d5fb08f
KS
154 desc!(audio; "alaw", "A-law PCM"),
155 desc!(audio; "ulaw", "mu-law PCM"),
e8e022f4 156
45e794c4
KS
157 desc!(video-im; "indeo1", "Intel Raw IF09"),
158 desc!(video-im; "indeo2", "Intel Indeo 2"),
159 desc!(video; "indeo3", "Intel Indeo 3"),
160 desc!(video; "indeo4", "Intel Indeo 4", CODEC_CAP_REORDER | CODEC_CAP_SCALABLE),
161 desc!(video; "indeo5", "Intel Indeo 5", CODEC_CAP_REORDER | CODEC_CAP_SCALABLE),
1a36a05d 162 desc!(video; "intel263", "Intel I263", CODEC_CAP_REORDER),
45e794c4
KS
163 desc!(audio; "iac", "Intel Indeo audio"),
164 desc!(audio; "imc", "Intel Music Coder"),
ce52b3b5
KS
165
166 desc!(video; "realvideo1", "Real Video 1"),
6b2cdc84 167 desc!(video; "realvideo2", "Real Video 2", CODEC_CAP_REORDER),
ce52b3b5
KS
168 desc!(video; "realvideo3", "Real Video 3", CODEC_CAP_REORDER),
169 desc!(video; "realvideo4", "Real Video 4", CODEC_CAP_REORDER),
0b791d5c 170 desc!(video; "realvideo6", "Real Video 6", CODEC_CAP_REORDER),
ce52b3b5 171 desc!(video; "clearvideo", "ClearVideo"),
750b299c 172 desc!(video; "clearvideo_rm", "ClearVideo"),
ce52b3b5
KS
173 desc!(audio; "ra14.4", "RealAudio 14.4"),
174 desc!(audio; "ra28.8", "RealAudio 28.8"),
175 desc!(audio; "cook", "RealAudio Cooker"),
176 desc!(audio; "ralf", "RealAudio Lossless"),
177 desc!(audio; "aac", "AAC"),
16dd4f44 178 desc!(audio; "ac3", "ETSI TS 102 366"),
ce52b3b5
KS
179 desc!(audio; "atrac3", "Sony Atrac3"),
180 desc!(audio; "sipro", "Sipro Labs ADPCM"),
e8e022f4 181
57777a0a
KS
182 desc!(video; "cinepak", "Cinepak"),
183
4abcd842 184 desc!(video; "msvideo1", "MS Video 1"),
03c406ea 185 desc!(video; "msrle", "MS RLE"),
4abcd842
KS
186 desc!(audio; "ms-adpcm", "MS ADPCM"),
187 desc!(audio; "ima-adpcm-ms", "IMA ADPCM (MS variant)"),
188
3d5fb08f
KS
189 desc!(video; "qt-smc", "Apple Graphics"),
190 desc!(video; "qt-rle", "Apple Animation"),
191 desc!(video; "apple-video", "Apple video"),
192 desc!(video; "sorenson-video", "Sorenson Video"),
8251c0ab 193 desc!(video; "sorenson-video3", "Sorenson Video 3", CODEC_CAP_REORDER),
3d5fb08f
KS
194 desc!(audio; "mace-3", "MACE 3:1"),
195 desc!(audio; "mace-6", "MACE 6:1"),
196 desc!(audio; "ima-adpcm-qt", "IMA ADPCM (Apple variant)"),
197 desc!(audio; "qdesign-music", "QDesign Music"),
198 desc!(audio; "qdesign-music2", "QDesign Music v2"),
199 desc!(audio; "qualcomm-purevoice", "Qualcomm PureVoice"),
200
d24468d9
KS
201 desc!(video; "truemotion1", "TrueMotion 1"),
202 desc!(video-im; "truemotionrt", "TrueMotion RT"),
203 desc!(video; "truemotion2", "TrueMotion 2"),
e8e022f4
KS
204 desc!(video; "truemotion2x", "TrueMotion 2X"),
205 desc!(video; "vp3", "VP3"),
206 desc!(video; "vp4", "VP4"),
207 desc!(video; "vp5", "VP5"),
208 desc!(video; "vp6", "VP6"),
629a1025 209 desc!(video; "vp6a", "VP6"),
e8e022f4
KS
210 desc!(video; "vp7", "VP7"),
211 desc!(video; "vp8", "VP8"),
212 desc!(video; "vp9", "VP9"),
213 desc!(audio; "adpcm-dk3", "Duck DK3 ADPCM"),
214 desc!(audio; "adpcm-dk4", "Duck DK4 ADPCM"),
629a1025
KS
215 desc!(audio; "on2avc-500", "On2 AVC"),
216 desc!(audio; "on2avc-501", "On2 AVC"),
e8e022f4
KS
217
218 desc!(video; "gdv-video", "Gremlin Digital Video - video"),
219 desc!(audio; "gdv-audio", "Gremlin Digital Video - audio"),
220 desc!(video; "bmv-video", "BMV video"),
221 desc!(audio; "bmv-audio", "BMV audio"),
ecda1cc1
KS
222 desc!(video; "bmv3-video", "DW Noir BMV video"),
223 desc!(audio; "bmv3-audio", "DW Noir BMV audio"),
801bba83
KS
224 desc!(video; "midivid", "MidiVid"),
225 desc!(video; "midivid3", "MidiVid 3"),
226 desc!(video-ll; "midivid-ll", "MidiVid Lossless"),
9895bd7b
KS
227 desc!(video; "vmd-video", "VMD video"),
228 desc!(audio; "vmd-audio", "VMD audio"),
e8e022f4
KS
229
230 desc!(video; "smacker-video", "Smacker video"),
231 desc!(audio; "smacker-audio", "Smacker audio"),
232 desc!(video; "bink-video", "Bink video"),
233 desc!(video; "bink2-video", "Bink2 video"),
234 desc!(audio; "bink-audio-dct", "Bink audio (DCT)"),
235 desc!(audio; "bink-audio-rdft", "Bink audio (RDFT)"),
ed374345
KS
236
237 desc!(audio; "lhst15f8", "L&H StreamTalk 15kbps at 8 kHz"),
238 desc!(audio; "lhst250f11", "L&H StreamTalk 25kbps at 11 kHz"),
239 desc!(audio; "lhst500f22", "L&H StreamTalk 50kpbs at 22 kHz"),
240 desc!(audio; "lhst48", "L&H StreamTalk CELP Codec 4.8kbps at 8 kHz"),
31cf33ac
KS
241
242 desc!(video; "vivo1", "VivoActive Video 1.0"),
243 desc!(video; "vivo2", "VivoActive Video 2.0", CODEC_CAP_REORDER),
244 desc!(audio; "g723.1", "ITU G.723.1"),
245 desc!(audio; "siren", "Polycom Siren"),
d48ee414
KS
246];
247
248static AVI_VIDEO_CODEC_REGISTER: &'static [(&[u8;4], &str)] = &[
423005dc
KS
249 (&[1, 0, 0, 0], "msrle"),
250 (&[2, 0, 0, 0], "msrle"),
251
4abcd842
KS
252 (b"CRAM", "msvideo1"),
253 (b"MSVC", "msvideo1"),
254 (b"WHAM", "msvideo1"),
255
45e794c4
KS
256 (b"IF09", "indeo1"),
257 (b"RT21", "indeo2"),
258 (b"IV31", "indeo3"),
259 (b"IV32", "indeo3"),
260 (b"IV41", "indeo4"),
261 (b"IV50", "indeo5"),
836bf150 262 (b"I263", "intel263"),
ce52b3b5 263
750b299c 264 (b"UCOD", "clearvideo"),
57777a0a 265 (b"cvid", "cinepak"),
b2d656d0 266
801bba83
KS
267 (b"MVDV", "midivid"),
268 (b"MV30", "midivid3"),
269 (b"MVLZ", "midivid-ll"),
270
b2d656d0
KS
271 (b"DUCK", "truemotion1"),
272 (b"TR20", "truemotionrt"),
273 (b"TM20", "truemotion2"),
274 (b"TM2A", "truemotion2x"),
275 (b"TM2X", "truemotion2x"),
40e95291
KS
276 (b"VP30", "vp3"),
277 (b"VP31", "vp3"),
278 (b"VP40", "vp4"),
279 (b"VP50", "vp5"),
280 (b"VP60", "vp6"),
281 (b"VP61", "vp6"),
282 (b"VP62", "vp6"),
1bf8e0fc 283 (b"VP6A", "vp6a"),
40e95291 284 (b"VP70", "vp7"),
d48ee414
KS
285];
286
287static WAV_CODEC_REGISTER: &'static [(u16, &str)] = &[
9d9c811b 288 (0x0000, "unknown"),
45e794c4 289 (0x0001, "pcm"),
4abcd842 290 (0x0002, "ms-adpcm"),
45e794c4 291 (0x0003, "pcm"),
4abcd842 292 (0x0011, "ima-adpcm-ms"),
fadee95f
KS
293 (0x0061, "adpcm-dk4"),
294 (0x0062, "adpcm-dk3"),
45e794c4
KS
295 (0x0401, "imc"),
296 (0x0402, "iac"),
a38be6e4
KS
297 (0x0500, "on2avc-500"),
298 (0x0501, "on2avc-501"),
d48ee414
KS
299];
300
646f4c43
KS
301static MOV_VIDEO_CODEC_REGISTER: &'static [(&[u8;4], &str)] = &[
302 (b"cvid", "cinepak"),
303 (b"jpeg", "jpeg"),
304 //(b"raw ", "raw"),
305 //(b"Yuv2", "raw"),
306 (b"smc ", "qt-smc"),
307 (b"rle ", "qt-rle"),
308 (b"rpza", "apple-video"),
309 (b"kpcd", "kodak-photocd"),
310 //(b"mpeg", "mpeg-video"),
311 (b"mjpa", "mjpeg-a"),
312 (b"mjpb", "mjpeg-b"),
313 (b"svqi", "sorenson-video"),
b2689495 314 (b"SVQ1", "sorenson-video"),
3d5fb08f 315 (b"svq3", "sorenson-video3"),
b2689495 316 (b"SVQ3", "sorenson-video3"),
646f4c43
KS
317
318 (b"IV31", "indeo3"),
319 (b"IV32", "indeo3"),
320
321 (b"UCOD", "clearvideo"),
322
323 (b"VP30", "vp3"),
324 (b"VP31", "vp3"),
325];
326
327static MOV_AUDIO_CODEC_REGISTER: &'static [(&[u8;4], &str)] = &[
328 (b"NONE", "pcm"),
329 (b"raw ", "pcm"),
330 (b"twos", "pcm"),
331 (b"sowt", "pcm"),
332 (b"fl32", "pcm"),
333 (b"fl64", "pcm"),
334 (b"in24", "pcm"),
335 (b"in32", "pcm"),
336 (b"MAC3", "mace-3"),
337 (b"MAC6", "mace-6"),
338 (b"ima4", "ima-adpcm-qt"),
339 (b"ulaw", "ulaw"),
340 (b"alaw", "alaw"),
341 (b"dvca", "dv-audio"),
342 (b"QDMC", "qdesign-music"),
343 (b"QDM2", "qdesign-music2"),
344 (b"Qclp", "qualcomm-purevoice"),
345 //(b".mp3", "mpeg-layer3"),
346];
347
285f4c72 348/// Returns video codec short name for provided FOURCC (used in AVI format).
d48ee414 349pub fn find_codec_from_avi_fourcc(fcc: &[u8;4]) -> Option<&'static str> {
e243ceb4
KS
350 for (fourcc, name) in AVI_VIDEO_CODEC_REGISTER.iter() {
351 if *fourcc == fcc { return Some(name); }
d48ee414
KS
352 }
353 None
354}
355
9a3ce86c
KS
356/// Returns FOURCC (used in AVI format) for provided codec name.
357pub fn find_avi_fourcc(codecname: &str) -> Option<[u8; 4]> {
358 for (fourcc, name) in AVI_VIDEO_CODEC_REGISTER.iter() {
359 if *name == codecname { return Some(**fourcc); }
360 }
361 None
362}
363
285f4c72 364/// Returns known audio codec short name for provided TWOCC (used in WAV and AVI format).
d48ee414 365pub fn find_codec_from_wav_twocc(tcc: u16) -> Option<&'static str> {
e243ceb4
KS
366 for (twocc, name) in WAV_CODEC_REGISTER.iter() {
367 if *twocc == tcc { return Some(name); }
d48ee414
KS
368 }
369 None
370}
371
9a3ce86c
KS
372/// Returns TWOCC (used in WAV and AVI format for provided codec name.
373pub fn find_wav_twocc(codecname: &str) -> Option<u16> {
374 for (twocc, name) in WAV_CODEC_REGISTER.iter() {
375 if *name == codecname { return Some(*twocc); }
376 }
377 None
378}
379
646f4c43
KS
380/// Returns video codec short name for provided FOURCC (used in MOV format).
381pub fn find_codec_from_mov_video_fourcc(fcc: &[u8;4]) -> Option<&'static str> {
382 for (fourcc, name) in MOV_VIDEO_CODEC_REGISTER.iter() {
383 if *fourcc == fcc { return Some(name); }
384 }
385 None
386}
387
388/// Returns known audio codec short name for provided FOURCC (used in MOV format).
389pub fn find_codec_from_mov_audio_fourcc(fcc: &[u8;4]) -> Option<&'static str> {
390 for (fourcc, name) in MOV_AUDIO_CODEC_REGISTER.iter() {
391 if *fourcc == fcc { return Some(name); }
392 }
393 None
394}
395
d48ee414
KS
396#[cfg(test)]
397mod test {
398 use super::*;
399
400 #[test]
401 fn test_register() {
402 let c1 = find_codec_from_avi_fourcc(b"IV41").unwrap();
403 let c2 = find_codec_from_wav_twocc(0x401).unwrap();
404 println!("found {} and {}", c1, c2);
405 let cd1 = get_codec_description(c1).unwrap();
406 let cd2 = get_codec_description(c2).unwrap();
407 println!("got {} and {}", cd1, cd2);
408 }
b58d7656 409}