Actimagine VX demuxer and decoders
[nihav.git] / nihav-registry / src / register.rs
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.
4 use std::fmt;
5
6 /// Codec types.
7 #[derive(Debug,Clone,Copy,PartialEq)]
8 #[allow(dead_code)]
9 pub 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
22 impl 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.
35 pub const CODEC_CAP_INTRAONLY:u32 = 0x0001;
36 /// Codec capability flag for lossless codecs.
37 pub const CODEC_CAP_LOSSLESS:u32 = 0x0002;
38 /// Codec capability flag for codecs with frame reordering.
39 pub const CODEC_CAP_REORDER:u32 = 0x0004;
40 /// Codec capability flag for codecs that can be both lossy and lossless.
41 pub const CODEC_CAP_HYBRID:u32 = 0x0008;
42 /// Codec capability flag for codecs with scalability features.
43 pub const CODEC_CAP_SCALABLE:u32 = 0x0010;
44
45 /// Codec description structure.
46 #[derive(Clone)]
47 pub struct CodecDescription {
48 /// Short codec name.
49 ///
50 /// Short codec name is used inside NihAV as the unique identifier.
51 pub name: &'static str,
52 /// Full codec name.
53 pub fname: &'static str,
54 /// Codec type.
55 pub ctype: CodecType,
56 /// Codec capabilities.
57 pub caps: u32,
58 }
59
60 impl CodecDescription {
61 /// Returns short codec name.
62 pub fn get_name(&self) -> &'static str { self.name }
63 /// Returns full codec name.
64 pub fn get_full_name(&self) -> &'static str { self.fname }
65 /// Returns codec type.
66 pub fn get_codec_type(&self) -> CodecType { self.ctype }
67 /// Reports whether the codec has only intra frames or not.
68 pub fn is_intraonly(&self) -> bool { (self.caps & CODEC_CAP_INTRAONLY) != 0 }
69 /// Reports whether the codec is lossless.
70 pub fn is_lossless(&self) -> bool { (self.caps & CODEC_CAP_LOSSLESS) != 0 }
71 /// Reports whether the codec requires frame reordering.
72 pub fn has_reorder(&self) -> bool { (self.caps & CODEC_CAP_REORDER) != 0 }
73 /// Reports whether the codec can be either lossless or lossy.
74 pub fn is_hybrid(&self) -> bool { (self.caps & CODEC_CAP_HYBRID) != 0 }
75 /// Reports whether codec supports scalability.
76 ///
77 /// Scalability means that codec can be decoded in reduced resolution by design.
78 pub fn is_scalable(&self) -> bool { (self.caps & CODEC_CAP_SCALABLE) != 0 }
79 }
80
81 impl fmt::Display for CodecDescription {
82 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
83 let mut out = self.fname.to_string();
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
107 macro_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
142 /// Returns codec description for the provided codec short name if it is found.
143 pub fn get_codec_description(name: &str) -> Option<&'static CodecDescription> {
144 for reg in CODEC_REGISTER {
145 if reg.name == name {
146 return Some(reg);
147 }
148 }
149 None
150 }
151
152 static CODEC_REGISTER: &'static [CodecDescription] = &[
153 desc!(audio-ll; "pcm", "PCM"),
154 desc!(audio; "alaw", "A-law PCM"),
155 desc!(audio; "ulaw", "mu-law PCM"),
156
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),
162 desc!(video; "intel263", "Intel I263", CODEC_CAP_REORDER),
163 desc!(audio; "iac", "Intel Indeo audio"),
164 desc!(audio; "imc", "Intel Music Coder"),
165
166 desc!(video; "realvideo1", "Real Video 1"),
167 desc!(video; "realvideo2", "Real Video 2", CODEC_CAP_REORDER),
168 desc!(video; "realvideo3", "Real Video 3", CODEC_CAP_REORDER),
169 desc!(video; "realvideo4", "Real Video 4", CODEC_CAP_REORDER),
170 desc!(video; "realvideo6", "Real Video 6", CODEC_CAP_REORDER),
171 desc!(video; "clearvideo", "ClearVideo"),
172 desc!(video; "clearvideo_rm", "ClearVideo"),
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"),
178 desc!(audio; "ac3", "ETSI TS 102 366"),
179 desc!(audio; "atrac3", "Sony Atrac3"),
180 desc!(audio; "sipro", "Sipro Labs ADPCM"),
181
182 desc!(video; "cinepak", "Cinepak"),
183
184 desc!(video; "msvideo1", "MS Video 1"),
185 desc!(video; "msrle", "MS RLE"),
186 desc!(audio; "ms-adpcm", "MS ADPCM"),
187 desc!(audio; "ima-adpcm-ms", "IMA ADPCM (MS variant)"),
188
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"),
193 desc!(video; "sorenson-video3", "Sorenson Video 3", CODEC_CAP_REORDER),
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
201 desc!(video; "truemotion1", "TrueMotion 1"),
202 desc!(video-im; "truemotionrt", "TrueMotion RT"),
203 desc!(video; "truemotion2", "TrueMotion 2"),
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"),
209 desc!(video; "vp6a", "VP6"),
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"),
215 desc!(audio; "on2avc-500", "On2 AVC"),
216 desc!(audio; "on2avc-501", "On2 AVC"),
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"),
222 desc!(video; "bmv3-video", "DW Noir BMV video"),
223 desc!(audio; "bmv3-audio", "DW Noir BMV audio"),
224 desc!(video; "midivid", "MidiVid"),
225 desc!(video; "midivid3", "MidiVid 3"),
226 desc!(video-ll; "midivid-ll", "MidiVid Lossless"),
227 desc!(video; "vmd-video", "VMD video"),
228 desc!(audio; "vmd-audio", "VMD audio"),
229 desc!(video; "vxvideo", "Actimagine Vx"),
230 desc!(audio; "vxaudio", "Actimagine Sx"),
231
232 desc!(video; "smacker-video", "Smacker video"),
233 desc!(audio; "smacker-audio", "Smacker audio"),
234 desc!(video; "bink-video", "Bink video"),
235 desc!(video; "bink2-video", "Bink2 video"),
236 desc!(audio; "bink-audio-dct", "Bink audio (DCT)"),
237 desc!(audio; "bink-audio-rdft", "Bink audio (RDFT)"),
238
239 desc!(audio; "lhst15f8", "L&H StreamTalk 15kbps at 8 kHz"),
240 desc!(audio; "lhst250f11", "L&H StreamTalk 25kbps at 11 kHz"),
241 desc!(audio; "lhst500f22", "L&H StreamTalk 50kpbs at 22 kHz"),
242 desc!(audio; "lhst48", "L&H StreamTalk CELP Codec 4.8kbps at 8 kHz"),
243
244 desc!(video; "vivo1", "VivoActive Video 1.0"),
245 desc!(video; "vivo2", "VivoActive Video 2.0", CODEC_CAP_REORDER),
246 desc!(audio; "g723.1", "ITU G.723.1"),
247 desc!(audio; "siren", "Polycom Siren"),
248 ];
249
250 static AVI_VIDEO_CODEC_REGISTER: &'static [(&[u8;4], &str)] = &[
251 (&[1, 0, 0, 0], "msrle"),
252 (&[2, 0, 0, 0], "msrle"),
253
254 (b"CRAM", "msvideo1"),
255 (b"MSVC", "msvideo1"),
256 (b"WHAM", "msvideo1"),
257
258 (b"IF09", "indeo1"),
259 (b"RT21", "indeo2"),
260 (b"IV31", "indeo3"),
261 (b"IV32", "indeo3"),
262 (b"IV41", "indeo4"),
263 (b"IV50", "indeo5"),
264 (b"I263", "intel263"),
265
266 (b"UCOD", "clearvideo"),
267 (b"cvid", "cinepak"),
268
269 (b"MVDV", "midivid"),
270 (b"MV30", "midivid3"),
271 (b"MVLZ", "midivid-ll"),
272
273 (b"DUCK", "truemotion1"),
274 (b"TR20", "truemotionrt"),
275 (b"TM20", "truemotion2"),
276 (b"TM2A", "truemotion2x"),
277 (b"TM2X", "truemotion2x"),
278 (b"VP30", "vp3"),
279 (b"VP31", "vp3"),
280 (b"VP40", "vp4"),
281 (b"VP50", "vp5"),
282 (b"VP60", "vp6"),
283 (b"VP61", "vp6"),
284 (b"VP62", "vp6"),
285 (b"VP6A", "vp6a"),
286 (b"VP70", "vp7"),
287 ];
288
289 static WAV_CODEC_REGISTER: &'static [(u16, &str)] = &[
290 (0x0000, "unknown"),
291 (0x0001, "pcm"),
292 (0x0002, "ms-adpcm"),
293 (0x0003, "pcm"),
294 (0x0011, "ima-adpcm-ms"),
295 (0x0061, "adpcm-dk4"),
296 (0x0062, "adpcm-dk3"),
297 (0x0401, "imc"),
298 (0x0402, "iac"),
299 (0x0500, "on2avc-500"),
300 (0x0501, "on2avc-501"),
301 ];
302
303 static MOV_VIDEO_CODEC_REGISTER: &'static [(&[u8;4], &str)] = &[
304 (b"cvid", "cinepak"),
305 (b"jpeg", "jpeg"),
306 //(b"raw ", "raw"),
307 //(b"Yuv2", "raw"),
308 (b"smc ", "qt-smc"),
309 (b"rle ", "qt-rle"),
310 (b"rpza", "apple-video"),
311 (b"kpcd", "kodak-photocd"),
312 //(b"mpeg", "mpeg-video"),
313 (b"mjpa", "mjpeg-a"),
314 (b"mjpb", "mjpeg-b"),
315 (b"svqi", "sorenson-video"),
316 (b"SVQ1", "sorenson-video"),
317 (b"svq3", "sorenson-video3"),
318 (b"SVQ3", "sorenson-video3"),
319
320 (b"IV31", "indeo3"),
321 (b"IV32", "indeo3"),
322
323 (b"UCOD", "clearvideo"),
324
325 (b"VP30", "vp3"),
326 (b"VP31", "vp3"),
327 ];
328
329 static MOV_AUDIO_CODEC_REGISTER: &'static [(&[u8;4], &str)] = &[
330 (b"NONE", "pcm"),
331 (b"raw ", "pcm"),
332 (b"twos", "pcm"),
333 (b"sowt", "pcm"),
334 (b"fl32", "pcm"),
335 (b"fl64", "pcm"),
336 (b"in24", "pcm"),
337 (b"in32", "pcm"),
338 (b"MAC3", "mace-3"),
339 (b"MAC6", "mace-6"),
340 (b"ima4", "ima-adpcm-qt"),
341 (b"ulaw", "ulaw"),
342 (b"alaw", "alaw"),
343 (b"dvca", "dv-audio"),
344 (b"QDMC", "qdesign-music"),
345 (b"QDM2", "qdesign-music2"),
346 (b"Qclp", "qualcomm-purevoice"),
347 //(b".mp3", "mpeg-layer3"),
348 ];
349
350 /// Returns video codec short name for provided FOURCC (used in AVI format).
351 pub fn find_codec_from_avi_fourcc(fcc: &[u8;4]) -> Option<&'static str> {
352 for (fourcc, name) in AVI_VIDEO_CODEC_REGISTER.iter() {
353 if *fourcc == fcc { return Some(name); }
354 }
355 None
356 }
357
358 /// Returns FOURCC (used in AVI format) for provided codec name.
359 pub fn find_avi_fourcc(codecname: &str) -> Option<[u8; 4]> {
360 for (fourcc, name) in AVI_VIDEO_CODEC_REGISTER.iter() {
361 if *name == codecname { return Some(**fourcc); }
362 }
363 None
364 }
365
366 /// Returns known audio codec short name for provided TWOCC (used in WAV and AVI format).
367 pub fn find_codec_from_wav_twocc(tcc: u16) -> Option<&'static str> {
368 for (twocc, name) in WAV_CODEC_REGISTER.iter() {
369 if *twocc == tcc { return Some(name); }
370 }
371 None
372 }
373
374 /// Returns TWOCC (used in WAV and AVI format for provided codec name.
375 pub fn find_wav_twocc(codecname: &str) -> Option<u16> {
376 for (twocc, name) in WAV_CODEC_REGISTER.iter() {
377 if *name == codecname { return Some(*twocc); }
378 }
379 None
380 }
381
382 /// Returns video codec short name for provided FOURCC (used in MOV format).
383 pub fn find_codec_from_mov_video_fourcc(fcc: &[u8;4]) -> Option<&'static str> {
384 for (fourcc, name) in MOV_VIDEO_CODEC_REGISTER.iter() {
385 if *fourcc == fcc { return Some(name); }
386 }
387 None
388 }
389
390 /// Returns known audio codec short name for provided FOURCC (used in MOV format).
391 pub fn find_codec_from_mov_audio_fourcc(fcc: &[u8;4]) -> Option<&'static str> {
392 for (fourcc, name) in MOV_AUDIO_CODEC_REGISTER.iter() {
393 if *fourcc == fcc { return Some(name); }
394 }
395 None
396 }
397
398 #[cfg(test)]
399 mod test {
400 use super::*;
401
402 #[test]
403 fn test_register() {
404 let c1 = find_codec_from_avi_fourcc(b"IV41").unwrap();
405 let c2 = find_codec_from_wav_twocc(0x401).unwrap();
406 println!("found {} and {}", c1, c2);
407 let cd1 = get_codec_description(c1).unwrap();
408 let cd2 = get_codec_description(c2).unwrap();
409 println!("got {} and {}", cd1, cd2);
410 }
411 }