remove trailing whitespaces
[nihav.git] / nihav-core / src / register.rs
1 use std::fmt;
2
3 #[derive(Debug,Clone,Copy,PartialEq)]
4 #[allow(dead_code)]
5 pub enum CodecType {
6 Video,
7 Audio,
8 Subtitles,
9 Data,
10 None,
11 }
12
13 impl fmt::Display for CodecType {
14 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
15 match *self {
16 CodecType::Video => write!(f, "Video"),
17 CodecType::Audio => write!(f, "Audio"),
18 CodecType::Subtitles => write!(f, "Subtitles"),
19 CodecType::Data => write!(f, "Data"),
20 CodecType::None => write!(f, "-"),
21 }
22 }
23 }
24
25 const CODEC_CAP_INTRAONLY:u32 = 0x0001;
26 const CODEC_CAP_LOSSLESS:u32 = 0x0002;
27 const CODEC_CAP_REORDER:u32 = 0x0004;
28 const CODEC_CAP_HYBRID:u32 = 0x0008;
29 const CODEC_CAP_SCALABLE:u32 = 0x0010;
30
31 #[derive(Clone)]
32 pub struct CodecDescription {
33 pub name: &'static str,
34 pub fname: &'static str,
35 pub ctype: CodecType,
36 pub caps: u32,
37 }
38
39 impl CodecDescription {
40 pub fn get_name(&self) -> &'static str { self.name }
41 pub fn get_full_name(&self) -> &'static str { self.fname }
42 pub fn get_codec_type(&self) -> CodecType { self.ctype }
43 pub fn is_intraonly(&self) -> bool { (self.caps & CODEC_CAP_INTRAONLY) != 0 }
44 pub fn is_lossless(&self) -> bool { (self.caps & CODEC_CAP_LOSSLESS) != 0 }
45 pub fn has_reorder(&self) -> bool { (self.caps & CODEC_CAP_REORDER) != 0 }
46 pub fn is_hybrid(&self) -> bool { (self.caps & CODEC_CAP_HYBRID) != 0 }
47 pub fn is_scalable(&self) -> bool { (self.caps & CODEC_CAP_SCALABLE) != 0 }
48 }
49
50 impl fmt::Display for CodecDescription {
51 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
52 let mut out = self.fname.to_string();
53 if self.caps != 0 {
54 let mut capfmt = "".to_string();
55 if (self.caps & CODEC_CAP_INTRAONLY) != 0 {
56 capfmt = format!("{} Intra-only", capfmt);
57 }
58 if (self.caps & CODEC_CAP_LOSSLESS) != 0 {
59 capfmt = format!("{} Lossless", capfmt);
60 }
61 if (self.caps & CODEC_CAP_REORDER) != 0 {
62 capfmt = format!("{} Frame reorder", capfmt);
63 }
64 if (self.caps & CODEC_CAP_HYBRID) != 0 {
65 capfmt = format!("{} Can be lossy and lossless", capfmt);
66 }
67 if (self.caps & CODEC_CAP_SCALABLE) != 0 {
68 capfmt = format!("{} Scalable", capfmt);
69 }
70 out = format!("{} ({})", out, capfmt);
71 }
72 write!(f, "{}", out)
73 }
74 }
75
76 macro_rules! desc {
77 (video; $n:expr, $fn:expr) => ({
78 CodecDescription{ name: $n, fname: $fn, ctype: CodecType::Video,
79 caps: 0 }
80 });
81 (video; $n:expr, $fn:expr, $c:expr) => ({
82 CodecDescription{ name: $n, fname: $fn, ctype: CodecType::Video,
83 caps: $c }
84 });
85 (video-ll; $n:expr, $fn:expr) => ({
86 CodecDescription{ name: $n, fname: $fn, ctype: CodecType::Video,
87 caps: CODEC_CAP_LOSSLESS | CODEC_CAP_INTRAONLY }
88 });
89 (video-llp; $n:expr, $fn:expr) => ({
90 CodecDescription{ name: $n, fname: $fn, ctype: CodecType::Video,
91 caps: CODEC_CAP_LOSSLESS }
92 });
93 (video-im; $n:expr, $fn:expr) => ({
94 CodecDescription{ name: $n, fname: $fn, ctype: CodecType::Video,
95 caps: CODEC_CAP_INTRAONLY }
96 });
97 (video-modern; $n:expr, $fn:expr) => ({
98 CodecDescription{ name: $n, fname: $fn, ctype: CodecType::Video,
99 caps: CODEC_CAP_REORDER | CODEC_CAP_HYBRID }
100 });
101 (audio; $n:expr, $fn:expr) => ({
102 CodecDescription{ name: $n, fname: $fn, ctype: CodecType::Audio,
103 caps: 0 }
104 });
105 (audio-ll; $n:expr, $fn:expr) => ({
106 CodecDescription{ name: $n, fname: $fn, ctype: CodecType::Audio,
107 caps: CODEC_CAP_LOSSLESS | CODEC_CAP_INTRAONLY }
108 });
109 }
110
111 pub fn get_codec_description(name: &str) -> Option<&'static CodecDescription> {
112 for reg in CODEC_REGISTER {
113 if reg.name == name {
114 return Some(reg);
115 }
116 }
117 None
118 }
119
120 static CODEC_REGISTER: &'static [CodecDescription] = &[
121 desc!(audio-ll; "pcm", "PCM"),
122
123 desc!(video-im; "indeo1", "Intel Raw IF09"),
124 desc!(video-im; "indeo2", "Intel Indeo 2"),
125 desc!(video; "indeo3", "Intel Indeo 3"),
126 desc!(video; "indeo4", "Intel Indeo 4", CODEC_CAP_REORDER | CODEC_CAP_SCALABLE),
127 desc!(video; "indeo5", "Intel Indeo 5", CODEC_CAP_REORDER | CODEC_CAP_SCALABLE),
128 desc!(video; "intel263", "Intel I263", CODEC_CAP_REORDER),
129 desc!(audio; "iac", "Intel Indeo audio"),
130 desc!(audio; "imc", "Intel Music Coder"),
131
132 desc!(video; "realvideo1", "Real Video 1"),
133 desc!(video; "realvideo2", "Real Video 2"),
134 desc!(video; "realvideo3", "Real Video 3", CODEC_CAP_REORDER),
135 desc!(video; "realvideo4", "Real Video 4", CODEC_CAP_REORDER),
136 desc!(video; "realvideo6", "Real Video 6", CODEC_CAP_REORDER),
137 desc!(video; "clearvideo", "ClearVideo"),
138 desc!(video; "clearvideo_rm", "ClearVideo"),
139 desc!(audio; "ra14.4", "RealAudio 14.4"),
140 desc!(audio; "ra28.8", "RealAudio 28.8"),
141 desc!(audio; "cook", "RealAudio Cooker"),
142 desc!(audio; "ralf", "RealAudio Lossless"),
143 desc!(audio; "aac", "AAC"),
144 desc!(audio; "ac3", "ETSI TS 102 366"),
145 desc!(audio; "atrac3", "Sony Atrac3"),
146 desc!(audio; "sipro", "Sipro Labs ADPCM"),
147
148 desc!(video; "truemotion1", "TrueMotion 1"),
149 desc!(video-im; "truemotionrt", "TrueMotion RT"),
150 desc!(video; "truemotion2", "TrueMotion 2"),
151 desc!(video; "truemotion2x", "TrueMotion 2X"),
152 desc!(video; "vp3", "VP3"),
153 desc!(video; "vp4", "VP4"),
154 desc!(video; "vp5", "VP5"),
155 desc!(video; "vp6", "VP6"),
156 desc!(video; "vp6a", "VP6"),
157 desc!(video; "vp7", "VP7"),
158 desc!(video; "vp8", "VP8"),
159 desc!(video; "vp9", "VP9"),
160 desc!(audio; "adpcm-dk3", "Duck DK3 ADPCM"),
161 desc!(audio; "adpcm-dk4", "Duck DK4 ADPCM"),
162 desc!(audio; "on2avc-500", "On2 AVC"),
163 desc!(audio; "on2avc-501", "On2 AVC"),
164
165 desc!(video; "gdv-video", "Gremlin Digital Video - video"),
166 desc!(audio; "gdv-audio", "Gremlin Digital Video - audio"),
167 desc!(video; "bmv-video", "BMV video"),
168 desc!(audio; "bmv-audio", "BMV audio"),
169 desc!(video; "bmv3-video", "DW Noir BMV video"),
170 desc!(audio; "bmv3-audio", "DW Noir BMV audio"),
171 desc!(video; "midivid", "MidiVid"),
172 desc!(video; "midivid3", "MidiVid 3"),
173 desc!(video-ll; "midivid-ll", "MidiVid Lossless"),
174 desc!(video; "vmd-video", "VMD video"),
175 desc!(audio; "vmd-audio", "VMD audio"),
176
177 desc!(video; "smacker-video", "Smacker video"),
178 desc!(audio; "smacker-audio", "Smacker audio"),
179 desc!(video; "bink-video", "Bink video"),
180 desc!(video; "bink2-video", "Bink2 video"),
181 desc!(audio; "bink-audio-dct", "Bink audio (DCT)"),
182 desc!(audio; "bink-audio-rdft", "Bink audio (RDFT)"),
183 ];
184
185 static AVI_VIDEO_CODEC_REGISTER: &'static [(&[u8;4], &str)] = &[
186 (b"IF09", "indeo1"),
187 (b"RT21", "indeo2"),
188 (b"IV31", "indeo3"),
189 (b"IV32", "indeo3"),
190 (b"IV41", "indeo4"),
191 (b"IV50", "indeo5"),
192 (b"I263", "intel263"),
193
194 (b"UCOD", "clearvideo"),
195
196 (b"MVDV", "midivid"),
197 (b"MV30", "midivid3"),
198 (b"MVLZ", "midivid-ll"),
199
200 (b"DUCK", "truemotion1"),
201 (b"TR20", "truemotionrt"),
202 (b"TM20", "truemotion2"),
203 (b"TM2A", "truemotion2x"),
204 (b"TM2X", "truemotion2x"),
205 (b"VP30", "vp3"),
206 (b"VP31", "vp3"),
207 (b"VP40", "vp4"),
208 (b"VP50", "vp5"),
209 (b"VP60", "vp6"),
210 (b"VP61", "vp6"),
211 (b"VP62", "vp6"),
212 (b"VP6A", "vp6a"),
213 (b"VP70", "vp7"),
214 ];
215
216 static WAV_CODEC_REGISTER: &'static [(u16, &str)] = &[
217 (0x0000, "pcm"),
218 (0x0001, "pcm"),
219 (0x0003, "pcm"),
220 (0x0061, "adpcm-dk4"),
221 (0x0062, "adpcm-dk3"),
222 (0x0401, "imc"),
223 (0x0402, "iac"),
224 (0x0500, "on2avc-500"),
225 (0x0501, "on2avc-501"),
226 ];
227
228 pub fn find_codec_from_avi_fourcc(fcc: &[u8;4]) -> Option<&'static str> {
229 for (fourcc, name) in AVI_VIDEO_CODEC_REGISTER.iter() {
230 if *fourcc == fcc { return Some(name); }
231 }
232 None
233 }
234
235 pub fn find_codec_from_wav_twocc(tcc: u16) -> Option<&'static str> {
236 for (twocc, name) in WAV_CODEC_REGISTER.iter() {
237 if *twocc == tcc { return Some(name); }
238 }
239 None
240 }
241
242 #[cfg(test)]
243 mod test {
244 use super::*;
245
246 #[test]
247 fn test_register() {
248 let c1 = find_codec_from_avi_fourcc(b"IV41").unwrap();
249 let c2 = find_codec_from_wav_twocc(0x401).unwrap();
250 println!("found {} and {}", c1, c2);
251 let cd1 = get_codec_description(c1).unwrap();
252 let cd2 = get_codec_description(c2).unwrap();
253 println!("got {} and {}", cd1, cd2);
254 }
255 }