From cd830591a8770b4a56ce9b938574adcee3ed33f5 Mon Sep 17 00:00:00 2001 From: Kostya Shishkov Date: Sun, 28 Apr 2019 16:37:59 +0200 Subject: [PATCH] add NASimpleVideoFrame and try it in RV60 decoder --- nihav-core/src/frame.rs | 42 ++++++++++ nihav-realmedia/src/codecs/rv60.rs | 109 ++++++++++++-------------- nihav-realmedia/src/codecs/rv60dsp.rs | 70 +++++++---------- 3 files changed, 120 insertions(+), 101 deletions(-) diff --git a/nihav-core/src/frame.rs b/nihav-core/src/frame.rs index ea9f203..45e05ca 100644 --- a/nihav-core/src/frame.rs +++ b/nihav-core/src/frame.rs @@ -256,6 +256,48 @@ impl NABufferType { } } +const NA_SIMPLE_VFRAME_COMPONENTS: usize = 4; +pub struct NASimpleVideoFrame<'a, T: Copy> { + pub width: [usize; NA_SIMPLE_VFRAME_COMPONENTS], + pub height: [usize; NA_SIMPLE_VFRAME_COMPONENTS], + pub flip: bool, + pub stride: [usize; NA_SIMPLE_VFRAME_COMPONENTS], + pub offset: [usize; NA_SIMPLE_VFRAME_COMPONENTS], + pub components: usize, + pub data: &'a mut Vec, +} + +impl<'a, T:Copy> NASimpleVideoFrame<'a, T> { + pub fn from_video_buf(vbuf: &'a mut NAVideoBuffer) -> Option { + let vinfo = vbuf.get_info(); + let components = vinfo.format.components as usize; + if components > NA_SIMPLE_VFRAME_COMPONENTS { + return None; + } + let mut w: [usize; NA_SIMPLE_VFRAME_COMPONENTS] = [0; NA_SIMPLE_VFRAME_COMPONENTS]; + let mut h: [usize; NA_SIMPLE_VFRAME_COMPONENTS] = [0; NA_SIMPLE_VFRAME_COMPONENTS]; + let mut s: [usize; NA_SIMPLE_VFRAME_COMPONENTS] = [0; NA_SIMPLE_VFRAME_COMPONENTS]; + let mut o: [usize; NA_SIMPLE_VFRAME_COMPONENTS] = [0; NA_SIMPLE_VFRAME_COMPONENTS]; + for comp in 0..components { + let (width, height) = vbuf.get_dimensions(comp); + w[comp] = width; + h[comp] = height; + s[comp] = vbuf.get_stride(comp); + o[comp] = vbuf.get_offset(comp); + } + let flip = vinfo.flipped; + Some(NASimpleVideoFrame { + width: w, + height: h, + flip, + stride: s, + offset: o, + components, + data: vbuf.data.as_mut().unwrap(), + }) + } +} + #[derive(Debug,Clone,Copy,PartialEq)] pub enum AllocatorError { TooLargeDimensions, diff --git a/nihav-realmedia/src/codecs/rv60.rs b/nihav-realmedia/src/codecs/rv60.rs index 007450a..b430b5b 100644 --- a/nihav-realmedia/src/codecs/rv60.rs +++ b/nihav-realmedia/src/codecs/rv60.rs @@ -671,7 +671,7 @@ impl RealVideo60Decoder { ypos: 0, } } - fn decode_cu_line(&mut self, buf: &mut NAVideoBuffer, hdr: &FrameHeader, src: &[u8], cu_y: usize) -> DecoderResult<()> { + fn decode_cu_line(&mut self, buf: &mut NASimpleVideoFrame, hdr: &FrameHeader, src: &[u8], cu_y: usize) -> DecoderResult<()> { let mut br = BitReader::new(src, src.len(), BitReaderMode::BE); let cu_w = hdr.get_width_cu(); let dqp = hdr.read_line_qp_offset(&mut br)?; @@ -713,7 +713,7 @@ println!(" left {} bits", br.left()); } Ok(()) } - fn decode_cb_tree(&mut self, buf: &mut NAVideoBuffer, hdr: &FrameHeader, br: &mut BitReader, xpos: usize, ypos: usize, log_size: u8) -> DecoderResult<()> { + fn decode_cb_tree(&mut self, buf: &mut NASimpleVideoFrame, hdr: &FrameHeader, br: &mut BitReader, xpos: usize, ypos: usize, log_size: u8) -> DecoderResult<()> { if (xpos >= hdr.width) || (ypos >= hdr.height) { return Ok(()); } let size = 1 << log_size; @@ -738,19 +738,17 @@ println!(" left {} bits", br.left()); CUType::Intra => { let itype = self.blk_info[self.blk_pos].imode; if !split_i4x4 { - let dstride = buf.get_stride(0); + let dstride = buf.stride[0]; let off = xpos + ypos * dstride; - let mut data = buf.get_data_mut().unwrap(); - let dst = &mut data; + let dst = &mut buf.data; self.populate_ipred(hdr, dst, 0, dstride, 0, 0, size, true); self.ipred.pred_angle(dst, off, dstride, size, itype as usize, true); } for comp in 1..3 { - let dstride = buf.get_stride(comp); - let soff = buf.get_offset(comp); + let dstride = buf.stride[comp]; + let soff = buf.offset[comp]; let off = soff + (xpos >> 1) + (ypos >> 1) * dstride; - let mut data = buf.get_data_mut().unwrap(); - let mut dst = &mut data; + let mut dst = &mut buf.data; self.populate_ipred(hdr, dst, soff, dstride, 0, 0, size >> 1, false); self.ipred.pred_angle(&mut dst, off, dstride, size >> 1, itype as usize, false); } @@ -793,7 +791,10 @@ println!(" left {} bits", br.left()); validate!(hdr.ftype == FrameType::B); if let (Some(ref prevbuf), Some(ref nextbuf)) = (self.ipbs.get_b_fwdref(), self.ipbs.get_b_bwdref()) { self.dsp.do_mc(buf, prevbuf, bx, by, bw, bh, mv.f_mv, false); - self.dsp.do_mc(&mut self.avg_buf, nextbuf, bx, by, bw, bh, mv.b_mv, true); + { + let mut avg_buf = NASimpleVideoFrame::from_video_buf(&mut self.avg_buf).unwrap(); + self.dsp.do_mc(&mut avg_buf, nextbuf, bx, by, bw, bh, mv.b_mv, true); + } self.dsp.do_avg(buf, &self.avg_buf, bx, by, bw, bh); } }, @@ -846,10 +847,9 @@ println!(" left {} bits", br.left()); let i = x + y * 4; if ((cbp16 >> i) & 1) != 0 { self.dsp.transform4x4(&mut self.y_coeffs[i * 16..][..16]); - let dstride = buf.get_stride(0); + let dstride = buf.stride[0]; let off = xpos + x * 4 + (ypos + y * 4) * dstride; - let mut data = buf.get_data_mut().unwrap(); - let mut dst = &mut data; + let mut dst = &mut buf.data; self.dsp.add_block(&mut dst, off, dstride, &self.y_coeffs[i*16..][..16], 4); } } @@ -861,18 +861,16 @@ println!(" left {} bits", br.left()); let yoff = (ypos >> 1) + y * 4; if ((cbp16 >> (16 + i)) & 1) != 0 { self.dsp.transform4x4(&mut self.u_coeffs[i * 16..][..16]); - let dstride = buf.get_stride(1); - let off = buf.get_offset(1) + xoff + yoff * dstride; - let mut data = buf.get_data_mut().unwrap(); - let mut dst = &mut data; + let dstride = buf.stride[1]; + let off = buf.offset[1] + xoff + yoff * dstride; + let mut dst = &mut buf.data; self.dsp.add_block(&mut dst, off, dstride, &self.u_coeffs[i * 16..][..16], 4); } if ((cbp16 >> (20 + i)) & 1) != 0 { self.dsp.transform4x4(&mut self.v_coeffs[i * 16..][..16]); - let dstride = buf.get_stride(2); - let off = buf.get_offset(2) + xoff + yoff * dstride; - let mut data = buf.get_data_mut().unwrap(); - let mut dst = &mut data; + let dstride = buf.stride[2]; + let off = buf.offset[2] + xoff + yoff * dstride; + let mut dst = &mut buf.data; self.dsp.add_block(&mut dst, off, dstride, &self.v_coeffs[i * 16..][..16], 4); } } @@ -888,10 +886,9 @@ println!(" left {} bits", br.left()); let xoff = (i & 1) * 4; let yoff = (i & 2) * 2; if split_i4x4 { - let dstride = buf.get_stride(0); + let dstride = buf.stride[0]; let off = xpos + xoff + (ypos + yoff) * dstride; - let mut data = buf.get_data_mut().unwrap(); - let mut dst = &mut data; + let mut dst = &mut buf.data; self.populate_ipred(hdr, dst, 0, dstride, xoff, yoff, 4, true); let itype = self.blk_info[self.blk_pos + (i & 1) + (i >> 1) * self.blk_stride].imode; self.ipred.pred_angle(&mut dst, off, dstride, 4, itype as usize, false); @@ -899,30 +896,27 @@ println!(" left {} bits", br.left()); if ((cbp8 >> i) & 1) != 0 { let blk = &mut self.y_coeffs[i * 16..][..16]; self.dsp.transform4x4(blk); - let dstride = buf.get_stride(0); - let soff = buf.get_offset(0); + let dstride = buf.stride[0]; + let soff = buf.offset[0]; let off = soff + xpos + xoff + (ypos + yoff) * dstride; - let mut data = buf.get_data_mut().unwrap(); - let mut dst = &mut data; + let mut dst = &mut buf.data; self.dsp.add_block(&mut dst, off, dstride, blk, 4); } } if ((cbp8 >> 4) & 1) != 0 { self.dsp.transform4x4(&mut self.u_coeffs); - let dstride = buf.get_stride(1); - let soff = buf.get_offset(1); + let dstride = buf.stride[1]; + let soff = buf.offset[1]; let off = soff + (xpos >> 1) + (ypos >> 1) * dstride; - let mut data = buf.get_data_mut().unwrap(); - let mut dst = &mut data; + let mut dst = &mut buf.data; self.dsp.add_block(&mut dst, off, dstride, &self.u_coeffs, 4); } if ((cbp8 >> 5) & 1) != 0 { self.dsp.transform4x4(&mut self.v_coeffs); - let dstride = buf.get_stride(2); - let soff = buf.get_offset(2); + let dstride = buf.stride[2]; + let soff = buf.offset[2]; let off = soff + (xpos >> 1) + (ypos >> 1) * dstride; - let mut data = buf.get_data_mut().unwrap(); - let mut dst = &mut data; + let mut dst = &mut buf.data; self.dsp.add_block(&mut dst, off, dstride, &self.v_coeffs, 4); } } @@ -935,28 +929,25 @@ println!(" left {} bits", br.left()); rv6_decode_cu_8x8(br, &self.cbs, is_intra, self.qp, self.sel_qp, &mut self.y_coeffs, &mut self.u_coeffs, &mut self.v_coeffs, cbp8, false)?; if (cbp8 & 0xF) != 0 { self.dsp.transform8x8(&mut self.y_coeffs); - let dstride = buf.get_stride(0); + let dstride = buf.stride[0]; let off = xpos + ypos * dstride; - let mut data = buf.get_data_mut().unwrap(); - let mut dst = &mut data; + let mut dst = &mut buf.data; self.dsp.add_block(&mut dst, off, dstride, &self.y_coeffs, 8); } if ((cbp8 >> 4) & 1) != 0 { self.dsp.transform4x4(&mut self.u_coeffs); - let dstride = buf.get_stride(1); - let soff = buf.get_offset(1); + let dstride = buf.stride[1]; + let soff = buf.offset[1]; let off = soff + (xpos >> 1) + (ypos >> 1) * dstride; - let mut data = buf.get_data_mut().unwrap(); - let mut dst = &mut data; + let mut dst = &mut buf.data; self.dsp.add_block(&mut dst, off, dstride, &self.u_coeffs, 4); } if ((cbp8 >> 5) & 1) != 0 { self.dsp.transform4x4(&mut self.v_coeffs); - let dstride = buf.get_stride(2); - let soff = buf.get_offset(2); + let dstride = buf.stride[2]; + let soff = buf.offset[2]; let off = soff + (xpos >> 1) + (ypos >> 1) * dstride; - let mut data = buf.get_data_mut().unwrap(); - let mut dst = &mut data; + let mut dst = &mut buf.data; self.dsp.add_block(&mut dst, off, dstride, &self.v_coeffs, 4); } } @@ -980,28 +971,25 @@ println!(" left {} bits", br.left()); rv6_decode_cu_16x16(br, &self.cbs, is_intra, self.qp, self.sel_qp, &mut self.y_coeffs, &mut self.u_coeffs, &mut self.v_coeffs, super_cbp)?; if (super_cbp & 0xFFFF) != 0 { self.dsp.transform16x16(&mut self.y_coeffs); - let dstride = buf.get_stride(0); + let dstride = buf.stride[0]; let off = xpos + x * 16 + (ypos + y * 16) * dstride; - let mut data = buf.get_data_mut().unwrap(); - let mut dst = &mut data; + let mut dst = &mut buf.data; self.dsp.add_block(&mut dst, off, dstride, &self.y_coeffs, 16); } if ((super_cbp >> 16) & 0xF) != 0 { self.dsp.transform8x8(&mut self.u_coeffs); - let dstride = buf.get_stride(1); - let soff = buf.get_offset(1); + let dstride = buf.stride[1]; + let soff = buf.offset[1]; let off = soff + (xpos >> 1) + x * 8 + ((ypos >> 1) + y * 8) * dstride; - let mut data = buf.get_data_mut().unwrap(); - let mut dst = &mut data; + let mut dst = &mut buf.data; self.dsp.add_block(&mut dst, off, dstride, &self.u_coeffs, 8); } if ((super_cbp >> 20) & 0xF) != 0 { self.dsp.transform8x8(&mut self.v_coeffs); - let dstride = buf.get_stride(2); - let soff = buf.get_offset(2); + let dstride = buf.stride[2]; + let soff = buf.offset[2]; let off = soff + (xpos >> 1) + x * 8 + ((ypos >> 1) + y * 8) * dstride; - let mut data = buf.get_data_mut().unwrap(); - let mut dst = &mut data; + let mut dst = &mut buf.data; self.dsp.add_block(&mut dst, off, dstride, &self.v_coeffs, 8); } } @@ -1337,7 +1325,7 @@ println!(" left {} bits", br.left()); skip_cand.list[i] = MVInfo { f_mv: ZERO_MV, b_mv: ZERO_MV, mvref: MVRef::Ref0 }; } } - fn deblock_cb_tree(&mut self, buf: &mut NAVideoBuffer, hdr: &FrameHeader, xpos: usize, ypos: usize, log_size: u8) { + fn deblock_cb_tree(&mut self, buf: &mut NASimpleVideoFrame, hdr: &FrameHeader, xpos: usize, ypos: usize, log_size: u8) { if (xpos >= hdr.width) || (ypos >= hdr.height) { return; } let split = (log_size > 3) && self.cu_splits.pop().unwrap(); if split { @@ -1459,8 +1447,9 @@ println!("???"); self.dblk.reinit(hdr.width, hdr.height); } let mut off = hsize + ((br.tell() >> 3) as usize); + let mut dframe = NASimpleVideoFrame::from_video_buf(&mut buf).unwrap(); for (cu_y, size) in slices.into_iter().enumerate() { - self.decode_cu_line(&mut buf, &hdr, &src[off..][..size], cu_y)?; + self.decode_cu_line(&mut dframe, &hdr, &src[off..][..size], cu_y)?; off += size; } if (hdr.ftype == FrameType::I) || (hdr.ftype == FrameType::P) { diff --git a/nihav-realmedia/src/codecs/rv60dsp.rs b/nihav-realmedia/src/codecs/rv60dsp.rs index 0fa8beb..ab90105 100644 --- a/nihav-realmedia/src/codecs/rv60dsp.rs +++ b/nihav-realmedia/src/codecs/rv60dsp.rs @@ -1,4 +1,4 @@ -use nihav_core::frame::NAVideoBuffer; +use nihav_core::frame::{NAVideoBuffer, NASimpleVideoFrame}; use nihav_core::codecs::MV; use nihav_core::codecs::blockdsp::edge_emu; @@ -450,14 +450,13 @@ impl RV60DSP { sidx += sstride; } } - pub fn do_avg(&self, frame: &mut NAVideoBuffer, prev_frame: &NAVideoBuffer, x: usize, y: usize, w: usize, h: usize) { + pub fn do_avg(&self, frame: &mut NASimpleVideoFrame, prev_frame: &NAVideoBuffer, x: usize, y: usize, w: usize, h: usize) { for comp in 0..3 { - let dstride = frame.get_stride(comp); + let dstride = frame.stride[comp]; let sstride = prev_frame.get_stride(comp); - let doff = if comp == 0 { x + y * dstride } else { frame.get_offset(comp) + (x >> 1) + (y >> 1) * dstride }; + let doff = if comp == 0 { x + y * dstride } else { frame.offset[comp] + (x >> 1) + (y >> 1) * dstride }; let soff = prev_frame.get_offset(comp); - let ddata = frame.get_data_mut().unwrap(); - let dst: &mut [u8] = ddata.as_mut_slice(); + let dst = &mut frame.data; let sdata = prev_frame.get_data(); let src: &[u8] = sdata.as_slice(); @@ -468,12 +467,11 @@ impl RV60DSP { } } } - pub fn do_mc(&self, frame: &mut NAVideoBuffer, prev_frame: &NAVideoBuffer, x: usize, y: usize, w: usize, h: usize, mv: MV, avg: bool) { + pub fn do_mc(&self, frame: &mut NASimpleVideoFrame, prev_frame: &NAVideoBuffer, x: usize, y: usize, w: usize, h: usize, mv: MV, avg: bool) { { // luma - let dstride = frame.get_stride(0); - let doffset = frame.get_offset(0) + (if !avg { x + y * dstride } else { 0 }); - let data = frame.get_data_mut().unwrap(); - let dst: &mut [u8] = data.as_mut_slice(); + let dstride = frame.stride[0]; + let doffset = frame.offset[0] + (if !avg { x + y * dstride } else { 0 }); + let dst = &mut frame.data; let (w_, h_) = prev_frame.get_dimensions(0); let fw = (w_ + 15) & !15; @@ -510,25 +508,23 @@ impl RV60DSP { let ch = h >> 1; for comp in 1..3 { // chroma - let dstride = frame.get_stride(comp); - let doffset = frame.get_offset(comp) + (if !avg { (x >> 1) + (y >> 1) * dstride } else { 0 }); - let data = frame.get_data_mut().unwrap(); - let dst: &mut [u8] = data.as_mut_slice(); + let dstride = frame.stride[comp]; + let doffset = frame.offset[comp] + (if !avg { (x >> 1) + (y >> 1) * dstride } else { 0 }); if check_pos(x >> 1, y >> 1, cw, ch, fw, fh, dx, dy, 0, 1, 0, 1) { let sstride = prev_frame.get_stride(comp); let mut soffset = prev_frame.get_offset(comp) + (x >> 1) + (y >> 1) * sstride; let data = prev_frame.get_data(); let src: &[u8] = data.as_slice(); soffset = ((soffset as isize) + (dx as isize) + (dy as isize) * (sstride as isize)) as usize; - chroma_mc(dst, doffset, dstride, src, soffset, sstride, cw, ch, 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); - chroma_mc(dst, doffset, dstride, &ebuf, 0, 40, cw, ch, cx, cy); + chroma_mc(frame.data, doffset, dstride, &ebuf, 0, 40, cw, ch, cx, cy); } } } - fn deblock_edge4_ver(&self, frame: &mut NAVideoBuffer, xpos: usize, ypos: usize, + fn deblock_edge4_ver(&self, frame: &mut NASimpleVideoFrame, xpos: usize, ypos: usize, dblk_l: u8, dblk_r: u8, deblock_chroma: bool) { let qp_l = dblk_l >> 2; let str_l = dblk_l & 3; @@ -541,23 +537,19 @@ impl RV60DSP { let lim1 = dl_r[2] as i16; let lim2 = (dl_r[3] * 4) as i16; { - let stride = frame.get_stride(0); - let offset = frame.get_offset(0) + xpos + ypos * stride; - let data = frame.get_data_mut().unwrap(); - let dst: &mut [u8] = data.as_mut_slice(); - filter_luma_edge(dst, offset, 1, stride, mode_l, mode_r, lim1, lim2); + let stride = frame.stride[0]; + let offset = frame.offset[0] + xpos + ypos * stride; + filter_luma_edge(frame.data, offset, 1, stride, mode_l, mode_r, lim1, lim2); } if ((str_l | str_r) >= 2) && deblock_chroma { for comp in 1..2 { - let stride = frame.get_stride(comp); - let offset = frame.get_offset(comp) + (xpos >> 1) + (ypos >> 1) * stride; - let data = frame.get_data_mut().unwrap(); - let dst: &mut [u8] = data.as_mut_slice(); - filter_chroma_edge(dst, offset, 1, stride, mode_l, mode_r, lim1, lim2); + let stride = frame.stride[comp]; + let offset = frame.offset[comp] + (xpos >> 1) + (ypos >> 1) * stride; + filter_chroma_edge(frame.data, offset, 1, stride, mode_l, mode_r, lim1, lim2); } } } - fn deblock_edge4_hor(&self, frame: &mut NAVideoBuffer, xpos: usize, ypos: usize, + fn deblock_edge4_hor(&self, frame: &mut NASimpleVideoFrame, xpos: usize, ypos: usize, dblk_t: u8, dblk_d: u8, deblock_chroma: bool) { let qp_t = dblk_t >> 2; let str_t = dblk_t & 3; @@ -570,23 +562,19 @@ impl RV60DSP { let lim1 = dl_d[2] as i16; let lim2 = (dl_d[3] * 4) as i16; { - let stride = frame.get_stride(0); - let offset = frame.get_offset(0) + xpos + ypos * stride; - let data = frame.get_data_mut().unwrap(); - let dst: &mut [u8] = data.as_mut_slice(); - filter_luma_edge(dst, offset, stride, 1, mode_t, mode_d, lim1, lim2); + let stride = frame.stride[0]; + let offset = frame.offset[0] + xpos + ypos * stride; + filter_luma_edge(frame.data, offset, stride, 1, mode_t, mode_d, lim1, lim2); } if ((str_t | str_d) >= 2) && deblock_chroma { for comp in 1..2 { - let stride = frame.get_stride(comp); - let offset = frame.get_offset(comp) + (xpos >> 1) + (ypos >> 1) * stride; - let data = frame.get_data_mut().unwrap(); - let dst: &mut [u8] = data.as_mut_slice(); - filter_chroma_edge(dst, offset, stride, 1, mode_t, mode_d, lim1, lim2); + let stride = frame.stride[comp]; + let offset = frame.offset[comp] + (xpos >> 1) + (ypos >> 1) * stride; + filter_chroma_edge(frame.data, offset, stride, 1, mode_t, mode_d, lim1, lim2); } } } - fn deblock8x8(&self, dparams: &RV60DeblockParams, frame: &mut NAVideoBuffer, + fn deblock8x8(&self, dparams: &RV60DeblockParams, frame: &mut NASimpleVideoFrame, xpos: usize, ypos: usize, top_str: &[u8], left_str: &[u8], dblkpos: usize) { if xpos > 0 { if ypos > 0 { @@ -635,7 +623,7 @@ impl RV60DSP { } } } - pub fn do_deblock(&self, dparams: &RV60DeblockParams, frame: &mut NAVideoBuffer, + pub fn do_deblock(&self, dparams: &RV60DeblockParams, frame: &mut NASimpleVideoFrame, xpos: usize, ypos: usize, size: usize, top_str: &[u8], left_str: &[u8], dpos: usize) { for x in 0..(size >> 3) { self.deblock8x8(dparams, frame, xpos + x * 8, ypos, -- 2.39.5