1 use nihav_core::frame::{NAVideoBuffer, NAVideoBufferRef, NASimpleVideoFrame};
2 use super::{BlockDSP, CBPInfo, MV};
3 use super::super::blockdsp;
4 use super::data::H263_CHROMA_ROUND;
6 /*const W1: i32 = 22725;
10 const W5: i32 = 12873;
14 const ROW_SHIFT: u8 = 11;
15 const COL_SHIFT: u8 = 20;
17 fn 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;
27 let mut a0 = in0 * W1 + (1 << (ROW_SHIFT - 1));
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;
42 a0 += W4 * in4 + W6 * in6;
43 a1 -= W4 * in4 + W2 * in6;
44 a2 -= W4 * in4 - W2 * in6;
45 a3 += W4 * in4 - W6 * in6;
47 b0 += W5 * in5 + W7 * in7;
48 b1 -= W1 * in5 + W5 * in7;
49 b2 += W7 * in5 + W3 * in7;
50 b3 += W3 * in5 - W1 * in7;
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;
62 fn 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;
72 let mut a0 = in0 * W1 + (1 << (COL_SHIFT - 1));
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;
87 a0 += W4 * in4 + W6 * in6;
88 a1 -= W4 * in4 + W2 * in6;
89 a2 -= W4 * in4 - W2 * in6;
90 a3 += W4 * in4 - W6 * in6;
92 b0 += W5 * in5 + W7 * in7;
93 b1 -= W1 * in5 + W5 * in7;
94 b2 += W7 * in5 + W3 * in7;
95 b3 += W3 * in5 - W1 * in7;
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;
108 pub 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); }
113 const W1: i32 = 2841;
114 const W2: i32 = 2676;
115 const W3: i32 = 2408;
116 const W5: i32 = 1609;
117 const W6: i32 = 1108;
121 const ROW_SHIFT: u8 = 8;
122 const COL_SHIFT: u8 = 14;
124 #[allow(clippy::erasing_op)]
125 fn idct_row(row: &mut [i16]) {
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]);
135 let tmp = W7 * (in4 + in5);
136 let a4 = tmp + (W1 - W7) * in4;
137 let a5 = tmp - (W1 + W7) * in5;
139 let tmp = W3 * (in6 + in7);
140 let a6 = tmp - (W3 - W5) * in6;
141 let a7 = tmp - (W3 + W5) * in7;
146 let t1 = W6 * (in2 + in3);
147 let a2 = t1 - (W2 + W6) * in2;
148 let a3 = t1 + (W2 - W6) * in3;
158 let b2 = (W8 * (b4 + t2) + 128) >> 8;
159 let b4 = (W8 * (b4 - t2) + 128) >> 8;
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;
171 #[allow(clippy::erasing_op)]
172 fn idct_col(blk: &mut [i16; 64], off: usize) {
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]);
182 let tmp = W7 * (in4 + in5);
183 let a4 = (tmp + (W1 - W7) * in4) >> 3;
184 let a5 = (tmp - (W1 + W7) * in5) >> 3;
186 let tmp = W3 * (in6 + in7);
187 let a6 = (tmp - (W3 - W5) * in6) >> 3;
188 let a7 = (tmp - (W3 + W5) * in7) >> 3;
193 let t1 = W6 * (in2 + in3);
194 let a2 = (t1 - (W2 + W6) * in2) >> 3;
195 let a3 = (t1 + (W2 - W6) * in3) >> 3;
205 let b2 = (W8 * (b4 + t2) + 128) >> 8;
206 let b4 = (W8 * (b4 - t2) + 128) >> 8;
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;
219 pub 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); }
224 fn h263_interp00(dst: &mut [u8], dstride: usize, src: &[u8], sstride: usize, bw: usize, bh: usize)
229 for x in 0..bw { dst[didx + x] = src[sidx + x]; }
235 fn h263_interp01(dst: &mut [u8], dstride: usize, src: &[u8], sstride: usize, bw: usize, bh: usize)
240 for x in 0..bw { dst[didx + x] = (((src[sidx + x] as u16) + (src[sidx + x + 1] as u16) + 1) >> 1) as u8; }
246 fn h263_interp10(dst: &mut [u8], dstride: usize, src: &[u8], sstride: usize, bw: usize, bh: usize)
251 for x in 0..bw { dst[didx + x] = (((src[sidx + x] as u16) + (src[sidx + x + sstride] as u16) + 1) >> 1) as u8; }
257 fn h263_interp11(dst: &mut [u8], dstride: usize, src: &[u8], sstride: usize, bw: usize, bh: usize)
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;
273 pub const H263_INTERP_FUNCS: &[blockdsp::BlkInterpFunc] = &[
274 h263_interp00, h263_interp01, h263_interp10, h263_interp11 ];
276 fn h263_interp00_avg(dst: &mut [u8], dstride: usize, src: &[u8], sstride: usize, bw: usize, bh: usize)
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;
291 fn h263_interp01_avg(dst: &mut [u8], dstride: usize, src: &[u8], sstride: usize, bw: usize, bh: usize)
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;
306 fn h263_interp10_avg(dst: &mut [u8], dstride: usize, src: &[u8], sstride: usize, bw: usize, bh: usize)
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;
321 fn h263_interp11_avg(dst: &mut [u8], dstride: usize, src: &[u8], sstride: usize, bw: usize, bh: usize)
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;
339 pub const H263_INTERP_AVG_FUNCS: &[blockdsp::BlkInterpFunc] = &[
340 h263_interp00_avg, h263_interp01_avg, h263_interp10_avg, h263_interp11_avg ];
343 pub struct H263BlockDSP { }
346 pub fn new() -> Self {
351 #[allow(clippy::erasing_op)]
352 fn deblock_hor(buf: &mut NAVideoBuffer<u8>, comp: usize, strength: u8, off: usize) {
353 let stride = buf.get_stride(comp);
354 let dptr = buf.get_data_mut().unwrap();
355 let buf = dptr.as_mut_slice();
357 let a = buf[off - 2 * stride + x] as i16;
358 let b = buf[off - 1 * stride + x] as i16;
359 let c = buf[off + 0 * stride + x] as i16;
360 let d = buf[off + 1 * stride + x] as i16;
361 let diff = ((a - d) + (c - b) * 4) / 8;
362 if (diff != 0) && (diff > -24) && (diff < 24) {
363 let d1a = (diff.abs() - 2 * (diff.abs() - (strength as i16)).max(0)).max(0);
364 let d1 = if diff < 0 { -d1a } else { d1a };
366 let d2 = ((a - d) / 4).max(-hd1).min(hd1);
368 buf[off - 2 * stride + x] = (a - d2) as u8;
369 buf[off - 1 * stride + x] = (b + d1).max(0).min(255) as u8;
370 buf[off + 0 * stride + x] = (c - d1).max(0).min(255) as u8;
371 buf[off + 1 * stride + x] = (d + d2) as u8;
376 fn deblock_ver(buf: &mut NAVideoBuffer<u8>, comp: usize, strength: u8, off: usize) {
377 let stride = buf.get_stride(comp);
378 let dptr = buf.get_data_mut().unwrap();
379 let buf = dptr.as_mut_slice();
381 let a = buf[off - 2 + y * stride] as i16;
382 let b = buf[off - 1 + y * stride] as i16;
383 let c = buf[off + 0 + y * stride] as i16;
384 let d = buf[off + 1 + y * stride] as i16;
385 let diff = (a - d + (c - b) * 4) / 8;
386 if (diff != 0) && (diff > -24) && (diff < 24) {
387 let d1a = (diff.abs() - 2 * (diff.abs() - (strength as i16)).max(0)).max(0);
388 let d1 = if diff < 0 { -d1a } else { d1a };
390 let d2 = ((a - d) / 4).max(-hd1).min(hd1);
392 buf[off - 2 + y * stride] = (a - d2) as u8;
393 buf[off - 1 + y * stride] = (b + d1).max(0).min(255) as u8;
394 buf[off + y * stride] = (c - d1).max(0).min(255) as u8;
395 buf[off + 1 + y * stride] = (d + d2) as u8;
400 const FILTER_STRENGTH: [u8; 32] = [
401 1, 1, 2, 2, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6, 7, 7,
402 7, 8, 8, 8, 9, 9, 9, 10, 10, 10, 11, 11, 11, 12, 12, 12
405 pub fn h263_filter_row(buf: &mut NAVideoBuffer<u8>, mb_y: usize, mb_w: usize, cbpi: &CBPInfo) {
406 let stride = buf.get_stride(0);
407 let mut off = buf.get_offset(0) + mb_y * 16 * stride;
408 for mb_x in 0..mb_w {
410 let coded0 = cbpi.is_coded(mb_x, 0);
411 let coded1 = cbpi.is_coded(mb_x, 1);
412 let q = cbpi.get_q(mb_w + mb_x);
413 let str = if q < 32 { FILTER_STRENGTH[q as usize] } else { 0 };
415 if coded0 && cbpi.is_coded_top(mb_x, 0) { deblock_hor(buf, 0, str, coff); }
416 if coded1 && cbpi.is_coded_top(mb_x, 1) { deblock_hor(buf, 0, str, coff + 8); }
418 let coff = off + 8 * stride;
419 if cbpi.is_coded(mb_x, 2) && coded0 { deblock_hor(buf, 0, q, coff); }
420 if cbpi.is_coded(mb_x, 3) && coded1 { deblock_hor(buf, 0, q, coff + 8); }
423 let mut leftt = false;
424 let mut leftc = false;
425 let mut off = buf.get_offset(0) + mb_y * 16 * stride;
426 for mb_x in 0..mb_w {
427 let ctop0 = cbpi.is_coded_top(mb_x, 0);
428 let ctop1 = cbpi.is_coded_top(mb_x, 0);
429 let ccur0 = cbpi.is_coded(mb_x, 0);
430 let ccur1 = cbpi.is_coded(mb_x, 1);
431 let q = cbpi.get_q(mb_w + mb_x);
432 let str = if q < 32 { FILTER_STRENGTH[q as usize] } else { 0 };
434 let coff = off - 8 * stride;
435 let qtop = cbpi.get_q(mb_x);
436 let strtop = if qtop < 32 { FILTER_STRENGTH[qtop as usize] } else { 0 };
437 if leftt && ctop0 { deblock_ver(buf, 0, strtop, coff); }
438 if ctop0 && ctop1 { deblock_ver(buf, 0, strtop, coff + 8); }
440 if leftc && ccur0 { deblock_ver(buf, 0, str, off); }
441 if ccur0 && ccur1 { deblock_ver(buf, 0, str, off + 8); }
446 let strideu = buf.get_stride(1);
447 let stridev = buf.get_stride(2);
448 let offu = buf.get_offset(1) + mb_y * 8 * strideu;
449 let offv = buf.get_offset(2) + mb_y * 8 * stridev;
451 for mb_x in 0..mb_w {
452 let ctu = cbpi.is_coded_top(mb_x, 4);
453 let ccu = cbpi.is_coded(mb_x, 4);
454 let ctv = cbpi.is_coded_top(mb_x, 5);
455 let ccv = cbpi.is_coded(mb_x, 5);
456 let q = cbpi.get_q(mb_w + mb_x);
457 let str = if q < 32 { FILTER_STRENGTH[q as usize] } else { 0 };
458 if ctu && ccu { deblock_hor(buf, 1, str, offu + mb_x * 8); }
459 if ctv && ccv { deblock_hor(buf, 2, str, offv + mb_x * 8); }
461 let mut leftu = false;
462 let mut leftv = false;
463 let offu = buf.get_offset(1) + (mb_y - 1) * 8 * strideu;
464 let offv = buf.get_offset(2) + (mb_y - 1) * 8 * stridev;
465 for mb_x in 0..mb_w {
466 let ctu = cbpi.is_coded_top(mb_x, 4);
467 let ctv = cbpi.is_coded_top(mb_x, 5);
468 let qt = cbpi.get_q(mb_x);
469 let strt = if qt < 32 { FILTER_STRENGTH[qt as usize] } else { 0 };
470 if leftu && ctu { deblock_ver(buf, 1, strt, offu + mb_x * 8); }
471 if leftv && ctv { deblock_ver(buf, 2, strt, offv + mb_x * 8); }
478 impl BlockDSP for H263BlockDSP {
479 fn idct(&self, blk: &mut [i16; 64]) {
482 fn copy_blocks(&self, dst: &mut NAVideoBuffer<u8>, src: NAVideoBufferRef<u8>, xpos: usize, ypos: usize, mv: MV) {
483 let mode = ((mv.x & 1) + (mv.y & 1) * 2) as usize;
484 let cmode = (if (mv.x & 3) != 0 { 1 } else { 0 }) + (if (mv.y & 3) != 0 { 2 } else { 0 });
486 let mut dst = NASimpleVideoFrame::from_video_buf(dst).unwrap();
488 blockdsp::copy_block(&mut dst, src.clone(), 0, xpos, ypos, mv.x >> 1, mv.y >> 1, 16, 16, 0, 1, mode, H263_INTERP_FUNCS);
489 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);
490 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);
492 fn copy_blocks8x8(&self, dst: &mut NAVideoBuffer<u8>, src: NAVideoBufferRef<u8>, xpos: usize, ypos: usize, mvs: &[MV; 4]) {
493 let mut dst = NASimpleVideoFrame::from_video_buf(dst).unwrap();
496 let xadd = (i & 1) * 8;
497 let yadd = (i & 2) * 4;
498 let mode = ((mvs[i].x & 1) + (mvs[i].y & 1) * 2) as usize;
500 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);
503 let sum_mv = mvs[0] + mvs[1] + mvs[2] + mvs[3];
504 let cmx = (sum_mv.x >> 3) + H263_CHROMA_ROUND[(sum_mv.x & 0xF) as usize];
505 let cmy = (sum_mv.y >> 3) + H263_CHROMA_ROUND[(sum_mv.y & 0xF) as usize];
506 let mode = ((cmx & 1) + (cmy & 1) * 2) as usize;
508 blockdsp::copy_block(&mut dst, src.clone(), plane, xpos >> 1, ypos >> 1, cmx >> 1, cmy >> 1, 8, 8, 0, 1, mode, H263_INTERP_FUNCS);
511 fn avg_blocks(&self, dst: &mut NAVideoBuffer<u8>, src: NAVideoBufferRef<u8>, xpos: usize, ypos: usize, mv: MV) {
512 let mode = ((mv.x & 1) + (mv.y & 1) * 2) as usize;
513 let cmode = (if (mv.x & 3) != 0 { 1 } else { 0 }) + (if (mv.y & 3) != 0 { 2 } else { 0 });
515 let mut dst = NASimpleVideoFrame::from_video_buf(dst).unwrap();
517 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);
518 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);
519 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);
521 fn avg_blocks8x8(&self, dst: &mut NAVideoBuffer<u8>, src: NAVideoBufferRef<u8>, xpos: usize, ypos: usize, mvs: &[MV; 4]) {
522 let mut dst = NASimpleVideoFrame::from_video_buf(dst).unwrap();
525 let xadd = (i & 1) * 8;
526 let yadd = (i & 2) * 4;
527 let mode = ((mvs[i].x & 1) + (mvs[i].y & 1) * 2) as usize;
529 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);
532 let sum_mv = mvs[0] + mvs[1] + mvs[2] + mvs[3];
533 let cmx = (sum_mv.x >> 3) + H263_CHROMA_ROUND[(sum_mv.x & 0xF) as usize];
534 let cmy = (sum_mv.y >> 3) + H263_CHROMA_ROUND[(sum_mv.y & 0xF) as usize];
535 let mode = ((cmx & 1) + (cmy & 1) * 2) as usize;
537 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);
540 fn filter_row(&self, buf: &mut NAVideoBuffer<u8>, mb_y: usize, mb_w: usize, cbpi: &CBPInfo) {
541 h263_filter_row(buf, mb_y, mb_w, cbpi)
545 macro_rules! obmc_filter {
546 ($src: expr, $base_off: expr, $off0: expr, $w0: expr, $off1: expr, $w1: expr, $off2: expr, $w2: expr) => ({
547 let a = $src[$base_off + $off0] as u16;
548 let b = $src[$base_off + $off1] as u16;
549 let c = $src[$base_off + $off2] as u16;
550 ((a * $w0 + b * $w1 + c * $w2 + 4) >> 3) as u8
553 pub fn obmc_filter(dst: &mut [u8], dstride: usize, src: &[u8], sstride: usize) {
554 let top_off = 8 + sstride * 0;
555 let left_off = 0 + sstride * 8;
556 let right_off = 16 + sstride * 8;
557 let bottom_off = 8 + sstride * 16;
558 let cur_off = 8 + sstride * 8;
563 dst[doff + 0] = obmc_filter!(src, soff + 0, left_off, 2, top_off, 2, cur_off, 4);
564 dst[doff + 1] = obmc_filter!(src, soff + 1, left_off, 1, top_off, 2, cur_off, 5);
565 dst[doff + 2] = obmc_filter!(src, soff + 2, left_off, 1, top_off, 2, cur_off, 5);
566 dst[doff + 3] = obmc_filter!(src, soff + 3, left_off, 1, top_off, 2, cur_off, 5);
567 dst[doff + 4] = obmc_filter!(src, soff + 4, right_off, 1, top_off, 2, cur_off, 5);
568 dst[doff + 5] = obmc_filter!(src, soff + 5, right_off, 1, top_off, 2, cur_off, 5);
569 dst[doff + 6] = obmc_filter!(src, soff + 6, right_off, 1, top_off, 2, cur_off, 5);
570 dst[doff + 7] = obmc_filter!(src, soff + 7, right_off, 2, top_off, 2, cur_off, 4);
574 dst[doff + 0] = obmc_filter!(src, soff + 0, left_off, 2, top_off, 1, cur_off, 5);
575 dst[doff + 1] = obmc_filter!(src, soff + 1, left_off, 2, top_off, 1, cur_off, 5);
576 dst[doff + 2] = obmc_filter!(src, soff + 2, left_off, 1, top_off, 2, cur_off, 5);
577 dst[doff + 3] = obmc_filter!(src, soff + 3, left_off, 1, top_off, 2, cur_off, 5);
578 dst[doff + 4] = obmc_filter!(src, soff + 4, right_off, 1, top_off, 2, cur_off, 5);
579 dst[doff + 5] = obmc_filter!(src, soff + 5, right_off, 1, top_off, 2, cur_off, 5);
580 dst[doff + 6] = obmc_filter!(src, soff + 6, right_off, 2, top_off, 1, cur_off, 5);
581 dst[doff + 7] = obmc_filter!(src, soff + 7, right_off, 2, top_off, 1, cur_off, 5);
585 dst[doff + 0] = obmc_filter!(src, soff + 0, left_off, 2, top_off, 1, cur_off, 5);
586 dst[doff + 1] = obmc_filter!(src, soff + 1, left_off, 2, top_off, 1, cur_off, 5);
587 dst[doff + 2] = obmc_filter!(src, soff + 2, left_off, 1, top_off, 1, cur_off, 6);
588 dst[doff + 3] = obmc_filter!(src, soff + 3, left_off, 1, top_off, 1, cur_off, 6);
589 dst[doff + 4] = obmc_filter!(src, soff + 4, right_off, 1, top_off, 1, cur_off, 6);
590 dst[doff + 5] = obmc_filter!(src, soff + 5, right_off, 1, top_off, 1, cur_off, 6);
591 dst[doff + 6] = obmc_filter!(src, soff + 6, right_off, 2, top_off, 1, cur_off, 5);
592 dst[doff + 7] = obmc_filter!(src, soff + 7, right_off, 2, top_off, 1, cur_off, 5);
596 dst[doff + 0] = obmc_filter!(src, soff + 0, left_off, 2, top_off, 1, cur_off, 5);
597 dst[doff + 1] = obmc_filter!(src, soff + 1, left_off, 2, top_off, 1, cur_off, 5);
598 dst[doff + 2] = obmc_filter!(src, soff + 2, left_off, 1, top_off, 1, cur_off, 6);
599 dst[doff + 3] = obmc_filter!(src, soff + 3, left_off, 1, top_off, 1, cur_off, 6);
600 dst[doff + 4] = obmc_filter!(src, soff + 4, right_off, 1, top_off, 1, cur_off, 6);
601 dst[doff + 5] = obmc_filter!(src, soff + 5, right_off, 1, top_off, 1, cur_off, 6);
602 dst[doff + 6] = obmc_filter!(src, soff + 6, right_off, 2, top_off, 1, cur_off, 5);
603 dst[doff + 7] = obmc_filter!(src, soff + 7, right_off, 2, top_off, 1, cur_off, 5);
607 dst[doff + 0] = obmc_filter!(src, soff + 0, left_off, 2, bottom_off, 1, cur_off, 5);
608 dst[doff + 1] = obmc_filter!(src, soff + 1, left_off, 2, bottom_off, 1, cur_off, 5);
609 dst[doff + 2] = obmc_filter!(src, soff + 2, left_off, 1, bottom_off, 1, cur_off, 6);
610 dst[doff + 3] = obmc_filter!(src, soff + 3, left_off, 1, bottom_off, 1, cur_off, 6);
611 dst[doff + 4] = obmc_filter!(src, soff + 4, right_off, 1, bottom_off, 1, cur_off, 6);
612 dst[doff + 5] = obmc_filter!(src, soff + 5, right_off, 1, bottom_off, 1, cur_off, 6);
613 dst[doff + 6] = obmc_filter!(src, soff + 6, right_off, 2, bottom_off, 1, cur_off, 5);
614 dst[doff + 7] = obmc_filter!(src, soff + 7, right_off, 2, bottom_off, 1, cur_off, 5);
618 dst[doff + 0] = obmc_filter!(src, soff + 0, left_off, 2, bottom_off, 1, cur_off, 5);
619 dst[doff + 1] = obmc_filter!(src, soff + 1, left_off, 2, bottom_off, 1, cur_off, 5);
620 dst[doff + 2] = obmc_filter!(src, soff + 2, left_off, 1, bottom_off, 1, cur_off, 6);
621 dst[doff + 3] = obmc_filter!(src, soff + 3, left_off, 1, bottom_off, 1, cur_off, 6);
622 dst[doff + 4] = obmc_filter!(src, soff + 4, right_off, 1, bottom_off, 1, cur_off, 6);
623 dst[doff + 5] = obmc_filter!(src, soff + 5, right_off, 1, bottom_off, 1, cur_off, 6);
624 dst[doff + 6] = obmc_filter!(src, soff + 6, right_off, 2, bottom_off, 1, cur_off, 5);
625 dst[doff + 7] = obmc_filter!(src, soff + 7, right_off, 2, bottom_off, 1, cur_off, 5);
629 dst[doff + 0] = obmc_filter!(src, soff + 0, left_off, 2, bottom_off, 1, cur_off, 5);
630 dst[doff + 1] = obmc_filter!(src, soff + 1, left_off, 2, bottom_off, 1, cur_off, 5);
631 dst[doff + 2] = obmc_filter!(src, soff + 2, left_off, 1, bottom_off, 2, cur_off, 5);
632 dst[doff + 3] = obmc_filter!(src, soff + 3, left_off, 1, bottom_off, 2, cur_off, 5);
633 dst[doff + 4] = obmc_filter!(src, soff + 4, right_off, 1, bottom_off, 2, cur_off, 5);
634 dst[doff + 5] = obmc_filter!(src, soff + 5, right_off, 1, bottom_off, 2, cur_off, 5);
635 dst[doff + 6] = obmc_filter!(src, soff + 6, right_off, 2, bottom_off, 1, cur_off, 5);
636 dst[doff + 7] = obmc_filter!(src, soff + 7, right_off, 2, bottom_off, 1, cur_off, 5);
640 dst[doff + 0] = obmc_filter!(src, soff + 0, left_off, 2, bottom_off, 2, cur_off, 4);
641 dst[doff + 1] = obmc_filter!(src, soff + 1, left_off, 1, bottom_off, 2, cur_off, 5);
642 dst[doff + 2] = obmc_filter!(src, soff + 2, left_off, 1, bottom_off, 2, cur_off, 5);
643 dst[doff + 3] = obmc_filter!(src, soff + 3, left_off, 1, bottom_off, 2, cur_off, 5);
644 dst[doff + 4] = obmc_filter!(src, soff + 4, right_off, 1, bottom_off, 2, cur_off, 5);
645 dst[doff + 5] = obmc_filter!(src, soff + 5, right_off, 1, bottom_off, 2, cur_off, 5);
646 dst[doff + 6] = obmc_filter!(src, soff + 6, right_off, 1, bottom_off, 2, cur_off, 5);
647 dst[doff + 7] = obmc_filter!(src, soff + 7, right_off, 2, bottom_off, 2, cur_off, 4);