X-Git-Url: https://git.nihav.org/?a=blobdiff_plain;f=nihav-itu%2Fsrc%2Fcodecs%2Fh264%2Fdsp%2Fmc%2Fmod.rs;h=615563ee78113f1e4a629da2361bd96d1f6ef83d;hb=eea05a77c2b998c94087825a60d1a9f0f4fe2b7d;hp=19f2f28a39bc8fa611d1fa7fda97d31eea68d3a7;hpb=834e7b28f36dbc5f46197730781b0b74c0c215f7;p=nihav.git diff --git a/nihav-itu/src/codecs/h264/dsp/mc/mod.rs b/nihav-itu/src/codecs/h264/dsp/mc/mod.rs index 19f2f28..615563e 100644 --- a/nihav-itu/src/codecs/h264/dsp/mc/mod.rs +++ b/nihav-itu/src/codecs/h264/dsp/mc/mod.rs @@ -1,6 +1,6 @@ use nihav_core::frame::*; use nihav_codec_support::codecs::MV; -use nihav_codec_support::codecs::blockdsp::*; +use super::super::SimpleFrame; macro_rules! module_selector { ($( ($cond:meta, $module:ident) ),*) => { @@ -81,7 +81,7 @@ impl H264MC { self.width = width; self.height = height; } - pub fn do_mc(&mut self, frm: &mut NASimpleVideoFrame, refpic: NAVideoBufferRef, xpos: usize, ypos: usize, w: usize, h: usize, mv: MV) { + pub fn do_mc(&mut self, frm: &mut NASimpleVideoFrame, refpic: &SimpleFrame, xpos: usize, ypos: usize, w: usize, h: usize, mv: MV) { let mut ebuf = [0u8; 22 * 22]; let mvx = mv.x >> 2; let mvy = mv.y >> 2; @@ -89,16 +89,16 @@ impl H264MC { let pre = if mode != 0 { 2isize } else { 0 }; let post = if mode != 0 { 3isize } else { 0 }; let (yw, yh) = (self.width, self.height); - let src = refpic.get_data(); - let systride = refpic.get_stride(0); + let src = refpic.data; + let systride = refpic.stride[0]; let src_x = (xpos as isize) + (mvx as isize); let src_y = (ypos as isize) + (mvy as isize); let (ysrc, ystride) = if (src_x - pre < 0) || (src_x + (w as isize) + post > (yw as isize)) || (src_y - pre < 0) || (src_y + (h as isize) + post > (yh as isize)) { let add = (pre + post) as usize; - edge_emu(&refpic, src_x - pre, src_y - pre, w + add, h + add, &mut ebuf, 22, 0, 0); + edge_emu_sf(refpic, src_x - pre, src_y - pre, yw, yh, w + add, h + add, &mut ebuf, 22, 0); (&ebuf[..], 22) } else { - (&src[refpic.get_offset(0) + ((src_x - pre) as usize) + ((src_y - pre) as usize) * systride..], systride) + (&src[refpic.offset[0] + ((src_x - pre) as usize) + ((src_y - pre) as usize) * systride..], systride) }; let wmode = match w { 4 => 0, @@ -114,15 +114,17 @@ impl H264MC { let dy = (mv.y & 7) as u16; let src_x = ((xpos >> 1) as isize) + (mvx as isize); let src_y = ((ypos >> 1) as isize) + (mvy as isize); - let suoff = refpic.get_offset(1); - let svoff = refpic.get_offset(2); - let sustride = refpic.get_stride(1); - let svstride = refpic.get_stride(2); + let suoff = refpic.offset[1]; + let svoff = refpic.offset[2]; + let sustride = refpic.stride[1]; + let svstride = refpic.stride[2]; let cbw = w / 2; let cbh = h / 2; let (csrc, cstride) = if (src_x < 0) || (src_x + (cbw as isize) + 1 > (cw as isize)) || (src_y < 0) || (src_y + (cbh as isize) + 1 > (ch as isize)) { - edge_emu(&refpic, src_x, src_y, cbw+1, cbh+1, &mut ebuf, 18, 1, 4); - edge_emu(&refpic, src_x, src_y, cbw+1, cbh+1, &mut ebuf[9..], 18, 2, 4); + let aw = (cw + 7) & !7; + let ah = (ch + 7) & !7; + edge_emu_sf(refpic, src_x, src_y, aw, ah, cbw+1, cbh+1, &mut ebuf, 18, 1); + edge_emu_sf(refpic, src_x, src_y, aw, ah, cbw+1, cbh+1, &mut ebuf[9..], 18, 2); ([&ebuf, &ebuf[9..]], [18, 18]) } else { ([&src[suoff + (src_x as usize) + (src_y as usize) * sustride..], @@ -135,7 +137,7 @@ impl H264MC { } } - pub fn mc_blocks(&mut self, dst: &mut McBlock, refpic: NAVideoBufferRef, xpos: usize, ypos: usize, w: usize, h: usize, mv: MV) { + pub fn mc_blocks(&mut self, dst: &mut McBlock, refpic: &SimpleFrame, xpos: usize, ypos: usize, w: usize, h: usize, mv: MV) { let mode = ((mv.x & 3) + (mv.y & 3) * 4) as usize; let pre = if mode != 0 { 2 } else { 0 }; @@ -155,14 +157,13 @@ impl H264MC { if (sx - pre < 0) || (sx + (w as isize) + post > (width as isize)) || (sy - pre < 0) || (sy + (h as isize) + post > (height as isize)) { let edge = (pre + post) as usize; - edge_emu(&refpic, sx - pre, sy - pre, w + edge, h + edge, - &mut ebuf, EBUF_STRIDE, 0, 0); + edge_emu_sf(refpic, sx - pre, sy - pre, width, height, w + edge, h + edge, + &mut ebuf, EBUF_STRIDE, 0); (H264_LUMA_INTERP[wmode][mode])(&mut dst.y, 16, &ebuf, EBUF_STRIDE, h); } else { - let sstride = refpic.get_stride(0); - let soff = refpic.get_offset(0); - let sdta = refpic.get_data(); - let sbuf: &[u8] = sdta.as_slice(); + let sstride = refpic.stride[0]; + let soff = refpic.offset[0]; + let sbuf = refpic.data; let saddr = soff + ((sx - pre) as usize) + ((sy - pre) as usize) * sstride; (H264_LUMA_INTERP[wmode][mode])(&mut dst.y, 16, &sbuf[saddr..], sstride, h); } @@ -174,16 +175,18 @@ impl H264MC { let dy = (mv.y & 7) as u16; let src_x = ((xpos >> 1) as isize) + (mvx as isize); let src_y = ((ypos >> 1) as isize) + (mvy as isize); - let suoff = refpic.get_offset(1); - let svoff = refpic.get_offset(2); - let sustride = refpic.get_stride(1); - let svstride = refpic.get_stride(2); - let src = refpic.get_data(); + let suoff = refpic.offset[1]; + let svoff = refpic.offset[2]; + let sustride = refpic.stride[1]; + let svstride = refpic.stride[2]; + let src = refpic.data; let cbw = w / 2; let cbh = h / 2; let (csrc, cstride) = if (src_x < 0) || (src_x + (cbw as isize) + 1 > (cw as isize)) || (src_y < 0) || (src_y + (cbh as isize) + 1 > (ch as isize)) { - edge_emu(&refpic, src_x, src_y, cbw+1, cbh+1, &mut ebuf, 18, 1, 4); - edge_emu(&refpic, src_x, src_y, cbw+1, cbh+1, &mut ebuf[9..], 18, 2, 4); + let aw = (cw + 7) & !7; + let ah = (ch + 7) & !7; + edge_emu_sf(refpic, src_x, src_y, aw, ah, cbw+1, cbh+1, &mut ebuf, 18, 1); + edge_emu_sf(refpic, src_x, src_y, aw, ah, cbw+1, cbh+1, &mut ebuf[9..], 18, 2); ([&ebuf, &ebuf[9..]], [18, 18]) } else { ([&src[suoff + (src_x as usize) + (src_y as usize) * sustride..], @@ -194,9 +197,23 @@ impl H264MC { (self.chroma_interp[wmode])(&mut dst.v, 16, csrc[1], cstride[1], dx, dy, cbh); } - pub fn do_mc_avg(&mut self, frm: &mut NASimpleVideoFrame, refpic: NAVideoBufferRef, xpos: usize, ypos: usize, w: usize, h: usize, mv: MV) { + pub fn do_mc_avg(&mut self, frm: &mut NASimpleVideoFrame, refpic: &SimpleFrame, xpos: usize, ypos: usize, w: usize, h: usize, mv: MV) { let mut abuf = self.avg_buf.clone(); - let mut afrm = NASimpleVideoFrame::from_video_buf(&mut abuf).unwrap(); + let stride_y = abuf.get_stride(0); + let stride_c = abuf.get_stride(1); + let off_y = abuf.get_offset(0); + let off_u = abuf.get_offset(1); + let off_v = abuf.get_offset(2); + let data = abuf.get_data_mut().unwrap(); + let mut afrm = NASimpleVideoFrame { + width: [64, 32, 32, 0], + height: [64, 32, 32, 0], + flip: false, + stride: [stride_y, stride_c, stride_c, 0], + offset: [off_y, off_u, off_v, 0], + components: 3, + data, + }; let amv = MV { x: mv.x + (xpos as i16) * 4, y: mv.y + (ypos as i16) * 4 }; self.do_mc(&mut afrm, refpic, 0, 0, w, h, amv); let wsize = match w { @@ -233,6 +250,27 @@ impl H264MC { } } +fn edge_emu_sf(src: &SimpleFrame, xpos: isize, ypos: isize, w: usize, h: usize, bw: usize, bh: usize, dst: &mut [u8], dstride: usize, comp: usize) { + let stride = src.stride[comp]; + let offs = src.offset[comp]; + let framebuf = src.data; + + for y in 0..bh { + let srcy; + if (y as isize) + ypos < 0 { srcy = 0; } + else if (y as isize) + ypos >= (h as isize) { srcy = h - 1; } + else { srcy = ((y as isize) + ypos) as usize; } + + for x in 0..bw { + let srcx; + if (x as isize) + xpos < 0 { srcx = 0; } + else if (x as isize) + xpos >= (w as isize) { srcx = w - 1; } + else { srcx = ((x as isize) + xpos) as usize; } + dst[x + y * dstride] = framebuf[offs + srcx + srcy * stride]; + } + } +} + fn avg(dst: &mut [u8], dstride: usize, src: &[u8], sstride: usize, bw: usize, bh: usize) { for (dline, sline) in dst.chunks_mut(dstride).zip(src.chunks(sstride)).take(bh) { for (dst, src) in dline.iter_mut().zip(sline.iter()).take(bw) { @@ -273,7 +311,7 @@ fn put_block_weighted(dst: &mut [u8], stride: usize, src: &[u8], w: usize, h: us let wshift = wparams[2] as u8; let bias = (1 << wshift) >> 1; - for (drow, srow) in dst.chunks_mut(stride).zip(src.chunks(16)).take(h) { + for (drow, srow) in dst.chunks_mut(stride).zip(src.chunks_exact(16)).take(h) { for (dst, &src) in drow[..w].iter_mut().zip(srow.iter()) { *dst = clip_u8(((i16::from(src) * weight + bias) >> wshift) + offset); } @@ -302,7 +340,7 @@ fn put_block_weighted2(dst: &mut [u8], stride: usize, src0: &[u8], src1: &[u8], let offset = (offset0 + offset1 + 1) >> 1; let bias = (1 << wshift) >> 1; - for (drow, (srow0, srow1)) in dst.chunks_mut(stride).zip(src0.chunks(16).zip(src1.chunks(16))).take(h) { + for (drow, (srow0, srow1)) in dst.chunks_mut(stride).zip(src0.chunks_exact(16).zip(src1.chunks_exact(16))).take(h) { for (dst, (&src0, &src1)) in drow[..w].iter_mut().zip(srow0.iter().zip(srow1.iter())) { *dst = clip_u8(((i16::from(src0) * weight0 + i16::from(src1) * weight1 + bias) >> wshift) + offset); }