core/frame: add truncate() for NAAudioBuffer
[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
2793026b
KS
34/// Codec capability flag for intra-only codecs.
35pub const CODEC_CAP_INTRAONLY:u32 = 0x0001;
36/// Codec capability flag for lossless codecs.
37pub const CODEC_CAP_LOSSLESS:u32 = 0x0002;
38/// Codec capability flag for codecs with frame reordering.
39pub const CODEC_CAP_REORDER:u32 = 0x0004;
40/// Codec capability flag for codecs that can be both lossy and lossless.
41pub const CODEC_CAP_HYBRID:u32 = 0x0008;
42/// Codec capability flag for codecs with scalability features.
43pub const CODEC_CAP_SCALABLE:u32 = 0x0010;
d48ee414 44
285f4c72 45/// Codec description structure.
34829caa 46#[derive(Clone)]
d48ee414 47pub struct CodecDescription {
285f4c72
KS
48 /// Short codec name.
49 ///
50 /// Short codec name is used inside NihAV as the unique identifier.
5641dccf 51 pub name: &'static str,
285f4c72 52 /// Full codec name.
5641dccf 53 pub fname: &'static str,
285f4c72 54 /// Codec type.
5641dccf 55 pub ctype: CodecType,
285f4c72 56 /// Codec capabilities.
5641dccf 57 pub caps: u32,
d48ee414
KS
58}
59
60impl CodecDescription {
285f4c72 61 /// Returns short codec name.
d48ee414 62 pub fn get_name(&self) -> &'static str { self.name }
285f4c72 63 /// Returns full codec name.
d48ee414 64 pub fn get_full_name(&self) -> &'static str { self.fname }
285f4c72 65 /// Returns codec type.
d48ee414 66 pub fn get_codec_type(&self) -> CodecType { self.ctype }
285f4c72 67 /// Reports whether the codec has only intra frames or not.
d48ee414 68 pub fn is_intraonly(&self) -> bool { (self.caps & CODEC_CAP_INTRAONLY) != 0 }
285f4c72 69 /// Reports whether the codec is lossless.
d48ee414 70 pub fn is_lossless(&self) -> bool { (self.caps & CODEC_CAP_LOSSLESS) != 0 }
285f4c72 71 /// Reports whether the codec requires frame reordering.
d48ee414 72 pub fn has_reorder(&self) -> bool { (self.caps & CODEC_CAP_REORDER) != 0 }
285f4c72 73 /// Reports whether the codec can be either lossless or lossy.
d48ee414 74 pub fn is_hybrid(&self) -> bool { (self.caps & CODEC_CAP_HYBRID) != 0 }
285f4c72
KS
75 /// Reports whether codec supports scalability.
76 ///
77 /// Scalability means that codec can be decoded in reduced resolution by design.
d48ee414
KS
78 pub fn is_scalable(&self) -> bool { (self.caps & CODEC_CAP_SCALABLE) != 0 }
79}
80
81impl fmt::Display for CodecDescription {
82 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
e243ceb4 83 let mut out = self.fname.to_string();
d48ee414
KS
84 if self.caps != 0 {
85 let mut capfmt = "".to_string();
86 if (self.caps & CODEC_CAP_INTRAONLY) != 0 {
87 capfmt = format!("{} Intra-only", capfmt);
88 }
89 if (self.caps & CODEC_CAP_LOSSLESS) != 0 {
90 capfmt = format!("{} Lossless", capfmt);
91 }
92 if (self.caps & CODEC_CAP_REORDER) != 0 {
93 capfmt = format!("{} Frame reorder", capfmt);
94 }
95 if (self.caps & CODEC_CAP_HYBRID) != 0 {
96 capfmt = format!("{} Can be lossy and lossless", capfmt);
97 }
98 if (self.caps & CODEC_CAP_SCALABLE) != 0 {
99 capfmt = format!("{} Scalable", capfmt);
100 }
101 out = format!("{} ({})", out, capfmt);
102 }
103 write!(f, "{}", out)
104 }
105}
106
107macro_rules! desc {
108 (video; $n:expr, $fn:expr) => ({
109 CodecDescription{ name: $n, fname: $fn, ctype: CodecType::Video,
110 caps: 0 }
111 });
112 (video; $n:expr, $fn:expr, $c:expr) => ({
113 CodecDescription{ name: $n, fname: $fn, ctype: CodecType::Video,
114 caps: $c }
115 });
116 (video-ll; $n:expr, $fn:expr) => ({
117 CodecDescription{ name: $n, fname: $fn, ctype: CodecType::Video,
118 caps: CODEC_CAP_LOSSLESS | CODEC_CAP_INTRAONLY }
119 });
120 (video-llp; $n:expr, $fn:expr) => ({
121 CodecDescription{ name: $n, fname: $fn, ctype: CodecType::Video,
122 caps: CODEC_CAP_LOSSLESS }
123 });
124 (video-im; $n:expr, $fn:expr) => ({
125 CodecDescription{ name: $n, fname: $fn, ctype: CodecType::Video,
126 caps: CODEC_CAP_INTRAONLY }
127 });
128 (video-modern; $n:expr, $fn:expr) => ({
129 CodecDescription{ name: $n, fname: $fn, ctype: CodecType::Video,
130 caps: CODEC_CAP_REORDER | CODEC_CAP_HYBRID }
131 });
132 (audio; $n:expr, $fn:expr) => ({
133 CodecDescription{ name: $n, fname: $fn, ctype: CodecType::Audio,
134 caps: 0 }
135 });
136 (audio-ll; $n:expr, $fn:expr) => ({
137 CodecDescription{ name: $n, fname: $fn, ctype: CodecType::Audio,
138 caps: CODEC_CAP_LOSSLESS | CODEC_CAP_INTRAONLY }
139 });
140}
141
285f4c72 142/// Returns codec description for the provided codec short name if it is found.
d48ee414 143pub fn get_codec_description(name: &str) -> Option<&'static CodecDescription> {
34829caa
KS
144 for reg in CODEC_REGISTER {
145 if reg.name == name {
146 return Some(reg);
d48ee414
KS
147 }
148 }
149 None
150}
151
152static CODEC_REGISTER: &'static [CodecDescription] = &[
e8e022f4 153 desc!(audio-ll; "pcm", "PCM"),
3d5fb08f
KS
154 desc!(audio; "alaw", "A-law PCM"),
155 desc!(audio; "ulaw", "mu-law PCM"),
e8e022f4 156
45e794c4
KS
157 desc!(video-im; "indeo1", "Intel Raw IF09"),
158 desc!(video-im; "indeo2", "Intel Indeo 2"),
159 desc!(video; "indeo3", "Intel Indeo 3"),
160 desc!(video; "indeo4", "Intel Indeo 4", CODEC_CAP_REORDER | CODEC_CAP_SCALABLE),
161 desc!(video; "indeo5", "Intel Indeo 5", CODEC_CAP_REORDER | CODEC_CAP_SCALABLE),
1a36a05d 162 desc!(video; "intel263", "Intel I263", CODEC_CAP_REORDER),
45e794c4
KS
163 desc!(audio; "iac", "Intel Indeo audio"),
164 desc!(audio; "imc", "Intel Music Coder"),
ce52b3b5
KS
165
166 desc!(video; "realvideo1", "Real Video 1"),
6b2cdc84 167 desc!(video; "realvideo2", "Real Video 2", CODEC_CAP_REORDER),
ce52b3b5
KS
168 desc!(video; "realvideo3", "Real Video 3", CODEC_CAP_REORDER),
169 desc!(video; "realvideo4", "Real Video 4", CODEC_CAP_REORDER),
0b791d5c 170 desc!(video; "realvideo6", "Real Video 6", CODEC_CAP_REORDER),
ce52b3b5 171 desc!(video; "clearvideo", "ClearVideo"),
750b299c 172 desc!(video; "clearvideo_rm", "ClearVideo"),
ce52b3b5
KS
173 desc!(audio; "ra14.4", "RealAudio 14.4"),
174 desc!(audio; "ra28.8", "RealAudio 28.8"),
175 desc!(audio; "cook", "RealAudio Cooker"),
176 desc!(audio; "ralf", "RealAudio Lossless"),
177 desc!(audio; "aac", "AAC"),
16dd4f44 178 desc!(audio; "ac3", "ETSI TS 102 366"),
ce52b3b5
KS
179 desc!(audio; "atrac3", "Sony Atrac3"),
180 desc!(audio; "sipro", "Sipro Labs ADPCM"),
e8e022f4 181
57777a0a
KS
182 desc!(video; "cinepak", "Cinepak"),
183
4abcd842 184 desc!(video; "msvideo1", "MS Video 1"),
03c406ea 185 desc!(video; "msrle", "MS RLE"),
4abcd842
KS
186 desc!(audio; "ms-adpcm", "MS ADPCM"),
187 desc!(audio; "ima-adpcm-ms", "IMA ADPCM (MS variant)"),
188
3d5fb08f
KS
189 desc!(video; "qt-smc", "Apple Graphics"),
190 desc!(video; "qt-rle", "Apple Animation"),
191 desc!(video; "apple-video", "Apple video"),
192 desc!(video; "sorenson-video", "Sorenson Video"),
8251c0ab 193 desc!(video; "sorenson-video3", "Sorenson Video 3", CODEC_CAP_REORDER),
3d5fb08f
KS
194 desc!(audio; "mace-3", "MACE 3:1"),
195 desc!(audio; "mace-6", "MACE 6:1"),
196 desc!(audio; "ima-adpcm-qt", "IMA ADPCM (Apple variant)"),
197 desc!(audio; "qdesign-music", "QDesign Music"),
198 desc!(audio; "qdesign-music2", "QDesign Music v2"),
199 desc!(audio; "qualcomm-purevoice", "Qualcomm PureVoice"),
200
d24468d9
KS
201 desc!(video; "truemotion1", "TrueMotion 1"),
202 desc!(video-im; "truemotionrt", "TrueMotion RT"),
203 desc!(video; "truemotion2", "TrueMotion 2"),
e8e022f4
KS
204 desc!(video; "truemotion2x", "TrueMotion 2X"),
205 desc!(video; "vp3", "VP3"),
206 desc!(video; "vp4", "VP4"),
207 desc!(video; "vp5", "VP5"),
208 desc!(video; "vp6", "VP6"),
629a1025 209 desc!(video; "vp6a", "VP6"),
e8e022f4
KS
210 desc!(video; "vp7", "VP7"),
211 desc!(video; "vp8", "VP8"),
212 desc!(video; "vp9", "VP9"),
213 desc!(audio; "adpcm-dk3", "Duck DK3 ADPCM"),
214 desc!(audio; "adpcm-dk4", "Duck DK4 ADPCM"),
629a1025
KS
215 desc!(audio; "on2avc-500", "On2 AVC"),
216 desc!(audio; "on2avc-501", "On2 AVC"),
e8e022f4
KS
217
218 desc!(video; "gdv-video", "Gremlin Digital Video - video"),
219 desc!(audio; "gdv-audio", "Gremlin Digital Video - audio"),
220 desc!(video; "bmv-video", "BMV video"),
221 desc!(audio; "bmv-audio", "BMV audio"),
ecda1cc1
KS
222 desc!(video; "bmv3-video", "DW Noir BMV video"),
223 desc!(audio; "bmv3-audio", "DW Noir BMV audio"),
801bba83
KS
224 desc!(video; "midivid", "MidiVid"),
225 desc!(video; "midivid3", "MidiVid 3"),
226 desc!(video-ll; "midivid-ll", "MidiVid Lossless"),
9895bd7b
KS
227 desc!(video; "vmd-video", "VMD video"),
228 desc!(audio; "vmd-audio", "VMD audio"),
55d85231
KS
229 desc!(video; "vxvideo", "Actimagine Vx"),
230 desc!(audio; "vxaudio", "Actimagine Sx"),
e8e022f4
KS
231
232 desc!(video; "smacker-video", "Smacker video"),
233 desc!(audio; "smacker-audio", "Smacker audio"),
234 desc!(video; "bink-video", "Bink video"),
235 desc!(video; "bink2-video", "Bink2 video"),
236 desc!(audio; "bink-audio-dct", "Bink audio (DCT)"),
237 desc!(audio; "bink-audio-rdft", "Bink audio (RDFT)"),
ed374345
KS
238
239 desc!(audio; "lhst15f8", "L&H StreamTalk 15kbps at 8 kHz"),
240 desc!(audio; "lhst250f11", "L&H StreamTalk 25kbps at 11 kHz"),
241 desc!(audio; "lhst500f22", "L&H StreamTalk 50kpbs at 22 kHz"),
242 desc!(audio; "lhst48", "L&H StreamTalk CELP Codec 4.8kbps at 8 kHz"),
31cf33ac
KS
243
244 desc!(video; "vivo1", "VivoActive Video 1.0"),
245 desc!(video; "vivo2", "VivoActive Video 2.0", CODEC_CAP_REORDER),
246 desc!(audio; "g723.1", "ITU G.723.1"),
247 desc!(audio; "siren", "Polycom Siren"),
d48ee414
KS
248];
249
250static AVI_VIDEO_CODEC_REGISTER: &'static [(&[u8;4], &str)] = &[
423005dc
KS
251 (&[1, 0, 0, 0], "msrle"),
252 (&[2, 0, 0, 0], "msrle"),
253
4abcd842
KS
254 (b"CRAM", "msvideo1"),
255 (b"MSVC", "msvideo1"),
256 (b"WHAM", "msvideo1"),
257
45e794c4
KS
258 (b"IF09", "indeo1"),
259 (b"RT21", "indeo2"),
260 (b"IV31", "indeo3"),
261 (b"IV32", "indeo3"),
262 (b"IV41", "indeo4"),
263 (b"IV50", "indeo5"),
836bf150 264 (b"I263", "intel263"),
ce52b3b5 265
750b299c 266 (b"UCOD", "clearvideo"),
57777a0a 267 (b"cvid", "cinepak"),
b2d656d0 268
801bba83
KS
269 (b"MVDV", "midivid"),
270 (b"MV30", "midivid3"),
271 (b"MVLZ", "midivid-ll"),
272
b2d656d0
KS
273 (b"DUCK", "truemotion1"),
274 (b"TR20", "truemotionrt"),
275 (b"TM20", "truemotion2"),
276 (b"TM2A", "truemotion2x"),
277 (b"TM2X", "truemotion2x"),
40e95291
KS
278 (b"VP30", "vp3"),
279 (b"VP31", "vp3"),
280 (b"VP40", "vp4"),
281 (b"VP50", "vp5"),
282 (b"VP60", "vp6"),
283 (b"VP61", "vp6"),
284 (b"VP62", "vp6"),
1bf8e0fc 285 (b"VP6A", "vp6a"),
40e95291 286 (b"VP70", "vp7"),
d48ee414
KS
287];
288
289static WAV_CODEC_REGISTER: &'static [(u16, &str)] = &[
9d9c811b 290 (0x0000, "unknown"),
45e794c4 291 (0x0001, "pcm"),
4abcd842 292 (0x0002, "ms-adpcm"),
45e794c4 293 (0x0003, "pcm"),
4abcd842 294 (0x0011, "ima-adpcm-ms"),
fadee95f
KS
295 (0x0061, "adpcm-dk4"),
296 (0x0062, "adpcm-dk3"),
45e794c4
KS
297 (0x0401, "imc"),
298 (0x0402, "iac"),
a38be6e4
KS
299 (0x0500, "on2avc-500"),
300 (0x0501, "on2avc-501"),
d48ee414
KS
301];
302
646f4c43
KS
303static MOV_VIDEO_CODEC_REGISTER: &'static [(&[u8;4], &str)] = &[
304 (b"cvid", "cinepak"),
305 (b"jpeg", "jpeg"),
306 //(b"raw ", "raw"),
307 //(b"Yuv2", "raw"),
308 (b"smc ", "qt-smc"),
309 (b"rle ", "qt-rle"),
310 (b"rpza", "apple-video"),
311 (b"kpcd", "kodak-photocd"),
312 //(b"mpeg", "mpeg-video"),
313 (b"mjpa", "mjpeg-a"),
314 (b"mjpb", "mjpeg-b"),
315 (b"svqi", "sorenson-video"),
b2689495 316 (b"SVQ1", "sorenson-video"),
3d5fb08f 317 (b"svq3", "sorenson-video3"),
b2689495 318 (b"SVQ3", "sorenson-video3"),
646f4c43
KS
319
320 (b"IV31", "indeo3"),
321 (b"IV32", "indeo3"),
322
323 (b"UCOD", "clearvideo"),
324
325 (b"VP30", "vp3"),
326 (b"VP31", "vp3"),
327];
328
329static MOV_AUDIO_CODEC_REGISTER: &'static [(&[u8;4], &str)] = &[
330 (b"NONE", "pcm"),
331 (b"raw ", "pcm"),
332 (b"twos", "pcm"),
333 (b"sowt", "pcm"),
334 (b"fl32", "pcm"),
335 (b"fl64", "pcm"),
336 (b"in24", "pcm"),
337 (b"in32", "pcm"),
338 (b"MAC3", "mace-3"),
339 (b"MAC6", "mace-6"),
340 (b"ima4", "ima-adpcm-qt"),
341 (b"ulaw", "ulaw"),
342 (b"alaw", "alaw"),
343 (b"dvca", "dv-audio"),
344 (b"QDMC", "qdesign-music"),
345 (b"QDM2", "qdesign-music2"),
346 (b"Qclp", "qualcomm-purevoice"),
347 //(b".mp3", "mpeg-layer3"),
348];
349
285f4c72 350/// Returns video codec short name for provided FOURCC (used in AVI format).
d48ee414 351pub fn find_codec_from_avi_fourcc(fcc: &[u8;4]) -> Option<&'static str> {
e243ceb4
KS
352 for (fourcc, name) in AVI_VIDEO_CODEC_REGISTER.iter() {
353 if *fourcc == fcc { return Some(name); }
d48ee414
KS
354 }
355 None
356}
357
9a3ce86c
KS
358/// Returns FOURCC (used in AVI format) for provided codec name.
359pub fn find_avi_fourcc(codecname: &str) -> Option<[u8; 4]> {
360 for (fourcc, name) in AVI_VIDEO_CODEC_REGISTER.iter() {
361 if *name == codecname { return Some(**fourcc); }
362 }
363 None
364}
365
285f4c72 366/// Returns known audio codec short name for provided TWOCC (used in WAV and AVI format).
d48ee414 367pub fn find_codec_from_wav_twocc(tcc: u16) -> Option<&'static str> {
e243ceb4
KS
368 for (twocc, name) in WAV_CODEC_REGISTER.iter() {
369 if *twocc == tcc { return Some(name); }
d48ee414
KS
370 }
371 None
372}
373
9a3ce86c
KS
374/// Returns TWOCC (used in WAV and AVI format for provided codec name.
375pub fn find_wav_twocc(codecname: &str) -> Option<u16> {
376 for (twocc, name) in WAV_CODEC_REGISTER.iter() {
377 if *name == codecname { return Some(*twocc); }
378 }
379 None
380}
381
646f4c43
KS
382/// Returns video codec short name for provided FOURCC (used in MOV format).
383pub fn find_codec_from_mov_video_fourcc(fcc: &[u8;4]) -> Option<&'static str> {
384 for (fourcc, name) in MOV_VIDEO_CODEC_REGISTER.iter() {
385 if *fourcc == fcc { return Some(name); }
386 }
387 None
388}
389
390/// Returns known audio codec short name for provided FOURCC (used in MOV format).
391pub fn find_codec_from_mov_audio_fourcc(fcc: &[u8;4]) -> Option<&'static str> {
392 for (fourcc, name) in MOV_AUDIO_CODEC_REGISTER.iter() {
393 if *fourcc == fcc { return Some(name); }
394 }
395 None
396}
397
d48ee414
KS
398#[cfg(test)]
399mod test {
400 use super::*;
401
402 #[test]
403 fn test_register() {
404 let c1 = find_codec_from_avi_fourcc(b"IV41").unwrap();
405 let c2 = find_codec_from_wav_twocc(0x401).unwrap();
406 println!("found {} and {}", c1, c2);
407 let cd1 = get_codec_description(c1).unwrap();
408 let cd2 = get_codec_description(c2).unwrap();
409 println!("got {} and {}", cd1, cd2);
410 }
b58d7656 411}