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