}
/// 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 {
&sbuf[saddr..], sstride, bw, bh);
}
}
+
+fn hpel_interp00(dst: &mut [u8], dstride: usize, src: &[u8], sstride: usize, bw: usize, bh: usize)
+{
+ let mut didx = 0;
+ let mut sidx = 0;
+ for _ in 0..bh {
+ dst[didx..][..bw].copy_from_slice(&src[sidx..][..bw]);
+ didx += dstride;
+ sidx += sstride;
+ }
+}
+
+fn hpel_interp01(dst: &mut [u8], dstride: usize, src: &[u8], sstride: usize, bw: usize, bh: usize)
+{
+ let mut didx = 0;
+ let mut sidx = 0;
+ for _ in 0..bh {
+ for x in 0..bw { dst[didx + x] = ((u16::from(src[sidx + x]) + u16::from(src[sidx + x + 1]) + 1) >> 1) as u8; }
+ didx += dstride;
+ sidx += sstride;
+ }
+}
+
+fn hpel_interp10(dst: &mut [u8], dstride: usize, src: &[u8], sstride: usize, bw: usize, bh: usize)
+{
+ let mut didx = 0;
+ let mut sidx = 0;
+ for _ in 0..bh {
+ for x in 0..bw { dst[didx + x] = ((u16::from(src[sidx + x]) + u16::from(src[sidx + x + sstride]) + 1) >> 1) as u8; }
+ didx += dstride;
+ sidx += sstride;
+ }
+}
+
+fn hpel_interp11(dst: &mut [u8], dstride: usize, src: &[u8], sstride: usize, bw: usize, bh: usize)
+{
+ let mut didx = 0;
+ let mut sidx = 0;
+ for _ in 0..bh {
+ for x in 0..bw {
+ dst[didx + x] = ((u16::from(src[sidx + x]) +
+ u16::from(src[sidx + x + 1]) +
+ u16::from(src[sidx + x + sstride]) +
+ u16::from(src[sidx + x + sstride + 1]) + 2) >> 2) as u8;
+ }
+ didx += dstride;
+ sidx += sstride;
+ }
+}
+
+/// Half-pixel interpolation functions.
+pub const HALFPEL_INTERP_FUNCS: &[BlkInterpFunc] = &[
+ hpel_interp00, hpel_interp01, hpel_interp10, hpel_interp11 ];
+