Cinepak decoder
[nihav.git] / nihav-registry / src / register.rs
... / ...
CommitLineData
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.
4use std::fmt;
5
6/// Codec types.
7#[derive(Debug,Clone,Copy,PartialEq)]
8#[allow(dead_code)]
9pub 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
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
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;
39
40/// Codec description structure.
41#[derive(Clone)]
42pub struct CodecDescription {
43 /// Short codec name.
44 ///
45 /// Short codec name is used inside NihAV as the unique identifier.
46 pub name: &'static str,
47 /// Full codec name.
48 pub fname: &'static str,
49 /// Codec type.
50 pub ctype: CodecType,
51 /// Codec capabilities.
52 pub caps: u32,
53}
54
55impl CodecDescription {
56 /// Returns short codec name.
57 pub fn get_name(&self) -> &'static str { self.name }
58 /// Returns full codec name.
59 pub fn get_full_name(&self) -> &'static str { self.fname }
60 /// Returns codec type.
61 pub fn get_codec_type(&self) -> CodecType { self.ctype }
62 /// Reports whether the codec has only intra frames or not.
63 pub fn is_intraonly(&self) -> bool { (self.caps & CODEC_CAP_INTRAONLY) != 0 }
64 /// Reports whether the codec is lossless.
65 pub fn is_lossless(&self) -> bool { (self.caps & CODEC_CAP_LOSSLESS) != 0 }
66 /// Reports whether the codec requires frame reordering.
67 pub fn has_reorder(&self) -> bool { (self.caps & CODEC_CAP_REORDER) != 0 }
68 /// Reports whether the codec can be either lossless or lossy.
69 pub fn is_hybrid(&self) -> bool { (self.caps & CODEC_CAP_HYBRID) != 0 }
70 /// Reports whether codec supports scalability.
71 ///
72 /// Scalability means that codec can be decoded in reduced resolution by design.
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 {
78 let mut out = self.fname.to_string();
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
137/// Returns codec description for the provided codec short name if it is found.
138pub fn get_codec_description(name: &str) -> Option<&'static CodecDescription> {
139 for reg in CODEC_REGISTER {
140 if reg.name == name {
141 return Some(reg);
142 }
143 }
144 None
145}
146
147static CODEC_REGISTER: &'static [CodecDescription] = &[
148 desc!(audio-ll; "pcm", "PCM"),
149
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),
155 desc!(video; "intel263", "Intel I263", CODEC_CAP_REORDER),
156 desc!(audio; "iac", "Intel Indeo audio"),
157 desc!(audio; "imc", "Intel Music Coder"),
158
159 desc!(video; "realvideo1", "Real Video 1"),
160 desc!(video; "realvideo2", "Real Video 2", CODEC_CAP_REORDER),
161 desc!(video; "realvideo3", "Real Video 3", CODEC_CAP_REORDER),
162 desc!(video; "realvideo4", "Real Video 4", CODEC_CAP_REORDER),
163 desc!(video; "realvideo6", "Real Video 6", CODEC_CAP_REORDER),
164 desc!(video; "clearvideo", "ClearVideo"),
165 desc!(video; "clearvideo_rm", "ClearVideo"),
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"),
171 desc!(audio; "ac3", "ETSI TS 102 366"),
172 desc!(audio; "atrac3", "Sony Atrac3"),
173 desc!(audio; "sipro", "Sipro Labs ADPCM"),
174
175 desc!(video; "cinepak", "Cinepak"),
176
177 desc!(video; "truemotion1", "TrueMotion 1"),
178 desc!(video-im; "truemotionrt", "TrueMotion RT"),
179 desc!(video; "truemotion2", "TrueMotion 2"),
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"),
185 desc!(video; "vp6a", "VP6"),
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"),
191 desc!(audio; "on2avc-500", "On2 AVC"),
192 desc!(audio; "on2avc-501", "On2 AVC"),
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"),
198 desc!(video; "bmv3-video", "DW Noir BMV video"),
199 desc!(audio; "bmv3-audio", "DW Noir BMV audio"),
200 desc!(video; "midivid", "MidiVid"),
201 desc!(video; "midivid3", "MidiVid 3"),
202 desc!(video-ll; "midivid-ll", "MidiVid Lossless"),
203 desc!(video; "vmd-video", "VMD video"),
204 desc!(audio; "vmd-audio", "VMD audio"),
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)"),
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"),
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"),
222];
223
224static AVI_VIDEO_CODEC_REGISTER: &'static [(&[u8;4], &str)] = &[
225 (b"IF09", "indeo1"),
226 (b"RT21", "indeo2"),
227 (b"IV31", "indeo3"),
228 (b"IV32", "indeo3"),
229 (b"IV41", "indeo4"),
230 (b"IV50", "indeo5"),
231 (b"I263", "intel263"),
232
233 (b"UCOD", "clearvideo"),
234 (b"cvid", "cinepak"),
235
236 (b"MVDV", "midivid"),
237 (b"MV30", "midivid3"),
238 (b"MVLZ", "midivid-ll"),
239
240 (b"DUCK", "truemotion1"),
241 (b"TR20", "truemotionrt"),
242 (b"TM20", "truemotion2"),
243 (b"TM2A", "truemotion2x"),
244 (b"TM2X", "truemotion2x"),
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"),
252 (b"VP6A", "vp6a"),
253 (b"VP70", "vp7"),
254];
255
256static WAV_CODEC_REGISTER: &'static [(u16, &str)] = &[
257 (0x0000, "pcm"),
258 (0x0001, "pcm"),
259 (0x0003, "pcm"),
260 (0x0061, "adpcm-dk4"),
261 (0x0062, "adpcm-dk3"),
262 (0x0401, "imc"),
263 (0x0402, "iac"),
264 (0x0500, "on2avc-500"),
265 (0x0501, "on2avc-501"),
266];
267
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
312/// Returns video codec short name for provided FOURCC (used in AVI format).
313pub fn find_codec_from_avi_fourcc(fcc: &[u8;4]) -> Option<&'static str> {
314 for (fourcc, name) in AVI_VIDEO_CODEC_REGISTER.iter() {
315 if *fourcc == fcc { return Some(name); }
316 }
317 None
318}
319
320/// Returns known audio codec short name for provided TWOCC (used in WAV and AVI format).
321pub fn find_codec_from_wav_twocc(tcc: u16) -> Option<&'static str> {
322 for (twocc, name) in WAV_CODEC_REGISTER.iter() {
323 if *twocc == tcc { return Some(name); }
324 }
325 None
326}
327
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
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 }
357}