preliminary work on Intel I.263
[nihav.git] / src / register.rs
CommitLineData
d48ee414
KS
1use std::fmt;
2
34829caa 3#[derive(Debug,Clone,Copy,PartialEq)]
d48ee414
KS
4#[allow(dead_code)]
5pub enum CodecType {
6 Video,
7 Audio,
8 Subtitles,
9 Data,
10 None,
11}
12
13impl 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
25const CODEC_CAP_INTRAONLY:u32 = 0x000001;
26const CODEC_CAP_LOSSLESS:u32 = 0x000002;
27const CODEC_CAP_REORDER:u32 = 0x000004;
28const CODEC_CAP_HYBRID:u32 = 0x000008;
29const CODEC_CAP_SCALABLE:u32 = 0x000010;
30
34829caa 31#[derive(Clone)]
d48ee414
KS
32pub struct CodecDescription {
33 name: &'static str,
34 fname: &'static str,
35 ctype: CodecType,
36 caps: u32,
37}
38
39impl 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
50impl 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
76macro_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
111pub fn get_codec_description(name: &str) -> Option<&'static CodecDescription> {
34829caa
KS
112 for reg in CODEC_REGISTER {
113 if reg.name == name {
114 return Some(reg);
d48ee414
KS
115 }
116 }
117 None
118}
119
120static CODEC_REGISTER: &'static [CodecDescription] = &[
45e794c4
KS
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),
836bf150 126 desc!(video; "intel264", "Intel I263", CODEC_CAP_REORDER),
45e794c4
KS
127 desc!(audio; "iac", "Intel Indeo audio"),
128 desc!(audio; "imc", "Intel Music Coder"),
d48ee414
KS
129];
130
131static AVI_VIDEO_CODEC_REGISTER: &'static [(&[u8;4], &str)] = &[
45e794c4
KS
132 (b"IF09", "indeo1"),
133 (b"RT21", "indeo2"),
134 (b"IV31", "indeo3"),
135 (b"IV32", "indeo3"),
136 (b"IV41", "indeo4"),
137 (b"IV50", "indeo5"),
836bf150 138 (b"I263", "intel263"),
d48ee414
KS
139];
140
141static WAV_CODEC_REGISTER: &'static [(u16, &str)] = &[
45e794c4
KS
142 (0x0000, "pcm"),
143 (0x0001, "pcm"),
144 (0x0003, "pcm"),
145 (0x0401, "imc"),
146 (0x0402, "iac"),
d48ee414
KS
147];
148
149pub fn find_codec_from_avi_fourcc(fcc: &[u8;4]) -> Option<&'static str> {
150 for i in 0..AVI_VIDEO_CODEC_REGISTER.len() {
151 let (fourcc, name) = AVI_VIDEO_CODEC_REGISTER[i];
152 if fourcc == fcc { return Some(name); }
153 }
154 None
155}
156
157pub fn find_codec_from_wav_twocc(tcc: u16) -> Option<&'static str> {
158 for i in 0..WAV_CODEC_REGISTER.len() {
159 let (twocc, name) = WAV_CODEC_REGISTER[i];
160 if twocc == tcc { return Some(name); }
161 }
162 None
163}
164
165#[cfg(test)]
166mod test {
167 use super::*;
168
169 #[test]
170 fn test_register() {
171 let c1 = find_codec_from_avi_fourcc(b"IV41").unwrap();
172 let c2 = find_codec_from_wav_twocc(0x401).unwrap();
173 println!("found {} and {}", c1, c2);
174 let cd1 = get_codec_description(c1).unwrap();
175 let cd2 = get_codec_description(c2).unwrap();
176 println!("got {} and {}", cd1, cd2);
177 }
b58d7656 178}