split nihav-registry from nihav-core
[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"),
160 desc!(video; "realvideo2", "Real Video 2"),
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
d24468d9
KS
175 desc!(video; "truemotion1", "TrueMotion 1"),
176 desc!(video-im; "truemotionrt", "TrueMotion RT"),
177 desc!(video; "truemotion2", "TrueMotion 2"),
e8e022f4
KS
178 desc!(video; "truemotion2x", "TrueMotion 2X"),
179 desc!(video; "vp3", "VP3"),
180 desc!(video; "vp4", "VP4"),
181 desc!(video; "vp5", "VP5"),
182 desc!(video; "vp6", "VP6"),
629a1025 183 desc!(video; "vp6a", "VP6"),
e8e022f4
KS
184 desc!(video; "vp7", "VP7"),
185 desc!(video; "vp8", "VP8"),
186 desc!(video; "vp9", "VP9"),
187 desc!(audio; "adpcm-dk3", "Duck DK3 ADPCM"),
188 desc!(audio; "adpcm-dk4", "Duck DK4 ADPCM"),
629a1025
KS
189 desc!(audio; "on2avc-500", "On2 AVC"),
190 desc!(audio; "on2avc-501", "On2 AVC"),
e8e022f4
KS
191
192 desc!(video; "gdv-video", "Gremlin Digital Video - video"),
193 desc!(audio; "gdv-audio", "Gremlin Digital Video - audio"),
194 desc!(video; "bmv-video", "BMV video"),
195 desc!(audio; "bmv-audio", "BMV audio"),
ecda1cc1
KS
196 desc!(video; "bmv3-video", "DW Noir BMV video"),
197 desc!(audio; "bmv3-audio", "DW Noir BMV audio"),
801bba83
KS
198 desc!(video; "midivid", "MidiVid"),
199 desc!(video; "midivid3", "MidiVid 3"),
200 desc!(video-ll; "midivid-ll", "MidiVid Lossless"),
9895bd7b
KS
201 desc!(video; "vmd-video", "VMD video"),
202 desc!(audio; "vmd-audio", "VMD audio"),
e8e022f4
KS
203
204 desc!(video; "smacker-video", "Smacker video"),
205 desc!(audio; "smacker-audio", "Smacker audio"),
206 desc!(video; "bink-video", "Bink video"),
207 desc!(video; "bink2-video", "Bink2 video"),
208 desc!(audio; "bink-audio-dct", "Bink audio (DCT)"),
209 desc!(audio; "bink-audio-rdft", "Bink audio (RDFT)"),
d48ee414
KS
210];
211
212static AVI_VIDEO_CODEC_REGISTER: &'static [(&[u8;4], &str)] = &[
45e794c4
KS
213 (b"IF09", "indeo1"),
214 (b"RT21", "indeo2"),
215 (b"IV31", "indeo3"),
216 (b"IV32", "indeo3"),
217 (b"IV41", "indeo4"),
218 (b"IV50", "indeo5"),
836bf150 219 (b"I263", "intel263"),
ce52b3b5 220
750b299c 221 (b"UCOD", "clearvideo"),
b2d656d0 222
801bba83
KS
223 (b"MVDV", "midivid"),
224 (b"MV30", "midivid3"),
225 (b"MVLZ", "midivid-ll"),
226
b2d656d0
KS
227 (b"DUCK", "truemotion1"),
228 (b"TR20", "truemotionrt"),
229 (b"TM20", "truemotion2"),
230 (b"TM2A", "truemotion2x"),
231 (b"TM2X", "truemotion2x"),
40e95291
KS
232 (b"VP30", "vp3"),
233 (b"VP31", "vp3"),
234 (b"VP40", "vp4"),
235 (b"VP50", "vp5"),
236 (b"VP60", "vp6"),
237 (b"VP61", "vp6"),
238 (b"VP62", "vp6"),
1bf8e0fc 239 (b"VP6A", "vp6a"),
40e95291 240 (b"VP70", "vp7"),
d48ee414
KS
241];
242
243static WAV_CODEC_REGISTER: &'static [(u16, &str)] = &[
45e794c4
KS
244 (0x0000, "pcm"),
245 (0x0001, "pcm"),
246 (0x0003, "pcm"),
fadee95f
KS
247 (0x0061, "adpcm-dk4"),
248 (0x0062, "adpcm-dk3"),
45e794c4
KS
249 (0x0401, "imc"),
250 (0x0402, "iac"),
a38be6e4
KS
251 (0x0500, "on2avc-500"),
252 (0x0501, "on2avc-501"),
d48ee414
KS
253];
254
285f4c72 255/// Returns video codec short name for provided FOURCC (used in AVI format).
d48ee414 256pub fn find_codec_from_avi_fourcc(fcc: &[u8;4]) -> Option<&'static str> {
e243ceb4
KS
257 for (fourcc, name) in AVI_VIDEO_CODEC_REGISTER.iter() {
258 if *fourcc == fcc { return Some(name); }
d48ee414
KS
259 }
260 None
261}
262
285f4c72 263/// Returns known audio codec short name for provided TWOCC (used in WAV and AVI format).
d48ee414 264pub fn find_codec_from_wav_twocc(tcc: u16) -> Option<&'static str> {
e243ceb4
KS
265 for (twocc, name) in WAV_CODEC_REGISTER.iter() {
266 if *twocc == tcc { return Some(name); }
d48ee414
KS
267 }
268 None
269}
270
271#[cfg(test)]
272mod test {
273 use super::*;
274
275 #[test]
276 fn test_register() {
277 let c1 = find_codec_from_avi_fourcc(b"IV41").unwrap();
278 let c2 = find_codec_from_wav_twocc(0x401).unwrap();
279 println!("found {} and {}", c1, c2);
280 let cd1 = get_codec_description(c1).unwrap();
281 let cd2 = get_codec_description(c2).unwrap();
282 println!("got {} and {}", cd1, cd2);
283 }
b58d7656 284}