}
/// Copies block from the picture with pixels beyond the picture borders being replaced with replicated edge pixels.
-pub fn edge_emu(src: &NAVideoBuffer<u8>, xpos: isize, ypos: isize, bw: usize, bh: usize, dst: &mut [u8], dstride: usize, comp: usize) {
+pub fn edge_emu(src: &NAVideoBuffer<u8>, xpos: isize, ypos: isize, bw: usize, bh: usize, dst: &mut [u8], dstride: usize, comp: usize, align: u8) {
let stride = src.get_stride(comp);
let offs = src.get_offset(comp);
- let (w, h) = src.get_dimensions(comp);
+ let (w_, h_) = src.get_dimensions(comp);
+ let (hss, vss) = src.get_info().get_format().get_chromaton(comp).unwrap().get_subsampling();
let data = src.get_data();
let framebuf: &[u8] = data.as_slice();
+ let (w, h) = if align == 0 {
+ (w_, h_)
+ } else {
+ let wa = if align > hss { (1 << (align - hss)) - 1 } else { 0 };
+ let ha = if align > vss { (1 << (align - vss)) - 1 } else { 0 };
+ ((w_ + wa) & !wa, (h_ + ha) & !ha)
+ };
+
for y in 0..bh {
let srcy;
if (y as isize) + ypos < 0 { srcy = 0; }
let bw_ = (if comp > 0 { bw/2 } else { bw }) + ((pre + post) as usize);
let bh_ = (if comp > 0 { bh/2 } else { bh }) + ((pre + post) as usize);
edge_emu(src, sx_ - pre, sy_ - pre, bw_, bh_,
- ebuf.as_mut_slice(), ebuf_stride, comp);
+ ebuf.as_mut_slice(), ebuf_stride, comp, 0);
let bw_ = if comp > 0 { bw/2 } else { bw };
let bh_ = if comp > 0 { bh/2 } else { bh };
(interp[mode])(&mut dbuf[doff + x + y * dstride..], dstride, ebuf.as_slice(), ebuf_stride, bw_, bh_);
let doff = dst.offset[comp];
let edge = (pre + post) as usize;
edge_emu(&src, sx - pre, sy - pre, bw + edge, bh + edge,
- ebuf.as_mut_slice(), ebuf_stride, comp);
+ ebuf.as_mut_slice(), ebuf_stride, comp, 0);
(interp[mode])(&mut dst.data[doff + dx + dy * dstride..], dstride,
ebuf.as_slice(), ebuf_stride, bw, bh);
} else {
if (sx - 2 < 0) || (sx + 8 + 2 > (w as isize)) ||
(sy - 2 < 0) || (sy + 8 + 2 > (h as isize)) {
edge_emu(&src, sx - 2, sy - 2, 8 + 2 + 2, 8 + 2 + 2,
- dst, dstride, comp);
+ dst, dstride, comp, 0);
} else {
let sstride = src.get_stride(comp);
let soff = src.get_offset(comp);
let ref_y = (ypos as isize) + ((mvy >> 3) as isize) - (EDGE_PRE as isize);
let (src, sstride) = if (ref_x < 0) || (ref_x + bsize > wa) || (ref_y < 0) || (ref_y + bsize > ha) {
- edge_emu(&reffrm, ref_x, ref_y, bsize as usize, bsize as usize, mc_buf, 32, plane);
+ edge_emu(&reffrm, ref_x, ref_y, bsize as usize, bsize as usize, mc_buf, 32, plane, 0);
(mc_buf as &[u8], 32)
} else {
let off = reffrm.get_offset(plane);
let bw = size + EDGE_PRE + EDGE_POST + add;
let bh = (end_y - start_y) as usize;
let bo = if xstep >= 0 { 0 } else { add };
- edge_emu(&reffrm, start_x + (bo as isize), start_y, bw, bh, mc_buf, 128, plane);
+ edge_emu(&reffrm, start_x + (bo as isize), start_y, bw, bh, mc_buf, 128, plane, 0);
(&mc_buf[bo..], (128 + xstep) as usize)
};
let mx = (mvx & 7) as usize;
let src_y = sy - (pre as isize);
{
let tmp_buf = NASimpleVideoFrame::from_video_buf(&mut mc_buf).unwrap();
- edge_emu(src.as_ref(), src_x, src_y, bsize, bsize, &mut tmp_buf.data[tmp_buf.offset[comp]..], tmp_buf.stride[comp], comp);
+ edge_emu(src.as_ref(), src_x, src_y, bsize, bsize, &mut tmp_buf.data[tmp_buf.offset[comp]..], tmp_buf.stride[comp], comp, 0);
// copy_block(&mut tmp_buf, src, comp, 0, 0, src_x as i16, src_y as i16,
// bsize, bsize, 0, 0, 0, interp);
if (sx & 7) != 0 {
self.luma_mc[if use16 { 0 } else { 1 }][mode](dst, doffset, dstride, src, soffset, sstride);
} else {
let mut ebuf: [u8; 32*20] = [0; 32*20];
- 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);
+ 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);
self.luma_mc[if use16 { 0 } else { 1 }][mode](dst, doffset, dstride, &ebuf, 32 + 1, 32);
}
}
rv30_chroma_mc(dst, doffset, dstride, src, soffset, sstride, size, cx, cy);
} else {
let mut ebuf: [u8; 16*10] = [0; 16*10];
- edge_emu(prev_frame, (x as isize) + (dx as isize), (y as isize) + (dy as isize), 8+1, 8+1, &mut ebuf, 16, comp);
+ 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);
rv30_chroma_mc(dst, doffset, dstride, &ebuf, 0, 16, size, cx, cy);
}
}
self.luma_mc[if use16 { 0 } else { 1 }][mode](dst, doffset, dstride, src, soffset, sstride);
} else {
let mut ebuf: [u8; 32*22] = [0; 32*22];
- edge_emu(prev_frame, (x as isize) + (dx as isize) - 2, (y as isize) + (dy as isize) - 2, 16+5, 16+5, &mut ebuf, 32, 0);
+ edge_emu(prev_frame, (x as isize) + (dx as isize) - 2, (y as isize) + (dy as isize) - 2, 16+5, 16+5, &mut ebuf, 32, 0, 4);
self.luma_mc[if use16 { 0 } else { 1 }][mode](dst, doffset, dstride, &ebuf, 32*2 + 2, 32);
}
}
rv40_chroma_mc(dst, doffset, dstride, src, soffset, sstride, size, cx, cy);
} else {
let mut ebuf: [u8; 16*10] = [0; 16*10];
- edge_emu(prev_frame, (x as isize) + (dx as isize), (y as isize) + (dy as isize), 8+1, 8+1, &mut ebuf, 16, comp);
+ 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);
rv40_chroma_mc(dst, doffset, dstride, &ebuf, 0, 16, size, cx, cy);
}
}
luma_mc(dst, doffset, dstride, src, soffset, sstride, w, h, cx, cy);
} else {
let mut ebuf: [u8; 70*70] = [0; 70*70];
- edge_emu(prev_frame, (x as isize) + (dx as isize) - 2, (y as isize) + (dy as isize) - 2, w+5, h+5, &mut ebuf, 70, 0);
+ edge_emu(prev_frame, (x as isize) + (dx as isize) - 2, (y as isize) + (dy as isize) - 2, w+5, h+5, &mut ebuf, 70, 0, 0);
luma_mc(dst, doffset, dstride, &ebuf, 70*2 + 2, 70, w, h, cx, cy);
}
}
chroma_mc(frame.data, doffset, dstride, src, soffset, sstride, cw, ch, cx, cy);
} else {
let mut ebuf: [u8; 40*40] = [0; 40*40];
- edge_emu(prev_frame, ((x >> 1) as isize) + (dx as isize), ((y >> 1) as isize) + (dy as isize), cw+1, ch+1, &mut ebuf, 40, comp);
+ edge_emu(prev_frame, ((x >> 1) as isize) + (dx as isize), ((y >> 1) as isize) + (dy as isize), cw+1, ch+1, &mut ebuf, 40, comp, 0);
chroma_mc(frame.data, doffset, dstride, &ebuf, 0, 40, cw, ch, cx, cy);
}
}