core/blockdsp: add copy_block()
[nihav.git] / nihav-core / src / codecs / blockdsp.rs
CommitLineData
aca89041 1use crate::frame::*;
cf64af13
KS
2
3pub fn put_blocks(buf: &mut NAVideoBuffer<u8>, xpos: usize, ypos: usize, blk: &[[i16;64]; 6]) {
4 let stridey = buf.get_stride(0);
5 let strideu = buf.get_stride(1);
6 let stridev = buf.get_stride(2);
7 let mut idxy = buf.get_offset(0) + xpos * 16 + ypos * 16 * stridey;
8 let mut idxu = buf.get_offset(1) + xpos * 8 + ypos * 8 * strideu;
9 let mut idxv = buf.get_offset(2) + xpos * 8 + ypos * 8 * stridev;
10
1a967e6b 11 let data = buf.get_data_mut().unwrap();
9037cf6b 12 let framebuf: &mut [u8] = data.as_mut_slice();
cf64af13
KS
13
14 for j in 0..8 {
15 for k in 0..8 {
16 let mut v = blk[0][k + j * 8];
e243ceb4 17 if v < 0 { v = 0; } else if v > 255 { v = 255; }
cf64af13
KS
18 framebuf[idxy + k] = v as u8;
19 }
20 for k in 0..8 {
21 let mut v = blk[1][k + j * 8];
e243ceb4 22 if v < 0 { v = 0; } else if v > 255 { v = 255; }
cf64af13
KS
23 framebuf[idxy + k + 8] = v as u8;
24 }
25 idxy += stridey;
26 }
27 for j in 0..8 {
28 for k in 0..8 {
29 let mut v = blk[2][k + j * 8];
e243ceb4 30 if v < 0 { v = 0; } else if v > 255 { v = 255; }
cf64af13
KS
31 framebuf[idxy + k] = v as u8;
32 }
33 for k in 0..8 {
34 let mut v = blk[3][k + j * 8];
e243ceb4 35 if v < 0 { v = 0; } else if v > 255 { v = 255; }
cf64af13
KS
36 framebuf[idxy + k + 8] = v as u8;
37 }
38 idxy += stridey;
39 }
40
41 for j in 0..8 {
42 for k in 0..8 {
43 let mut v = blk[4][k + j * 8];
e243ceb4 44 if v < 0 { v = 0; } else if v > 255 { v = 255; }
cf64af13
KS
45 framebuf[idxu + k] = v as u8;
46 }
47 for k in 0..8 {
48 let mut v = blk[5][k + j * 8];
e243ceb4 49 if v < 0 { v = 0; } else if v > 255 { v = 255; }
cf64af13
KS
50 framebuf[idxv + k] = v as u8;
51 }
52 idxu += strideu;
53 idxv += stridev;
54 }
55}
56
57pub fn add_blocks(buf: &mut NAVideoBuffer<u8>, xpos: usize, ypos: usize, blk: &[[i16;64]; 6]) {
58 let stridey = buf.get_stride(0);
59 let strideu = buf.get_stride(1);
60 let stridev = buf.get_stride(2);
61 let mut idxy = buf.get_offset(0) + xpos * 16 + ypos * 16 * stridey;
62 let mut idxu = buf.get_offset(1) + xpos * 8 + ypos * 8 * strideu;
63 let mut idxv = buf.get_offset(2) + xpos * 8 + ypos * 8 * stridev;
64
1a967e6b 65 let data = buf.get_data_mut().unwrap();
9037cf6b 66 let framebuf: &mut [u8] = data.as_mut_slice();
cf64af13
KS
67
68 for j in 0..8 {
69 for k in 0..8 {
e243ceb4
KS
70 let mut v = blk[0][k + j * 8] + i16::from(framebuf[idxy + k]);
71 if v < 0 { v = 0; } else if v > 255 { v = 255; }
cf64af13
KS
72 framebuf[idxy + k] = v as u8;
73 }
74 for k in 0..8 {
e243ceb4
KS
75 let mut v = blk[1][k + j * 8] + i16::from(framebuf[idxy + k + 8]);
76 if v < 0 { v = 0; } else if v > 255 { v = 255; }
cf64af13
KS
77 framebuf[idxy + k + 8] = v as u8;
78 }
79 idxy += stridey;
80 }
81 for j in 0..8 {
82 for k in 0..8 {
e243ceb4
KS
83 let mut v = blk[2][k + j * 8] + i16::from(framebuf[idxy + k]);
84 if v < 0 { v = 0; } else if v > 255 { v = 255; }
cf64af13
KS
85 framebuf[idxy + k] = v as u8;
86 }
87 for k in 0..8 {
e243ceb4
KS
88 let mut v = blk[3][k + j * 8] + i16::from(framebuf[idxy + k + 8]);
89 if v < 0 { v = 0; } else if v > 255 { v = 255; }
cf64af13
KS
90 framebuf[idxy + k + 8] = v as u8;
91 }
92 idxy += stridey;
93 }
94
95 for j in 0..8 {
96 for k in 0..8 {
e243ceb4
KS
97 let mut v = blk[4][k + j * 8] + i16::from(framebuf[idxu + k]);
98 if v < 0 { v = 0; } else if v > 255 { v = 255; }
cf64af13
KS
99 framebuf[idxu + k] = v as u8;
100 }
101 for k in 0..8 {
e243ceb4
KS
102 let mut v = blk[5][k + j * 8] + i16::from(framebuf[idxv + k]);
103 if v < 0 { v = 0; } else if v > 255 { v = 255; }
cf64af13
KS
104 framebuf[idxv + k] = v as u8;
105 }
106 idxu += strideu;
107 idxv += stridev;
108 }
109}
110
47527732 111pub fn edge_emu(src: &NAVideoBuffer<u8>, xpos: isize, ypos: isize, bw: usize, bh: usize, dst: &mut [u8], dstride: usize, comp: usize) {
cf64af13
KS
112 let stride = src.get_stride(comp);
113 let offs = src.get_offset(comp);
114 let (w, h) = src.get_dimensions(comp);
115 let data = src.get_data();
116 let framebuf: &[u8] = data.as_slice();
117
118 for y in 0..bh {
119 let srcy;
120 if (y as isize) + ypos < 0 { srcy = 0; }
121 else if (y as isize) + ypos >= (h as isize) { srcy = h - 1; }
122 else { srcy = ((y as isize) + ypos) as usize; }
123
124 for x in 0..bw {
125 let srcx;
126 if (x as isize) + xpos < 0 { srcx = 0; }
127 else if (x as isize) + xpos >= (w as isize) { srcx = w - 1; }
128 else { srcx = ((x as isize) + xpos) as usize; }
129 dst[x + y * dstride] = framebuf[offs + srcx + srcy * stride];
130 }
131 }
132}
133
fdb4b2fb
KS
134pub type BlkInterpFunc = fn(&mut [u8], usize, &[u8], usize, usize, usize);
135
cf64af13
KS
136pub fn copy_blocks(dst: &mut NAVideoBuffer<u8>, src: &NAVideoBuffer<u8>,
137 dx: usize, dy: usize, sx: isize, sy: isize, bw: usize, bh: usize,
138 preborder: usize, postborder: usize,
fdb4b2fb 139 mode: usize, interp: &[BlkInterpFunc])
cf64af13
KS
140{
141 let pre = if mode != 0 { preborder as isize } else { 0 };
142 let post = if mode != 0 { postborder as isize } else { 0 };
143 let (w, h) = src.get_dimensions(0);
144
145 if (sx - pre < 0) || ((sx >> 1) - pre < 0) || (sx + (bw as isize) + post > (w as isize)) ||
146 (sy - pre < 0) || ((sy >> 1) - pre < 0) || (sy + (bh as isize) + post > (h as isize)) {
147 let ebuf_stride: usize = 32;
e243ceb4 148 let mut ebuf: Vec<u8> = vec![0; ebuf_stride * (bh + ((pre + post) as usize))];
cf64af13
KS
149
150 for comp in 0..3 {
2bfdf329 151 let dstride = dst.get_stride(comp);
cf64af13 152 let doff = dst.get_offset(comp);
1a967e6b 153 let ddta = dst.get_data_mut().unwrap();
4a9d2671 154 let dbuf: &mut [u8] = ddta.as_mut_slice();
cf64af13
KS
155 let x = if comp > 0 { dx/2 } else { dx };
156 let y = if comp > 0 { dy/2 } else { dy };
157 let sx_ = (if comp > 0 { sx >> 1 } else { sx }) - pre;
158 let sy_ = (if comp > 0 { sy >> 1 } else { sy }) - pre;
159 let bw_ = (if comp > 0 { bw/2 } else { bw }) + ((pre + post) as usize);
160 let bh_ = (if comp > 0 { bh/2 } else { bh }) + ((pre + post) as usize);
161 edge_emu(src, sx_ - pre, sy_ - pre, bw_, bh_,
162 ebuf.as_mut_slice(), ebuf_stride, comp);
163 let bw_ = if comp > 0 { bw/2 } else { bw };
164 let bh_ = if comp > 0 { bh/2 } else { bh };
165 (interp[mode])(&mut dbuf[doff + x + y * dstride..], dstride, ebuf.as_slice(), ebuf_stride, bw_, bh_);
166 }
cf64af13
KS
167 } else {
168 for comp in 0..3 {
169 let sstride = src.get_stride(comp);
170 let soff = src.get_offset(comp);
171 let sdta = src.get_data();
172 let sbuf: &[u8] = sdta.as_slice();
2bfdf329 173 let dstride = dst.get_stride(comp);
cf64af13 174 let doff = dst.get_offset(comp);
1a967e6b 175 let ddta = dst.get_data_mut().unwrap();
4a9d2671 176 let dbuf: &mut [u8] = ddta.as_mut_slice();
cf64af13
KS
177 let x = if comp > 0 { dx/2 } else { dx };
178 let y = if comp > 0 { dy/2 } else { dy };
179 let sx_ = ((if comp > 0 { sx >> 1 } else { sx }) - pre) as usize;
180 let sy_ = ((if comp > 0 { sy >> 1 } else { sy }) - pre) as usize;
181 let bw_ = if comp > 0 { bw/2 } else { bw };
182 let bh_ = if comp > 0 { bh/2 } else { bh };
183 (interp[mode])(&mut dbuf[doff + x + y * dstride..], dstride, &sbuf[(soff + sx_ + sy_ * sstride)..], sstride, bw_, bh_);
184 }
185 }
186}
c6670064
KS
187
188pub fn copy_block(dst: &mut NASimpleVideoFrame<u8>, src: NAVideoBufferRef<u8>, comp: usize,
189 dx: usize, dy: usize, mv_x: i16, mv_y: i16, bw: usize, bh: usize,
190 preborder: usize, postborder: usize,
191 mode: usize, interp: &[BlkInterpFunc])
192{
193 let pre = if mode != 0 { preborder as isize } else { 0 };
194 let post = if mode != 0 { postborder as isize } else { 0 };
195 let (w, h) = src.get_dimensions(comp);
196 let sx = (dx as isize) + (mv_x as isize);
197 let sy = (dy as isize) + (mv_y as isize);
198
199 if (sx - pre < 0) || (sx + (bw as isize) + post > (w as isize)) ||
200 (sy - pre < 0) || (sy + (bh as isize) + post > (h as isize)) {
201 let ebuf_stride: usize = 32;
202 let mut ebuf: Vec<u8> = vec![0; ebuf_stride * (bh + ((pre + post) as usize))];
203
204 let dstride = dst.stride[comp];
205 let doff = dst.offset[comp];
206 let edge = (pre + post) as usize;
207 edge_emu(&src, sx - pre, sy - pre, bw + edge, bh + edge,
208 ebuf.as_mut_slice(), ebuf_stride, comp);
209 (interp[mode])(&mut dst.data[doff + dx + dy * dstride..], dstride,
210 ebuf.as_slice(), ebuf_stride, bw, bh);
211 } else {
212 let sstride = src.get_stride(comp);
213 let soff = src.get_offset(comp);
214 let sdta = src.get_data();
215 let sbuf: &[u8] = sdta.as_slice();
216 let dstride = dst.stride[comp];
217 let doff = dst.offset[comp];
218 let saddr = soff + ((sx - pre) as usize) + ((sy - pre) as usize) * sstride;
219 (interp[mode])(&mut dst.data[doff + dx + dy * dstride..], dstride,
220 &sbuf[saddr..], sstride, bw, bh);
221 }
222}