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