a9d354a8a2381c4e396a3cd603231907916dcac4
[nihav.git] / nihav-core / src / scale / repack.rs
1 use crate::formats::*;
2 use super::*;
3 use super::kernel::Kernel;
4
5 fn 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)]
23 struct 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
31 impl PackKernel {
32 fn new() -> Self { Self::default() }
33 }
34
35 impl Kernel for PackKernel {
36 fn init(&mut self, in_fmt: &ScaleInfo, dest_fmt: &ScaleInfo) -> ScaleResult<NABufferType> {
37 self.ncomps = in_fmt.fmt.components.min(dest_fmt.fmt.components) as usize;
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 {
64 dst[x * step + self.ooff[comp]] = convert_depth(u32::from(src[x]), self.depths[comp], self.osize[comp]) as u8;
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 {
83 let c = u32::from(src[ioff[comp] + x]);
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 {
93 unimplemented!();
94 }
95 } else if let Some(ref _buf) = pic_in.get_vbuf16() {
96 unimplemented!();
97 } else if let Some(ref _buf) = pic_in.get_vbuf32() {
98 unimplemented!();
99 } else {
100 unreachable!();
101 }
102 }
103 }
104
105 pub fn create_pack() -> Box<dyn Kernel> {
106 Box::new(PackKernel::new())
107 }
108
109 #[derive(Default)]
110 struct 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
118 impl UnpackKernel {
119 fn new() -> Self { Self::default() }
120 }
121
122 impl Kernel for UnpackKernel {
123 fn init(&mut self, in_fmt: &ScaleInfo, dest_fmt: &ScaleInfo) -> ScaleResult<NABufferType> {
124 self.ncomps = in_fmt.fmt.components.min(dest_fmt.fmt.components) as usize;
125 let mut chr: Vec<Option<NAPixelChromaton>> = Vec::with_capacity(MAX_CHROMATONS);
126 for i in 0..self.ncomps {
127 let ichr = in_fmt.fmt.comp_info[i].unwrap();
128 let ochr = dest_fmt.fmt.comp_info[i].unwrap();
129 self.shifts[i] = ichr.shift;
130 self.masks[i] = (1 << ichr.depth) - 1;
131 if ochr.depth > ichr.depth {
132 self.osize[i] = ochr.depth;
133 } else {
134 self.osize[i] = (ichr.depth + 7) & !7;
135 }
136 self.depths[i] = ichr.depth;
137 let mut dchr = ichr;
138 dchr.packed = false;
139 dchr.depth = self.osize[i];
140 dchr.shift = 0;
141 dchr.comp_offs = 0;
142 dchr.next_elem = 0;
143 chr.push(Some(dchr));
144 }
145 let mut df = in_fmt.fmt;
146 df.comp_info[..self.ncomps].clone_from_slice(&chr[..self.ncomps]);
147 df.components = self.ncomps as u8;
148 df.palette = false;
149 println!(" [intermediate format {}]", df);
150 let res = alloc_video_buffer(NAVideoInfo::new(in_fmt.width, in_fmt.height, false, df), 3);
151 if res.is_err() { return Err(ScaleError::AllocError); }
152 Ok(res.unwrap())
153 }
154 fn process(&mut self, pic_in: &NABufferType, pic_out: &mut NABufferType) {
155 if let Some(ref buf) = pic_in.get_vbuf() {
156 let step = buf.get_info().get_format().elem_size as usize;
157 let mut soff: [usize; MAX_CHROMATONS] = [0; MAX_CHROMATONS];
158 for i in 0..self.ncomps {
159 soff[i] = buf.get_info().get_format().get_chromaton(i).unwrap().get_offset() as usize;
160 }
161 let (w, h) = buf.get_dimensions(0);
162 let ioff = buf.get_offset(0);
163 let istride = buf.get_stride(0);
164 let sdata1 = buf.get_data();
165 let sdata = &sdata1[ioff..];
166 let ychr = buf.get_info().get_format().get_chromaton(0).unwrap();
167 if let Some(ref mut dbuf) = pic_out.get_vbuf() {
168 let mut ostride: [usize; MAX_CHROMATONS] = [0; MAX_CHROMATONS];
169 let mut offs: [usize; MAX_CHROMATONS] = [0; MAX_CHROMATONS];
170 for i in 0..self.ncomps {
171 ostride[i] = dbuf.get_stride(i);
172 offs[i] = dbuf.get_offset(i);
173 }
174 let dst = dbuf.get_data_mut().unwrap();
175 if ychr.next_elem == 0 || usize::from(ychr.next_elem) == step {
176 for src in sdata.chunks(istride).take(h) {
177 for x in 0..w {
178 for i in 0..self.ncomps {
179 dst[offs[i] + x] = src[x * step + soff[i]];
180 }
181 }
182 for i in 0..self.ncomps { offs[i] += ostride[i]; }
183 }
184 } else {
185 let mut steps: [usize; MAX_CHROMATONS] = [0; MAX_CHROMATONS];
186 for i in 0..self.ncomps {
187 steps[i] = buf.get_info().get_format().get_chromaton(i).unwrap().next_elem as usize;
188 }
189
190 for src in sdata.chunks(istride).take(h) {
191 let mut x = offs;
192 for piece in src.chunks(step) {
193 for i in 0..self.ncomps {
194 let mut co = soff[i];
195 while co < step {
196 dst[x[i]] = piece[co];
197 x[i] += 1;
198 co += steps[i];
199 }
200 }
201 }
202 for i in 0..self.ncomps { offs[i] += ostride[i]; }
203 }
204 }
205 } else {
206 unimplemented!();
207 }
208 } else if let Some(ref buf) = pic_in.get_vbuf16() {
209 let (w, h) = buf.get_dimensions(0);
210 let ioff = buf.get_offset(0);
211 let istride = buf.get_stride(0);
212 let sdata1 = buf.get_data();
213 let sdata = &sdata1[ioff..];
214 if let Some(ref mut dbuf) = pic_out.get_vbuf() {
215 let mut ostride: [usize; MAX_CHROMATONS] = [0; MAX_CHROMATONS];
216 let mut offs: [usize; MAX_CHROMATONS] = [0; MAX_CHROMATONS];
217 for i in 0..self.ncomps {
218 ostride[i] = dbuf.get_stride(i);
219 offs[i] = dbuf.get_offset(i);
220 }
221 let dst = dbuf.get_data_mut().unwrap();
222 for src in sdata.chunks(istride).take(h) {
223 for x in 0..w {
224 let elem = u32::from(src[x]);
225 for i in 0..self.ncomps {
226 dst[offs[i] + x] = convert_depth((elem >> self.shifts[i]) & self.masks[i], self.depths[i], self.osize[i]) as u8;
227 }
228 }
229 for i in 0..self.ncomps { offs[i] += ostride[i]; }
230 }
231 } else {
232 unimplemented!();
233 }
234 } else if let Some(ref _buf) = pic_in.get_vbuf32() {
235 unimplemented!();
236 } else {
237 unreachable!();
238 }
239 }
240 }
241
242 pub fn create_unpack() -> Box<dyn Kernel> {
243 Box::new(UnpackKernel::new())
244 }
245
246 #[derive(Default)]
247 struct DepalKernel {
248 depths: [u8; MAX_CHROMATONS],
249 coffs: [usize; MAX_CHROMATONS],
250 ncomps: usize,
251 palstep: usize,
252 }
253
254 impl DepalKernel {
255 fn new() -> Self { Self::default() }
256 }
257
258 impl Kernel for DepalKernel {
259 fn init(&mut self, in_fmt: &ScaleInfo, _dest_fmt: &ScaleInfo) -> ScaleResult<NABufferType> {
260 //todo select output more fitting for dest_fmt if possible
261 self.ncomps = in_fmt.fmt.components as usize;
262 let mut chr: Vec<Option<NAPixelChromaton>> = Vec::with_capacity(MAX_CHROMATONS);
263 self.palstep = in_fmt.fmt.elem_size as usize;
264 for i in 0..self.ncomps {
265 let ichr = in_fmt.fmt.comp_info[i].unwrap();
266 self.coffs[i] = ichr.comp_offs as usize;
267 self.depths[i] = ichr.depth;
268 let mut dchr = ichr;
269 dchr.packed = false;
270 dchr.depth = 8;
271 dchr.shift = 0;
272 dchr.comp_offs = i as u8;
273 dchr.next_elem = 0;
274 chr.push(Some(dchr));
275 }
276 let mut df = in_fmt.fmt;
277 df.palette = false;
278 df.comp_info[..self.ncomps].clone_from_slice(&chr[..self.ncomps]);
279 println!(" [intermediate format {}]", df);
280 let res = alloc_video_buffer(NAVideoInfo::new(in_fmt.width, in_fmt.height, false, df), 3);
281 if res.is_err() { return Err(ScaleError::AllocError); }
282 Ok(res.unwrap())
283 }
284 fn process(&mut self, pic_in: &NABufferType, pic_out: &mut NABufferType) {
285 if let (Some(ref sbuf), Some(ref mut dbuf)) = (pic_in.get_vbuf(), pic_out.get_vbuf()) {
286 let ioff = sbuf.get_offset(0);
287 let paloff = sbuf.get_offset(1);
288 let (w, h) = sbuf.get_dimensions(0);
289 let istride = sbuf.get_stride(0);
290 let sdata1 = sbuf.get_data();
291 let sdata = &sdata1[ioff..];
292 let pal = &sdata1[paloff..];
293
294 let mut ostride: [usize; MAX_CHROMATONS] = [0; MAX_CHROMATONS];
295 let mut offs: [usize; MAX_CHROMATONS] = [0; MAX_CHROMATONS];
296 for i in 0..self.ncomps {
297 ostride[i] = dbuf.get_stride(i);
298 offs[i] = dbuf.get_offset(i);
299 }
300 let dst = dbuf.get_data_mut().unwrap();
301 for src in sdata.chunks(istride).take(h) {
302 for x in 0..w {
303 let palidx = src[x] as usize;
304 for i in 0..self.ncomps {
305 let elem = u32::from(pal[palidx * self.palstep + self.coffs[i]]);
306 dst[offs[i] + x] = convert_depth(elem, self.depths[i], 8) as u8;
307 }
308 }
309 for i in 0..self.ncomps { offs[i] += ostride[i]; }
310 }
311 } else {
312 unreachable!();
313 }
314 }
315 }
316
317 pub fn create_depal() -> Box<dyn Kernel> {
318 Box::new(DepalKernel::new())
319 }