From: Kostya Shishkov Date: Sat, 10 Jun 2017 10:41:33 +0000 (+0200) Subject: reorganise codecs and improve i263 a bit X-Git-Url: https://git.nihav.org/?a=commitdiff_plain;h=88c58b1b958a5478dca6595e2efc3a1a6b5f7e19;p=nihav.git reorganise codecs and improve i263 a bit --- diff --git a/Cargo.toml b/Cargo.toml index a7cb1da..91acac6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,12 +14,15 @@ demuxer_avi = ["demuxers"] demuxer_gdv = ["demuxers"] decoders = [] +h263 = [] + all_decoders = ["all_video_decoders", "all_audio_decoders"] -all_video_decoders = ["decoder_gdvvid", "decoder_indeo2", "decoder_indeo3"] +all_video_decoders = ["decoder_gdvvid", "decoder_indeo2", "decoder_indeo3", "decoder_intel263"] decoder_gdvvid = ["decoders"] decoder_indeo2 = ["decoders"] decoder_indeo3 = ["decoders"] +decoder_intel263 = ["h263", "decoders"] all_audio_decoders = ["decoder_pcm"] decoder_pcm = ["decoders"] diff --git a/src/codecs/h263code.rs b/src/codecs/h263/code.rs similarity index 100% rename from src/codecs/h263code.rs rename to src/codecs/h263/code.rs diff --git a/src/codecs/h263data.rs b/src/codecs/h263/data.rs similarity index 100% rename from src/codecs/h263data.rs rename to src/codecs/h263/data.rs diff --git a/src/codecs/blockdec.rs b/src/codecs/h263/decoder.rs similarity index 55% rename from src/codecs/blockdec.rs rename to src/codecs/h263/decoder.rs index 64eb6cb..11eb2be 100644 --- a/src/codecs/blockdec.rs +++ b/src/codecs/h263/decoder.rs @@ -1,257 +1,11 @@ use std::mem; -use std::ops::{Add, Sub}; +use frame::*; +use super::super::*; +use super::super::blockdsp; use super::*; -use super::blockdsp; -use super::h263code::*; +use super::code::*; use formats; -#[derive(Debug,Clone,Copy,PartialEq)] -pub enum Type { - I, P, Skip, Special -} - -#[allow(dead_code)] -#[derive(Debug,Clone,Copy)] -pub struct PBInfo { - trb: u8, - dbquant: u8, -} - -impl PBInfo { - pub fn new(trb: u8, dbquant: u8) -> Self { - PBInfo{ trb: trb, dbquant: dbquant } - } - pub fn get_trb(&self) -> u8 { self.trb } - pub fn get_dbquant(&self) -> u8 { self.dbquant } -} - -#[allow(dead_code)] -#[derive(Debug,Clone,Copy)] -pub struct PicInfo { - w: usize, - h: usize, - mode: Type, - quant: u8, - apm: bool, - umv: bool, - pb: Option, - ts: u8, - deblock: bool, -} - -#[allow(dead_code)] -impl PicInfo { - pub fn new(w: usize, h: usize, mode: Type, quant: u8, apm: bool, umv: bool, ts: u8, pb: Option, deblock: bool) -> Self { - PicInfo{ w: w, h: h, mode: mode, quant: quant, apm: apm, umv: umv, ts: ts, pb: pb, deblock: deblock } - } - 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_umv(&self) -> bool { self.umv } - 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() } -} - -#[derive(Debug,Clone,Copy)] -pub struct Slice { - mb_x: usize, - mb_y: usize, - 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 } - } - pub fn get_default_slice(pinfo: &PicInfo) -> Self { - Slice{ mb_x: 0, mb_y: 0, quant: pinfo.get_quant() } - } - pub fn get_quant(&self) -> u8 { self.quant } -} - -#[derive(Debug,Clone,Copy)] -pub struct MV { - x: i16, - y: i16, -} - -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, umv: bool) -> Self { - let mut new_mv = pred_mv + add; - if umv { - if pred_mv.x > 32 && new_mv.x > 63 { new_mv.x -= 64; } - if pred_mv.x < -31 && new_mv.x < -63 { new_mv.x += 64; } - if pred_mv.y > 32 && new_mv.y > 63 { new_mv.y -= 64; } - if pred_mv.y < -31 && new_mv.y < -63 { new_mv.y += 64; } - } else { - if new_mv.x > 31 { new_mv.x -= 64; } - else if new_mv.x < -32 { new_mv.x += 64; } - if new_mv.y > 31 { new_mv.y -= 64; } - else if new_mv.y < -32 { new_mv.y += 64; } - } - new_mv - } - fn scale(&self, trb: u8, trd: u8) -> Self { - 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) } - } - } - 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 }; - 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 } } -} - -#[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, -} - -#[allow(dead_code)] -#[derive(Debug,Clone,Copy)] -pub struct BBlockInfo { - present: bool, - cbp: u8, - num_mv: usize, - fwd: bool, -} - -#[allow(dead_code)] -impl BlockInfo { - pub fn new(mode: Type, cbp: u8, q: u8) -> Self { - BlockInfo { - intra: mode == Type::I, - skip: (cbp == 0) && (mode != Type::I), - mode: mode, - cbp: cbp, - q: q, - mv: [MV::new(0, 0), MV::new(0, 0), MV::new(0, 0), MV::new(0, 0)], - num_mv: 0, - bpart: false, - b_cbp: 0, - mv2: [ZERO_MV, ZERO_MV], - num_mv2: 0, - fwd: false, - } - } - pub fn is_intra(&self) -> bool { self.intra } - pub fn is_skipped(&self) -> bool { self.skip } - pub fn get_mode(&self) -> Type { self.mode } - pub fn get_cbp(&self) -> u8 { self.cbp } - pub fn get_q(&self) -> u8 { self.q } - pub fn get_num_mvs(&self) -> usize { self.num_mv } - pub fn get_mv(&self, idx: usize) -> MV { self.mv[idx] } - pub fn has_b_part(&self) -> bool { self.bpart } - pub fn get_cbp_b(&self) -> u8 { self.b_cbp } - pub fn get_num_mvs2(&self) -> usize { self.num_mv2 } - pub fn get_mv2(&self, idx: usize) -> MV { self.mv2[idx] } - pub fn set_mv(&mut self, mvs: &[MV]) { - if mvs.len() > 0 { self.skip = false; } - let mut mv_arr: [MV; 4] = [MV::new(0, 0), MV::new(0, 0), MV::new(0, 0), MV::new(0, 0)]; - for i in 0..mvs.len() { mv_arr[i] = mvs[i]; } - self.mv = mv_arr; - self.num_mv = mvs.len(); - } - pub fn set_bpart(&mut self, bbinfo: BBlockInfo) { - self.bpart = bbinfo.present; - self.b_cbp = bbinfo.cbp; - self.fwd = bbinfo.fwd; - self.num_mv2 = bbinfo.get_num_mv(); - } - pub fn set_b_mv(&mut self, mvs: &[MV]) { - 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; - } - pub fn is_b_fwd(&self) -> bool { self.fwd } -} - -impl BBlockInfo { - pub fn new(present: bool, cbp: u8, num_mv: usize, fwd: bool) -> Self { - BBlockInfo { - present: present, - cbp: cbp, - num_mv: num_mv, - fwd: fwd, - } - } - pub fn get_num_mv(&self) -> usize { self.num_mv } -} - -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 is_slice_end(&mut self) -> bool; - - fn filter_row(&mut self, buf: &mut NAVideoBuffer, mb_y: usize, mb_w: usize, cbpi: &CBPInfo); -} - #[allow(dead_code)] struct MVInfo { mv: Vec, @@ -285,7 +39,6 @@ impl MVInfo { let B; let C; let last = mb_x == self.mb_w - 1; -//println!(" pred from {}.{} blk {}.{}/{} top {}", diff.x, diff.y, mb_x, blk_no,self.mb_start,self.top); match blk_no { 0 => { if mb_x != self.mb_start { @@ -313,7 +66,6 @@ impl MVInfo { }, _ => { return ZERO_MV; } } -//println!(" A = {}.{} B = {}.{} C = {}.{}", A.x,A.y,B.x,B.y,C.x,C.y); let pred_mv = MV::pred(A, B, C); let new_mv = MV::add_umv(pred_mv, diff, self.umv); if !use4 { @@ -341,52 +93,6 @@ impl MVInfo { } } -#[allow(dead_code)] -pub struct CBPInfo { - cbp: Vec, - q: Vec, - mb_w: usize, -} - -impl CBPInfo { - fn new() -> Self { CBPInfo{ cbp: Vec::new(), q: Vec::new(), mb_w: 0 } } - fn reset(&mut self, mb_w: usize) { - self.mb_w = mb_w; - self.cbp.truncate(0); - self.cbp.resize(self.mb_w * 2, 0); - self.q.truncate(0); - self.q.resize(self.mb_w * 2, 0); - } - fn update_row(&mut self) { - for i in 0..self.mb_w { - self.cbp[i] = self.cbp[self.mb_w + i]; - self.q[i] = self.q[self.mb_w + i]; - } - } - fn set_cbp(&mut self, mb_x: usize, cbp: u8) { - self.cbp[self.mb_w + mb_x] = cbp; - } - fn set_q(&mut self, mb_x: usize, q: u8) { - self.q[self.mb_w + mb_x] = q; - } - pub fn get_q(&self, mb_x: usize) -> u8 { self.q[mb_x] } - pub fn is_coded(&self, mb_x: usize, blk_no: usize) -> bool { - (self.cbp[self.mb_w + mb_x] & (1 << (5 - blk_no))) != 0 - } - pub fn is_coded_top(&self, mb_x: usize, blk_no: usize) -> bool { - let cbp = self.cbp[self.mb_w + mb_x]; - let cbp_top = self.cbp[mb_x]; - match blk_no { - 0 => { (cbp_top & 0b001000) != 0 }, - 1 => { (cbp_top & 0b000100) != 0 }, - 2 => { (cbp & 0b100000) != 0 }, - 3 => { (cbp & 0b010000) != 0 }, - 4 => { (cbp_top & 0b000010) != 0 }, - _ => { (cbp_top & 0b000001) != 0 }, - } - } -} - fn copy_blocks(dst: &mut NAVideoBuffer, src: &NAVideoBuffer, 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); @@ -418,7 +124,7 @@ impl BMB { fn new() -> Self { BMB {blk: [[0; 64]; 6], cbp: 0, fwd: false, mv_f: [ZERO_MV; 4], mv_b: [ZERO_MV; 4], num_mv: 0} } } -pub struct DCT8x8VideoDecoder { +pub struct H263BaseDecoder { w: usize, h: usize, mb_w: usize, @@ -433,9 +139,9 @@ pub struct DCT8x8VideoDecoder { } #[allow(dead_code)] -impl DCT8x8VideoDecoder { +impl H263BaseDecoder { pub fn new() -> Self { - DCT8x8VideoDecoder{ + H263BaseDecoder{ w: 0, h: 0, mb_w: 0, mb_h: 0, num_mb: 0, ftype: Type::Special, prev_frm: None, cur_frm: None, @@ -487,7 +193,6 @@ impl DCT8x8VideoDecoder { 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() { -//println!("new slice @{}.{}!",mb_x,mb_y); slice = bd.decode_slice_header(&pinfo)?; mvi.reset(self.mb_w, mb_x, pinfo.get_umv()); //cbpi.reset(self.mb_w); @@ -495,7 +200,6 @@ impl DCT8x8VideoDecoder { let binfo = bd.decode_block_header(&pinfo, &slice)?; let cbp = binfo.get_cbp(); -//println!("mb {}.{} CBP {:X} type {:?}, {} mvs skip {}", mb_x,mb_y, cbp, binfo.get_mode(), binfo.get_num_mvs(),binfo.is_skipped()); cbpi.set_cbp(mb_x, cbp); cbpi.set_q(mb_x, binfo.get_q()); if binfo.is_intra() { @@ -508,21 +212,18 @@ impl DCT8x8VideoDecoder { } else if !binfo.is_skipped() { if binfo.get_num_mvs() == 1 { let mv = mvi.predict(mb_x, 0, false, binfo.get_mv(0)); -//println!(" 1MV {}.{}", mv.x, mv.y); if let Some(ref srcbuf) = self.prev_frm { 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)); -//print!(" MV {}.{}", mv.x, mv.y); 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); } } -//println!(""); } for i in 0..6 { bd.decode_block_inter(&binfo, binfo.get_q(), i, ((cbp >> (5 - i)) & 1) != 0, &mut blk[i])?; @@ -550,22 +251,22 @@ impl DCT8x8VideoDecoder { h263_idct(&mut b_mb.blk[i]); } - let is_fwd = binfo.is_b_fwd(); + let is_fwd = !binfo.is_b_fwd(); b_mb.fwd = is_fwd; b_mb.num_mv = binfo.get_num_mvs(); if binfo.get_num_mvs() == 0 { b_mb.num_mv = 1; b_mb.mv_f[0] = binfo.get_mv2(1); b_mb.mv_b[0] = binfo.get_mv2(0); - } if binfo.get_num_mvs() == 1 { - let src_mv = if is_fwd { ZERO_MV } else { binfo.get_mv(0).scale(bsdiff, tsdiff) }; + } else if binfo.get_num_mvs() == 1 { + let src_mv = binfo.get_mv(0).scale(bsdiff, tsdiff); let mv_f = MV::add_umv(src_mv, binfo.get_mv2(0), pinfo.get_umv()); let mv_b = MV::b_sub(binfo.get_mv(0), mv_f, binfo.get_mv2(0), bsdiff, tsdiff); b_mb.mv_f[0] = mv_f; b_mb.mv_b[0] = mv_b; } else { for blk_no in 0..4 { - let src_mv = if is_fwd { ZERO_MV } else { binfo.get_mv(blk_no).scale(bsdiff, tsdiff) }; + let src_mv = binfo.get_mv(blk_no).scale(bsdiff, tsdiff); let mv_f = MV::add_umv(src_mv, binfo.get_mv2(0), pinfo.get_umv()); let mv_b = MV::b_sub(binfo.get_mv(blk_no), mv_f, binfo.get_mv2(0), bsdiff, tsdiff); b_mb.mv_f[blk_no] = mv_f; @@ -584,7 +285,6 @@ impl DCT8x8VideoDecoder { self.cur_frm = Some(buf); self.last_ts = pinfo.ts; -//println!("unpacked all"); Ok(bufinfo) } @@ -624,17 +324,17 @@ fn recon_b_frame(b_buf: &mut NAVideoBuffer, bck_buf: &NAVideoBuffer, fwd let cbp = b_data[cur_mb].cbp; cbpi.set_cbp(mb_x, cbp); if num_mv == 1 { - copy_blocks(b_buf, bck_buf, mb_x * 16, mb_y * 16, 16, 16, b_data[cur_mb].mv_f[0]); + 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, fwd_buf, mb_x * 16, mb_y * 16, 16, 16, b_data[cur_mb].mv_b[0]); + 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, bck_buf, xpos, ypos, 8, 8, b_data[cur_mb].mv_f[blk_no]); + 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, fwd_buf, xpos, ypos, 8, 8, b_data[cur_mb].mv_b[blk_no]); + avg_blocks(b_buf, bck_buf, xpos, ypos, 8, 8, b_data[cur_mb].mv_f[blk_no]); } } } diff --git a/src/codecs/intel263.rs b/src/codecs/h263/intel263.rs similarity index 99% rename from src/codecs/intel263.rs rename to src/codecs/h263/intel263.rs index 99f0d4c..7ef46e6 100644 --- a/src/codecs/intel263.rs +++ b/src/codecs/h263/intel263.rs @@ -1,9 +1,10 @@ use io::bitreader::*; use io::codebook::*; use formats; +use super::super::*; use super::*; -use super::blockdec::*; -use super::h263data::*; +use super::decoder::*; +use super::data::*; #[allow(dead_code)] struct Tables { @@ -17,7 +18,7 @@ struct Tables { struct Intel263Decoder { info: Rc, - dec: DCT8x8VideoDecoder, + dec: H263BaseDecoder, tables: Tables, } @@ -466,7 +467,7 @@ impl Intel263Decoder { Intel263Decoder{ info: Rc::new(DUMMY_CODEC_INFO), - dec: DCT8x8VideoDecoder::new(), + dec: H263BaseDecoder::new(), tables: tables, } } @@ -556,7 +557,7 @@ mod test { panic!("error"); } let pkt = pktres.unwrap(); - //if pkt.get_pts().unwrap() > 263 { break; } + //if pkt.get_pts().unwrap() > 146 { break; } let streamno = pkt.get_stream().get_id() as usize; if let Some(ref mut dec) = decs[streamno] { let frm = dec.decode(&pkt).unwrap(); diff --git a/src/codecs/h263/mod.rs b/src/codecs/h263/mod.rs new file mode 100644 index 0000000..90170e3 --- /dev/null +++ b/src/codecs/h263/mod.rs @@ -0,0 +1,311 @@ +use std::fmt; +use std::ops::{Add, Sub}; +use super::DecoderResult; +use frame::NAVideoBuffer; + +pub mod code; +pub mod data; +pub mod decoder; + +#[cfg(feature="decoder_intel263")] +pub mod intel263; + +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 is_slice_end(&mut self) -> bool; + + fn filter_row(&mut self, buf: &mut NAVideoBuffer, mb_y: usize, mb_w: usize, cbpi: &CBPInfo); +} + +#[derive(Debug,Clone,Copy,PartialEq)] +pub enum Type { + I, P, Skip, Special +} + +#[allow(dead_code)] +#[derive(Debug,Clone,Copy)] +pub struct PBInfo { + trb: u8, + dbquant: u8, +} + +impl PBInfo { + pub fn new(trb: u8, dbquant: u8) -> Self { + PBInfo{ trb: trb, dbquant: dbquant } + } + pub fn get_trb(&self) -> u8 { self.trb } + pub fn get_dbquant(&self) -> u8 { self.dbquant } +} + +#[allow(dead_code)] +#[derive(Debug,Clone,Copy)] +pub struct PicInfo { + w: usize, + h: usize, + mode: Type, + quant: u8, + apm: bool, + umv: bool, + pb: Option, + ts: u8, + deblock: bool, +} + +#[allow(dead_code)] +impl PicInfo { + pub fn new(w: usize, h: usize, mode: Type, quant: u8, apm: bool, umv: bool, ts: u8, pb: Option, deblock: bool) -> Self { + PicInfo{ w: w, h: h, mode: mode, quant: quant, apm: apm, umv: umv, ts: ts, pb: pb, deblock: deblock } + } + 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_umv(&self) -> bool { self.umv } + 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() } +} + +#[derive(Debug,Clone,Copy)] +pub struct Slice { + mb_x: usize, + mb_y: usize, + 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 } + } + pub fn get_default_slice(pinfo: &PicInfo) -> Self { + Slice{ mb_x: 0, mb_y: 0, quant: pinfo.get_quant() } + } + pub fn get_quant(&self) -> u8 { self.quant } +} + +#[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, +} + +#[allow(dead_code)] +#[derive(Debug,Clone,Copy)] +pub struct BBlockInfo { + present: bool, + cbp: u8, + num_mv: usize, + fwd: bool, +} + +#[allow(dead_code)] +impl BlockInfo { + pub fn new(mode: Type, cbp: u8, q: u8) -> Self { + BlockInfo { + intra: mode == Type::I, + skip: (cbp == 0) && (mode != Type::I), + mode: mode, + cbp: cbp, + q: q, + mv: [MV::new(0, 0), MV::new(0, 0), MV::new(0, 0), MV::new(0, 0)], + num_mv: 0, + bpart: false, + b_cbp: 0, + mv2: [ZERO_MV, ZERO_MV], + num_mv2: 0, + fwd: false, + } + } + pub fn is_intra(&self) -> bool { self.intra } + pub fn is_skipped(&self) -> bool { self.skip } + pub fn get_mode(&self) -> Type { self.mode } + pub fn get_cbp(&self) -> u8 { self.cbp } + pub fn get_q(&self) -> u8 { self.q } + pub fn get_num_mvs(&self) -> usize { self.num_mv } + pub fn get_mv(&self, idx: usize) -> MV { self.mv[idx] } + pub fn has_b_part(&self) -> bool { self.bpart } + pub fn get_cbp_b(&self) -> u8 { self.b_cbp } + pub fn get_num_mvs2(&self) -> usize { self.num_mv2 } + pub fn get_mv2(&self, idx: usize) -> MV { self.mv2[idx] } + pub fn set_mv(&mut self, mvs: &[MV]) { + if mvs.len() > 0 { self.skip = false; } + let mut mv_arr: [MV; 4] = [MV::new(0, 0), MV::new(0, 0), MV::new(0, 0), MV::new(0, 0)]; + for i in 0..mvs.len() { mv_arr[i] = mvs[i]; } + self.mv = mv_arr; + self.num_mv = mvs.len(); + } + pub fn set_bpart(&mut self, bbinfo: BBlockInfo) { + self.bpart = bbinfo.present; + self.b_cbp = bbinfo.cbp; + self.fwd = bbinfo.fwd; + self.num_mv2 = bbinfo.get_num_mv(); + } + pub fn set_b_mv(&mut self, mvs: &[MV]) { + 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; + } + pub fn is_b_fwd(&self) -> bool { self.fwd } +} + +impl BBlockInfo { + pub fn new(present: bool, cbp: u8, num_mv: usize, fwd: bool) -> Self { + BBlockInfo { + present: present, + cbp: cbp, + num_mv: num_mv, + fwd: fwd, + } + } + pub fn get_num_mv(&self) -> usize { self.num_mv } +} + +#[derive(Debug,Clone,Copy)] +pub struct MV { + x: i16, + y: i16, +} + +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, umv: bool) -> Self { + let mut new_mv = pred_mv + add; + if umv { + if pred_mv.x > 32 && new_mv.x > 63 { new_mv.x -= 64; } + if pred_mv.x < -31 && new_mv.x < -63 { new_mv.x += 64; } + if pred_mv.y > 32 && new_mv.y > 63 { new_mv.y -= 64; } + if pred_mv.y < -31 && new_mv.y < -63 { new_mv.y += 64; } + } else { + if new_mv.x > 31 { new_mv.x -= 64; } + else if new_mv.x < -32 { new_mv.x += 64; } + if new_mv.y > 31 { new_mv.y -= 64; } + else if new_mv.y < -32 { new_mv.y += 64; } + } + new_mv + } + fn scale(&self, trb: u8, trd: u8) -> Self { + 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) } + } + } + 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 }; + 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, + q: Vec, + mb_w: usize, +} + +impl CBPInfo { + fn new() -> Self { CBPInfo{ cbp: Vec::new(), q: Vec::new(), mb_w: 0 } } + fn reset(&mut self, mb_w: usize) { + self.mb_w = mb_w; + self.cbp.truncate(0); + self.cbp.resize(self.mb_w * 2, 0); + self.q.truncate(0); + self.q.resize(self.mb_w * 2, 0); + } + fn update_row(&mut self) { + for i in 0..self.mb_w { + self.cbp[i] = self.cbp[self.mb_w + i]; + self.q[i] = self.q[self.mb_w + i]; + } + } + fn set_cbp(&mut self, mb_x: usize, cbp: u8) { + self.cbp[self.mb_w + mb_x] = cbp; + } + fn set_q(&mut self, mb_x: usize, q: u8) { + self.q[self.mb_w + mb_x] = q; + } + pub fn get_q(&self, mb_x: usize) -> u8 { self.q[mb_x] } + pub fn is_coded(&self, mb_x: usize, blk_no: usize) -> bool { + (self.cbp[self.mb_w + mb_x] & (1 << (5 - blk_no))) != 0 + } + pub fn is_coded_top(&self, mb_x: usize, blk_no: usize) -> bool { + let cbp = self.cbp[self.mb_w + mb_x]; + let cbp_top = self.cbp[mb_x]; + match blk_no { + 0 => { (cbp_top & 0b001000) != 0 }, + 1 => { (cbp_top & 0b000100) != 0 }, + 2 => { (cbp & 0b100000) != 0 }, + 3 => { (cbp & 0b010000) != 0 }, + 4 => { (cbp_top & 0b000010) != 0 }, + _ => { (cbp_top & 0b000001) != 0 }, + } + } +} + diff --git a/src/codecs/indeo2.rs b/src/codecs/indeo/indeo2.rs similarity index 99% rename from src/codecs/indeo2.rs rename to src/codecs/indeo/indeo2.rs index b6bb441..681101f 100644 --- a/src/codecs/indeo2.rs +++ b/src/codecs/indeo/indeo2.rs @@ -1,7 +1,7 @@ use io::bitreader::*; use io::codebook::*; use formats; -use super::*; +use super::super::*; static INDEO2_DELTA_TABLE: [[u8; 256]; 4] = [ [ diff --git a/src/codecs/indeo3.rs b/src/codecs/indeo/indeo3.rs similarity index 99% rename from src/codecs/indeo3.rs rename to src/codecs/indeo/indeo3.rs index e5a6c0b..5851b54 100644 --- a/src/codecs/indeo3.rs +++ b/src/codecs/indeo/indeo3.rs @@ -1,5 +1,5 @@ use formats; -use super::*; +use super::super::*; use io::byteio::*; use std::io::SeekFrom; use std::mem; diff --git a/src/codecs/indeo/mod.rs b/src/codecs/indeo/mod.rs new file mode 100644 index 0000000..c019f47 --- /dev/null +++ b/src/codecs/indeo/mod.rs @@ -0,0 +1,5 @@ +#[cfg(feature="decoder_indeo2")] +pub mod indeo2; +#[cfg(feature="decoder_indeo3")] +pub mod indeo3; + diff --git a/src/codecs/mod.rs b/src/codecs/mod.rs index ec67a4d..4978124 100644 --- a/src/codecs/mod.rs +++ b/src/codecs/mod.rs @@ -40,11 +40,6 @@ macro_rules! validate { ($a:expr) => { if !$a { return Err(DecoderError::InvalidData); } }; } -mod blockdsp; -mod blockdec; -mod h263code; -mod h263data; - #[allow(dead_code)] struct HAMShuffler { lastframe: Option>, @@ -113,14 +108,16 @@ pub struct DecoderInfo { get_decoder: fn () -> Box, } +#[cfg(feature="h263")] +mod blockdsp; + #[cfg(feature="decoder_gdvvid")] mod gremlinvideo; -#[cfg(feature="decoder_indeo2")] -mod indeo2; -#[cfg(feature="decoder_indeo3")] -mod indeo3; +#[cfg(any(feature="decoder_indeo2", feature="decoder_indeo3"))] +mod indeo; +#[cfg(feature="h263")] +mod h263; -mod intel263; #[cfg(feature="decoder_pcm")] mod pcm; @@ -128,11 +125,11 @@ const DECODERS: &[DecoderInfo] = &[ #[cfg(feature="decoder_gdvvid")] DecoderInfo { name: "gdv-video", get_decoder: gremlinvideo::get_decoder }, #[cfg(feature="decoder_indeo2")] - DecoderInfo { name: "indeo2", get_decoder: indeo2::get_decoder }, + DecoderInfo { name: "indeo2", get_decoder: indeo::indeo2::get_decoder }, #[cfg(feature="decoder_indeo3")] - DecoderInfo { name: "indeo3", get_decoder: indeo3::get_decoder }, - - DecoderInfo { name: "intel263", get_decoder: intel263::get_decoder }, + DecoderInfo { name: "indeo3", get_decoder: indeo::indeo3::get_decoder }, +#[cfg(feature="decoder_intel263")] + DecoderInfo { name: "intel263", get_decoder: h263::intel263::get_decoder }, #[cfg(feature="decoder_pcm")] DecoderInfo { name: "pcm", get_decoder: pcm::get_decoder },