| 1 | use nihav_core::frame::{FrameType, NAVideoBuffer}; |
| 2 | use nihav_codec_support::codecs::MV; |
| 3 | use nihav_codec_support::codecs::blockdsp::edge_emu; |
| 4 | use super::rv3040::{RV34DSP, RV34MBInfo}; |
| 5 | |
| 6 | fn clip8(a: i16) -> u8 { |
| 7 | if a < 0 { 0 } |
| 8 | else if a > 255 { 255 } |
| 9 | else { a as u8 } |
| 10 | } |
| 11 | |
| 12 | fn rv3_filter_h(dst: &mut [u8], mut didx: usize, dstride: usize, src: &[u8], mut sidx: usize, sstride: usize, bsize: usize, c1: i16, c2: i16) { |
| 13 | for _ in 0..bsize { |
| 14 | for x in 0..bsize { |
| 15 | dst[didx + x] = clip8((-((src[sidx + x - 1] as i16) + (src[sidx + x + 2] as i16)) + (src[sidx + x + 0] as i16) * c1 + (src[sidx + x + 1] as i16) * c2 + 8) >> 4); |
| 16 | } |
| 17 | sidx += sstride; |
| 18 | didx += dstride; |
| 19 | } |
| 20 | } |
| 21 | |
| 22 | fn rv3_filter_v(dst: &mut [u8], mut didx: usize, dstride: usize, src: &[u8], mut sidx: usize, sstride: usize, bsize: usize, c1: i16, c2: i16) { |
| 23 | for _ in 0..bsize { |
| 24 | for x in 0..bsize { |
| 25 | dst[didx + x] = clip8((-((src[sidx + x - 1 * sstride] as i16) + (src[sidx + x + 2 * sstride] as i16)) + (src[sidx + x + 0 * sstride] as i16) * c1 + (src[sidx + x + 1 * sstride] as i16) * c2 + 8) >> 4); |
| 26 | } |
| 27 | sidx += sstride; |
| 28 | didx += dstride; |
| 29 | } |
| 30 | } |
| 31 | |
| 32 | macro_rules! mc_matrix { |
| 33 | ($s: ident, $o: expr, $c1: expr) => ( |
| 34 | ($c1 * 6) * ($s[$o] as i32) + ($c1 * 9) * ($s[$o + 1] as i32) + ($c1) * ($s[$o + 2] as i32) |
| 35 | ); |
| 36 | ($s: ident, $o: expr, $c1: expr, $d1: expr, $d2: expr) => ( |
| 37 | -($c1) * ($s[$o - 1] as i32) + ($c1 * $d1) * ($s[$o] as i32) + ($c1 * $d2) * ($s[$o + 1] as i32) + -($c1) * ($s[$o + 2] as i32) |
| 38 | ); |
| 39 | ($s: ident, $o: expr, $ss: expr, $c1: expr, $c2: expr, $d1: expr, $d2: expr) => ( |
| 40 | ((mc_matrix!($s, $o - $ss, -1, $d1, $d2) + |
| 41 | mc_matrix!($s, $o , $c1, $d1, $d2) + |
| 42 | mc_matrix!($s, $o + $ss, $c2, $d1, $d2) + |
| 43 | mc_matrix!($s, $o + 2 * $ss, -1, $d1, $d2) + 128) >> 8) as i16 |
| 44 | ); |
| 45 | (m22; $s: ident, $o: expr, $ss: expr) => ( |
| 46 | ((mc_matrix!($s, $o + 0 * $ss, 6) + |
| 47 | mc_matrix!($s, $o + 1 * $ss, 9) + |
| 48 | mc_matrix!($s, $o + 2 * $ss, 1) + 128) >> 8) as i16 |
| 49 | ); |
| 50 | } |
| 51 | |
| 52 | macro_rules! mc_func { |
| 53 | (copy; $name: ident, $size: expr) => ( |
| 54 | fn $name (dst: &mut [u8], mut didx: usize, dstride: usize, src: &[u8], mut sidx: usize, sstride: usize) { |
| 55 | for _ in 0..$size { |
| 56 | let d = &mut dst[didx..][..$size]; |
| 57 | let s = &src[sidx..][..$size]; |
| 58 | for x in 0..$size { d[x] = s[x]; } |
| 59 | didx += dstride; |
| 60 | sidx += sstride; |
| 61 | } |
| 62 | } |
| 63 | ); |
| 64 | (hor; $name: ident, $c1: expr, $c2: expr, $size: expr) => ( |
| 65 | fn $name (dst: &mut [u8], didx: usize, dstride: usize, src: &[u8], sidx: usize, sstride: usize) { |
| 66 | rv3_filter_h(dst, didx, dstride, src, sidx, sstride, $size, $c1, $c2); |
| 67 | } |
| 68 | ); |
| 69 | (ver; $name: ident, $c1: expr, $c2: expr, $size: expr) => ( |
| 70 | fn $name (dst: &mut [u8], didx: usize, dstride: usize, src: &[u8], sidx: usize, sstride: usize) { |
| 71 | rv3_filter_v(dst, didx, dstride, src, sidx, sstride, $size, $c1, $c2); |
| 72 | } |
| 73 | ); |
| 74 | (m11; $name: ident, $size: expr) => ( |
| 75 | fn $name (dst: &mut [u8], mut didx: usize, dstride: usize, src: &[u8], mut sidx: usize, sstride: usize) { |
| 76 | for _ in 0..$size { |
| 77 | for x in 0..$size { |
| 78 | dst[didx + x] = clip8(mc_matrix!(src, sidx + x, sstride, 12, 6, 12, 6)); |
| 79 | } |
| 80 | didx += dstride; |
| 81 | sidx += sstride; |
| 82 | } |
| 83 | } |
| 84 | ); |
| 85 | (m12; $name: ident, $size: expr) => ( |
| 86 | fn $name (dst: &mut [u8], mut didx: usize, dstride: usize, src: &[u8], mut sidx: usize, sstride: usize) { |
| 87 | for _ in 0..$size { |
| 88 | for x in 0..$size { |
| 89 | dst[didx + x] = clip8(mc_matrix!(src, sidx + x, sstride, 6, 12, 12, 6)); |
| 90 | } |
| 91 | didx += dstride; |
| 92 | sidx += sstride; |
| 93 | } |
| 94 | } |
| 95 | ); |
| 96 | (m21; $name: ident, $size: expr) => ( |
| 97 | fn $name (dst: &mut [u8], mut didx: usize, dstride: usize, src: &[u8], mut sidx: usize, sstride: usize) { |
| 98 | for _ in 0..$size { |
| 99 | for x in 0..$size { |
| 100 | dst[didx + x] = clip8(mc_matrix!(src, sidx + x, sstride, 12, 6, 6, 12)); |
| 101 | } |
| 102 | didx += dstride; |
| 103 | sidx += sstride; |
| 104 | } |
| 105 | } |
| 106 | ); |
| 107 | (m22; $name: ident, $size: expr) => ( |
| 108 | fn $name (dst: &mut [u8], mut didx: usize, dstride: usize, src: &[u8], mut sidx: usize, sstride: usize) { |
| 109 | for _ in 0..$size { |
| 110 | for x in 0..$size { |
| 111 | dst[didx + x] = clip8(mc_matrix!(m22; src, sidx + x, sstride)); |
| 112 | } |
| 113 | didx += dstride; |
| 114 | sidx += sstride; |
| 115 | } |
| 116 | } |
| 117 | ); |
| 118 | } |
| 119 | mc_func!(copy; copy_16, 16); |
| 120 | mc_func!(copy; copy_8, 8); |
| 121 | mc_func!(hor; luma_mc_10_16, 12, 6, 16); |
| 122 | mc_func!(hor; luma_mc_20_16, 6, 12, 16); |
| 123 | mc_func!(hor; luma_mc_10_8, 12, 6, 8); |
| 124 | mc_func!(hor; luma_mc_20_8, 6, 12, 8); |
| 125 | mc_func!(ver; luma_mc_01_16, 12, 6, 16); |
| 126 | mc_func!(ver; luma_mc_02_16, 6, 12, 16); |
| 127 | mc_func!(ver; luma_mc_01_8, 12, 6, 8); |
| 128 | mc_func!(ver; luma_mc_02_8, 6, 12, 8); |
| 129 | mc_func!(m11; luma_mc_11_16, 16); |
| 130 | mc_func!(m11; luma_mc_11_8, 8); |
| 131 | mc_func!(m21; luma_mc_21_16, 16); |
| 132 | mc_func!(m21; luma_mc_21_8, 8); |
| 133 | mc_func!(m12; luma_mc_12_16, 16); |
| 134 | mc_func!(m12; luma_mc_12_8, 8); |
| 135 | mc_func!(m22; luma_mc_22_16, 16); |
| 136 | mc_func!(m22; luma_mc_22_8, 8); |
| 137 | |
| 138 | const RV30_CHROMA_FRAC1: [u16; 3] = [ 8, 5, 3 ]; |
| 139 | const RV30_CHROMA_FRAC2: [u16; 3] = [ 0, 3, 5 ]; |
| 140 | fn rv30_chroma_mc(dst: &mut [u8], mut didx: usize, dstride: usize, src: &[u8], mut sidx: usize, sstride: usize, size: usize, x: usize, y: usize) { |
| 141 | if (x == 0) && (y == 0) { |
| 142 | for _ in 0..size { |
| 143 | dst[didx..][..size].copy_from_slice(&src[sidx..][..size]); |
| 144 | didx += dstride; |
| 145 | sidx += sstride; |
| 146 | } |
| 147 | return; |
| 148 | } |
| 149 | let a = RV30_CHROMA_FRAC1[x] * RV30_CHROMA_FRAC1[y]; |
| 150 | let b = RV30_CHROMA_FRAC2[x] * RV30_CHROMA_FRAC1[y]; |
| 151 | let c = RV30_CHROMA_FRAC1[x] * RV30_CHROMA_FRAC2[y]; |
| 152 | let d = RV30_CHROMA_FRAC2[x] * RV30_CHROMA_FRAC2[y]; |
| 153 | for _ in 0..size { |
| 154 | for x in 0..size { |
| 155 | dst[didx + x] = ((a * (src[sidx + x] as u16) |
| 156 | + b * (src[sidx + x + 1] as u16) |
| 157 | + c * (src[sidx + x + sstride] as u16) |
| 158 | + d * (src[sidx + x + 1 + sstride] as u16) + 32) >> 6) as u8; |
| 159 | } |
| 160 | didx += dstride; |
| 161 | sidx += sstride; |
| 162 | } |
| 163 | } |
| 164 | |
| 165 | #[allow(clippy::type_complexity)] |
| 166 | pub struct RV30DSP { |
| 167 | luma_mc: [[fn (&mut [u8], usize, usize, &[u8], usize, usize); 9]; 2], |
| 168 | } |
| 169 | |
| 170 | impl RV30DSP { |
| 171 | pub fn new() -> Self { |
| 172 | RV30DSP { |
| 173 | luma_mc: [ |
| 174 | [ copy_16, luma_mc_10_16, luma_mc_20_16, |
| 175 | luma_mc_01_16, luma_mc_11_16, luma_mc_21_16, |
| 176 | luma_mc_02_16, luma_mc_12_16, luma_mc_22_16 ], |
| 177 | [ copy_8, luma_mc_10_8, luma_mc_20_8, |
| 178 | luma_mc_01_8, luma_mc_11_8, luma_mc_21_8, |
| 179 | luma_mc_02_8, luma_mc_12_8, luma_mc_22_8 ] ], |
| 180 | } |
| 181 | } |
| 182 | } |
| 183 | |
| 184 | macro_rules! el { |
| 185 | ($src: ident, $o: expr) => ($src[$o] as i16); |
| 186 | } |
| 187 | |
| 188 | fn clip_symm(a: i16, lim: i16) -> i16 { |
| 189 | if a < -lim { |
| 190 | -lim |
| 191 | } else if a > lim { |
| 192 | lim |
| 193 | } else { |
| 194 | a |
| 195 | } |
| 196 | } |
| 197 | |
| 198 | const RV30_LOOP_FILTER_STRENGTH: [i16; 32] = [ |
| 199 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, |
| 200 | 2, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5 |
| 201 | ]; |
| 202 | |
| 203 | macro_rules! test_bit { |
| 204 | ($pat: expr, $x: expr) => ( (($pat >> $x) & 1) != 0 ) |
| 205 | } |
| 206 | |
| 207 | fn rv30_loop_filter4(pix: &mut [u8], mut off: usize, step: usize, stride: usize, lim: i16) { |
| 208 | for _ in 0..4 { |
| 209 | let a = el!(pix, off - 2*step); |
| 210 | let b = el!(pix, off - step); |
| 211 | let c = el!(pix, off); |
| 212 | let d = el!(pix, off + step); |
| 213 | let diff0 = ((a - d) - (b - c) * 4) >> 3; |
| 214 | let diff = clip_symm(diff0, lim); |
| 215 | pix[off - step] = clip8(b + diff); |
| 216 | pix[off ] = clip8(c - diff); |
| 217 | off += stride; |
| 218 | } |
| 219 | } |
| 220 | |
| 221 | fn rv30_div_mv(mv: i16) -> (i16, usize) { |
| 222 | let i = mv / 3; |
| 223 | let f = mv - i * 3; |
| 224 | if f < 0 { |
| 225 | (i - 1, (f + 3) as usize) |
| 226 | } else { |
| 227 | (i, f as usize) |
| 228 | } |
| 229 | } |
| 230 | |
| 231 | fn check_pos(x: usize, y: usize, size: usize, w: usize, h: usize, dx: i16, dy: i16, e0: isize, e1: isize, e2: isize, e3: isize) -> bool { |
| 232 | let xn = (x as isize) + (dx as isize); |
| 233 | let yn = (y as isize) + (dy as isize); |
| 234 | |
| 235 | (xn - e0 >= 0) && (xn + (size as isize) + e1 <= (w as isize)) && (yn - e2 >= 0) && (yn + (size as isize) + e3 <= (h as isize)) |
| 236 | } |
| 237 | |
| 238 | const RV30_EDGE1: [isize; 3] = [ 0, 1, 1 ]; |
| 239 | const RV30_EDGE2: [isize; 3] = [ 0, 2, 2 ]; |
| 240 | |
| 241 | impl RV34DSP for RV30DSP { |
| 242 | #[allow(clippy::cognitive_complexity)] |
| 243 | fn loop_filter(&self, frame: &mut NAVideoBuffer<u8>, _ftype: FrameType, mbinfo: &[RV34MBInfo], mb_w: usize, _mb_h: usize, row: usize) { |
| 244 | let mut offs: [usize; 3] = [0; 3]; |
| 245 | let mut stride: [usize; 3] = [0; 3]; |
| 246 | |
| 247 | for comp in 0..3 { |
| 248 | stride[comp] = frame.get_stride(comp); |
| 249 | let start = if comp == 0 { row * 16 } else { row * 8 }; |
| 250 | offs[comp] = frame.get_offset(comp) + start * stride[comp]; |
| 251 | } |
| 252 | |
| 253 | let data = frame.get_data_mut().unwrap(); |
| 254 | let dst: &mut [u8] = data.as_mut_slice(); |
| 255 | |
| 256 | // vertical filter |
| 257 | let mut left_cbp = 0; |
| 258 | let mut left_lim = 0; |
| 259 | let mut left_dbk = 0; |
| 260 | let mut mb_pos: usize = row * mb_w; |
| 261 | for mb_x in 0..mb_w { |
| 262 | let cur_lim = RV30_LOOP_FILTER_STRENGTH[mbinfo[mb_pos].q as usize]; |
| 263 | let cur_dbk = mbinfo[mb_pos].deblock; |
| 264 | let cur_cbp = mbinfo[mb_pos].cbp_c; |
| 265 | let xstart = if mb_x == 0 { 1 } else { 0 }; |
| 266 | for y in 0..4 { |
| 267 | let yoff = offs[0] + mb_x * 16 + y * 4 * stride[0]; |
| 268 | for x in xstart..4 { |
| 269 | let cs = x + y*4; |
| 270 | let loc_lim; |
| 271 | |
| 272 | if test_bit!(cur_dbk, cs) { |
| 273 | loc_lim = cur_lim; |
| 274 | } else if (x == 0) && test_bit!(left_dbk, cs + 3) { |
| 275 | loc_lim = left_lim; |
| 276 | } else if (x != 0) && test_bit!(cur_dbk, cs - 1) { |
| 277 | loc_lim = cur_lim; |
| 278 | } else { |
| 279 | loc_lim = 0; |
| 280 | } |
| 281 | if loc_lim != 0 { |
| 282 | rv30_loop_filter4(dst, yoff + x * 4, 1, stride[0], loc_lim); |
| 283 | } |
| 284 | } |
| 285 | } |
| 286 | |
| 287 | for comp in 1..3 { |
| 288 | for y in 0..2 { |
| 289 | let coff = offs[comp] + mb_x * 8 + y * 4 * stride[comp]; |
| 290 | for x in xstart..2 { |
| 291 | let cs = x + y * 2 + (comp - 1) * 4; |
| 292 | let loc_lim; |
| 293 | |
| 294 | if test_bit!(cur_cbp, cs) { |
| 295 | loc_lim = cur_lim; |
| 296 | } else if (x == 0) && test_bit!(left_cbp, cs + 1) { |
| 297 | loc_lim = left_lim; |
| 298 | } else if (x != 0) && test_bit!(cur_cbp, cs - 1) { |
| 299 | loc_lim = cur_lim; |
| 300 | } else { |
| 301 | loc_lim = 0; |
| 302 | } |
| 303 | if loc_lim != 0 { |
| 304 | rv30_loop_filter4(dst, coff + x * 4, 1, stride[comp], loc_lim); |
| 305 | } |
| 306 | } |
| 307 | } |
| 308 | } |
| 309 | |
| 310 | left_lim = cur_lim; |
| 311 | left_dbk = cur_dbk; |
| 312 | left_cbp = cur_cbp; |
| 313 | mb_pos += 1; |
| 314 | } |
| 315 | |
| 316 | // horizontal filter |
| 317 | let mut mb_pos: usize = row * mb_w; |
| 318 | for mb_x in 0..mb_w { |
| 319 | let cur_lim = RV30_LOOP_FILTER_STRENGTH[mbinfo[mb_pos].q as usize]; |
| 320 | let cur_dbk = mbinfo[mb_pos].deblock; |
| 321 | let cur_cbp = mbinfo[mb_pos].cbp_c; |
| 322 | let ystart = if row == 0 { 1 } else { 0 }; |
| 323 | let top_lim; |
| 324 | let top_dbk; |
| 325 | let top_cbp; |
| 326 | if row > 0 { |
| 327 | top_lim = RV30_LOOP_FILTER_STRENGTH[mbinfo[mb_pos - mb_w].q as usize]; |
| 328 | top_dbk = mbinfo[mb_pos - mb_w].deblock; |
| 329 | top_cbp = mbinfo[mb_pos - mb_w].cbp_c; |
| 330 | } else { |
| 331 | top_lim = 0; |
| 332 | top_dbk = 0; |
| 333 | top_cbp = 0; |
| 334 | } |
| 335 | for y in ystart..4 { |
| 336 | let yoff = offs[0] + mb_x * 16 + y * 4 * stride[0]; |
| 337 | for x in 0..4 { |
| 338 | let cs = x + y*4; |
| 339 | let loc_lim; |
| 340 | |
| 341 | if test_bit!(cur_dbk, cs) { |
| 342 | loc_lim = cur_lim; |
| 343 | } else if (y == 0) && test_bit!(top_dbk, cs + 12) { |
| 344 | loc_lim = top_lim; |
| 345 | } else if (y != 0) && test_bit!(cur_dbk, cs - 4) { |
| 346 | loc_lim = cur_lim; |
| 347 | } else { |
| 348 | loc_lim = 0; |
| 349 | } |
| 350 | if loc_lim != 0 { |
| 351 | rv30_loop_filter4(dst, yoff + x * 4, stride[0], 1, loc_lim); |
| 352 | } |
| 353 | } |
| 354 | } |
| 355 | |
| 356 | for comp in 1..3 { |
| 357 | for y in ystart..2 { |
| 358 | let coff = offs[comp] + mb_x * 8 + y * 4 * stride[comp]; |
| 359 | for x in 0..2 { |
| 360 | let cs = x + y * 2 + (comp - 1) * 4; |
| 361 | let loc_lim; |
| 362 | |
| 363 | if test_bit!(cur_cbp, cs) { |
| 364 | loc_lim = cur_lim; |
| 365 | } else if (y == 0) && test_bit!(top_cbp, cs + 2) { |
| 366 | loc_lim = top_lim; |
| 367 | } else if (y != 0) && test_bit!(cur_cbp, cs - 2) { |
| 368 | loc_lim = cur_lim; |
| 369 | } else { |
| 370 | loc_lim = 0; |
| 371 | } |
| 372 | if loc_lim != 0 { |
| 373 | rv30_loop_filter4(dst, coff + x * 4, stride[comp], 1, loc_lim); |
| 374 | } |
| 375 | } |
| 376 | } |
| 377 | } |
| 378 | |
| 379 | mb_pos += 1; |
| 380 | } |
| 381 | } |
| 382 | fn do_luma_mc(&self, frame: &mut NAVideoBuffer<u8>, prev_frame: &NAVideoBuffer<u8>, x: usize, y: usize, mv: MV, use16: bool, avg: bool) { |
| 383 | let size: usize = if use16 { 16 } else { 8 }; |
| 384 | let dstride = frame.get_stride(0); |
| 385 | let doffset = frame.get_offset(0) + (if !avg { x + y * dstride } else { 0 }); |
| 386 | let data = frame.get_data_mut().unwrap(); |
| 387 | let dst: &mut [u8] = data.as_mut_slice(); |
| 388 | |
| 389 | let (w_, h_) = prev_frame.get_dimensions(0); |
| 390 | let w = (w_ + 15) & !15; |
| 391 | let h = (h_ + 15) & !15; |
| 392 | |
| 393 | let (dx, cx) = rv30_div_mv(mv.x); |
| 394 | let (dy, cy) = rv30_div_mv(mv.y); |
| 395 | let mode = cx + cy * 3; |
| 396 | |
| 397 | if check_pos(x, y, size, w, h, dx, dy, RV30_EDGE1[cx], RV30_EDGE2[cx], RV30_EDGE1[cy], RV30_EDGE2[cy]) { |
| 398 | let sstride = prev_frame.get_stride(0); |
| 399 | let mut soffset = prev_frame.get_offset(0) + x + y * sstride; |
| 400 | let data = prev_frame.get_data(); |
| 401 | let src: &[u8] = data.as_slice(); |
| 402 | soffset = ((soffset as isize) + (dx as isize) + (dy as isize) * (sstride as isize)) as usize; |
| 403 | self.luma_mc[if use16 { 0 } else { 1 }][mode](dst, doffset, dstride, src, soffset, sstride); |
| 404 | } else { |
| 405 | let mut ebuf: [u8; 32*20] = [0; 32*20]; |
| 406 | edge_emu(prev_frame, (x as isize) + (dx as isize) - 1, (y as isize) + (dy as isize) - 1, 16+3, 16+3, &mut ebuf, 32, 0, 4); |
| 407 | self.luma_mc[if use16 { 0 } else { 1 }][mode](dst, doffset, dstride, &ebuf, 32 + 1, 32); |
| 408 | } |
| 409 | } |
| 410 | fn do_chroma_mc(&self, frame: &mut NAVideoBuffer<u8>, prev_frame: &NAVideoBuffer<u8>, x: usize, y: usize, comp: usize, mv: MV, use8: bool, avg: bool) { |
| 411 | let size: usize = if use8 { 8 } else { 4 }; |
| 412 | let dstride = frame.get_stride(comp); |
| 413 | let doffset = frame.get_offset(comp) + (if !avg { x + y * dstride } else { 0 }); |
| 414 | let data = frame.get_data_mut().unwrap(); |
| 415 | let dst: &mut [u8] = data.as_mut_slice(); |
| 416 | |
| 417 | let (w_, h_) = prev_frame.get_dimensions(comp); |
| 418 | let w = (w_ + 7) & !7; |
| 419 | let h = (h_ + 7) & !7; |
| 420 | |
| 421 | let (dx, cx) = rv30_div_mv(mv.x / 2); |
| 422 | let (dy, cy) = rv30_div_mv(mv.y / 2); |
| 423 | |
| 424 | if check_pos(x, y, size, w, h, dx, dy, 0, 1, 0, 1) { |
| 425 | let sstride = prev_frame.get_stride(comp); |
| 426 | let mut soffset = prev_frame.get_offset(comp) + x + y * sstride; |
| 427 | let data = prev_frame.get_data(); |
| 428 | let src: &[u8] = data.as_slice(); |
| 429 | soffset = ((soffset as isize) + (dx as isize) + (dy as isize) * (sstride as isize)) as usize; |
| 430 | rv30_chroma_mc(dst, doffset, dstride, src, soffset, sstride, size, cx, cy); |
| 431 | } else { |
| 432 | let mut ebuf: [u8; 16*10] = [0; 16*10]; |
| 433 | edge_emu(prev_frame, (x as isize) + (dx as isize), (y as isize) + (dy as isize), 8+1, 8+1, &mut ebuf, 16, comp, 4); |
| 434 | rv30_chroma_mc(dst, doffset, dstride, &ebuf, 0, 16, size, cx, cy); |
| 435 | } |
| 436 | } |
| 437 | } |