registry: mark Sorenson Video 3 as having B-frames
[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 148 desc!(audio-ll; "pcm", "PCM"),
3d5fb08f
KS
149 desc!(audio; "alaw", "A-law PCM"),
150 desc!(audio; "ulaw", "mu-law PCM"),
e8e022f4 151
45e794c4
KS
152 desc!(video-im; "indeo1", "Intel Raw IF09"),
153 desc!(video-im; "indeo2", "Intel Indeo 2"),
154 desc!(video; "indeo3", "Intel Indeo 3"),
155 desc!(video; "indeo4", "Intel Indeo 4", CODEC_CAP_REORDER | CODEC_CAP_SCALABLE),
156 desc!(video; "indeo5", "Intel Indeo 5", CODEC_CAP_REORDER | CODEC_CAP_SCALABLE),
1a36a05d 157 desc!(video; "intel263", "Intel I263", CODEC_CAP_REORDER),
45e794c4
KS
158 desc!(audio; "iac", "Intel Indeo audio"),
159 desc!(audio; "imc", "Intel Music Coder"),
ce52b3b5
KS
160
161 desc!(video; "realvideo1", "Real Video 1"),
6b2cdc84 162 desc!(video; "realvideo2", "Real Video 2", CODEC_CAP_REORDER),
ce52b3b5
KS
163 desc!(video; "realvideo3", "Real Video 3", CODEC_CAP_REORDER),
164 desc!(video; "realvideo4", "Real Video 4", CODEC_CAP_REORDER),
0b791d5c 165 desc!(video; "realvideo6", "Real Video 6", CODEC_CAP_REORDER),
ce52b3b5 166 desc!(video; "clearvideo", "ClearVideo"),
750b299c 167 desc!(video; "clearvideo_rm", "ClearVideo"),
ce52b3b5
KS
168 desc!(audio; "ra14.4", "RealAudio 14.4"),
169 desc!(audio; "ra28.8", "RealAudio 28.8"),
170 desc!(audio; "cook", "RealAudio Cooker"),
171 desc!(audio; "ralf", "RealAudio Lossless"),
172 desc!(audio; "aac", "AAC"),
16dd4f44 173 desc!(audio; "ac3", "ETSI TS 102 366"),
ce52b3b5
KS
174 desc!(audio; "atrac3", "Sony Atrac3"),
175 desc!(audio; "sipro", "Sipro Labs ADPCM"),
e8e022f4 176
57777a0a
KS
177 desc!(video; "cinepak", "Cinepak"),
178
4abcd842 179 desc!(video; "msvideo1", "MS Video 1"),
03c406ea 180 desc!(video; "msrle", "MS RLE"),
4abcd842
KS
181 desc!(audio; "ms-adpcm", "MS ADPCM"),
182 desc!(audio; "ima-adpcm-ms", "IMA ADPCM (MS variant)"),
183
3d5fb08f
KS
184 desc!(video; "qt-smc", "Apple Graphics"),
185 desc!(video; "qt-rle", "Apple Animation"),
186 desc!(video; "apple-video", "Apple video"),
187 desc!(video; "sorenson-video", "Sorenson Video"),
8251c0ab 188 desc!(video; "sorenson-video3", "Sorenson Video 3", CODEC_CAP_REORDER),
3d5fb08f
KS
189 desc!(audio; "mace-3", "MACE 3:1"),
190 desc!(audio; "mace-6", "MACE 6:1"),
191 desc!(audio; "ima-adpcm-qt", "IMA ADPCM (Apple variant)"),
192 desc!(audio; "qdesign-music", "QDesign Music"),
193 desc!(audio; "qdesign-music2", "QDesign Music v2"),
194 desc!(audio; "qualcomm-purevoice", "Qualcomm PureVoice"),
195
d24468d9
KS
196 desc!(video; "truemotion1", "TrueMotion 1"),
197 desc!(video-im; "truemotionrt", "TrueMotion RT"),
198 desc!(video; "truemotion2", "TrueMotion 2"),
e8e022f4
KS
199 desc!(video; "truemotion2x", "TrueMotion 2X"),
200 desc!(video; "vp3", "VP3"),
201 desc!(video; "vp4", "VP4"),
202 desc!(video; "vp5", "VP5"),
203 desc!(video; "vp6", "VP6"),
629a1025 204 desc!(video; "vp6a", "VP6"),
e8e022f4
KS
205 desc!(video; "vp7", "VP7"),
206 desc!(video; "vp8", "VP8"),
207 desc!(video; "vp9", "VP9"),
208 desc!(audio; "adpcm-dk3", "Duck DK3 ADPCM"),
209 desc!(audio; "adpcm-dk4", "Duck DK4 ADPCM"),
629a1025
KS
210 desc!(audio; "on2avc-500", "On2 AVC"),
211 desc!(audio; "on2avc-501", "On2 AVC"),
e8e022f4
KS
212
213 desc!(video; "gdv-video", "Gremlin Digital Video - video"),
214 desc!(audio; "gdv-audio", "Gremlin Digital Video - audio"),
215 desc!(video; "bmv-video", "BMV video"),
216 desc!(audio; "bmv-audio", "BMV audio"),
ecda1cc1
KS
217 desc!(video; "bmv3-video", "DW Noir BMV video"),
218 desc!(audio; "bmv3-audio", "DW Noir BMV audio"),
801bba83
KS
219 desc!(video; "midivid", "MidiVid"),
220 desc!(video; "midivid3", "MidiVid 3"),
221 desc!(video-ll; "midivid-ll", "MidiVid Lossless"),
9895bd7b
KS
222 desc!(video; "vmd-video", "VMD video"),
223 desc!(audio; "vmd-audio", "VMD audio"),
e8e022f4
KS
224
225 desc!(video; "smacker-video", "Smacker video"),
226 desc!(audio; "smacker-audio", "Smacker audio"),
227 desc!(video; "bink-video", "Bink video"),
228 desc!(video; "bink2-video", "Bink2 video"),
229 desc!(audio; "bink-audio-dct", "Bink audio (DCT)"),
230 desc!(audio; "bink-audio-rdft", "Bink audio (RDFT)"),
ed374345
KS
231
232 desc!(audio; "lhst15f8", "L&H StreamTalk 15kbps at 8 kHz"),
233 desc!(audio; "lhst250f11", "L&H StreamTalk 25kbps at 11 kHz"),
234 desc!(audio; "lhst500f22", "L&H StreamTalk 50kpbs at 22 kHz"),
235 desc!(audio; "lhst48", "L&H StreamTalk CELP Codec 4.8kbps at 8 kHz"),
31cf33ac
KS
236
237 desc!(video; "vivo1", "VivoActive Video 1.0"),
238 desc!(video; "vivo2", "VivoActive Video 2.0", CODEC_CAP_REORDER),
239 desc!(audio; "g723.1", "ITU G.723.1"),
240 desc!(audio; "siren", "Polycom Siren"),
d48ee414
KS
241];
242
243static AVI_VIDEO_CODEC_REGISTER: &'static [(&[u8;4], &str)] = &[
423005dc
KS
244 (&[1, 0, 0, 0], "msrle"),
245 (&[2, 0, 0, 0], "msrle"),
246
4abcd842
KS
247 (b"CRAM", "msvideo1"),
248 (b"MSVC", "msvideo1"),
249 (b"WHAM", "msvideo1"),
250
45e794c4
KS
251 (b"IF09", "indeo1"),
252 (b"RT21", "indeo2"),
253 (b"IV31", "indeo3"),
254 (b"IV32", "indeo3"),
255 (b"IV41", "indeo4"),
256 (b"IV50", "indeo5"),
836bf150 257 (b"I263", "intel263"),
ce52b3b5 258
750b299c 259 (b"UCOD", "clearvideo"),
57777a0a 260 (b"cvid", "cinepak"),
b2d656d0 261
801bba83
KS
262 (b"MVDV", "midivid"),
263 (b"MV30", "midivid3"),
264 (b"MVLZ", "midivid-ll"),
265
b2d656d0
KS
266 (b"DUCK", "truemotion1"),
267 (b"TR20", "truemotionrt"),
268 (b"TM20", "truemotion2"),
269 (b"TM2A", "truemotion2x"),
270 (b"TM2X", "truemotion2x"),
40e95291
KS
271 (b"VP30", "vp3"),
272 (b"VP31", "vp3"),
273 (b"VP40", "vp4"),
274 (b"VP50", "vp5"),
275 (b"VP60", "vp6"),
276 (b"VP61", "vp6"),
277 (b"VP62", "vp6"),
1bf8e0fc 278 (b"VP6A", "vp6a"),
40e95291 279 (b"VP70", "vp7"),
d48ee414
KS
280];
281
282static WAV_CODEC_REGISTER: &'static [(u16, &str)] = &[
9d9c811b 283 (0x0000, "unknown"),
45e794c4 284 (0x0001, "pcm"),
4abcd842 285 (0x0002, "ms-adpcm"),
45e794c4 286 (0x0003, "pcm"),
4abcd842 287 (0x0011, "ima-adpcm-ms"),
fadee95f
KS
288 (0x0061, "adpcm-dk4"),
289 (0x0062, "adpcm-dk3"),
45e794c4
KS
290 (0x0401, "imc"),
291 (0x0402, "iac"),
a38be6e4
KS
292 (0x0500, "on2avc-500"),
293 (0x0501, "on2avc-501"),
d48ee414
KS
294];
295
646f4c43
KS
296static MOV_VIDEO_CODEC_REGISTER: &'static [(&[u8;4], &str)] = &[
297 (b"cvid", "cinepak"),
298 (b"jpeg", "jpeg"),
299 //(b"raw ", "raw"),
300 //(b"Yuv2", "raw"),
301 (b"smc ", "qt-smc"),
302 (b"rle ", "qt-rle"),
303 (b"rpza", "apple-video"),
304 (b"kpcd", "kodak-photocd"),
305 //(b"mpeg", "mpeg-video"),
306 (b"mjpa", "mjpeg-a"),
307 (b"mjpb", "mjpeg-b"),
308 (b"svqi", "sorenson-video"),
b2689495 309 (b"SVQ1", "sorenson-video"),
3d5fb08f 310 (b"svq3", "sorenson-video3"),
b2689495 311 (b"SVQ3", "sorenson-video3"),
646f4c43
KS
312
313 (b"IV31", "indeo3"),
314 (b"IV32", "indeo3"),
315
316 (b"UCOD", "clearvideo"),
317
318 (b"VP30", "vp3"),
319 (b"VP31", "vp3"),
320];
321
322static MOV_AUDIO_CODEC_REGISTER: &'static [(&[u8;4], &str)] = &[
323 (b"NONE", "pcm"),
324 (b"raw ", "pcm"),
325 (b"twos", "pcm"),
326 (b"sowt", "pcm"),
327 (b"fl32", "pcm"),
328 (b"fl64", "pcm"),
329 (b"in24", "pcm"),
330 (b"in32", "pcm"),
331 (b"MAC3", "mace-3"),
332 (b"MAC6", "mace-6"),
333 (b"ima4", "ima-adpcm-qt"),
334 (b"ulaw", "ulaw"),
335 (b"alaw", "alaw"),
336 (b"dvca", "dv-audio"),
337 (b"QDMC", "qdesign-music"),
338 (b"QDM2", "qdesign-music2"),
339 (b"Qclp", "qualcomm-purevoice"),
340 //(b".mp3", "mpeg-layer3"),
341];
342
285f4c72 343/// Returns video codec short name for provided FOURCC (used in AVI format).
d48ee414 344pub fn find_codec_from_avi_fourcc(fcc: &[u8;4]) -> Option<&'static str> {
e243ceb4
KS
345 for (fourcc, name) in AVI_VIDEO_CODEC_REGISTER.iter() {
346 if *fourcc == fcc { return Some(name); }
d48ee414
KS
347 }
348 None
349}
350
9a3ce86c
KS
351/// Returns FOURCC (used in AVI format) for provided codec name.
352pub fn find_avi_fourcc(codecname: &str) -> Option<[u8; 4]> {
353 for (fourcc, name) in AVI_VIDEO_CODEC_REGISTER.iter() {
354 if *name == codecname { return Some(**fourcc); }
355 }
356 None
357}
358
285f4c72 359/// Returns known audio codec short name for provided TWOCC (used in WAV and AVI format).
d48ee414 360pub fn find_codec_from_wav_twocc(tcc: u16) -> Option<&'static str> {
e243ceb4
KS
361 for (twocc, name) in WAV_CODEC_REGISTER.iter() {
362 if *twocc == tcc { return Some(name); }
d48ee414
KS
363 }
364 None
365}
366
9a3ce86c
KS
367/// Returns TWOCC (used in WAV and AVI format for provided codec name.
368pub fn find_wav_twocc(codecname: &str) -> Option<u16> {
369 for (twocc, name) in WAV_CODEC_REGISTER.iter() {
370 if *name == codecname { return Some(*twocc); }
371 }
372 None
373}
374
646f4c43
KS
375/// Returns video codec short name for provided FOURCC (used in MOV format).
376pub fn find_codec_from_mov_video_fourcc(fcc: &[u8;4]) -> Option<&'static str> {
377 for (fourcc, name) in MOV_VIDEO_CODEC_REGISTER.iter() {
378 if *fourcc == fcc { return Some(name); }
379 }
380 None
381}
382
383/// Returns known audio codec short name for provided FOURCC (used in MOV format).
384pub fn find_codec_from_mov_audio_fourcc(fcc: &[u8;4]) -> Option<&'static str> {
385 for (fourcc, name) in MOV_AUDIO_CODEC_REGISTER.iter() {
386 if *fourcc == fcc { return Some(name); }
387 }
388 None
389}
390
d48ee414
KS
391#[cfg(test)]
392mod test {
393 use super::*;
394
395 #[test]
396 fn test_register() {
397 let c1 = find_codec_from_avi_fourcc(b"IV41").unwrap();
398 let c2 = find_codec_from_wav_twocc(0x401).unwrap();
399 println!("found {} and {}", c1, c2);
400 let cd1 = get_codec_description(c1).unwrap();
401 let cd2 = get_codec_description(c2).unwrap();
402 println!("got {} and {}", cd1, cd2);
403 }
b58d7656 404}