core/scale: add options support
[nihav.git] / nihav-core / src / scale / repack.rs
CommitLineData
03accf76
KS
1use crate::formats::*;
2use super::*;
3use super::kernel::Kernel;
4
5fn convert_depth(val: u32, indepth: u8, outdepth: u8) -> u32 {
6 if indepth >= outdepth {
7 val >> (indepth - outdepth)
8 } else {
9 let mut val2 = val << (outdepth - indepth);
10 let mut shift = outdepth - indepth;
11 while shift >= indepth {
12 shift -= indepth;
13 val2 |= val << shift;
14 }
15 if shift > 0 {
16 val2 |= val >> (indepth - shift);
17 }
18 val2
19 }
20}
21
22#[derive(Default)]
23struct PackKernel {
24 shifts: [u8; MAX_CHROMATONS],
25 depths: [u8; MAX_CHROMATONS],
26 ncomps: usize,
27 osize: [u8; MAX_CHROMATONS],
28 ooff: [usize; MAX_CHROMATONS],
29}
30
31impl PackKernel {
32 fn new() -> Self { Self::default() }
33}
34
35impl Kernel for PackKernel {
25e0bf9a 36 fn init(&mut self, in_fmt: &ScaleInfo, dest_fmt: &ScaleInfo, _options: &[(String, String)]) -> ScaleResult<NABufferType> {
4997179d 37 self.ncomps = in_fmt.fmt.components.min(dest_fmt.fmt.components) as usize;
03accf76
KS
38 for i in 0..self.ncomps {
39 let ichr = in_fmt.fmt.comp_info[i].unwrap();
40 let ochr = dest_fmt.fmt.comp_info[i].unwrap();
41 self.shifts[i] = ochr.shift;
42 self.osize[i] = ochr.depth;
43 self.depths[i] = ichr.depth;
44 self.ooff[i] = ochr.comp_offs as usize;
45 }
46 let res = alloc_video_buffer(NAVideoInfo::new(in_fmt.width, in_fmt.height, false, dest_fmt.fmt), 3);
47 if res.is_err() { return Err(ScaleError::AllocError); }
48 Ok(res.unwrap())
49 }
50 fn process(&mut self, pic_in: &NABufferType, pic_out: &mut NABufferType) {
51 if let Some(ref buf) = pic_in.get_vbuf() {
52 if let Some(ref mut dbuf) = pic_out.get_vbuf() {
53 let dstride = dbuf.get_stride(0);
54 for comp in 0..self.ncomps {
55 let ioff = buf.get_offset(comp);
56 let istride = buf.get_stride(comp);
57 let step = dbuf.get_info().get_format().get_chromaton(comp).unwrap().get_step() as usize;
58 let (w, h) = dbuf.get_dimensions(comp);
59 let sdata = buf.get_data();
60 let sdata = &sdata[ioff..];
61 let ddata = dbuf.get_data_mut().unwrap();
62 for (src, dst) in sdata.chunks(istride).zip(ddata.chunks_mut(dstride)).take(h) {
63 for x in 0..w {
e243ceb4 64 dst[x * step + self.ooff[comp]] = convert_depth(u32::from(src[x]), self.depths[comp], self.osize[comp]) as u8;
03accf76
KS
65 }
66 }
67 }
68 } else if let Some(ref mut dbuf) = pic_out.get_vbuf16() {
69 let (w, h) = dbuf.get_dimensions(0);
70 let dstride = dbuf.get_stride(0);
71 let ddata = dbuf.get_data_mut().unwrap();
72 let src = buf.get_data();
73 let mut ioff: [usize; MAX_CHROMATONS] = [0; MAX_CHROMATONS];
74 let mut istride: [usize; MAX_CHROMATONS] = [0; MAX_CHROMATONS];
75 for comp in 0..self.ncomps {
76 ioff[comp] = buf.get_offset(comp);
77 istride[comp] = buf.get_stride(comp);
78 }
79 for dst in ddata.chunks_mut(dstride).take(h) {
80 for x in 0..w {
81 let mut elem: u32 = 0;
82 for comp in 0..self.ncomps {
e243ceb4 83 let c = u32::from(src[ioff[comp] + x]);
03accf76
KS
84 elem |= convert_depth(c, self.depths[comp], self.osize[comp]) << self.shifts[comp];
85 }
86 dst[x] = elem as u16;
87 }
88 for comp in 0..self.ncomps {
89 ioff[comp] += istride[comp];
90 }
91 }
92 } else {
93unimplemented!();
94 }
95 } else if let Some(ref _buf) = pic_in.get_vbuf16() {
96unimplemented!();
97 } else if let Some(ref _buf) = pic_in.get_vbuf32() {
98unimplemented!();
99 } else {
100 unreachable!();
101 }
102 }
103}
104
6011e201 105pub fn create_pack() -> Box<dyn Kernel> {
03accf76
KS
106 Box::new(PackKernel::new())
107}
108
109#[derive(Default)]
110struct UnpackKernel {
111 shifts: [u8; MAX_CHROMATONS],
112 masks: [u32; MAX_CHROMATONS],
113 depths: [u8; MAX_CHROMATONS],
114 ncomps: usize,
115 osize: [u8; MAX_CHROMATONS],
116}
117
118impl UnpackKernel {
119 fn new() -> Self { Self::default() }
120}
121
122impl Kernel for UnpackKernel {
25e0bf9a
KS
123 fn init(&mut self, in_fmt: &ScaleInfo, dest_fmt: &ScaleInfo, options: &[(String, String)]) -> ScaleResult<NABufferType> {
124 let mut debug = false;
125 for (name, value) in options.iter() {
126 match (name.as_str(), value.as_str()) {
127 ("debug", "") => { debug = true; },
128 ("debug", "true") => { debug = true; },
129 _ => {},
130 }
131 }
132
4997179d 133 self.ncomps = in_fmt.fmt.components.min(dest_fmt.fmt.components) as usize;
03accf76
KS
134 let mut chr: Vec<Option<NAPixelChromaton>> = Vec::with_capacity(MAX_CHROMATONS);
135 for i in 0..self.ncomps {
136 let ichr = in_fmt.fmt.comp_info[i].unwrap();
137 let ochr = dest_fmt.fmt.comp_info[i].unwrap();
138 self.shifts[i] = ichr.shift;
139 self.masks[i] = (1 << ichr.depth) - 1;
140 if ochr.depth > ichr.depth {
141 self.osize[i] = ochr.depth;
142 } else {
143 self.osize[i] = (ichr.depth + 7) & !7;
144 }
145 self.depths[i] = ichr.depth;
146 let mut dchr = ichr;
147 dchr.packed = false;
148 dchr.depth = self.osize[i];
149 dchr.shift = 0;
150 dchr.comp_offs = 0;
151 dchr.next_elem = 0;
152 chr.push(Some(dchr));
153 }
154 let mut df = in_fmt.fmt;
b36f412c 155 df.comp_info[..self.ncomps].clone_from_slice(&chr[..self.ncomps]);
4997179d 156 df.components = self.ncomps as u8;
4b459d0b 157 df.palette = false;
25e0bf9a
KS
158 if debug {
159 println!(" [intermediate format {}]", df);
160 }
03accf76
KS
161 let res = alloc_video_buffer(NAVideoInfo::new(in_fmt.width, in_fmt.height, false, df), 3);
162 if res.is_err() { return Err(ScaleError::AllocError); }
163 Ok(res.unwrap())
164 }
165 fn process(&mut self, pic_in: &NABufferType, pic_out: &mut NABufferType) {
166 if let Some(ref buf) = pic_in.get_vbuf() {
871c9432 167 let step = buf.get_info().get_format().elem_size as usize;
03accf76
KS
168 let mut soff: [usize; MAX_CHROMATONS] = [0; MAX_CHROMATONS];
169 for i in 0..self.ncomps {
170 soff[i] = buf.get_info().get_format().get_chromaton(i).unwrap().get_offset() as usize;
171 }
172 let (w, h) = buf.get_dimensions(0);
173 let ioff = buf.get_offset(0);
174 let istride = buf.get_stride(0);
175 let sdata1 = buf.get_data();
176 let sdata = &sdata1[ioff..];
871c9432 177 let ychr = buf.get_info().get_format().get_chromaton(0).unwrap();
03accf76
KS
178 if let Some(ref mut dbuf) = pic_out.get_vbuf() {
179 let mut ostride: [usize; MAX_CHROMATONS] = [0; MAX_CHROMATONS];
180 let mut offs: [usize; MAX_CHROMATONS] = [0; MAX_CHROMATONS];
181 for i in 0..self.ncomps {
182 ostride[i] = dbuf.get_stride(i);
183 offs[i] = dbuf.get_offset(i);
184 }
185 let dst = dbuf.get_data_mut().unwrap();
871c9432
KS
186 if ychr.next_elem == 0 || usize::from(ychr.next_elem) == step {
187 for src in sdata.chunks(istride).take(h) {
188 for x in 0..w {
189 for i in 0..self.ncomps {
190 dst[offs[i] + x] = src[x * step + soff[i]];
191 }
192 }
193 for i in 0..self.ncomps { offs[i] += ostride[i]; }
194 }
195 } else {
196 let mut steps: [usize; MAX_CHROMATONS] = [0; MAX_CHROMATONS];
197 for i in 0..self.ncomps {
198 steps[i] = buf.get_info().get_format().get_chromaton(i).unwrap().next_elem as usize;
199 }
200
201 for src in sdata.chunks(istride).take(h) {
202 let mut x = offs;
203 for piece in src.chunks(step) {
204 for i in 0..self.ncomps {
205 let mut co = soff[i];
206 while co < step {
207 dst[x[i]] = piece[co];
208 x[i] += 1;
209 co += steps[i];
210 }
211 }
03accf76 212 }
871c9432 213 for i in 0..self.ncomps { offs[i] += ostride[i]; }
03accf76 214 }
03accf76
KS
215 }
216 } else {
217unimplemented!();
218 }
219 } else if let Some(ref buf) = pic_in.get_vbuf16() {
220 let (w, h) = buf.get_dimensions(0);
221 let ioff = buf.get_offset(0);
222 let istride = buf.get_stride(0);
223 let sdata1 = buf.get_data();
224 let sdata = &sdata1[ioff..];
225 if let Some(ref mut dbuf) = pic_out.get_vbuf() {
226 let mut ostride: [usize; MAX_CHROMATONS] = [0; MAX_CHROMATONS];
227 let mut offs: [usize; MAX_CHROMATONS] = [0; MAX_CHROMATONS];
228 for i in 0..self.ncomps {
229 ostride[i] = dbuf.get_stride(i);
230 offs[i] = dbuf.get_offset(i);
231 }
232 let dst = dbuf.get_data_mut().unwrap();
233 for src in sdata.chunks(istride).take(h) {
234 for x in 0..w {
e243ceb4 235 let elem = u32::from(src[x]);
03accf76
KS
236 for i in 0..self.ncomps {
237 dst[offs[i] + x] = convert_depth((elem >> self.shifts[i]) & self.masks[i], self.depths[i], self.osize[i]) as u8;
238 }
239 }
240 for i in 0..self.ncomps { offs[i] += ostride[i]; }
241 }
242 } else {
243unimplemented!();
244 }
245 } else if let Some(ref _buf) = pic_in.get_vbuf32() {
246unimplemented!();
247 } else {
248 unreachable!();
249 }
250 }
251}
252
6011e201 253pub fn create_unpack() -> Box<dyn Kernel> {
03accf76
KS
254 Box::new(UnpackKernel::new())
255}
256
257#[derive(Default)]
258struct DepalKernel {
259 depths: [u8; MAX_CHROMATONS],
260 coffs: [usize; MAX_CHROMATONS],
261 ncomps: usize,
262 palstep: usize,
263}
264
265impl DepalKernel {
266 fn new() -> Self { Self::default() }
267}
268
269impl Kernel for DepalKernel {
25e0bf9a
KS
270 fn init(&mut self, in_fmt: &ScaleInfo, _dest_fmt: &ScaleInfo, options: &[(String, String)]) -> ScaleResult<NABufferType> {
271 let mut debug = false;
272 for (name, value) in options.iter() {
273 match (name.as_str(), value.as_str()) {
274 ("debug", "") => { debug = true; },
275 ("debug", "true") => { debug = true; },
276 _ => {},
277 }
278 }
279
03accf76
KS
280//todo select output more fitting for dest_fmt if possible
281 self.ncomps = in_fmt.fmt.components as usize;
282 let mut chr: Vec<Option<NAPixelChromaton>> = Vec::with_capacity(MAX_CHROMATONS);
283 self.palstep = in_fmt.fmt.elem_size as usize;
284 for i in 0..self.ncomps {
285 let ichr = in_fmt.fmt.comp_info[i].unwrap();
286 self.coffs[i] = ichr.comp_offs as usize;
287 self.depths[i] = ichr.depth;
288 let mut dchr = ichr;
289 dchr.packed = false;
290 dchr.depth = 8;
291 dchr.shift = 0;
292 dchr.comp_offs = i as u8;
293 dchr.next_elem = 0;
294 chr.push(Some(dchr));
295 }
296 let mut df = in_fmt.fmt;
297 df.palette = false;
b36f412c 298 df.comp_info[..self.ncomps].clone_from_slice(&chr[..self.ncomps]);
25e0bf9a
KS
299 if debug {
300 println!(" [intermediate format {}]", df);
301 }
03accf76
KS
302 let res = alloc_video_buffer(NAVideoInfo::new(in_fmt.width, in_fmt.height, false, df), 3);
303 if res.is_err() { return Err(ScaleError::AllocError); }
304 Ok(res.unwrap())
305 }
306 fn process(&mut self, pic_in: &NABufferType, pic_out: &mut NABufferType) {
307 if let (Some(ref sbuf), Some(ref mut dbuf)) = (pic_in.get_vbuf(), pic_out.get_vbuf()) {
308 let ioff = sbuf.get_offset(0);
309 let paloff = sbuf.get_offset(1);
310 let (w, h) = sbuf.get_dimensions(0);
311 let istride = sbuf.get_stride(0);
312 let sdata1 = sbuf.get_data();
313 let sdata = &sdata1[ioff..];
314 let pal = &sdata1[paloff..];
315
316 let mut ostride: [usize; MAX_CHROMATONS] = [0; MAX_CHROMATONS];
317 let mut offs: [usize; MAX_CHROMATONS] = [0; MAX_CHROMATONS];
318 for i in 0..self.ncomps {
319 ostride[i] = dbuf.get_stride(i);
320 offs[i] = dbuf.get_offset(i);
321 }
322 let dst = dbuf.get_data_mut().unwrap();
323 for src in sdata.chunks(istride).take(h) {
324 for x in 0..w {
325 let palidx = src[x] as usize;
326 for i in 0..self.ncomps {
e243ceb4 327 let elem = u32::from(pal[palidx * self.palstep + self.coffs[i]]);
03accf76
KS
328 dst[offs[i] + x] = convert_depth(elem, self.depths[i], 8) as u8;
329 }
330 }
331 for i in 0..self.ncomps { offs[i] += ostride[i]; }
332 }
333 } else {
334 unreachable!();
335 }
336 }
337}
338
6011e201 339pub fn create_depal() -> Box<dyn Kernel> {
03accf76
KS
340 Box::new(DepalKernel::new())
341}