registry: add entry for MS RLE
[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 177 desc!(video; "msvideo1", "MS Video 1"),
03c406ea 178 desc!(video; "msrle", "MS RLE"),
4abcd842
KS
179 desc!(audio; "ms-adpcm", "MS ADPCM"),
180 desc!(audio; "ima-adpcm-ms", "IMA ADPCM (MS variant)"),
181
d24468d9
KS
182 desc!(video; "truemotion1", "TrueMotion 1"),
183 desc!(video-im; "truemotionrt", "TrueMotion RT"),
184 desc!(video; "truemotion2", "TrueMotion 2"),
e8e022f4
KS
185 desc!(video; "truemotion2x", "TrueMotion 2X"),
186 desc!(video; "vp3", "VP3"),
187 desc!(video; "vp4", "VP4"),
188 desc!(video; "vp5", "VP5"),
189 desc!(video; "vp6", "VP6"),
629a1025 190 desc!(video; "vp6a", "VP6"),
e8e022f4
KS
191 desc!(video; "vp7", "VP7"),
192 desc!(video; "vp8", "VP8"),
193 desc!(video; "vp9", "VP9"),
194 desc!(audio; "adpcm-dk3", "Duck DK3 ADPCM"),
195 desc!(audio; "adpcm-dk4", "Duck DK4 ADPCM"),
629a1025
KS
196 desc!(audio; "on2avc-500", "On2 AVC"),
197 desc!(audio; "on2avc-501", "On2 AVC"),
e8e022f4
KS
198
199 desc!(video; "gdv-video", "Gremlin Digital Video - video"),
200 desc!(audio; "gdv-audio", "Gremlin Digital Video - audio"),
201 desc!(video; "bmv-video", "BMV video"),
202 desc!(audio; "bmv-audio", "BMV audio"),
ecda1cc1
KS
203 desc!(video; "bmv3-video", "DW Noir BMV video"),
204 desc!(audio; "bmv3-audio", "DW Noir BMV audio"),
801bba83
KS
205 desc!(video; "midivid", "MidiVid"),
206 desc!(video; "midivid3", "MidiVid 3"),
207 desc!(video-ll; "midivid-ll", "MidiVid Lossless"),
9895bd7b
KS
208 desc!(video; "vmd-video", "VMD video"),
209 desc!(audio; "vmd-audio", "VMD audio"),
e8e022f4
KS
210
211 desc!(video; "smacker-video", "Smacker video"),
212 desc!(audio; "smacker-audio", "Smacker audio"),
213 desc!(video; "bink-video", "Bink video"),
214 desc!(video; "bink2-video", "Bink2 video"),
215 desc!(audio; "bink-audio-dct", "Bink audio (DCT)"),
216 desc!(audio; "bink-audio-rdft", "Bink audio (RDFT)"),
ed374345
KS
217
218 desc!(audio; "lhst15f8", "L&H StreamTalk 15kbps at 8 kHz"),
219 desc!(audio; "lhst250f11", "L&H StreamTalk 25kbps at 11 kHz"),
220 desc!(audio; "lhst500f22", "L&H StreamTalk 50kpbs at 22 kHz"),
221 desc!(audio; "lhst48", "L&H StreamTalk CELP Codec 4.8kbps at 8 kHz"),
31cf33ac
KS
222
223 desc!(video; "vivo1", "VivoActive Video 1.0"),
224 desc!(video; "vivo2", "VivoActive Video 2.0", CODEC_CAP_REORDER),
225 desc!(audio; "g723.1", "ITU G.723.1"),
226 desc!(audio; "siren", "Polycom Siren"),
d48ee414
KS
227];
228
229static AVI_VIDEO_CODEC_REGISTER: &'static [(&[u8;4], &str)] = &[
423005dc
KS
230 (&[1, 0, 0, 0], "msrle"),
231 (&[2, 0, 0, 0], "msrle"),
232
4abcd842
KS
233 (b"CRAM", "msvideo1"),
234 (b"MSVC", "msvideo1"),
235 (b"WHAM", "msvideo1"),
236
45e794c4
KS
237 (b"IF09", "indeo1"),
238 (b"RT21", "indeo2"),
239 (b"IV31", "indeo3"),
240 (b"IV32", "indeo3"),
241 (b"IV41", "indeo4"),
242 (b"IV50", "indeo5"),
836bf150 243 (b"I263", "intel263"),
ce52b3b5 244
750b299c 245 (b"UCOD", "clearvideo"),
57777a0a 246 (b"cvid", "cinepak"),
b2d656d0 247
801bba83
KS
248 (b"MVDV", "midivid"),
249 (b"MV30", "midivid3"),
250 (b"MVLZ", "midivid-ll"),
251
b2d656d0
KS
252 (b"DUCK", "truemotion1"),
253 (b"TR20", "truemotionrt"),
254 (b"TM20", "truemotion2"),
255 (b"TM2A", "truemotion2x"),
256 (b"TM2X", "truemotion2x"),
40e95291
KS
257 (b"VP30", "vp3"),
258 (b"VP31", "vp3"),
259 (b"VP40", "vp4"),
260 (b"VP50", "vp5"),
261 (b"VP60", "vp6"),
262 (b"VP61", "vp6"),
263 (b"VP62", "vp6"),
1bf8e0fc 264 (b"VP6A", "vp6a"),
40e95291 265 (b"VP70", "vp7"),
d48ee414
KS
266];
267
268static WAV_CODEC_REGISTER: &'static [(u16, &str)] = &[
9d9c811b 269 (0x0000, "unknown"),
45e794c4 270 (0x0001, "pcm"),
4abcd842 271 (0x0002, "ms-adpcm"),
45e794c4 272 (0x0003, "pcm"),
4abcd842 273 (0x0011, "ima-adpcm-ms"),
fadee95f
KS
274 (0x0061, "adpcm-dk4"),
275 (0x0062, "adpcm-dk3"),
45e794c4
KS
276 (0x0401, "imc"),
277 (0x0402, "iac"),
a38be6e4
KS
278 (0x0500, "on2avc-500"),
279 (0x0501, "on2avc-501"),
d48ee414
KS
280];
281
646f4c43
KS
282static MOV_VIDEO_CODEC_REGISTER: &'static [(&[u8;4], &str)] = &[
283 (b"cvid", "cinepak"),
284 (b"jpeg", "jpeg"),
285 //(b"raw ", "raw"),
286 //(b"Yuv2", "raw"),
287 (b"smc ", "qt-smc"),
288 (b"rle ", "qt-rle"),
289 (b"rpza", "apple-video"),
290 (b"kpcd", "kodak-photocd"),
291 //(b"mpeg", "mpeg-video"),
292 (b"mjpa", "mjpeg-a"),
293 (b"mjpb", "mjpeg-b"),
294 (b"svqi", "sorenson-video"),
295
296 (b"IV31", "indeo3"),
297 (b"IV32", "indeo3"),
298
299 (b"UCOD", "clearvideo"),
300
301 (b"VP30", "vp3"),
302 (b"VP31", "vp3"),
303];
304
305static MOV_AUDIO_CODEC_REGISTER: &'static [(&[u8;4], &str)] = &[
306 (b"NONE", "pcm"),
307 (b"raw ", "pcm"),
308 (b"twos", "pcm"),
309 (b"sowt", "pcm"),
310 (b"fl32", "pcm"),
311 (b"fl64", "pcm"),
312 (b"in24", "pcm"),
313 (b"in32", "pcm"),
314 (b"MAC3", "mace-3"),
315 (b"MAC6", "mace-6"),
316 (b"ima4", "ima-adpcm-qt"),
317 (b"ulaw", "ulaw"),
318 (b"alaw", "alaw"),
319 (b"dvca", "dv-audio"),
320 (b"QDMC", "qdesign-music"),
321 (b"QDM2", "qdesign-music2"),
322 (b"Qclp", "qualcomm-purevoice"),
323 //(b".mp3", "mpeg-layer3"),
324];
325
285f4c72 326/// Returns video codec short name for provided FOURCC (used in AVI format).
d48ee414 327pub fn find_codec_from_avi_fourcc(fcc: &[u8;4]) -> Option<&'static str> {
e243ceb4
KS
328 for (fourcc, name) in AVI_VIDEO_CODEC_REGISTER.iter() {
329 if *fourcc == fcc { return Some(name); }
d48ee414
KS
330 }
331 None
332}
333
9a3ce86c
KS
334/// Returns FOURCC (used in AVI format) for provided codec name.
335pub fn find_avi_fourcc(codecname: &str) -> Option<[u8; 4]> {
336 for (fourcc, name) in AVI_VIDEO_CODEC_REGISTER.iter() {
337 if *name == codecname { return Some(**fourcc); }
338 }
339 None
340}
341
285f4c72 342/// Returns known audio codec short name for provided TWOCC (used in WAV and AVI format).
d48ee414 343pub fn find_codec_from_wav_twocc(tcc: u16) -> Option<&'static str> {
e243ceb4
KS
344 for (twocc, name) in WAV_CODEC_REGISTER.iter() {
345 if *twocc == tcc { return Some(name); }
d48ee414
KS
346 }
347 None
348}
349
9a3ce86c
KS
350/// Returns TWOCC (used in WAV and AVI format for provided codec name.
351pub fn find_wav_twocc(codecname: &str) -> Option<u16> {
352 for (twocc, name) in WAV_CODEC_REGISTER.iter() {
353 if *name == codecname { return Some(*twocc); }
354 }
355 None
356}
357
646f4c43
KS
358/// Returns video codec short name for provided FOURCC (used in MOV format).
359pub fn find_codec_from_mov_video_fourcc(fcc: &[u8;4]) -> Option<&'static str> {
360 for (fourcc, name) in MOV_VIDEO_CODEC_REGISTER.iter() {
361 if *fourcc == fcc { return Some(name); }
362 }
363 None
364}
365
366/// Returns known audio codec short name for provided FOURCC (used in MOV format).
367pub fn find_codec_from_mov_audio_fourcc(fcc: &[u8;4]) -> Option<&'static str> {
368 for (fourcc, name) in MOV_AUDIO_CODEC_REGISTER.iter() {
369 if *fourcc == fcc { return Some(name); }
370 }
371 None
372}
373
d48ee414
KS
374#[cfg(test)]
375mod test {
376 use super::*;
377
378 #[test]
379 fn test_register() {
380 let c1 = find_codec_from_avi_fourcc(b"IV41").unwrap();
381 let c2 = find_codec_from_wav_twocc(0x401).unwrap();
382 println!("found {} and {}", c1, c2);
383 let cd1 = get_codec_description(c1).unwrap();
384 let cd2 = get_codec_description(c2).unwrap();
385 println!("got {} and {}", cd1, cd2);
386 }
b58d7656 387}