From: Kostya Shishkov Date: Sat, 25 Nov 2017 18:11:01 +0000 (+0100) Subject: h263: implement coefficient prediction for AIC X-Git-Url: https://git.nihav.org/?a=commitdiff_plain;h=ef3209c74c9d639a57a2434aaba87e0a19bfe9b3;p=nihav.git h263: implement coefficient prediction for AIC --- diff --git a/src/codecs/h263/data.rs b/src/codecs/h263/data.rs index 76c3c43..98c0a81 100644 --- a/src/codecs/h263/data.rs +++ b/src/codecs/h263/data.rs @@ -15,6 +15,28 @@ pub const H263_ZIGZAG: &[usize] = &[ 53, 60, 61, 54, 47, 55, 62, 63 ]; +pub const H263_SCAN_H: &[usize] = &[ + 0, 1, 2, 3, 8, 9, 16, 17, + 10, 11, 4, 5, 6, 7, 15, 14, + 13, 12, 19, 18, 24, 25, 32, 33, + 26, 27, 20, 21, 22, 23, 28, 29, + 30, 31, 34, 35, 40, 41, 48, 49, + 42, 43, 36, 37, 38, 39, 44, 45, + 46, 47, 50, 51, 56, 57, 58, 59, + 52, 53, 54, 55, 60, 61, 62, 63 +]; + +pub const H263_SCAN_V: &[usize] = &[ + 0, 8, 16, 24, 1, 9, 2, 10, + 17, 25, 32, 40, 48, 56, 57, 49, + 41, 33, 26, 18, 3, 11, 4, 12, + 19, 27, 34, 42, 50, 58, 35, 43, + 51, 59, 20, 28, 5, 13, 6, 14, + 21, 29, 36, 44, 52, 60, 37, 45, + 53, 61, 22, 30, 7, 15, 23, 31, + 38, 46, 54, 62, 39, 47, 55, 63 +]; + pub const H263_SIZES: &[(usize, usize)] = &[ (0, 0), (128, 96), (176, 144), (352, 288), (704, 576), (1408, 1152) ]; diff --git a/src/codecs/h263/decoder.rs b/src/codecs/h263/decoder.rs index a126bd3..db200e7 100644 --- a/src/codecs/h263/decoder.rs +++ b/src/codecs/h263/decoder.rs @@ -108,6 +108,14 @@ 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} } } +#[derive(Clone,Copy)] +struct PredCoeffs { + hor: [[i16; 8]; 6], + ver: [[i16; 8]; 6], +} + +const ZERO_PRED_COEFFS: PredCoeffs = PredCoeffs { hor: [[0; 8]; 6], ver: [[0; 8]; 6] }; + pub struct H263BaseDecoder { w: usize, h: usize, @@ -120,6 +128,21 @@ pub struct H263BaseDecoder { last_ts: u8, has_b: bool, b_data: Vec, + pred_coeffs: Vec, +} + +#[inline] +fn clip_dc(dc: i16) -> i16 { + if dc < 0 { 0 } + else if dc > 2046 { 2046 } + else { (dc + 1) & !1 } +} + +#[inline] +fn clip_ac(ac: i16) -> i16 { + if ac < -2048 { -2048 } + else if ac > 2047 { 2047 } + else { ac } } #[allow(dead_code)] @@ -131,6 +154,7 @@ impl H263BaseDecoder { prev_frm: None, cur_frm: None, last_ts: 0, has_b: false, b_data: Vec::new(), + pred_coeffs: Vec::new(), } } @@ -178,6 +202,11 @@ impl H263BaseDecoder { let mut blk: [[i16; 64]; 6] = [[0; 64]; 6]; let mut sstate = SliceState::new(pinfo.mode == Type::I); let mut mb_pos = 0; + let apply_acpred = (pinfo.mode == Type::I) && pinfo.plusinfo.is_some() && pinfo.plusinfo.unwrap().aic; + if apply_acpred { + self.pred_coeffs.truncate(0); + self.pred_coeffs.resize(self.mb_w * self.mb_h, ZERO_PRED_COEFFS); + } 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; } } @@ -195,6 +224,72 @@ impl H263BaseDecoder { if binfo.is_intra() { for i in 0..6 { bd.decode_block_intra(&binfo, &sstate, binfo.get_q(), i, (cbp & (1 << (5 - i))) != 0, &mut blk[i])?; + if apply_acpred && (binfo.acpred != ACPredMode::None) { + let has_b = (i == 1) || (i == 3) || (mb_x > 0); + let has_a = (i == 2) || (i == 3) || (mb_y > 0); + let (b_mb, b_blk) = if has_b { + if (i == 1) || (i == 3) { + (mb_pos, i - 1) + } else if i < 4 { + (mb_pos - 1, i + 1) + } else { + (mb_pos - 1, i) + } + } else { (0, 0) }; + let (a_mb, a_blk) = if has_a { + if (i == 2) || (i == 3) { + (mb_pos, i - 2) + } else if i < 4 { + (mb_pos - self.mb_w, i + 2) + } else { + (mb_pos - self.mb_w, i) + } + } else { (0, 0) }; + match binfo.acpred { + ACPredMode::DC => { + let dc; + if has_a && has_b { + dc = (self.pred_coeffs[b_mb].hor[b_blk][0] + self.pred_coeffs[a_mb].ver[a_blk][0]) / 2; + } else if has_a { + dc = self.pred_coeffs[a_mb].ver[a_blk][0]; + } else if has_b { + dc = self.pred_coeffs[b_mb].hor[b_blk][0]; + } else { + dc = 1024; + } + blk[i][0] = clip_dc(blk[i][0] + dc); + }, + ACPredMode::Hor => { + if has_b { + for k in 0..8 { + blk[i][k * 8] += self.pred_coeffs[b_mb].hor[b_blk][k]; + } + for k in 1..8 { + blk[i][k * 8] = clip_ac(blk[i][k * 8]); + } + } else { + blk[i][0] += 1024; + } + blk[i][0] = clip_dc(blk[i][0]); + }, + ACPredMode::Ver => { + if has_a { + for k in 0..8 { + blk[i][k] += self.pred_coeffs[a_mb].ver[a_blk][k]; + } + for k in 1..8 { + blk[i][k] = clip_ac(blk[i][k]); + } + } else { + blk[i][0] += 1024; + } + blk[i][0] = clip_dc(blk[i][0]); + }, + ACPredMode::None => {}, + }; + for t in 0..8 { self.pred_coeffs[mb_pos].hor[i][t] = blk[i][t * 8]; } + for t in 0..8 { self.pred_coeffs[mb_pos].ver[i][t] = blk[i][t]; } + } h263_idct(&mut blk[i]); } blockdsp::put_blocks(&mut buf, mb_x, mb_y, &blk); diff --git a/src/codecs/h263/mod.rs b/src/codecs/h263/mod.rs index a1446ae..28eb44f 100644 --- a/src/codecs/h263/mod.rs +++ b/src/codecs/h263/mod.rs @@ -150,18 +150,19 @@ impl SliceState { #[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)] @@ -173,6 +174,15 @@ pub struct BBlockInfo { fwd: bool, } +#[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 { @@ -189,6 +199,7 @@ impl BlockInfo { mv2: [ZERO_MV, ZERO_MV], num_mv2: 0, fwd: false, + acpred: ACPredMode::None, } } pub fn is_intra(&self) -> bool { self.intra } @@ -222,6 +233,8 @@ impl BlockInfo { self.mv2 = mv_arr; } 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 {