nihav_registry/register: make CODEC_CAP_* public and document them
[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
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)"),
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"),
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"),
246 ];
247
248 static AVI_VIDEO_CODEC_REGISTER: &'static [(&[u8;4], &str)] = &[
249 (&[1, 0, 0, 0], "msrle"),
250 (&[2, 0, 0, 0], "msrle"),
251
252 (b"CRAM", "msvideo1"),
253 (b"MSVC", "msvideo1"),
254 (b"WHAM", "msvideo1"),
255
256 (b"IF09", "indeo1"),
257 (b"RT21", "indeo2"),
258 (b"IV31", "indeo3"),
259 (b"IV32", "indeo3"),
260 (b"IV41", "indeo4"),
261 (b"IV50", "indeo5"),
262 (b"I263", "intel263"),
263
264 (b"UCOD", "clearvideo"),
265 (b"cvid", "cinepak"),
266
267 (b"MVDV", "midivid"),
268 (b"MV30", "midivid3"),
269 (b"MVLZ", "midivid-ll"),
270
271 (b"DUCK", "truemotion1"),
272 (b"TR20", "truemotionrt"),
273 (b"TM20", "truemotion2"),
274 (b"TM2A", "truemotion2x"),
275 (b"TM2X", "truemotion2x"),
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"),
283 (b"VP6A", "vp6a"),
284 (b"VP70", "vp7"),
285 ];
286
287 static WAV_CODEC_REGISTER: &'static [(u16, &str)] = &[
288 (0x0000, "unknown"),
289 (0x0001, "pcm"),
290 (0x0002, "ms-adpcm"),
291 (0x0003, "pcm"),
292 (0x0011, "ima-adpcm-ms"),
293 (0x0061, "adpcm-dk4"),
294 (0x0062, "adpcm-dk3"),
295 (0x0401, "imc"),
296 (0x0402, "iac"),
297 (0x0500, "on2avc-500"),
298 (0x0501, "on2avc-501"),
299 ];
300
301 static 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"),
314 (b"SVQ1", "sorenson-video"),
315 (b"svq3", "sorenson-video3"),
316 (b"SVQ3", "sorenson-video3"),
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
327 static 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
348 /// Returns video codec short name for provided FOURCC (used in AVI format).
349 pub fn find_codec_from_avi_fourcc(fcc: &[u8;4]) -> Option<&'static str> {
350 for (fourcc, name) in AVI_VIDEO_CODEC_REGISTER.iter() {
351 if *fourcc == fcc { return Some(name); }
352 }
353 None
354 }
355
356 /// Returns FOURCC (used in AVI format) for provided codec name.
357 pub 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
364 /// Returns known audio codec short name for provided TWOCC (used in WAV and AVI format).
365 pub fn find_codec_from_wav_twocc(tcc: u16) -> Option<&'static str> {
366 for (twocc, name) in WAV_CODEC_REGISTER.iter() {
367 if *twocc == tcc { return Some(name); }
368 }
369 None
370 }
371
372 /// Returns TWOCC (used in WAV and AVI format for provided codec name.
373 pub 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
380 /// Returns video codec short name for provided FOURCC (used in MOV format).
381 pub 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).
389 pub 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
396 #[cfg(test)]
397 mod 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 }
409 }