rename truemotion[3-7] into vp[3-7]
[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 = 0x000001;
26 const CODEC_CAP_LOSSLESS:u32 = 0x000002;
27 const CODEC_CAP_REORDER:u32 = 0x000004;
28 const CODEC_CAP_HYBRID:u32 = 0x000008;
29 const CODEC_CAP_SCALABLE:u32 = 0x000010;
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 = format!("{}", self.fname);
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!(video-im; "indeo1", "Intel Raw IF09"),
122 desc!(video-im; "indeo2", "Intel Indeo 2"),
123 desc!(video; "indeo3", "Intel Indeo 3"),
124 desc!(video; "indeo4", "Intel Indeo 4", CODEC_CAP_REORDER | CODEC_CAP_SCALABLE),
125 desc!(video; "indeo5", "Intel Indeo 5", CODEC_CAP_REORDER | CODEC_CAP_SCALABLE),
126 desc!(video; "intel263", "Intel I263", CODEC_CAP_REORDER),
127 desc!(audio; "iac", "Intel Indeo audio"),
128 desc!(audio; "imc", "Intel Music Coder"),
129
130 desc!(video; "realvideo1", "Real Video 1"),
131 desc!(video; "realvideo2", "Real Video 2"),
132 desc!(video; "realvideo3", "Real Video 3", CODEC_CAP_REORDER),
133 desc!(video; "realvideo4", "Real Video 4", CODEC_CAP_REORDER),
134 desc!(video; "realvideo6", "Real Video 6", CODEC_CAP_REORDER),
135 desc!(video; "clearvideo", "ClearVideo"),
136 desc!(video; "clearvideo_rm", "ClearVideo"),
137 desc!(audio; "ra14.4", "RealAudio 14.4"),
138 desc!(audio; "ra28.8", "RealAudio 28.8"),
139 desc!(audio; "cook", "RealAudio Cooker"),
140 desc!(audio; "ralf", "RealAudio Lossless"),
141 desc!(audio; "aac", "AAC"),
142 desc!(audio; "ac3", "ETSI TS 102 366"),
143 desc!(audio; "atrac3", "Sony Atrac3"),
144 desc!(audio; "sipro", "Sipro Labs ADPCM"),
145 ];
146
147 static AVI_VIDEO_CODEC_REGISTER: &'static [(&[u8;4], &str)] = &[
148 (b"IF09", "indeo1"),
149 (b"RT21", "indeo2"),
150 (b"IV31", "indeo3"),
151 (b"IV32", "indeo3"),
152 (b"IV41", "indeo4"),
153 (b"IV50", "indeo5"),
154 (b"I263", "intel263"),
155
156 (b"UCOD", "clearvideo"),
157
158 (b"DUCK", "truemotion1"),
159 (b"TR20", "truemotionrt"),
160 (b"TM20", "truemotion2"),
161 (b"TM2A", "truemotion2x"),
162 (b"TM2X", "truemotion2x"),
163 (b"VP30", "vp3"),
164 (b"VP31", "vp3"),
165 (b"VP40", "vp4"),
166 (b"VP50", "vp5"),
167 (b"VP60", "vp6"),
168 (b"VP61", "vp6"),
169 (b"VP62", "vp6"),
170 (b"VP70", "vp7"),
171 ];
172
173 static WAV_CODEC_REGISTER: &'static [(u16, &str)] = &[
174 (0x0000, "pcm"),
175 (0x0001, "pcm"),
176 (0x0003, "pcm"),
177 (0x0061, "adpcm-dk4"),
178 (0x0062, "adpcm-dk3"),
179 (0x0401, "imc"),
180 (0x0402, "iac"),
181 (0x0500, "on2avc-500"),
182 (0x0501, "on2avc-501"),
183 ];
184
185 pub fn find_codec_from_avi_fourcc(fcc: &[u8;4]) -> Option<&'static str> {
186 for i in 0..AVI_VIDEO_CODEC_REGISTER.len() {
187 let (fourcc, name) = AVI_VIDEO_CODEC_REGISTER[i];
188 if fourcc == fcc { return Some(name); }
189 }
190 None
191 }
192
193 pub fn find_codec_from_wav_twocc(tcc: u16) -> Option<&'static str> {
194 for i in 0..WAV_CODEC_REGISTER.len() {
195 let (twocc, name) = WAV_CODEC_REGISTER[i];
196 if twocc == tcc { return Some(name); }
197 }
198 None
199 }
200
201 #[cfg(test)]
202 mod test {
203 use super::*;
204
205 #[test]
206 fn test_register() {
207 let c1 = find_codec_from_avi_fourcc(b"IV41").unwrap();
208 let c2 = find_codec_from_wav_twocc(0x401).unwrap();
209 println!("found {} and {}", c1, c2);
210 let cd1 = get_codec_description(c1).unwrap();
211 let cd2 = get_codec_description(c2).unwrap();
212 println!("got {} and {}", cd1, cd2);
213 }
214 }