+use frame::NAVideoBuffer;
+use super::{BlockDSP, CBPInfo, MV};
+use super::super::blockdsp;
//use super::h263data::*;
/*const W1: i32 = 22725;
pub const H263_INTERP_AVG_FUNCS: &[fn(&mut [u8], usize, &[u8], usize, usize, usize)] = &[
h263_interp00_avg, h263_interp01_avg, h263_interp10_avg, h263_interp11_avg ];
+
+pub struct H263BlockDSP { }
+
+impl H263BlockDSP {
+ pub fn new() -> Self {
+ H263BlockDSP { }
+ }
+}
+
+fn deblock_hor(buf: &mut NAVideoBuffer<u8>, comp: usize, q: u8, off: usize) {
+ let stride = buf.get_stride(comp);
+ let mut dptr = buf.get_data_mut();
+ let mut buf = dptr.as_mut_slice();
+ for x in 0..8 {
+ let a = buf[off - 2 * stride + x] as i16;
+ let b = buf[off - 1 * stride + x] as i16;
+ let c = buf[off + 0 * stride + x] as i16;
+ let d = buf[off + 1 * stride + x] as i16;
+ let diff = ((a - d) * 3 + (c - b) * 8) >> 4;
+ if (diff != 0) && (diff >= -32) && (diff < 32) {
+ let d0 = diff.abs() * 2 - (q as i16);
+ let d1 = if d0 < 0 { 0 } else { d0 };
+ let d2 = diff.abs() - d1;
+ let d3 = if d2 < 0 { 0 } else { d2 };
+
+ let delta = if diff < 0 { -d3 } else { d3 };
+
+ let b1 = b + delta;
+ if b1 < 0 { buf[off - 1 * stride + x] = 0; }
+ else if b1 > 255 { buf[off - 1 * stride + x] = 0xFF; }
+ else { buf[off - 1 * stride + x] = b1 as u8; }
+ let c1 = c - delta;
+ if c1 < 0 { buf[off + x] = 0; }
+ else if c1 > 255 { buf[off + x] = 0xFF; }
+ else { buf[off + x] = c1 as u8; }
+ }
+ }
+}
+
+fn deblock_ver(buf: &mut NAVideoBuffer<u8>, comp: usize, q: u8, off: usize) {
+ let stride = buf.get_stride(comp);
+ let mut dptr = buf.get_data_mut();
+ let mut buf = dptr.as_mut_slice();
+ for y in 0..8 {
+ let a = buf[off - 2 + y * stride] as i16;
+ let b = buf[off - 1 + y * stride] as i16;
+ let c = buf[off + 0 + y * stride] as i16;
+ let d = buf[off + 1 + y * stride] as i16;
+ let diff = ((a - d) * 3 + (c - b) * 8) >> 4;
+ if (diff != 0) && (diff >= -32) && (diff < 32) {
+ let d0 = diff.abs() * 2 - (q as i16);
+ let d1 = if d0 < 0 { 0 } else { d0 };
+ let d2 = diff.abs() - d1;
+ let d3 = if d2 < 0 { 0 } else { d2 };
+
+ let delta = if diff < 0 { -d3 } else { d3 };
+
+ let b1 = b + delta;
+ if b1 < 0 { buf[off - 1 + y * stride] = 0; }
+ else if b1 > 255 { buf[off - 1 + y * stride] = 0xFF; }
+ else { buf[off - 1 + y * stride] = b1 as u8; }
+ let c1 = c - delta;
+ if c1 < 0 { buf[off + y * stride] = 0; }
+ else if c1 > 255 { buf[off + y * stride] = 0xFF; }
+ else { buf[off + y * stride] = c1 as u8; }
+ }
+ }
+}
+
+pub fn h263_filter_row(buf: &mut NAVideoBuffer<u8>, mb_y: usize, mb_w: usize, cbpi: &CBPInfo) {
+ let stride = buf.get_stride(0);
+ let mut off = buf.get_offset(0) + mb_y * 16 * stride;
+ for mb_x in 0..mb_w {
+ let coff = off;
+ let coded0 = cbpi.is_coded(mb_x, 0);
+ let coded1 = cbpi.is_coded(mb_x, 1);
+ let q = cbpi.get_q(mb_w + mb_x);
+ if mb_y != 0 {
+ if coded0 && cbpi.is_coded_top(mb_x, 0) { deblock_hor(buf, 0, q, coff); }
+ if coded1 && cbpi.is_coded_top(mb_x, 1) { deblock_hor(buf, 0, q, coff + 8); }
+ }
+ let coff = off + 8 * stride;
+ if cbpi.is_coded(mb_x, 2) && coded0 { deblock_hor(buf, 0, q, coff); }
+ if cbpi.is_coded(mb_x, 3) && coded1 { deblock_hor(buf, 0, q, coff + 8); }
+ off += 16;
+ }
+ let mut leftt = false;
+ let mut leftc = false;
+ let mut off = buf.get_offset(0) + mb_y * 16 * stride;
+ for mb_x in 0..mb_w {
+ let ctop0 = cbpi.is_coded_top(mb_x, 0);
+ let ctop1 = cbpi.is_coded_top(mb_x, 0);
+ let ccur0 = cbpi.is_coded(mb_x, 0);
+ let ccur1 = cbpi.is_coded(mb_x, 1);
+ let q = cbpi.get_q(mb_w + mb_x);
+ if mb_y != 0 {
+ let coff = off - 8 * stride;
+ let qtop = cbpi.get_q(mb_x);
+ if leftt && ctop0 { deblock_ver(buf, 0, qtop, coff); }
+ if ctop0 && ctop1 { deblock_ver(buf, 0, qtop, coff + 8); }
+ }
+ if leftc && ccur0 { deblock_ver(buf, 0, q, off); }
+ if ccur0 && ccur1 { deblock_ver(buf, 0, q, off + 8); }
+ leftt = ctop1;
+ leftc = ccur1;
+ off += 16;
+ }
+ let strideu = buf.get_stride(1);
+ let stridev = buf.get_stride(2);
+ let offu = buf.get_offset(1) + mb_y * 8 * strideu;
+ let offv = buf.get_offset(2) + mb_y * 8 * stridev;
+ if mb_y != 0 {
+ for mb_x in 0..mb_w {
+ let ctu = cbpi.is_coded_top(mb_x, 4);
+ let ccu = cbpi.is_coded(mb_x, 4);
+ let ctv = cbpi.is_coded_top(mb_x, 5);
+ let ccv = cbpi.is_coded(mb_x, 5);
+ let q = cbpi.get_q(mb_w + mb_x);
+ if ctu && ccu { deblock_hor(buf, 1, q, offu + mb_x * 8); }
+ if ctv && ccv { deblock_hor(buf, 2, q, offv + mb_x * 8); }
+ }
+ let mut leftu = false;
+ let mut leftv = false;
+ let offu = buf.get_offset(1) + (mb_y - 1) * 8 * strideu;
+ let offv = buf.get_offset(2) + (mb_y - 1) * 8 * stridev;
+ for mb_x in 0..mb_w {
+ let ctu = cbpi.is_coded_top(mb_x, 4);
+ let ctv = cbpi.is_coded_top(mb_x, 5);
+ let qt = cbpi.get_q(mb_x);
+ if leftu && ctu { deblock_ver(buf, 1, qt, offu + mb_x * 8); }
+ if leftv && ctv { deblock_ver(buf, 2, qt, offv + mb_x * 8); }
+ leftu = ctu;
+ leftv = ctv;
+ }
+ }
+}
+
+impl BlockDSP for H263BlockDSP {
+ fn idct(&self, blk: &mut [i16; 64]) {
+ h263_idct(blk)
+ }
+ fn copy_blocks(&self, dst: &mut NAVideoBuffer<u8>, src: &NAVideoBuffer<u8>, xpos: usize, ypos: usize, w: usize, h: usize, mv: MV) {
+ let srcx = ((mv.x >> 1) as isize) + (xpos as isize);
+ let srcy = ((mv.y >> 1) as isize) + (ypos as isize);
+ let mode = ((mv.x & 1) + (mv.y & 1) * 2) as usize;
+
+ blockdsp::copy_blocks(dst, src, xpos, ypos, srcx, srcy, w, h, 0, 1, mode, H263_INTERP_FUNCS);
+ }
+ fn avg_blocks(&self, dst: &mut NAVideoBuffer<u8>, src: &NAVideoBuffer<u8>, xpos: usize, ypos: usize, w: usize, h: usize, mv: MV) {
+ let srcx = ((mv.x >> 1) as isize) + (xpos as isize);
+ let srcy = ((mv.y >> 1) as isize) + (ypos as isize);
+ let mode = ((mv.x & 1) + (mv.y & 1) * 2) as usize;
+
+ blockdsp::copy_blocks(dst, src, xpos, ypos, srcx, srcy, w, h, 0, 1, mode, H263_INTERP_AVG_FUNCS);
+ }
+ fn filter_row(&self, buf: &mut NAVideoBuffer<u8>, mb_y: usize, mb_w: usize, cbpi: &CBPInfo) {
+ h263_filter_row(buf, mb_y, mb_w, cbpi)
+ }
+}
}
}
-fn copy_blocks(dst: &mut NAVideoBuffer<u8>, src: &NAVideoBuffer<u8>, xpos: usize, ypos: usize, w: usize, h: usize, mv: MV) {
- let srcx = ((mv.x >> 1) as isize) + (xpos as isize);
- let srcy = ((mv.y >> 1) as isize) + (ypos as isize);
- let mode = ((mv.x & 1) + (mv.y & 1) * 2) as usize;
-
- blockdsp::copy_blocks(dst, src, xpos, ypos, srcx, srcy, w, h, 0, 1, mode, H263_INTERP_FUNCS);
-}
-
-fn avg_blocks(dst: &mut NAVideoBuffer<u8>, src: &NAVideoBuffer<u8>, xpos: usize, ypos: usize, w: usize, h: usize, mv: MV) {
- let srcx = ((mv.x >> 1) as isize) + (xpos as isize);
- let srcy = ((mv.y >> 1) as isize) + (ypos as isize);
- let mode = ((mv.x & 1) + (mv.y & 1) * 2) as usize;
-
- blockdsp::copy_blocks(dst, src, xpos, ypos, srcx, srcy, w, h, 0, 1, mode, H263_INTERP_AVG_FUNCS);
-}
-
#[allow(dead_code)]
#[derive(Clone,Copy)]
struct BMB {
pub fn is_intra(&self) -> bool { self.ftype == Type::I }
pub fn get_dimensions(&self) -> (usize, usize) { (self.w, self.h) }
- pub fn parse_frame(&mut self, bd: &mut BlockDecoder) -> DecoderResult<NABufferType> {
+ pub fn parse_frame(&mut self, bd: &mut BlockDecoder, bdsp: &BlockDSP) -> DecoderResult<NABufferType> {
let pinfo = bd.decode_pichdr()?;
let mut mvi = MVInfo::new();
let mut cbpi = CBPInfo::new();
let mut bufinfo = bufret.unwrap();
let mut buf = bufinfo.get_vbuf().unwrap();
- let mut slice = Slice::get_default_slice(&pinfo);
+ let mut slice = if bd.is_gob() {
+ SliceInfo::get_default_slice(&pinfo)
+ } else {
+ bd.decode_slice_header(&pinfo)?
+ };
mvi.reset(self.mb_w, 0, pinfo.get_mvmode());
cbpi.reset(self.mb_w);
let mut blk: [[i16; 64]; 6] = [[0; 64]; 6];
+ let mut sstate = SliceState::new(pinfo.mode == Type::I);
+ let mut mb_pos = 0;
for mb_y in 0..self.mb_h {
for mb_x in 0..self.mb_w {
for i in 0..6 { for j in 0..64 { blk[i][j] = 0; } }
- if ((mb_x != 0) || (mb_y != 0)) && bd.is_slice_end() {
+ if slice.is_at_end(mb_pos) || (slice.needs_check() && mb_pos > 0 && bd.is_slice_end()) {
slice = bd.decode_slice_header(&pinfo)?;
//mvi.reset(self.mb_w, mb_x, pinfo.get_mvmode());
//cbpi.reset(self.mb_w);
}
- let binfo = bd.decode_block_header(&pinfo, &slice)?;
+ let binfo = bd.decode_block_header(&pinfo, &slice, &sstate)?;
let cbp = binfo.get_cbp();
cbpi.set_cbp(mb_x, cbp);
cbpi.set_q(mb_x, binfo.get_q());
if binfo.is_intra() {
for i in 0..6 {
- bd.decode_block_intra(&binfo, binfo.get_q(), i, (cbp & (1 << (5 - i))) != 0, &mut blk[i])?;
+ bd.decode_block_intra(&binfo, &sstate, binfo.get_q(), i, (cbp & (1 << (5 - i))) != 0, &mut blk[i])?;
h263_idct(&mut blk[i]);
}
blockdsp::put_blocks(&mut buf, mb_x, mb_y, &blk);
if binfo.get_num_mvs() == 1 {
let mv = mvi.predict(mb_x, 0, false, binfo.get_mv(0));
if let Some(ref srcbuf) = self.prev_frm {
- copy_blocks(&mut buf, srcbuf, mb_x * 16, mb_y * 16, 16, 16, mv);
+ bdsp.copy_blocks(&mut buf, srcbuf, mb_x * 16, mb_y * 16, 16, 16, mv);
}
} else {
for blk_no in 0..4 {
let mv = mvi.predict(mb_x, blk_no, true, binfo.get_mv(blk_no));
if let Some(ref srcbuf) = self.prev_frm {
- copy_blocks(&mut buf, srcbuf,
- mb_x * 16 + (blk_no & 1) * 8,
- mb_y * 16 + (blk_no & 2) * 4, 8, 8, mv);
+ bdsp.copy_blocks(&mut buf, srcbuf,
+ mb_x * 16 + (blk_no & 1) * 8,
+ mb_y * 16 + (blk_no & 2) * 4, 8, 8, mv);
}
}
}
for i in 0..6 {
- bd.decode_block_inter(&binfo, binfo.get_q(), i, ((cbp >> (5 - i)) & 1) != 0, &mut blk[i])?;
+ bd.decode_block_inter(&binfo, &sstate, binfo.get_q(), i, ((cbp >> (5 - i)) & 1) != 0, &mut blk[i])?;
h263_idct(&mut blk[i]);
}
blockdsp::add_blocks(&mut buf, mb_x, mb_y, &blk);
} else {
mvi.set_zero_mv(mb_x);
if let Some(ref srcbuf) = self.prev_frm {
- copy_blocks(&mut buf, srcbuf, mb_x * 16, mb_y * 16, 16, 16, ZERO_MV);
+ bdsp.copy_blocks(&mut buf, srcbuf, mb_x * 16, mb_y * 16, 16, 16, ZERO_MV);
}
}
if pinfo.is_pb() {
b_mb.cbp = cbp;
for i in 0..6 {
- bd.decode_block_inter(&binfo, bquant, i, (cbp & (1 << (5 - i))) != 0, &mut b_mb.blk[i])?;
+ bd.decode_block_inter(&binfo, &sstate, bquant, i, (cbp & (1 << (5 - i))) != 0, &mut b_mb.blk[i])?;
h263_idct(&mut b_mb.blk[i]);
}
}
self.b_data.push(b_mb);
}
+ sstate.next_mb();
+ mb_pos += 1;
}
- if pinfo.deblock {
- bd.filter_row(&mut buf, mb_y, self.mb_w, &cbpi);
+ if let Some(plusinfo) = pinfo.plusinfo {
+ if plusinfo.deblock {
+ bdsp.filter_row(&mut buf, mb_y, self.mb_w, &cbpi);
+ }
}
mvi.update_row();
cbpi.update_row();
+ sstate.new_row();
}
self.cur_frm = Some(buf);
Ok(bufinfo)
}
- pub fn get_bframe(&mut self) -> DecoderResult<NABufferType> {
+ pub fn get_bframe(&mut self, bdsp: &BlockDSP) -> DecoderResult<NABufferType> {
if !self.has_b || !self.cur_frm.is_some() || !self.prev_frm.is_some() {
return Err(DecoderError::MissingReference);
}
if let Some(ref bck_buf) = self.prev_frm {
if let Some(ref fwd_buf) = self.cur_frm {
- recon_b_frame(&mut b_buf, bck_buf, fwd_buf, self.mb_w, self.mb_h, &self.b_data);
+ recon_b_frame(&mut b_buf, bck_buf, fwd_buf, self.mb_w, self.mb_h, &self.b_data, bdsp);
}
}
}
fn recon_b_frame(b_buf: &mut NAVideoBuffer<u8>, bck_buf: &NAVideoBuffer<u8>, fwd_buf: &NAVideoBuffer<u8>,
- mb_w: usize, mb_h: usize, b_data: &Vec<BMB>) {
+ mb_w: usize, mb_h: usize, b_data: &Vec<BMB>, bdsp: &BlockDSP) {
let mut cbpi = CBPInfo::new();
let mut cur_mb = 0;
cbpi.reset(mb_w);
let cbp = b_data[cur_mb].cbp;
cbpi.set_cbp(mb_x, cbp);
if num_mv == 1 {
- copy_blocks(b_buf, fwd_buf, mb_x * 16, mb_y * 16, 16, 16, b_data[cur_mb].mv_b[0]);
+ bdsp.copy_blocks(b_buf, fwd_buf, mb_x * 16, mb_y * 16, 16, 16, b_data[cur_mb].mv_b[0]);
if !is_fwd {
- avg_blocks(b_buf, bck_buf, mb_x * 16, mb_y * 16, 16, 16, b_data[cur_mb].mv_f[0]);
+ bdsp.avg_blocks(b_buf, bck_buf, mb_x * 16, mb_y * 16, 16, 16, b_data[cur_mb].mv_f[0]);
}
} else {
for blk_no in 0..4 {
let xpos = mb_x * 16 + (blk_no & 1) * 8;
let ypos = mb_y * 16 + (blk_no & 2) * 4;
- copy_blocks(b_buf, fwd_buf, xpos, ypos, 8, 8, b_data[cur_mb].mv_b[blk_no]);
+ bdsp.copy_blocks(b_buf, fwd_buf, xpos, ypos, 8, 8, b_data[cur_mb].mv_b[blk_no]);
if !is_fwd {
- avg_blocks(b_buf, bck_buf, xpos, ypos, 8, 8, b_data[cur_mb].mv_f[blk_no]);
+ bdsp.avg_blocks(b_buf, bck_buf, xpos, ypos, 8, 8, b_data[cur_mb].mv_f[blk_no]);
}
}
}
use super::*;
use super::decoder::*;
use super::data::*;
+use super::code::H263BlockDSP;
#[allow(dead_code)]
struct Tables {
info: Rc<NACodecInfo>,
dec: H263BaseDecoder,
tables: Tables,
+ bdsp: H263BlockDSP,
}
struct Intel263BR<'a> {
self.mb_w = (w + 15) >> 4;
let ftype = if is_intra { Type::I } else { Type::P };
- let mvmode = if umv { MVMode::UMV } else { MVMode::Long };
- let picinfo = PicInfo::new(w, h, ftype, quant as u8, apm, mvmode, tr, pbinfo, deblock);
+ let plusinfo = if deblock { Some(PlusInfo::new(false, deblock, false, false)) } else { None };
+ let picinfo = PicInfo::new(w, h, ftype, umv, apm, quant as u8, tr, pbinfo, plusinfo);
Ok(picinfo)
}
#[allow(unused_variables)]
- fn decode_slice_header(&mut self, info: &PicInfo) -> DecoderResult<Slice> {
+ fn decode_slice_header(&mut self, info: &PicInfo) -> DecoderResult<SliceInfo> {
let mut br = &mut self.br;
let gbsc = br.read(17)?;
validate!(gbsc == 1);
let gfid = br.read(2)?;
let gquant = br.read(5)?;
//println!("GOB gn {:X} id {} q {}", gn, gfid, gquant);
- let ret = Slice::new(0, self.gob_no, gquant as u8);
+ let ret = SliceInfo::new_gob(0, self.gob_no, gquant as u8);
self.gob_no += 1;
Ok(ret)
}
- fn decode_block_header(&mut self, info: &PicInfo, slice: &Slice) -> DecoderResult<BlockInfo> {
+ #[allow(unused_variables)]
+ fn decode_block_header(&mut self, info: &PicInfo, slice: &SliceInfo, sstate: &SliceState) -> DecoderResult<BlockInfo> {
let mut br = &mut self.br;
let mut q = slice.get_quant();
match info.get_mode() {
}
#[allow(unused_variables)]
- fn decode_block_intra(&mut self, info: &BlockInfo, quant: u8, no: usize, coded: bool, blk: &mut [i16; 64]) -> DecoderResult<()> {
+ fn decode_block_intra(&mut self, info: &BlockInfo, sstate: &SliceState, quant: u8, no: usize, coded: bool, blk: &mut [i16; 64]) -> DecoderResult<()> {
self.decode_block(quant, true, coded, blk)
}
#[allow(unused_variables)]
- fn decode_block_inter(&mut self, info: &BlockInfo, quant: u8, no: usize, coded: bool, blk: &mut [i16; 64]) -> DecoderResult<()> {
+ fn decode_block_inter(&mut self, info: &BlockInfo, sstate: &SliceState, quant: u8, no: usize, coded: bool, blk: &mut [i16; 64]) -> DecoderResult<()> {
self.decode_block(quant, false, coded, blk)
}
fn is_slice_end(&mut self) -> bool { self.br.peek(16) == 0 }
- fn filter_row(&mut self, buf: &mut NAVideoBuffer<u8>, mb_y: usize, mb_w: usize, cbpi: &CBPInfo) {
- let stride = buf.get_stride(0);
- let mut off = buf.get_offset(0) + mb_y * 16 * stride;
- for mb_x in 0..mb_w {
- let coff = off;
- let coded0 = cbpi.is_coded(mb_x, 0);
- let coded1 = cbpi.is_coded(mb_x, 1);
- let q = cbpi.get_q(mb_w + mb_x);
- if mb_y != 0 {
- if coded0 && cbpi.is_coded_top(mb_x, 0) { deblock_hor(buf, 0, q, coff); }
- if coded1 && cbpi.is_coded_top(mb_x, 1) { deblock_hor(buf, 0, q, coff + 8); }
- }
- let coff = off + 8 * stride;
- if cbpi.is_coded(mb_x, 2) && coded0 { deblock_hor(buf, 0, q, coff); }
- if cbpi.is_coded(mb_x, 3) && coded1 { deblock_hor(buf, 0, q, coff + 8); }
- off += 16;
- }
- let mut leftt = false;
- let mut leftc = false;
- let mut off = buf.get_offset(0) + mb_y * 16 * stride;
- for mb_x in 0..mb_w {
- let ctop0 = cbpi.is_coded_top(mb_x, 0);
- let ctop1 = cbpi.is_coded_top(mb_x, 0);
- let ccur0 = cbpi.is_coded(mb_x, 0);
- let ccur1 = cbpi.is_coded(mb_x, 1);
- let q = cbpi.get_q(mb_w + mb_x);
- if mb_y != 0 {
- let coff = off - 8 * stride;
- let qtop = cbpi.get_q(mb_x);
- if leftt && ctop0 { deblock_ver(buf, 0, qtop, coff); }
- if ctop0 && ctop1 { deblock_ver(buf, 0, qtop, coff + 8); }
- }
- if leftc && ccur0 { deblock_ver(buf, 0, q, off); }
- if ccur0 && ccur1 { deblock_ver(buf, 0, q, off + 8); }
- leftt = ctop1;
- leftc = ccur1;
- off += 16;
- }
- let strideu = buf.get_stride(1);
- let stridev = buf.get_stride(2);
- let offu = buf.get_offset(1) + mb_y * 8 * strideu;
- let offv = buf.get_offset(2) + mb_y * 8 * stridev;
- if mb_y != 0 {
- for mb_x in 0..mb_w {
- let ctu = cbpi.is_coded_top(mb_x, 4);
- let ccu = cbpi.is_coded(mb_x, 4);
- let ctv = cbpi.is_coded_top(mb_x, 5);
- let ccv = cbpi.is_coded(mb_x, 5);
- let q = cbpi.get_q(mb_w + mb_x);
- if ctu && ccu { deblock_hor(buf, 1, q, offu + mb_x * 8); }
- if ctv && ccv { deblock_hor(buf, 2, q, offv + mb_x * 8); }
- }
- let mut leftu = false;
- let mut leftv = false;
- let offu = buf.get_offset(1) + (mb_y - 1) * 8 * strideu;
- let offv = buf.get_offset(2) + (mb_y - 1) * 8 * stridev;
- for mb_x in 0..mb_w {
- let ctu = cbpi.is_coded_top(mb_x, 4);
- let ctv = cbpi.is_coded_top(mb_x, 5);
- let qt = cbpi.get_q(mb_x);
- if leftu && ctu { deblock_ver(buf, 1, qt, offu + mb_x * 8); }
- if leftv && ctv { deblock_ver(buf, 2, qt, offv + mb_x * 8); }
- leftu = ctu;
- leftv = ctv;
- }
- }
- }
-}
-
-fn deblock_hor(buf: &mut NAVideoBuffer<u8>, comp: usize, q: u8, off: usize) {
- let stride = buf.get_stride(comp);
- let mut dptr = buf.get_data_mut();
- let mut buf = dptr.as_mut_slice();
- for x in 0..8 {
- let a = buf[off - 2 * stride + x] as i16;
- let b = buf[off - 1 * stride + x] as i16;
- let c = buf[off + 0 * stride + x] as i16;
- let d = buf[off + 1 * stride + x] as i16;
- let diff = ((a - d) * 3 + (c - b) * 8) >> 4;
- if (diff != 0) && (diff >= -32) && (diff < 32) {
- let d0 = diff.abs() * 2 - (q as i16);
- let d1 = if d0 < 0 { 0 } else { d0 };
- let d2 = diff.abs() - d1;
- let d3 = if d2 < 0 { 0 } else { d2 };
-
- let delta = if diff < 0 { -d3 } else { d3 };
-
- let b1 = b + delta;
- if b1 < 0 { buf[off - 1 * stride + x] = 0; }
- else if b1 > 255 { buf[off - 1 * stride + x] = 0xFF; }
- else { buf[off - 1 * stride + x] = b1 as u8; }
- let c1 = c - delta;
- if c1 < 0 { buf[off + x] = 0; }
- else if c1 > 255 { buf[off + x] = 0xFF; }
- else { buf[off + x] = c1 as u8; }
- }
- }
-}
-
-fn deblock_ver(buf: &mut NAVideoBuffer<u8>, comp: usize, q: u8, off: usize) {
- let stride = buf.get_stride(comp);
- let mut dptr = buf.get_data_mut();
- let mut buf = dptr.as_mut_slice();
- for y in 0..8 {
- let a = buf[off - 2 + y * stride] as i16;
- let b = buf[off - 1 + y * stride] as i16;
- let c = buf[off + 0 + y * stride] as i16;
- let d = buf[off + 1 + y * stride] as i16;
- let diff = ((a - d) * 3 + (c - b) * 8) >> 4;
- if (diff != 0) && (diff >= -32) && (diff < 32) {
- let d0 = diff.abs() * 2 - (q as i16);
- let d1 = if d0 < 0 { 0 } else { d0 };
- let d2 = diff.abs() - d1;
- let d3 = if d2 < 0 { 0 } else { d2 };
-
- let delta = if diff < 0 { -d3 } else { d3 };
-
- let b1 = b + delta;
- if b1 < 0 { buf[off - 1 + y * stride] = 0; }
- else if b1 > 255 { buf[off - 1 + y * stride] = 0xFF; }
- else { buf[off - 1 + y * stride] = b1 as u8; }
- let c1 = c - delta;
- if c1 < 0 { buf[off + y * stride] = 0; }
- else if c1 > 255 { buf[off + y * stride] = 0xFF; }
- else { buf[off + y * stride] = c1 as u8; }
- }
- }
+ fn is_gob(&mut self) -> bool { true }
}
impl Intel263Decoder {
info: Rc::new(DUMMY_CODEC_INFO),
dec: H263BaseDecoder::new(),
tables: tables,
+ bdsp: H263BlockDSP::new(),
}
}
}
let src = pkt.get_buffer();
if src.len() == 8 {
- let bret = self.dec.get_bframe();
+ let bret = self.dec.get_bframe(&self.bdsp);
let buftype;
let is_skip;
if let Ok(btype) = bret {
}
let mut ibr = Intel263BR::new(&src, &self.tables);
- let bufinfo = self.dec.parse_frame(&mut ibr)?;
+ let bufinfo = self.dec.parse_frame(&mut ibr, &self.bdsp)?;
let mut frm = NAFrame::new_from_pkt(pkt, self.info.clone(), bufinfo);
frm.set_keyframe(self.dec.is_intra());
use test::dec_video::test_file_decoding;
#[test]
fn test_intel263() {
- test_file_decoding("avi", "assets/neal73_saber.avi", Some(16), true, false, None);
+ test_file_decoding("avi", "assets/neal73_saber.avi", Some(16), true, false, Some("i263"));
}
}
pub trait BlockDecoder {
fn decode_pichdr(&mut self) -> DecoderResult<PicInfo>;
- fn decode_slice_header(&mut self, pinfo: &PicInfo) -> DecoderResult<Slice>;
- fn decode_block_header(&mut self, pinfo: &PicInfo, sinfo: &Slice) -> DecoderResult<BlockInfo>;
- fn decode_block_intra(&mut self, info: &BlockInfo, quant: u8, no: usize, coded: bool, blk: &mut [i16; 64]) -> DecoderResult<()>;
- fn decode_block_inter(&mut self, info: &BlockInfo, quant: u8, no: usize, coded: bool, blk: &mut [i16; 64]) -> DecoderResult<()>;
+ fn decode_slice_header(&mut self, pinfo: &PicInfo) -> DecoderResult<SliceInfo>;
+ fn decode_block_header(&mut self, pinfo: &PicInfo, sinfo: &SliceInfo, sstate: &SliceState) -> DecoderResult<BlockInfo>;
+ fn decode_block_intra(&mut self, info: &BlockInfo, sstate: &SliceState, quant: u8, no: usize, coded: bool, blk: &mut [i16; 64]) -> DecoderResult<()>;
+ fn decode_block_inter(&mut self, info: &BlockInfo, sstate: &SliceState, quant: u8, no: usize, coded: bool, blk: &mut [i16; 64]) -> DecoderResult<()>;
fn is_slice_end(&mut self) -> bool;
+ fn is_gob(&mut self) -> bool;
+}
- fn filter_row(&mut self, buf: &mut NAVideoBuffer<u8>, mb_y: usize, mb_w: usize, cbpi: &CBPInfo);
+pub trait BlockDSP {
+ fn idct(&self, blk: &mut [i16; 64]);
+ fn copy_blocks(&self, dst: &mut NAVideoBuffer<u8>, src: &NAVideoBuffer<u8>, xpos: usize, ypos: usize, w: usize, h: usize, mv: MV);
+ fn avg_blocks(&self, dst: &mut NAVideoBuffer<u8>, src: &NAVideoBuffer<u8>, xpos: usize, ypos: usize, w: usize, h: usize, mv: MV);
+ fn filter_row(&self, buf: &mut NAVideoBuffer<u8>, mb_y: usize, mb_w: usize, cbpi: &CBPInfo);
}
+#[allow(dead_code)]
#[derive(Debug,Clone,Copy,PartialEq)]
pub enum Type {
- I, P, Skip, Special
+ I, P, PB, Skip, B, Special
}
#[allow(dead_code)]
#[allow(dead_code)]
#[derive(Debug,Clone,Copy)]
pub struct PicInfo {
- w: usize,
- h: usize,
- mode: Type,
- quant: u8,
- apm: bool,
- mvmode: MVMode,
- pb: Option<PBInfo>,
- ts: u8,
- deblock: bool,
+ pub w: usize,
+ pub h: usize,
+ pub mode: Type,
+ pub umv: bool,
+ pub apm: bool,
+ pub quant: u8,
+ pub pb: Option<PBInfo>,
+ pub ts: u8,
+ pub plusinfo: Option<PlusInfo>,
}
#[allow(dead_code)]
impl PicInfo {
- pub fn new(w: usize, h: usize, mode: Type, quant: u8, apm: bool, mvmode: MVMode, ts: u8, pb: Option<PBInfo>, deblock: bool) -> Self {
- PicInfo{ w: w, h: h, mode: mode, quant: quant, apm: apm, mvmode: mvmode, ts: ts, pb: pb, deblock: deblock }
+ pub fn new(w: usize, h: usize, mode: Type, umv: bool, apm: bool, quant: u8, ts: u8, pb: Option<PBInfo>, plusinfo: Option<PlusInfo>) -> Self {
+ PicInfo {
+ w: w, h: h, mode: mode,
+ umv: umv, apm: apm, quant: quant,
+ pb: pb, ts: ts, plusinfo: plusinfo
+ }
}
pub fn get_width(&self) -> usize { self.w }
pub fn get_height(&self) -> usize { self.h }
pub fn get_mode(&self) -> Type { self.mode }
pub fn get_quant(&self) -> u8 { self.quant }
pub fn get_apm(&self) -> bool { self.apm }
- pub fn get_mvmode(&self) -> MVMode { self.mvmode }
pub fn is_pb(&self) -> bool { self.pb.is_some() }
pub fn get_ts(&self) -> u8 { self.ts }
pub fn get_pbinfo(&self) -> PBInfo { self.pb.unwrap() }
+ pub fn get_plusifo(&self) -> Option<PlusInfo> { self.plusinfo }
+ pub fn get_mvmode(&self) -> MVMode {
+ if self.umv { MVMode::UMV }
+ else if self.apm { MVMode::Long }
+ else { MVMode::Old }
+ }
}
+#[allow(dead_code)]
#[derive(Debug,Clone,Copy)]
-pub struct Slice {
- mb_x: usize,
- mb_y: usize,
- quant: u8,
+pub struct PlusInfo {
+ pub aic: bool,
+ pub deblock: bool,
+ pub aiv_mode: bool,
+ pub mq_mode: bool,
}
-impl Slice {
- pub fn new(mb_x: usize, mb_y: usize, quant: u8) -> Self {
- Slice{ mb_x: mb_x, mb_y: mb_y, quant: quant }
+impl PlusInfo {
+ pub fn new(aic: bool, deblock: bool, aiv_mode: bool, mq_mode: bool) -> Self {
+ PlusInfo { aic: aic, deblock: deblock, aiv_mode: aiv_mode, mq_mode: mq_mode }
+ }
+}
+
+#[allow(dead_code)]
+#[derive(Debug,Clone,Copy)]
+pub struct SliceInfo {
+ pub mb_x: usize,
+ pub mb_y: usize,
+ pub mb_end: usize,
+ pub quant: u8,
+}
+
+#[allow(dead_code)]
+#[derive(Debug,Clone,Copy)]
+pub struct SliceState {
+ pub is_iframe: bool,
+ pub mb_x: usize,
+ pub mb_y: usize,
+}
+
+const SLICE_NO_END: usize = 99999999;
+
+impl SliceInfo {
+ pub fn new(mb_x: usize, mb_y: usize, mb_end: usize, quant: u8) -> Self {
+ SliceInfo{ mb_x: mb_x, mb_y: mb_y, mb_end: mb_end, quant: quant }
+ }
+ pub fn new_gob(mb_x: usize, mb_y: usize, quant: u8) -> Self {
+ SliceInfo{ mb_x: mb_x, mb_y: mb_y, mb_end: SLICE_NO_END, quant: quant }
}
pub fn get_default_slice(pinfo: &PicInfo) -> Self {
- Slice{ mb_x: 0, mb_y: 0, quant: pinfo.get_quant() }
+ SliceInfo{ mb_x: 0, mb_y: 0, mb_end: SLICE_NO_END, quant: pinfo.get_quant() }
}
pub fn get_quant(&self) -> u8 { self.quant }
+ pub fn is_at_end(&self, mb_pos: usize) -> bool { self.mb_end == mb_pos }
+ pub fn needs_check(&self) -> bool { self.mb_end == SLICE_NO_END }
+}
+
+impl SliceState {
+ pub fn new(is_iframe: bool) -> Self {
+ SliceState { is_iframe: is_iframe, mb_x: 0, mb_y: 0 }
+ }
+ pub fn next_mb(&mut self) { self.mb_x += 1; }
+ pub fn new_row(&mut self) { self.mb_x = 0; self.mb_y += 1; }
}
#[derive(Debug,Clone,Copy)]
use formats;
use super::super::*;
use super::*;
+use super::code::H263BlockDSP;
use super::decoder::*;
use super::data::*;
w: usize,
h: usize,
new_ver: bool,
+ bdsp: H263BlockDSP,
}
struct RealVideo10BR<'a> {
h: usize,
mb_w: usize,
mb_h: usize,
- mb_x: usize,
- mb_y: usize,
- mb_count: usize,
- mb_end: usize,
new_ver: bool,
dc_coded: [bool; 3],
last_dc: [i16; 3],
- is_intra: bool,
}
struct RV10SliceInfo {
h: height,
mb_w: (width + 15) >> 4,
mb_h: (height + 15) >> 4,
- mb_x: 0,
- mb_y: 0,
- mb_count: 0,
- mb_end: 0,
new_ver: new_ver,
dc_coded: [false; 3],
last_dc: [0; 3],
- is_intra: false,
}
}
- fn decode_block(&mut self, quant: u8, intra: bool, coded: bool, blk: &mut [i16; 64], plane_no: usize) -> DecoderResult<()> {
+#[allow(unused_variables)]
+ fn decode_block(&mut self, sstate: &SliceState, quant: u8, intra: bool, coded: bool, blk: &mut [i16; 64], plane_no: usize) -> DecoderResult<()> {
let mut br = &mut self.br;
let mut idx = 0;
if intra {
let mut dc;
-//println!("dc prev {} @ {} of {},{} / {}x{}", self.last_dc[plane_no], br.tell() - (self.slice_off[self.slice_no - 1] as usize) * 8, self.mb_x, self.mb_y, self.mb_w, self.mb_h);
- if !self.new_ver || !self.is_intra {
+//println!("dc prev {} @ {} of {},{} / {}x{}", self.last_dc[plane_no], br.tell() - (self.slice_off[self.slice_no - 1] as usize) * 8, sstate.mb_x, sstate.mb_y, self.mb_w, self.mb_h);
+ if !self.new_ver || !sstate.is_iframe {
dc = br.read(8)? as i16;
if dc == 255 { dc = 128; }
} else {
fn decode_pichdr(&mut self) -> DecoderResult<PicInfo> {
self.slice_no = 0;
println!("decoding picture header size {}", if self.num_slices > 1 { self.slice_off[1] } else { ((self.br.tell() as u32) + (self.br.left() as u32))/8 });
- self.mb_x = 0;
- self.mb_y = 0;
- self.mb_count = self.mb_w * self.mb_h;
let shdr = self.read_slice_header()?;
- self.slice_no += 1;
validate!((shdr.mb_x == 0) && (shdr.mb_y == 0));
- self.mb_x = shdr.mb_x;
- self.mb_y = shdr.mb_y;
- self.mb_count = shdr.mb_c;
- self.mb_end = self.mb_x + self.mb_y * self.mb_w + self.mb_count;
- self.is_intra = !shdr.is_p;
+ let mb_end = shdr.mb_x + shdr.mb_y * self.mb_w + shdr.mb_c;
let ftype = if !shdr.is_p { Type::I } else { Type::P };
- let picinfo = PicInfo::new(self.w, self.h, ftype, shdr.qscale, false, MVMode::Old, 0, None, true);
+ let picinfo = PicInfo::new(self.w, self.h, ftype, false, false, shdr.qscale, 0, None, None);
Ok(picinfo)
}
#[allow(unused_variables)]
- fn decode_slice_header(&mut self, info: &PicInfo) -> DecoderResult<Slice> {
+ fn decode_slice_header(&mut self, info: &PicInfo) -> DecoderResult<SliceInfo> {
//println!("read slice {} header", self.slice_no);
let shdr = self.read_slice_header()?;
- let ret = Slice::new(shdr.mb_x, shdr.mb_y, shdr.qscale);
self.slice_no += 1;
- self.mb_x = shdr.mb_x;
- self.mb_y = shdr.mb_y;
- self.mb_count = shdr.mb_c;
- self.mb_end = self.mb_x + self.mb_y * self.mb_w + self.mb_count;
+ let mb_end = shdr.mb_x + shdr.mb_y * self.mb_w + shdr.mb_c;
+ let ret = SliceInfo::new(shdr.mb_x, shdr.mb_y, mb_end, shdr.qscale);
Ok(ret)
}
- fn decode_block_header(&mut self, info: &PicInfo, slice: &Slice) -> DecoderResult<BlockInfo> {
+ fn decode_block_header(&mut self, info: &PicInfo, slice: &SliceInfo, sstate: &SliceState) -> DecoderResult<BlockInfo> {
let mut br = &mut self.br;
let mut q = slice.get_quant();
match info.get_mode() {
let idx = br.read(2)? as usize;
q = ((q as i16) + (H263_DQUANT_TAB[idx] as i16)) as u8;
}
- self.mb_x += 1;
- if self.mb_x == self.mb_w {
- self.mb_x = 0;
- self.mb_y += 1;
- }
Ok(BlockInfo::new(Type::I, cbp, q))
},
Type::P => {
if br.read_bool()? {
-self.mb_x += 1;
-if self.mb_x == self.mb_w {
- self.mb_x = 0;
- self.mb_y += 1;
-}
return Ok(BlockInfo::new(Type::Skip, 0, info.get_quant()));
}
let mut cbpc = br.read_cb(&self.tables.inter_mcbpc_cb)?;
q = ((q as i16) + (H263_DQUANT_TAB[idx] as i16)) as u8;
}
let binfo = BlockInfo::new(Type::I, cbp, q);
- self.mb_x += 1;
- if self.mb_x == self.mb_w {
- self.mb_x = 0;
- self.mb_y += 1;
- }
return Ok(binfo);
}
let idx = br.read(2)? as usize;
q = ((q as i16) + (H263_DQUANT_TAB[idx] as i16)) as u8;
}
-println!(" MB {}.{} cbp = {:X}", self.mb_x, self.mb_y, cbp);
+println!(" MB {}.{} cbp = {:X}", sstate.mb_x, sstate.mb_y, cbp);
let mut binfo = BlockInfo::new(Type::P, cbp, q);
if !is_4x4 {
let mvec: [MV; 1] = [decode_mv(br, &self.tables.mv_cb)?];
];
binfo.set_mv(&mvec);
}
- self.mb_x += 1;
- if self.mb_x == self.mb_w {
- self.mb_x = 0;
- self.mb_y += 1;
- }
Ok(binfo)
},
_ => { println!("wrong info mode"); Err(DecoderError::InvalidData) },
}
#[allow(unused_variables)]
- fn decode_block_intra(&mut self, info: &BlockInfo, quant: u8, no: usize, coded: bool, blk: &mut [i16; 64]) -> DecoderResult<()> {
- self.decode_block(quant, true, coded, blk, if no < 4 { 0 } else { no - 3 })
+ fn decode_block_intra(&mut self, info: &BlockInfo, sstate: &SliceState, quant: u8, no: usize, coded: bool, blk: &mut [i16; 64]) -> DecoderResult<()> {
+ self.decode_block(sstate, quant, true, coded, blk, if no < 4 { 0 } else { no - 3 })
}
#[allow(unused_variables)]
- fn decode_block_inter(&mut self, info: &BlockInfo, quant: u8, no: usize, coded: bool, blk: &mut [i16; 64]) -> DecoderResult<()> {
- self.decode_block(quant, false, coded, blk, if no < 4 { 0 } else { no - 3 })
+ fn decode_block_inter(&mut self, info: &BlockInfo, sstate: &SliceState, quant: u8, no: usize, coded: bool, blk: &mut [i16; 64]) -> DecoderResult<()> {
+ self.decode_block(sstate, quant, false, coded, blk, if no < 4 { 0 } else { no - 3 })
}
- fn is_slice_end(&mut self) -> bool { self.mb_x + self.mb_y * self.mb_w >= self.mb_end }
-
- fn filter_row(&mut self, buf: &mut NAVideoBuffer<u8>, mb_y: usize, mb_w: usize, cbpi: &CBPInfo) {
- let stride = buf.get_stride(0);
- let mut off = buf.get_offset(0) + mb_y * 16 * stride;
- for mb_x in 0..mb_w {
- let coff = off;
- let coded0 = cbpi.is_coded(mb_x, 0);
- let coded1 = cbpi.is_coded(mb_x, 1);
- let q = cbpi.get_q(mb_w + mb_x);
- if mb_y != 0 {
- if coded0 && cbpi.is_coded_top(mb_x, 0) { deblock_hor(buf, 0, q, coff); }
- if coded1 && cbpi.is_coded_top(mb_x, 1) { deblock_hor(buf, 0, q, coff + 8); }
- }
- let coff = off + 8 * stride;
- if cbpi.is_coded(mb_x, 2) && coded0 { deblock_hor(buf, 0, q, coff); }
- if cbpi.is_coded(mb_x, 3) && coded1 { deblock_hor(buf, 0, q, coff + 8); }
- off += 16;
- }
- let mut leftt = false;
- let mut leftc = false;
- let mut off = buf.get_offset(0) + mb_y * 16 * stride;
- for mb_x in 0..mb_w {
- let ctop0 = cbpi.is_coded_top(mb_x, 0);
- let ctop1 = cbpi.is_coded_top(mb_x, 0);
- let ccur0 = cbpi.is_coded(mb_x, 0);
- let ccur1 = cbpi.is_coded(mb_x, 1);
- let q = cbpi.get_q(mb_w + mb_x);
- if mb_y != 0 {
- let coff = off - 8 * stride;
- let qtop = cbpi.get_q(mb_x);
- if leftt && ctop0 { deblock_ver(buf, 0, qtop, coff); }
- if ctop0 && ctop1 { deblock_ver(buf, 0, qtop, coff + 8); }
- }
- if leftc && ccur0 { deblock_ver(buf, 0, q, off); }
- if ccur0 && ccur1 { deblock_ver(buf, 0, q, off + 8); }
- leftt = ctop1;
- leftc = ccur1;
- off += 16;
- }
- let strideu = buf.get_stride(1);
- let stridev = buf.get_stride(2);
- let offu = buf.get_offset(1) + mb_y * 8 * strideu;
- let offv = buf.get_offset(2) + mb_y * 8 * stridev;
- if mb_y != 0 {
- for mb_x in 0..mb_w {
- let ctu = cbpi.is_coded_top(mb_x, 4);
- let ccu = cbpi.is_coded(mb_x, 4);
- let ctv = cbpi.is_coded_top(mb_x, 5);
- let ccv = cbpi.is_coded(mb_x, 5);
- let q = cbpi.get_q(mb_w + mb_x);
- if ctu && ccu { deblock_hor(buf, 1, q, offu + mb_x * 8); }
- if ctv && ccv { deblock_hor(buf, 2, q, offv + mb_x * 8); }
- }
- let mut leftu = false;
- let mut leftv = false;
- let offu = buf.get_offset(1) + (mb_y - 1) * 8 * strideu;
- let offv = buf.get_offset(2) + (mb_y - 1) * 8 * stridev;
- for mb_x in 0..mb_w {
- let ctu = cbpi.is_coded_top(mb_x, 4);
- let ctv = cbpi.is_coded_top(mb_x, 5);
- let qt = cbpi.get_q(mb_x);
- if leftu && ctu { deblock_ver(buf, 1, qt, offu + mb_x * 8); }
- if leftv && ctv { deblock_ver(buf, 2, qt, offv + mb_x * 8); }
- leftu = ctu;
- leftv = ctv;
- }
- }
- }
-}
+ fn is_slice_end(&mut self) -> bool { false }
-fn deblock_hor(buf: &mut NAVideoBuffer<u8>, comp: usize, q: u8, off: usize) {
- let stride = buf.get_stride(comp);
- let mut dptr = buf.get_data_mut();
- let mut buf = dptr.as_mut_slice();
- for x in 0..8 {
- let a = buf[off - 2 * stride + x] as i16;
- let b = buf[off - 1 * stride + x] as i16;
- let c = buf[off + 0 * stride + x] as i16;
- let d = buf[off + 1 * stride + x] as i16;
- let diff = ((a - d) * 3 + (c - b) * 8) >> 4;
- if (diff != 0) && (diff >= -32) && (diff < 32) {
- let d0 = diff.abs() * 2 - (q as i16);
- let d1 = if d0 < 0 { 0 } else { d0 };
- let d2 = diff.abs() - d1;
- let d3 = if d2 < 0 { 0 } else { d2 };
-
- let delta = if diff < 0 { -d3 } else { d3 };
-
- let b1 = b + delta;
- if b1 < 0 { buf[off - 1 * stride + x] = 0; }
- else if b1 > 255 { buf[off - 1 * stride + x] = 0xFF; }
- else { buf[off - 1 * stride + x] = b1 as u8; }
- let c1 = c - delta;
- if c1 < 0 { buf[off + x] = 0; }
- else if c1 > 255 { buf[off + x] = 0xFF; }
- else { buf[off + x] = c1 as u8; }
- }
- }
+ fn is_gob(&mut self) -> bool { false }
}
impl<'a> RealVideo10BR<'a> {
let mut br = &mut self.br;
br.seek(self.slice_off[self.slice_no] * 8)?;
-//println!(" slice at off {}", br.tell());
let marker = br.read(1)?;
validate!(marker == 1);
let mb_x;
let mb_y;
let mb_count;
- let mb_pos = self.mb_x + self.mb_y * self.mb_w;
- if (br.peek(12) == 0) || (mb_pos > 0) {
+ if (br.peek(12) == 0) || (self.slice_no > 0) {
mb_x = br.read(6)? as usize;
mb_y = br.read(6)? as usize;
mb_count = br.read(12)? as usize;
} else {
- mb_x = self.mb_x;
- mb_y = self.mb_y;
- mb_count = self.mb_count;
+ mb_x = 0;
+ mb_y = 0;
+ mb_count = self.mb_w * self.mb_h;
}
br.skip(3)?;
println!("slice q {} mb {},{} {}", qscale, mb_x, mb_y, mb_count);
}
}
-fn deblock_ver(buf: &mut NAVideoBuffer<u8>, comp: usize, q: u8, off: usize) {
- let stride = buf.get_stride(comp);
- let mut dptr = buf.get_data_mut();
- let mut buf = dptr.as_mut_slice();
- for y in 0..8 {
- let a = buf[off - 2 + y * stride] as i16;
- let b = buf[off - 1 + y * stride] as i16;
- let c = buf[off + 0 + y * stride] as i16;
- let d = buf[off + 1 + y * stride] as i16;
- let diff = ((a - d) * 3 + (c - b) * 8) >> 4;
- if (diff != 0) && (diff >= -32) && (diff < 32) {
- let d0 = diff.abs() * 2 - (q as i16);
- let d1 = if d0 < 0 { 0 } else { d0 };
- let d2 = diff.abs() - d1;
- let d3 = if d2 < 0 { 0 } else { d2 };
-
- let delta = if diff < 0 { -d3 } else { d3 };
-
- let b1 = b + delta;
- if b1 < 0 { buf[off - 1 + y * stride] = 0; }
- else if b1 > 255 { buf[off - 1 + y * stride] = 0xFF; }
- else { buf[off - 1 + y * stride] = b1 as u8; }
- let c1 = c - delta;
- if c1 < 0 { buf[off + y * stride] = 0; }
- else if c1 > 255 { buf[off + y * stride] = 0xFF; }
- else { buf[off + y * stride] = c1 as u8; }
- }
- }
-}
-
impl RealVideo10Decoder {
fn new() -> Self {
let mut coderead = H263ShortCodeReader::new(H263_INTRA_MCBPC);
w: 0,
h: 0,
new_ver: false,
+ bdsp: H263BlockDSP::new(),
}
}
}
println!(" decode frame size {}, {} slices", src.len(), src[0]+1);
let mut ibr = RealVideo10BR::new(&src, &self.tables, self.w, self.h, self.new_ver);
- let bufinfo = self.dec.parse_frame(&mut ibr)?;
+ let bufinfo = self.dec.parse_frame(&mut ibr, &self.bdsp)?;
let mut frm = NAFrame::new_from_pkt(pkt, self.info.clone(), bufinfo);
frm.set_keyframe(self.dec.is_intra());
use formats;
use super::super::*;
use super::*;
+use super::code::H263BlockDSP;
use super::decoder::*;
use super::data::*;
h: usize,
minor_ver: u8,
rpr: RPRInfo,
+ bdsp: H263BlockDSP,
}
struct RealVideo20BR<'a> {
h: usize,
mb_w: usize,
mb_h: usize,
- mb_x: usize,
- mb_y: usize,
mb_pos_bits: u8,
- mb_count: usize,
- mb_end: usize,
minor_ver: u8,
rpr: RPRInfo,
- is_intra: bool,
}
struct RV20SliceInfo {
mb_w: mb_w,
mb_h: mb_h,
mb_pos_bits: mbpb,
- mb_x: 0,
- mb_y: 0,
- mb_count: 0,
- mb_end: 0,
minor_ver: minor_ver,
rpr: rpr,
- is_intra: false,
}
}
- fn decode_block(&mut self, quant: u8, intra: bool, coded: bool, blk: &mut [i16; 64], plane_no: usize) -> DecoderResult<()> {
+#[allow(unused_variables)]
+ fn decode_block(&mut self, sstate: &SliceState, quant: u8, intra: bool, coded: bool, blk: &mut [i16; 64], plane_no: usize) -> DecoderResult<()> {
let mut br = &mut self.br;
let mut idx = 0;
- if !self.is_intra && intra {
+ if !sstate.is_iframe && intra {
let mut dc = br.read(8).unwrap() as i16;
if dc == 255 { dc = 128; }
blk[0] = dc << 3;
}
if !coded { return Ok(()); }
- let rl_cb = if self.is_intra { &self.tables.aic_rl_cb } else { &self.tables.rl_cb };
+ let rl_cb = if sstate.is_iframe { &self.tables.aic_rl_cb } else { &self.tables.rl_cb };
let q_add = if quant == 0 { 0i16 } else { ((quant - 1) | 1) as i16 };
let q = (quant * 2) as i16;
while idx < 64 {
fn decode_pichdr(&mut self) -> DecoderResult<PicInfo> {
self.slice_no = 0;
println!("decoding picture header size {}", if self.num_slices > 1 { self.slice_off[1] } else { ((self.br.tell() as u32) + (self.br.left() as u32))/8 });
- self.mb_x = 0;
- self.mb_y = 0;
- self.mb_count = self.mb_w * self.mb_h;
let shdr = self.read_slice_header().unwrap();
println!("slice ends @ {}\n", self.br.tell());
- self.slice_no += 1;
+// self.slice_no += 1;
validate!((shdr.mb_x == 0) && (shdr.mb_y == 0));
- let mb_count;
+/* let mb_count;
if self.slice_no < self.num_slices {
let pos = self.br.tell();
let shdr2 = self.read_slice_header().unwrap();
mb_count = shdr2.mb_pos - shdr.mb_pos;
} else {
mb_count = self.mb_w * self.mb_h;
- }
+ }*/
- self.mb_x = shdr.mb_x;
- self.mb_y = shdr.mb_y;
- self.mb_count = mb_count;
- self.mb_end = shdr.mb_pos + mb_count;
- self.is_intra = shdr.ftype == Type::I;
-
- let picinfo = PicInfo::new(shdr.w, shdr.h, shdr.ftype, shdr.qscale, false, MVMode::Old, 0, None, true);
+ let picinfo = PicInfo::new(shdr.w, shdr.h, shdr.ftype, false, false, shdr.qscale, 0, None, None);
Ok(picinfo)
}
#[allow(unused_variables)]
- fn decode_slice_header(&mut self, info: &PicInfo) -> DecoderResult<Slice> {
+ fn decode_slice_header(&mut self, info: &PicInfo) -> DecoderResult<SliceInfo> {
//println!("read slice {} header", self.slice_no);
let shdr = self.read_slice_header().unwrap();
self.slice_no += 1;
} else {
mb_count = self.mb_w * self.mb_h - shdr.mb_pos;
}
- let ret = Slice::new(shdr.mb_x, shdr.mb_y, shdr.qscale);
- self.mb_x = shdr.mb_x;
- self.mb_y = shdr.mb_y;
- self.mb_count = mb_count;
- self.mb_end = shdr.mb_pos + mb_count;
+ let ret = SliceInfo::new(shdr.mb_x, shdr.mb_y, shdr.mb_pos + mb_count, shdr.qscale);
Ok(ret)
}
- fn decode_block_header(&mut self, info: &PicInfo, slice: &Slice) -> DecoderResult<BlockInfo> {
+ fn decode_block_header(&mut self, info: &PicInfo, slice: &SliceInfo, sstate: &SliceState) -> DecoderResult<BlockInfo> {
let mut br = &mut self.br;
let mut q = slice.get_quant();
match info.get_mode() {
Type::I => {
let mut cbpc = br.read_cb(&self.tables.intra_mcbpc_cb).unwrap();
while cbpc == 8 { cbpc = br.read_cb(&self.tables.intra_mcbpc_cb).unwrap(); }
-if self.is_intra {
+if sstate.is_iframe {
let acpred = br.read_bool()?;
println!(" acp {} @ {}", acpred, br.tell());
if acpred {
let idx = br.read(2).unwrap() as usize;
q = ((q as i16) + (H263_DQUANT_TAB[idx] as i16)) as u8;
}
-println!(" MB {},{} CBP {:X} @ {}", self.mb_x, self.mb_y, cbp, br.tell());
- self.mb_x += 1;
- if self.mb_x == self.mb_w {
- self.mb_x = 0;
- self.mb_y += 1;
- }
+println!(" MB {},{} CBP {:X} @ {}", sstate.mb_x, sstate.mb_y, cbp, br.tell());
Ok(BlockInfo::new(Type::I, cbp, q))
},
Type::P => {
if br.read_bool().unwrap() {
-self.mb_x += 1;
-if self.mb_x == self.mb_w {
- self.mb_x = 0;
- self.mb_y += 1;
-}
return Ok(BlockInfo::new(Type::Skip, 0, info.get_quant()));
}
let mut cbpc = br.read_cb(&self.tables.inter_mcbpc_cb).unwrap();
q = ((q as i16) + (H263_DQUANT_TAB[idx] as i16)) as u8;
}
let binfo = BlockInfo::new(Type::I, cbp, q);
- self.mb_x += 1;
- if self.mb_x == self.mb_w {
- self.mb_x = 0;
- self.mb_y += 1;
- }
return Ok(binfo);
}
let idx = br.read(2).unwrap() as usize;
q = ((q as i16) + (H263_DQUANT_TAB[idx] as i16)) as u8;
}
-println!(" MB {}.{} cbp = {:X}", self.mb_x, self.mb_y, cbp);
+println!(" MB {}.{} cbp = {:X}", sstate.mb_x, sstate.mb_y, cbp);
let mut binfo = BlockInfo::new(Type::P, cbp, q);
if !is_4x4 {
let mvec: [MV; 1] = [decode_mv(br, &self.tables.mv_cb).unwrap()];
];
binfo.set_mv(&mvec);
}
- self.mb_x += 1;
- if self.mb_x == self.mb_w {
- self.mb_x = 0;
- self.mb_y += 1;
- }
Ok(binfo)
},
_ => { println!("wrong info mode"); Err(DecoderError::InvalidData) },
}
#[allow(unused_variables)]
- fn decode_block_intra(&mut self, info: &BlockInfo, quant: u8, no: usize, coded: bool, blk: &mut [i16; 64]) -> DecoderResult<()> {
- self.decode_block(quant, true, coded, blk, if no < 4 { 0 } else { no - 3 })
+ fn decode_block_intra(&mut self, info: &BlockInfo, sstate: &SliceState, quant: u8, no: usize, coded: bool, blk: &mut [i16; 64]) -> DecoderResult<()> {
+ self.decode_block(sstate, quant, true, coded, blk, if no < 4 { 0 } else { no - 3 })
}
#[allow(unused_variables)]
- fn decode_block_inter(&mut self, info: &BlockInfo, quant: u8, no: usize, coded: bool, blk: &mut [i16; 64]) -> DecoderResult<()> {
- self.decode_block(quant, false, coded, blk, if no < 4 { 0 } else { no - 3 })
+ fn decode_block_inter(&mut self, info: &BlockInfo, sstate: &SliceState, quant: u8, no: usize, coded: bool, blk: &mut [i16; 64]) -> DecoderResult<()> {
+ self.decode_block(sstate, quant, false, coded, blk, if no < 4 { 0 } else { no - 3 })
}
- fn is_slice_end(&mut self) -> bool { self.mb_x + self.mb_y * self.mb_w >= self.mb_end }
-
- fn filter_row(&mut self, buf: &mut NAVideoBuffer<u8>, mb_y: usize, mb_w: usize, cbpi: &CBPInfo) {
- let stride = buf.get_stride(0);
- let mut off = buf.get_offset(0) + mb_y * 16 * stride;
- for mb_x in 0..mb_w {
- let coff = off;
- let coded0 = cbpi.is_coded(mb_x, 0);
- let coded1 = cbpi.is_coded(mb_x, 1);
- let q = cbpi.get_q(mb_w + mb_x);
- if mb_y != 0 {
- if coded0 && cbpi.is_coded_top(mb_x, 0) { deblock_hor(buf, 0, q, coff); }
- if coded1 && cbpi.is_coded_top(mb_x, 1) { deblock_hor(buf, 0, q, coff + 8); }
- }
- let coff = off + 8 * stride;
- if cbpi.is_coded(mb_x, 2) && coded0 { deblock_hor(buf, 0, q, coff); }
- if cbpi.is_coded(mb_x, 3) && coded1 { deblock_hor(buf, 0, q, coff + 8); }
- off += 16;
- }
- let mut leftt = false;
- let mut leftc = false;
- let mut off = buf.get_offset(0) + mb_y * 16 * stride;
- for mb_x in 0..mb_w {
- let ctop0 = cbpi.is_coded_top(mb_x, 0);
- let ctop1 = cbpi.is_coded_top(mb_x, 0);
- let ccur0 = cbpi.is_coded(mb_x, 0);
- let ccur1 = cbpi.is_coded(mb_x, 1);
- let q = cbpi.get_q(mb_w + mb_x);
- if mb_y != 0 {
- let coff = off - 8 * stride;
- let qtop = cbpi.get_q(mb_x);
- if leftt && ctop0 { deblock_ver(buf, 0, qtop, coff); }
- if ctop0 && ctop1 { deblock_ver(buf, 0, qtop, coff + 8); }
- }
- if leftc && ccur0 { deblock_ver(buf, 0, q, off); }
- if ccur0 && ccur1 { deblock_ver(buf, 0, q, off + 8); }
- leftt = ctop1;
- leftc = ccur1;
- off += 16;
- }
- let strideu = buf.get_stride(1);
- let stridev = buf.get_stride(2);
- let offu = buf.get_offset(1) + mb_y * 8 * strideu;
- let offv = buf.get_offset(2) + mb_y * 8 * stridev;
- if mb_y != 0 {
- for mb_x in 0..mb_w {
- let ctu = cbpi.is_coded_top(mb_x, 4);
- let ccu = cbpi.is_coded(mb_x, 4);
- let ctv = cbpi.is_coded_top(mb_x, 5);
- let ccv = cbpi.is_coded(mb_x, 5);
- let q = cbpi.get_q(mb_w + mb_x);
- if ctu && ccu { deblock_hor(buf, 1, q, offu + mb_x * 8); }
- if ctv && ccv { deblock_hor(buf, 2, q, offv + mb_x * 8); }
- }
- let mut leftu = false;
- let mut leftv = false;
- let offu = buf.get_offset(1) + (mb_y - 1) * 8 * strideu;
- let offv = buf.get_offset(2) + (mb_y - 1) * 8 * stridev;
- for mb_x in 0..mb_w {
- let ctu = cbpi.is_coded_top(mb_x, 4);
- let ctv = cbpi.is_coded_top(mb_x, 5);
- let qt = cbpi.get_q(mb_x);
- if leftu && ctu { deblock_ver(buf, 1, qt, offu + mb_x * 8); }
- if leftv && ctv { deblock_ver(buf, 2, qt, offv + mb_x * 8); }
- leftu = ctu;
- leftv = ctv;
- }
- }
- }
-}
+ fn is_slice_end(&mut self) -> bool { false }
-fn deblock_hor(buf: &mut NAVideoBuffer<u8>, comp: usize, q: u8, off: usize) {
- let stride = buf.get_stride(comp);
- let mut dptr = buf.get_data_mut();
- let mut buf = dptr.as_mut_slice();
- for x in 0..8 {
- let a = buf[off - 2 * stride + x] as i16;
- let b = buf[off - 1 * stride + x] as i16;
- let c = buf[off + 0 * stride + x] as i16;
- let d = buf[off + 1 * stride + x] as i16;
- let diff = ((a - d) * 3 + (c - b) * 8) >> 4;
- if (diff != 0) && (diff >= -32) && (diff < 32) {
- let d0 = diff.abs() * 2 - (q as i16);
- let d1 = if d0 < 0 { 0 } else { d0 };
- let d2 = diff.abs() - d1;
- let d3 = if d2 < 0 { 0 } else { d2 };
-
- let delta = if diff < 0 { -d3 } else { d3 };
-
- let b1 = b + delta;
- if b1 < 0 { buf[off - 1 * stride + x] = 0; }
- else if b1 > 255 { buf[off - 1 * stride + x] = 0xFF; }
- else { buf[off - 1 * stride + x] = b1 as u8; }
- let c1 = c - delta;
- if c1 < 0 { buf[off + x] = 0; }
- else if c1 > 255 { buf[off + x] = 0xFF; }
- else { buf[off + x] = c1 as u8; }
- }
- }
+ fn is_gob(&mut self) -> bool { false }
}
impl<'a> RealVideo20BR<'a> {
+#[allow(unused_variables)]
fn read_slice_header(&mut self) -> DecoderResult<RV20SliceInfo> {
validate!(self.slice_no < self.num_slices);
}
}
-fn deblock_ver(buf: &mut NAVideoBuffer<u8>, comp: usize, q: u8, off: usize) {
- let stride = buf.get_stride(comp);
- let mut dptr = buf.get_data_mut();
- let mut buf = dptr.as_mut_slice();
- for y in 0..8 {
- let a = buf[off - 2 + y * stride] as i16;
- let b = buf[off - 1 + y * stride] as i16;
- let c = buf[off + 0 + y * stride] as i16;
- let d = buf[off + 1 + y * stride] as i16;
- let diff = ((a - d) * 3 + (c - b) * 8) >> 4;
- if (diff != 0) && (diff >= -32) && (diff < 32) {
- let d0 = diff.abs() * 2 - (q as i16);
- let d1 = if d0 < 0 { 0 } else { d0 };
- let d2 = diff.abs() - d1;
- let d3 = if d2 < 0 { 0 } else { d2 };
-
- let delta = if diff < 0 { -d3 } else { d3 };
-
- let b1 = b + delta;
- if b1 < 0 { buf[off - 1 + y * stride] = 0; }
- else if b1 > 255 { buf[off - 1 + y * stride] = 0xFF; }
- else { buf[off - 1 + y * stride] = b1 as u8; }
- let c1 = c - delta;
- if c1 < 0 { buf[off + y * stride] = 0; }
- else if c1 > 255 { buf[off + y * stride] = 0xFF; }
- else { buf[off + y * stride] = c1 as u8; }
- }
- }
-}
-
impl RealVideo20Decoder {
fn new() -> Self {
let mut coderead = H263ShortCodeReader::new(H263_INTRA_MCBPC);
h: 0,
minor_ver: 0,
rpr: RPRInfo { present: false, bits: 0, widths: [0; 8], heights: [0; 8] },
+ bdsp: H263BlockDSP::new(),
}
}
}
impl NADecoder for RealVideo20Decoder {
+#[allow(unused_variables)]
fn init(&mut self, info: Rc<NACodecInfo>) -> DecoderResult<()> {
if let NACodecTypeInfo::Video(vinfo) = info.get_properties() {
let w = vinfo.get_width();
println!(" decode frame size {}, {} slices", src.len(), src[0]+1);
let mut ibr = RealVideo20BR::new(&src, &self.tables, self.w, self.h, self.minor_ver, self.rpr);
- let bufinfo = self.dec.parse_frame(&mut ibr).unwrap();
+ let bufinfo = self.dec.parse_frame(&mut ibr, &self.bdsp).unwrap();
let mut frm = NAFrame::new_from_pkt(pkt, self.info.clone(), bufinfo);
frm.set_keyframe(self.dec.is_intra());
use test::dec_video::test_file_decoding;
#[test]
fn test_rv20() {
- test_file_decoding("realmedia", "assets/RV/rv20_cook_640x352_realproducer_plus_8.51.rm", None/*Some(160)*/, true, false, Some("rv20"));
+ test_file_decoding("realmedia", "assets/RV/rv20_cook_640x352_realproducer_plus_8.51.rm", /*None*/Some(160), true, false, Some("rv20"));
}
}