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