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