X-Git-Url: https://git.nihav.org/?a=blobdiff_plain;f=src%2Fcodecs%2Fh263%2Fmod.rs;h=50eed7d7102dffb9a501ddc05c87e0b299843ad1;hb=1a151e53b591a45fb7f009e480d7abb5e03f0cfe;hp=a0d21b21597bb81e12f21af23d8281e41b4e8819;hpb=be91b1c382e773807fa17615934355667403e0f9;p=nihav.git diff --git a/src/codecs/h263/mod.rs b/src/codecs/h263/mod.rs index a0d21b2..50eed7d 100644 --- a/src/codecs/h263/mod.rs +++ b/src/codecs/h263/mod.rs @@ -1,6 +1,4 @@ -use std::fmt; -use std::ops::{Add, Sub}; -use super::DecoderResult; +use super::{DecoderResult, MV, ZERO_MV}; use frame::NAVideoBuffer; pub mod code; @@ -16,18 +14,33 @@ pub mod rv20; pub trait BlockDecoder { fn decode_pichdr(&mut self) -> DecoderResult; - fn decode_slice_header(&mut self, pinfo: &PicInfo) -> DecoderResult; - fn decode_block_header(&mut self, pinfo: &PicInfo, sinfo: &Slice) -> DecoderResult; - 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; + fn decode_block_header(&mut self, pinfo: &PicInfo, sinfo: &SliceInfo, sstate: &SliceState) -> DecoderResult; + 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 filter_row(&mut self, buf: &mut NAVideoBuffer, 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, src: &NAVideoBuffer, xpos: usize, ypos: usize, w: usize, h: usize, mv: MV); + fn avg_blocks(&self, dst: &mut NAVideoBuffer, src: &NAVideoBuffer, xpos: usize, ypos: usize, w: usize, h: usize, mv: MV); + fn filter_row(&self, buf: &mut NAVideoBuffer, 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 +} + +impl Type { + pub fn is_ref(&self) -> bool { + match *self { + Type::I | Type::P | Type::PB => true, + _ => false, + } + } } #[allow(dead_code)] @@ -35,77 +48,157 @@ pub enum Type { pub struct PBInfo { trb: u8, dbquant: u8, + improved: bool, } impl PBInfo { - pub fn new(trb: u8, dbquant: u8) -> Self { - PBInfo{ trb: trb, dbquant: dbquant } + pub fn new(trb: u8, dbquant: u8, improved: bool) -> Self { + PBInfo{ trb: trb, dbquant: dbquant, improved: improved } } pub fn get_trb(&self) -> u8 { self.trb } pub fn get_dbquant(&self) -> u8 { self.dbquant } + pub fn is_improved(&self) -> bool { self.improved } } #[allow(dead_code)] #[derive(Debug,Clone,Copy)] pub struct PicInfo { - w: usize, - h: usize, - mode: Type, - quant: u8, - apm: bool, - mvmode: MVMode, - pb: Option, - ts: u8, - deblock: bool, + pub w: usize, + pub h: usize, + pub mode: Type, + pub mvmode: MVMode, + pub umv: bool, + pub apm: bool, + pub quant: u8, + pub pb: Option, + pub ts: u16, + pub plusinfo: Option, } #[allow(dead_code)] impl PicInfo { - pub fn new(w: usize, h: usize, mode: Type, quant: u8, apm: bool, mvmode: MVMode, ts: u8, pb: Option, 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, mvmode: MVMode, umv: bool, apm: bool, quant: u8, ts: u16, pb: Option, plusinfo: Option) -> Self { + PicInfo { + w: w, h: h, mode: mode, mvmode: mvmode, + 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 is_ipb(&self) -> bool { + if let Some(ref pbi) = self.pb { + pbi.is_improved() + } else { + false + } + } + pub fn get_ts(&self) -> u16 { self.ts } pub fn get_pbinfo(&self) -> PBInfo { self.pb.unwrap() } + pub fn get_plusifo(&self) -> Option { self.plusinfo } + pub fn get_mvmode(&self) -> MVMode { self.mvmode } +} + +#[allow(dead_code)] +#[derive(Debug,Clone,Copy)] +pub struct PlusInfo { + pub aic: bool, + pub deblock: bool, + pub aiv_mode: bool, + pub mq_mode: bool, +} + +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 Slice { - mb_x: usize, - mb_y: usize, - quant: u8, +pub struct SliceInfo { + pub mb_x: usize, + pub mb_y: usize, + pub mb_end: usize, + pub quant: u8, } -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 } +#[allow(dead_code)] +#[derive(Debug,Clone,Copy)] +pub struct SliceState { + pub is_iframe: bool, + pub mb_x: usize, + pub mb_y: usize, + pub first_line: bool, + pub first_mb: bool, + pub slice_mb_x: usize, + pub slice_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, first_line: true, first_mb: true, + slice_mb_x: 0, slice_mb_y: 0 + } + } + pub fn next_mb(&mut self) { + self.mb_x += 1; self.first_mb = false; + if self.mb_x >= self.slice_mb_x && self.mb_y > self.slice_mb_y { + self.first_line = false; + } + } + pub fn new_row(&mut self) { + self.mb_x = 0; self.mb_y += 1; + if self.mb_x >= self.slice_mb_x && self.mb_y > self.slice_mb_y { + self.first_line = false; + } + self.first_mb = true; + } + pub fn reset_slice(&mut self, smb_x: usize, smb_y: usize) { + self.slice_mb_x = smb_x; + self.slice_mb_y = smb_y; + self.first_line = true; + self.first_mb = true; + } } #[derive(Debug,Clone,Copy)] pub struct BlockInfo { - intra: bool, - skip: bool, - mode: Type, - cbp: u8, - q: u8, - mv: [MV; 4], - num_mv: usize, - bpart: bool, - b_cbp: u8, - mv2: [MV; 2], - num_mv2: usize, - fwd: bool, + pub intra: bool, + pub skip: bool, + pub mode: Type, + pub cbp: u8, + pub q: u8, + pub mv: [MV; 4], + pub num_mv: usize, + pub bpart: bool, + pub b_cbp: u8, + pub mv2: [MV; 2], + pub num_mv2: usize, + pub fwd: bool, + pub acpred: ACPredMode, } #[allow(dead_code)] @@ -117,6 +210,23 @@ pub struct BBlockInfo { fwd: bool, } +#[allow(non_camel_case_types)] +#[derive(Debug,Clone,Copy)] +pub enum BlockMVInfo { + Intra, + Inter_1MV(MV), + Inter_4MV([MV; 4]), +} + +#[allow(dead_code)] +#[derive(Debug,Clone,Copy,PartialEq)] +pub enum ACPredMode { + None, + DC, + Ver, + Hor, +} + #[allow(dead_code)] impl BlockInfo { pub fn new(mode: Type, cbp: u8, q: u8) -> Self { @@ -133,6 +243,7 @@ impl BlockInfo { mv2: [ZERO_MV, ZERO_MV], num_mv2: 0, fwd: false, + acpred: ACPredMode::None, } } pub fn is_intra(&self) -> bool { self.intra } @@ -163,9 +274,12 @@ impl BlockInfo { if mvs.len() > 0 { self.skip = false; } let mut mv_arr: [MV; 2] = [ZERO_MV, ZERO_MV]; for i in 0..mvs.len() { mv_arr[i] = mvs[i]; } - self.mv2 = mv_arr; + self.mv2 = mv_arr; + self.num_mv2 = mvs.len(); } pub fn is_b_fwd(&self) -> bool { self.fwd } + pub fn set_acpred(&mut self, acpred: ACPredMode) { self.acpred = acpred } + pub fn get_acpred(&self) -> ACPredMode { self.acpred } } impl BBlockInfo { @@ -187,46 +301,14 @@ pub enum MVMode { UMV, } -#[derive(Debug,Clone,Copy)] -pub struct MV { - x: i16, - y: i16, +pub trait H263MVTrait { + fn add_umv(pred_mv: MV, add: MV, mvmode: MVMode) -> MV; + fn scale(&self, trb: u16, trd: u16) -> MV; + fn b_sub(pvec: MV, fwdvec: MV, bvec: MV, trb: u16, trd: u16) -> MV; } -impl MV { - pub fn new(x: i16, y: i16) -> Self { MV{ x: x, y: y } } - pub fn pred(a: MV, b: MV, c: MV) -> Self { - let x; - if a.x < b.x { - if b.x < c.x { - x = b.x; - } else { - if a.x < c.x { x = c.x; } else { x = a.x; } - } - } else { - if b.x < c.x { - if a.x < c.x { x = a.x; } else { x = c.x; } - } else { - x = b.x; - } - } - let y; - if a.y < b.y { - if b.y < c.y { - y = b.y; - } else { - if a.y < c.y { y = c.y; } else { y = a.y; } - } - } else { - if b.y < c.y { - if a.y < c.y { y = a.y; } else { y = c.y; } - } else { - y = b.y; - } - } - MV { x: x, y: y } - } - fn add_umv(pred_mv: MV, add: MV, mvmode: MVMode) -> Self { +impl H263MVTrait for MV { + fn add_umv(pred_mv: MV, add: MV, mvmode: MVMode) -> MV { let mut new_mv = pred_mv + add; match mvmode { MVMode::Old => { @@ -250,39 +332,21 @@ impl MV { }; new_mv } - fn scale(&self, trb: u8, trd: u8) -> Self { + fn scale(&self, trb: u16, trd: u16) -> MV { if (trd == 0) || (trb == 0) { ZERO_MV } else { - MV { x: (self.x * (trb as i16)) / (trd as i16), y: (self.y * (trb as i16)) / (trd as i16) } + MV { x: (((self.x as i32) * (trb as i32)) / (trd as i32)) as i16, y: (((self.y as i32) * (trb as i32)) / (trd as i32)) as i16 } } } - fn b_sub(pvec: MV, fwdvec: MV, bvec: MV, trb: u8, trd: u8) -> Self { - let bscale = (trb as i16) - (trd as i16); - let x = if bvec.x != 0 { fwdvec.x - pvec.x } else if trd != 0 { bscale * pvec.x / (trd as i16) } else { 0 }; - let y = if bvec.y != 0 { fwdvec.y - pvec.y } else if trd != 0 { bscale * pvec.y / (trd as i16) } else { 0 }; + fn b_sub(pvec: MV, fwdvec: MV, bvec: MV, trb: u16, trd: u16) -> MV { + let bscale = (trb as i32) - (trd as i32); + let x = if bvec.x != 0 { fwdvec.x - pvec.x } else if trd != 0 { (bscale * (pvec.x as i32) / (trd as i32)) as i16 } else { 0 }; + let y = if bvec.y != 0 { fwdvec.y - pvec.y } else if trd != 0 { (bscale * (pvec.y as i32) / (trd as i32)) as i16 } else { 0 }; MV { x: x, y: y } } } -pub const ZERO_MV: MV = MV { x: 0, y: 0 }; - -impl Add for MV { - type Output = MV; - fn add(self, other: MV) -> MV { MV { x: self.x + other.x, y: self.y + other.y } } -} - -impl Sub for MV { - type Output = MV; - fn sub(self, other: MV) -> MV { MV { x: self.x - other.x, y: self.y - other.y } } -} - -impl fmt::Display for MV { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{},{}", self.x, self.y) - } -} - #[allow(dead_code)] pub struct CBPInfo { cbp: Vec,