h263-based codecs: use proper motion compensation
[nihav.git] / nihav-codec-support / src / codecs / h263 / code.rs
CommitLineData
401b2b60 1use nihav_core::frame::{NAVideoBuffer, NAVideoBufferRef, NASimpleVideoFrame};
2a2aa421
KS
2use super::{BlockDSP, CBPInfo, MV};
3use super::super::blockdsp;
401b2b60 4use super::data::H263_CHROMA_ROUND;
cf64af13
KS
5
6/*const W1: i32 = 22725;
7const W2: i32 = 21407;
8const W3: i32 = 19266;
9const W4: i32 = 16383;
10const W5: i32 = 12873;
11const W6: i32 = 8867;
12const W7: i32 = 4520;
13
14const ROW_SHIFT: u8 = 11;
15const COL_SHIFT: u8 = 20;
16
17fn idct_row(row: &mut [i16]) {
18 let in0 = row[0] as i32;
19 let in1 = row[1] as i32;
20 let in2 = row[2] as i32;
21 let in3 = row[3] as i32;
22 let in4 = row[4] as i32;
23 let in5 = row[5] as i32;
24 let in6 = row[6] as i32;
25 let in7 = row[7] as i32;
26
27 let mut a0 = in0 * W1 + (1 << (ROW_SHIFT - 1));
28 let mut a1 = a0;
29 let mut a2 = a0;
30 let mut a3 = a0;
31
32 a0 += W2 * in2;
33 a1 += W6 * in2;
34 a2 -= W6 * in2;
35 a3 -= W2 * in2;
36
37 let mut b0 = W1 * in1 + W3 * in3;
38 let mut b1 = W3 * in1 - W7 * in3;
39 let mut b2 = W5 * in1 - W1 * in3;
40 let mut b3 = W7 * in1 - W5 * in3;
41
42 a0 += W4 * in4 + W6 * in6;
43 a1 -= W4 * in4 + W2 * in6;
44 a2 -= W4 * in4 - W2 * in6;
45 a3 += W4 * in4 - W6 * in6;
46
47 b0 += W5 * in5 + W7 * in7;
48 b1 -= W1 * in5 + W5 * in7;
49 b2 += W7 * in5 + W3 * in7;
50 b3 += W3 * in5 - W1 * in7;
51
52 row[0] = ((a0 + b0) >> ROW_SHIFT) as i16;
53 row[7] = ((a0 - b0) >> ROW_SHIFT) as i16;
54 row[1] = ((a1 + b1) >> ROW_SHIFT) as i16;
55 row[6] = ((a1 - b1) >> ROW_SHIFT) as i16;
56 row[2] = ((a2 + b2) >> ROW_SHIFT) as i16;
57 row[5] = ((a2 - b2) >> ROW_SHIFT) as i16;
58 row[3] = ((a3 + b3) >> ROW_SHIFT) as i16;
59 row[4] = ((a3 - b3) >> ROW_SHIFT) as i16;
60}
61
62fn idct_col(blk: &mut [i16; 64], off: usize) {
63 let in0 = blk[off + 0*8] as i32;
64 let in1 = blk[off + 1*8] as i32;
65 let in2 = blk[off + 2*8] as i32;
66 let in3 = blk[off + 3*8] as i32;
67 let in4 = blk[off + 4*8] as i32;
68 let in5 = blk[off + 5*8] as i32;
69 let in6 = blk[off + 6*8] as i32;
70 let in7 = blk[off + 7*8] as i32;
71
72 let mut a0 = in0 * W1 + (1 << (COL_SHIFT - 1));
73 let mut a1 = a0;
74 let mut a2 = a0;
75 let mut a3 = a0;
76
77 a0 += W2 * in2;
78 a1 += W6 * in2;
79 a2 -= W6 * in2;
80 a3 -= W2 * in2;
81
82 let mut b0 = W1 * in1 + W3 * in3;
83 let mut b1 = W3 * in1 - W7 * in3;
84 let mut b2 = W5 * in1 - W1 * in3;
85 let mut b3 = W7 * in1 - W5 * in3;
86
87 a0 += W4 * in4 + W6 * in6;
88 a1 -= W4 * in4 + W2 * in6;
89 a2 -= W4 * in4 - W2 * in6;
90 a3 += W4 * in4 - W6 * in6;
91
92 b0 += W5 * in5 + W7 * in7;
93 b1 -= W1 * in5 + W5 * in7;
94 b2 += W7 * in5 + W3 * in7;
95 b3 += W3 * in5 - W1 * in7;
96
97 blk[off + 0*8] = ((a0 + b0) >> COL_SHIFT) as i16;
98 blk[off + 7*8] = ((a0 - b0) >> COL_SHIFT) as i16;
99 blk[off + 1*8] = ((a1 + b1) >> COL_SHIFT) as i16;
100 blk[off + 6*8] = ((a1 - b1) >> COL_SHIFT) as i16;
101 blk[off + 2*8] = ((a2 + b2) >> COL_SHIFT) as i16;
102 blk[off + 5*8] = ((a2 - b2) >> COL_SHIFT) as i16;
103 blk[off + 3*8] = ((a3 + b3) >> COL_SHIFT) as i16;
104 blk[off + 4*8] = ((a3 - b3) >> COL_SHIFT) as i16;
105}
106
107#[allow(dead_code)]
108pub fn h263_idct(blk: &mut [i16; 64]) {
109 for i in 0..8 { idct_row(&mut blk[i*8..(i+1)*8]); }
110 for i in 0..8 { idct_col(blk, i); }
111}*/
112
113const W1: i32 = 2841;
114const W2: i32 = 2676;
115const W3: i32 = 2408;
116const W5: i32 = 1609;
117const W6: i32 = 1108;
118const W7: i32 = 565;
119const W8: i32 = 181;
120
121const ROW_SHIFT: u8 = 8;
122const COL_SHIFT: u8 = 14;
123
e243ceb4 124#[allow(clippy::erasing_op)]
cf64af13 125fn idct_row(row: &mut [i16]) {
e243ceb4
KS
126 let in0 = ((i32::from(row[0])) << 11) + (1 << (ROW_SHIFT - 1));
127 let in1 = (i32::from(row[4])) << 11;
128 let in2 = i32::from(row[6]);
129 let in3 = i32::from(row[2]);
130 let in4 = i32::from(row[1]);
131 let in5 = i32::from(row[7]);
132 let in6 = i32::from(row[5]);
133 let in7 = i32::from(row[3]);
cf64af13
KS
134
135 let tmp = W7 * (in4 + in5);
136 let a4 = tmp + (W1 - W7) * in4;
137 let a5 = tmp - (W1 + W7) * in5;
138
139 let tmp = W3 * (in6 + in7);
140 let a6 = tmp - (W3 - W5) * in6;
141 let a7 = tmp - (W3 + W5) * in7;
142
143 let tmp = in0 + in1;
144
145 let a0 = in0 - in1;
146 let t1 = W6 * (in2 + in3);
147 let a2 = t1 - (W2 + W6) * in2;
148 let a3 = t1 + (W2 - W6) * in3;
149 let b1 = a4 + a6;
150
151 let b4 = a4 - a6;
152 let t2 = a5 - a7;
153 let b6 = a5 + a7;
154 let b7 = tmp + a3;
155 let b5 = tmp - a3;
156 let b3 = a0 + a2;
157 let b0 = a0 - a2;
158 let b2 = (W8 * (b4 + t2) + 128) >> 8;
159 let b4 = (W8 * (b4 - t2) + 128) >> 8;
160
161 row[0] = ((b7 + b1) >> ROW_SHIFT) as i16;
162 row[7] = ((b7 - b1) >> ROW_SHIFT) as i16;
163 row[1] = ((b3 + b2) >> ROW_SHIFT) as i16;
164 row[6] = ((b3 - b2) >> ROW_SHIFT) as i16;
165 row[2] = ((b0 + b4) >> ROW_SHIFT) as i16;
166 row[5] = ((b0 - b4) >> ROW_SHIFT) as i16;
167 row[3] = ((b5 + b6) >> ROW_SHIFT) as i16;
168 row[4] = ((b5 - b6) >> ROW_SHIFT) as i16;
169}
170
e243ceb4 171#[allow(clippy::erasing_op)]
cf64af13 172fn idct_col(blk: &mut [i16; 64], off: usize) {
e243ceb4
KS
173 let in0 = ((i32::from(blk[off + 0*8])) << 8) + (1 << (COL_SHIFT - 1));
174 let in1 = (i32::from(blk[off + 4*8])) << 8;
175 let in2 = i32::from(blk[off + 6*8]);
176 let in3 = i32::from(blk[off + 2*8]);
177 let in4 = i32::from(blk[off + 1*8]);
178 let in5 = i32::from(blk[off + 7*8]);
179 let in6 = i32::from(blk[off + 5*8]);
180 let in7 = i32::from(blk[off + 3*8]);
cf64af13
KS
181
182 let tmp = W7 * (in4 + in5);
183 let a4 = (tmp + (W1 - W7) * in4) >> 3;
184 let a5 = (tmp - (W1 + W7) * in5) >> 3;
185
186 let tmp = W3 * (in6 + in7);
187 let a6 = (tmp - (W3 - W5) * in6) >> 3;
188 let a7 = (tmp - (W3 + W5) * in7) >> 3;
189
190 let tmp = in0 + in1;
191
192 let a0 = in0 - in1;
193 let t1 = W6 * (in2 + in3);
194 let a2 = (t1 - (W2 + W6) * in2) >> 3;
195 let a3 = (t1 + (W2 - W6) * in3) >> 3;
196 let b1 = a4 + a6;
197
198 let b4 = a4 - a6;
199 let t2 = a5 - a7;
200 let b6 = a5 + a7;
201 let b7 = tmp + a3;
202 let b5 = tmp - a3;
203 let b3 = a0 + a2;
204 let b0 = a0 - a2;
205 let b2 = (W8 * (b4 + t2) + 128) >> 8;
206 let b4 = (W8 * (b4 - t2) + 128) >> 8;
207
208 blk[off + 0*8] = ((b7 + b1) >> COL_SHIFT) as i16;
209 blk[off + 7*8] = ((b7 - b1) >> COL_SHIFT) as i16;
210 blk[off + 1*8] = ((b3 + b2) >> COL_SHIFT) as i16;
211 blk[off + 6*8] = ((b3 - b2) >> COL_SHIFT) as i16;
212 blk[off + 2*8] = ((b0 + b4) >> COL_SHIFT) as i16;
213 blk[off + 5*8] = ((b0 - b4) >> COL_SHIFT) as i16;
214 blk[off + 3*8] = ((b5 + b6) >> COL_SHIFT) as i16;
215 blk[off + 4*8] = ((b5 - b6) >> COL_SHIFT) as i16;
216}
217
218#[allow(dead_code)]
219pub fn h263_idct(blk: &mut [i16; 64]) {
220 for i in 0..8 { idct_row(&mut blk[i*8..(i+1)*8]); }
221 for i in 0..8 { idct_col(blk, i); }
222}
223
224fn h263_interp00(dst: &mut [u8], dstride: usize, src: &[u8], sstride: usize, bw: usize, bh: usize)
225{
226 let mut didx = 0;
227 let mut sidx = 0;
228 for _ in 0..bh {
229 for x in 0..bw { dst[didx + x] = src[sidx + x]; }
230 didx += dstride;
231 sidx += sstride;
232 }
233}
234
235fn h263_interp01(dst: &mut [u8], dstride: usize, src: &[u8], sstride: usize, bw: usize, bh: usize)
236{
237 let mut didx = 0;
238 let mut sidx = 0;
239 for _ in 0..bh {
240 for x in 0..bw { dst[didx + x] = (((src[sidx + x] as u16) + (src[sidx + x + 1] as u16) + 1) >> 1) as u8; }
241 didx += dstride;
242 sidx += sstride;
243 }
244}
245
246fn h263_interp10(dst: &mut [u8], dstride: usize, src: &[u8], sstride: usize, bw: usize, bh: usize)
247{
248 let mut didx = 0;
249 let mut sidx = 0;
250 for _ in 0..bh {
251 for x in 0..bw { dst[didx + x] = (((src[sidx + x] as u16) + (src[sidx + x + sstride] as u16) + 1) >> 1) as u8; }
252 didx += dstride;
253 sidx += sstride;
254 }
255}
256
257fn h263_interp11(dst: &mut [u8], dstride: usize, src: &[u8], sstride: usize, bw: usize, bh: usize)
258{
259 let mut didx = 0;
260 let mut sidx = 0;
261 for _ in 0..bh {
262 for x in 0..bw {
263 dst[didx + x] = (((src[sidx + x] as u16) +
264 (src[sidx + x + 1] as u16) +
265 (src[sidx + x + sstride] as u16) +
266 (src[sidx + x + sstride + 1] as u16) + 2) >> 2) as u8;
267 }
268 didx += dstride;
269 sidx += sstride;
270 }
271}
272
fdb4b2fb 273pub const H263_INTERP_FUNCS: &[blockdsp::BlkInterpFunc] = &[
cf64af13 274 h263_interp00, h263_interp01, h263_interp10, h263_interp11 ];
21c16d5f
KS
275
276fn h263_interp00_avg(dst: &mut [u8], dstride: usize, src: &[u8], sstride: usize, bw: usize, bh: usize)
277{
278 let mut didx = 0;
279 let mut sidx = 0;
280 for _ in 0..bh {
281 for x in 0..bw {
282 let a = dst[didx + x] as u16;
283 let b = src[sidx + x] as u16;
284 dst[didx + x] = ((a + b + 1) >> 1) as u8;
285 }
286 didx += dstride;
287 sidx += sstride;
288 }
289}
290
291fn h263_interp01_avg(dst: &mut [u8], dstride: usize, src: &[u8], sstride: usize, bw: usize, bh: usize)
292{
293 let mut didx = 0;
294 let mut sidx = 0;
295 for _ in 0..bh {
296 for x in 0..bw {
297 let a = dst[didx + x] as u16;
298 let b = ((src[sidx + x] as u16) + (src[sidx + x + 1] as u16) + 1) >> 1;
299 dst[didx + x] = ((a + b + 1) >> 1) as u8;
300 }
301 didx += dstride;
302 sidx += sstride;
303 }
304}
305
306fn h263_interp10_avg(dst: &mut [u8], dstride: usize, src: &[u8], sstride: usize, bw: usize, bh: usize)
307{
308 let mut didx = 0;
309 let mut sidx = 0;
310 for _ in 0..bh {
311 for x in 0..bw {
312 let a = dst[didx + x] as u16;
313 let b = ((src[sidx + x] as u16) + (src[sidx + x + sstride] as u16) + 1) >> 1;
314 dst[didx + x] = ((a + b + 1) >> 1) as u8;
315 }
316 didx += dstride;
317 sidx += sstride;
318 }
319}
320
321fn h263_interp11_avg(dst: &mut [u8], dstride: usize, src: &[u8], sstride: usize, bw: usize, bh: usize)
322{
323 let mut didx = 0;
324 let mut sidx = 0;
325 for _ in 0..bh {
326 for x in 0..bw {
327 let a = dst[didx + x] as u16;
328 let b = ((src[sidx + x] as u16) +
329 (src[sidx + x + 1] as u16) +
330 (src[sidx + x + sstride] as u16) +
331 (src[sidx + x + sstride + 1] as u16) + 2) >> 2;
332 dst[didx + x] = ((a + b + 1) >> 1) as u8;
333 }
334 didx += dstride;
335 sidx += sstride;
336 }
337}
338
fdb4b2fb 339pub const H263_INTERP_AVG_FUNCS: &[blockdsp::BlkInterpFunc] = &[
21c16d5f 340 h263_interp00_avg, h263_interp01_avg, h263_interp10_avg, h263_interp11_avg ];
2a2aa421
KS
341
342pub struct H263BlockDSP { }
343
344impl H263BlockDSP {
345 pub fn new() -> Self {
346 H263BlockDSP { }
347 }
348}
349
e243ceb4 350#[allow(clippy::erasing_op)]
e2626d37 351fn deblock_hor(buf: &mut NAVideoBuffer<u8>, comp: usize, strength: u8, off: usize) {
2a2aa421 352 let stride = buf.get_stride(comp);
1a967e6b 353 let dptr = buf.get_data_mut().unwrap();
9037cf6b 354 let buf = dptr.as_mut_slice();
2a2aa421
KS
355 for x in 0..8 {
356 let a = buf[off - 2 * stride + x] as i16;
357 let b = buf[off - 1 * stride + x] as i16;
358 let c = buf[off + 0 * stride + x] as i16;
359 let d = buf[off + 1 * stride + x] as i16;
e2626d37
KS
360 let diff = ((a - d) + (c - b) * 4) / 8;
361 if (diff != 0) && (diff > -24) && (diff < 24) {
362 let d1a = (diff.abs() - 2 * (diff.abs() - (strength as i16)).max(0)).max(0);
363 let d1 = if d1a < 0 { 0 } else { d1a };
364 let hd1 = d1a / 2;
365 let d2 = ((a - d) / 4).max(-hd1).min(hd1);
366
367 buf[off - 2 * stride + x] = (a - d2) as u8;
368 buf[off - 1 * stride + x] = (b + d1).max(0).min(255) as u8;
369 buf[off + 0 * stride + x] = (c - d1).max(0).min(255) as u8;
370 buf[off + 1 * stride + x] = (d + d2) as u8;
2a2aa421
KS
371 }
372 }
373}
374
e2626d37 375fn deblock_ver(buf: &mut NAVideoBuffer<u8>, comp: usize, strength: u8, off: usize) {
2a2aa421 376 let stride = buf.get_stride(comp);
1a967e6b 377 let dptr = buf.get_data_mut().unwrap();
9037cf6b 378 let buf = dptr.as_mut_slice();
2a2aa421
KS
379 for y in 0..8 {
380 let a = buf[off - 2 + y * stride] as i16;
381 let b = buf[off - 1 + y * stride] as i16;
382 let c = buf[off + 0 + y * stride] as i16;
383 let d = buf[off + 1 + y * stride] as i16;
e2626d37
KS
384 let diff = (a - d + (c - b) * 4) / 8;
385 if (diff != 0) && (diff > -24) && (diff < 24) {
386 let d1a = (diff.abs() - 2 * (diff.abs() - (strength as i16)).max(0)).max(0);
387 let d1 = if d1a < 0 { 0 } else { d1a };
388 let hd1 = d1a / 2;
389 let d2 = ((a - d) / 4).max(-hd1).min(hd1);
390
391 buf[off - 2 + y * stride] = (a - d2) as u8;
392 buf[off - 1 + y * stride] = (b + d1).max(0).min(255) as u8;
393 buf[off + y * stride] = (c - d1).max(0).min(255) as u8;
394 buf[off + 1 + y * stride] = (d + d2) as u8;
2a2aa421
KS
395 }
396 }
397}
398
e2626d37
KS
399const FILTER_STRENGTH: [u8; 32] = [
400 1, 1, 2, 2, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6, 7, 7,
401 7, 8, 8, 8, 9, 9, 9, 10, 10, 10, 11, 11, 11, 12, 12, 12
402];
403
2a2aa421
KS
404pub fn h263_filter_row(buf: &mut NAVideoBuffer<u8>, mb_y: usize, mb_w: usize, cbpi: &CBPInfo) {
405 let stride = buf.get_stride(0);
406 let mut off = buf.get_offset(0) + mb_y * 16 * stride;
407 for mb_x in 0..mb_w {
408 let coff = off;
409 let coded0 = cbpi.is_coded(mb_x, 0);
410 let coded1 = cbpi.is_coded(mb_x, 1);
411 let q = cbpi.get_q(mb_w + mb_x);
e2626d37 412 let str = if q < 32 { FILTER_STRENGTH[q as usize] } else { 0 };
2a2aa421 413 if mb_y != 0 {
e2626d37
KS
414 if coded0 && cbpi.is_coded_top(mb_x, 0) { deblock_hor(buf, 0, str, coff); }
415 if coded1 && cbpi.is_coded_top(mb_x, 1) { deblock_hor(buf, 0, str, coff + 8); }
2a2aa421
KS
416 }
417 let coff = off + 8 * stride;
418 if cbpi.is_coded(mb_x, 2) && coded0 { deblock_hor(buf, 0, q, coff); }
419 if cbpi.is_coded(mb_x, 3) && coded1 { deblock_hor(buf, 0, q, coff + 8); }
420 off += 16;
421 }
422 let mut leftt = false;
423 let mut leftc = false;
424 let mut off = buf.get_offset(0) + mb_y * 16 * stride;
425 for mb_x in 0..mb_w {
426 let ctop0 = cbpi.is_coded_top(mb_x, 0);
427 let ctop1 = cbpi.is_coded_top(mb_x, 0);
428 let ccur0 = cbpi.is_coded(mb_x, 0);
429 let ccur1 = cbpi.is_coded(mb_x, 1);
430 let q = cbpi.get_q(mb_w + mb_x);
e2626d37 431 let str = if q < 32 { FILTER_STRENGTH[q as usize] } else { 0 };
2a2aa421 432 if mb_y != 0 {
ebdc6f41
KS
433 let coff = off - 8 * stride;
434 let qtop = cbpi.get_q(mb_x);
e2626d37
KS
435 let strtop = if qtop < 32 { FILTER_STRENGTH[qtop as usize] } else { 0 };
436 if leftt && ctop0 { deblock_ver(buf, 0, strtop, coff); }
437 if ctop0 && ctop1 { deblock_ver(buf, 0, strtop, coff + 8); }
2a2aa421 438 }
e2626d37
KS
439 if leftc && ccur0 { deblock_ver(buf, 0, str, off); }
440 if ccur0 && ccur1 { deblock_ver(buf, 0, str, off + 8); }
2a2aa421
KS
441 leftt = ctop1;
442 leftc = ccur1;
443 off += 16;
444 }
445 let strideu = buf.get_stride(1);
446 let stridev = buf.get_stride(2);
447 let offu = buf.get_offset(1) + mb_y * 8 * strideu;
448 let offv = buf.get_offset(2) + mb_y * 8 * stridev;
449 if mb_y != 0 {
450 for mb_x in 0..mb_w {
ebdc6f41
KS
451 let ctu = cbpi.is_coded_top(mb_x, 4);
452 let ccu = cbpi.is_coded(mb_x, 4);
453 let ctv = cbpi.is_coded_top(mb_x, 5);
454 let ccv = cbpi.is_coded(mb_x, 5);
455 let q = cbpi.get_q(mb_w + mb_x);
e2626d37
KS
456 let str = if q < 32 { FILTER_STRENGTH[q as usize] } else { 0 };
457 if ctu && ccu { deblock_hor(buf, 1, str, offu + mb_x * 8); }
458 if ctv && ccv { deblock_hor(buf, 2, str, offv + mb_x * 8); }
2a2aa421
KS
459 }
460 let mut leftu = false;
461 let mut leftv = false;
462 let offu = buf.get_offset(1) + (mb_y - 1) * 8 * strideu;
463 let offv = buf.get_offset(2) + (mb_y - 1) * 8 * stridev;
464 for mb_x in 0..mb_w {
ebdc6f41
KS
465 let ctu = cbpi.is_coded_top(mb_x, 4);
466 let ctv = cbpi.is_coded_top(mb_x, 5);
467 let qt = cbpi.get_q(mb_x);
e2626d37
KS
468 let strt = if qt < 32 { FILTER_STRENGTH[qt as usize] } else { 0 };
469 if leftu && ctu { deblock_ver(buf, 1, strt, offu + mb_x * 8); }
470 if leftv && ctv { deblock_ver(buf, 2, strt, offv + mb_x * 8); }
ebdc6f41
KS
471 leftu = ctu;
472 leftv = ctv;
2a2aa421
KS
473 }
474 }
475}
476
477impl BlockDSP for H263BlockDSP {
478 fn idct(&self, blk: &mut [i16; 64]) {
479 h263_idct(blk)
480 }
401b2b60 481 fn copy_blocks(&self, dst: &mut NAVideoBuffer<u8>, src: NAVideoBufferRef<u8>, xpos: usize, ypos: usize, mv: MV) {
2a2aa421 482 let mode = ((mv.x & 1) + (mv.y & 1) * 2) as usize;
401b2b60 483 let cmode = (if (mv.x & 3) != 0 { 1 } else { 0 }) + (if (mv.y & 3) != 0 { 2 } else { 0 });
2a2aa421 484
401b2b60
KS
485 let mut dst = NASimpleVideoFrame::from_video_buf(dst).unwrap();
486
487 blockdsp::copy_block(&mut dst, src.clone(), 0, xpos, ypos, mv.x >> 1, mv.y >> 1, 16, 16, 0, 1, mode, H263_INTERP_FUNCS);
488 blockdsp::copy_block(&mut dst, src.clone(), 1, xpos >> 1, ypos >> 1, mv.x >> 2, mv.y >> 2, 8, 8, 0, 1, cmode, H263_INTERP_FUNCS);
489 blockdsp::copy_block(&mut dst, src.clone(), 2, xpos >> 1, ypos >> 1, mv.x >> 2, mv.y >> 2, 8, 8, 0, 1, cmode, H263_INTERP_FUNCS);
490 }
491 fn copy_blocks8x8(&self, dst: &mut NAVideoBuffer<u8>, src: NAVideoBufferRef<u8>, xpos: usize, ypos: usize, mvs: &[MV; 4]) {
492 let mut dst = NASimpleVideoFrame::from_video_buf(dst).unwrap();
493
494 for i in 0..4 {
495 let xadd = (i & 1) * 8;
496 let yadd = (i & 2) * 4;
497 let mode = ((mvs[i].x & 1) + (mvs[i].y & 1) * 2) as usize;
498
499 blockdsp::copy_block(&mut dst, src.clone(), 0, xpos + xadd, ypos + yadd, mvs[i].x >> 1, mvs[i].y >> 1, 8, 8, 0, 1, mode, H263_INTERP_FUNCS);
500 }
501
502 let sum_mv = mvs[0] + mvs[1] + mvs[2] + mvs[3];
503 let cmx = (sum_mv.x >> 3) + H263_CHROMA_ROUND[(sum_mv.x & 0xF) as usize];
504 let cmy = (sum_mv.y >> 3) + H263_CHROMA_ROUND[(sum_mv.y & 0xF) as usize];
505 let mode = ((cmx & 1) + (cmy & 1) * 2) as usize;
506 for plane in 1..3 {
507 blockdsp::copy_block(&mut dst, src.clone(), plane, xpos >> 1, ypos >> 1, cmx >> 1, cmy >> 1, 8, 8, 0, 1, mode, H263_INTERP_FUNCS);
508 }
2a2aa421 509 }
401b2b60 510 fn avg_blocks(&self, dst: &mut NAVideoBuffer<u8>, src: NAVideoBufferRef<u8>, xpos: usize, ypos: usize, mv: MV) {
2a2aa421 511 let mode = ((mv.x & 1) + (mv.y & 1) * 2) as usize;
401b2b60 512 let cmode = (if (mv.x & 3) != 0 { 1 } else { 0 }) + (if (mv.y & 3) != 0 { 2 } else { 0 });
2a2aa421 513
401b2b60
KS
514 let mut dst = NASimpleVideoFrame::from_video_buf(dst).unwrap();
515
516 blockdsp::copy_block(&mut dst, src.clone(), 0, xpos, ypos, mv.x >> 1, mv.y >> 1, 16, 16, 0, 1, mode, H263_INTERP_AVG_FUNCS);
517 blockdsp::copy_block(&mut dst, src.clone(), 1, xpos >> 1, ypos >> 1, mv.x >> 2, mv.y >> 2, 8, 8, 0, 1, cmode, H263_INTERP_AVG_FUNCS);
518 blockdsp::copy_block(&mut dst, src.clone(), 2, xpos >> 1, ypos >> 1, mv.x >> 2, mv.y >> 2, 8, 8, 0, 1, cmode, H263_INTERP_AVG_FUNCS);
519 }
520 fn avg_blocks8x8(&self, dst: &mut NAVideoBuffer<u8>, src: NAVideoBufferRef<u8>, xpos: usize, ypos: usize, mvs: &[MV; 4]) {
521 let mut dst = NASimpleVideoFrame::from_video_buf(dst).unwrap();
522
523 for i in 0..4 {
524 let xadd = (i & 1) * 8;
525 let yadd = (i & 2) * 4;
526 let mode = ((mvs[i].x & 1) + (mvs[i].y & 1) * 2) as usize;
527
528 blockdsp::copy_block(&mut dst, src.clone(), 0, xpos + xadd, ypos + yadd, mvs[i].x >> 1, mvs[i].y >> 1, 8, 8, 0, 1, mode, H263_INTERP_AVG_FUNCS);
529 }
530
531 let sum_mv = mvs[0] + mvs[1] + mvs[2] + mvs[3];
532 let cmx = (sum_mv.x >> 3) + H263_CHROMA_ROUND[(sum_mv.x & 0xF) as usize];
533 let cmy = (sum_mv.y >> 3) + H263_CHROMA_ROUND[(sum_mv.y & 0xF) as usize];
534 let mode = ((cmx & 1) + (cmy & 1) * 2) as usize;
535 for plane in 1..3 {
536 blockdsp::copy_block(&mut dst, src.clone(), plane, xpos >> 1, ypos >> 1, cmx >> 1, cmy >> 1, 8, 8, 0, 1, mode, H263_INTERP_AVG_FUNCS);
537 }
2a2aa421
KS
538 }
539 fn filter_row(&self, buf: &mut NAVideoBuffer<u8>, mb_y: usize, mb_w: usize, cbpi: &CBPInfo) {
540 h263_filter_row(buf, mb_y, mb_w, cbpi)
541 }
542}