From: Kostya Shishkov Date: Sat, 8 Dec 2018 11:54:04 +0000 (+0100) Subject: h263+rv20: use modified dquant and chroma quant X-Git-Url: https://git.nihav.org/?a=commitdiff_plain;h=43c8b55e9b586d6814b0588516eadf9bd12c9685;p=nihav.git h263+rv20: use modified dquant and chroma quant --- diff --git a/src/codecs/h263/data.rs b/src/codecs/h263/data.rs index 38fa6ca..b5d3cb1 100644 --- a/src/codecs/h263/data.rs +++ b/src/codecs/h263/data.rs @@ -96,6 +96,21 @@ pub const H263_CBPC_B: &[(u8, u8)] = &[ pub const H263_DQUANT_TAB: &[i8] = &[-1, -2, 1, 2]; +pub const H263_MODIFIED_QUANT: [[u8; 32]; 2] = [ + [ + 0, 3, 1, 2, 3, 4, 5, 6, 7, 8, 9, 9, 10, 11, 12, 13, + 14, 15, 16, 17, 18, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28 + ], [ + 0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 14, 15, 16, 17, + 18, 19, 20, 21, 22, 24, 25, 26, 27, 28, 29, 30, 31, 31, 31, 26 + ] +]; + +pub const H263_CHROMA_QUANT: [u8; 32] = [ + 0, 1, 2, 3, 4, 5, 6, 6, 7, 8, 9, 9, 10, 10, 11, 11, + 12, 12, 12, 13, 13, 13, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15 +]; + pub struct H263ShortCodeReader { tab: &'static [(u8, u8)] } impl H263ShortCodeReader { diff --git a/src/codecs/h263/decoder.rs b/src/codecs/h263/decoder.rs index f871bbd..08b4751 100644 --- a/src/codecs/h263/decoder.rs +++ b/src/codecs/h263/decoder.rs @@ -243,6 +243,7 @@ impl H263BaseDecoder { self.pred_coeffs.truncate(0); self.pred_coeffs.resize(self.mb_w * self.mb_h, ZERO_PRED_COEFFS); } + sstate.quant = slice.quant; 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; } } @@ -256,6 +257,7 @@ impl H263BaseDecoder { } cbpi.reset(self.mb_w); sstate.reset_slice(mb_x, mb_y); + sstate.quant = slice.quant; } } @@ -263,6 +265,7 @@ impl H263BaseDecoder { let cbp = binfo.get_cbp(); cbpi.set_cbp(mb_x, cbp); cbpi.set_q(mb_x, binfo.get_q()); + sstate.quant = binfo.get_q(); if binfo.is_intra() { if save_b_data { self.mv_data.push(BlockMVInfo::Intra); diff --git a/src/codecs/h263/mod.rs b/src/codecs/h263/mod.rs index 50eed7d..aa274e7 100644 --- a/src/codecs/h263/mod.rs +++ b/src/codecs/h263/mod.rs @@ -137,6 +137,7 @@ pub struct SliceState { pub first_mb: bool, pub slice_mb_x: usize, pub slice_mb_y: usize, + pub quant: u8, } const SLICE_NO_END: usize = 99999999; @@ -160,7 +161,7 @@ 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 + slice_mb_x: 0, slice_mb_y: 0, quant: 0 } } pub fn next_mb(&mut self) { diff --git a/src/codecs/h263/rv20.rs b/src/codecs/h263/rv20.rs index 9e62875..3b9fa1b 100644 --- a/src/codecs/h263/rv20.rs +++ b/src/codecs/h263/rv20.rs @@ -129,7 +129,7 @@ impl<'a> RealVideo20BR<'a> { let rl_cb = if sstate.is_iframe { &self.tables.aic_rl_cb } else { &self.tables.rl_cb }; let q_add = if quant == 0 || sstate.is_iframe { 0i16 } else { ((quant - 1) | 1) as i16 }; - let q = (quant * 2) as i16; + let q = if plane_no == 0 { (quant * 2) as i16 } else { H263_CHROMA_QUANT[quant as usize] as i16 }; while idx < 64 { let code = br.read_cb(rl_cb)?; let run; @@ -181,6 +181,14 @@ fn decode_mv(br: &mut BitReader, mv_cb: &Codebook) -> DecoderResult { Ok(MV::new(xval, yval)) } +fn read_dquant(br: &mut BitReader, q: u8) -> DecoderResult { + if br.read_bool()? { + Ok(H263_MODIFIED_QUANT[br.read(1)? as usize][q as usize]) + } else { + Ok(br.read(5)? as u8) + } +} + impl<'a> BlockDecoder for RealVideo20BR<'a> { #[allow(unused_variables)] @@ -222,9 +230,9 @@ impl<'a> BlockDecoder for RealVideo20BR<'a> { Ok(ret) } - fn decode_block_header(&mut self, info: &PicInfo, slice: &SliceInfo, _sstate: &SliceState) -> DecoderResult { + fn decode_block_header(&mut self, info: &PicInfo, _slice: &SliceInfo, sstate: &SliceState) -> DecoderResult { let br = &mut self.br; - let mut q = slice.get_quant(); + let mut q = sstate.quant; match info.get_mode() { Type::I => { let mut cbpc = br.read_cb(&self.tables.intra_mcbpc_cb)?; @@ -243,8 +251,7 @@ impl<'a> BlockDecoder for RealVideo20BR<'a> { let cbp = (cbpy << 2) | (cbpc & 3); let dquant = (cbpc & 4) != 0; if dquant { - let idx = br.read(2)? as usize; - q = ((q as i16) + (H263_DQUANT_TAB[idx] as i16)) as u8; + q = read_dquant(br, q)?; } let mut binfo = BlockInfo::new(Type::I, cbp, q); binfo.set_acpred(acpred); @@ -263,8 +270,7 @@ impl<'a> BlockDecoder for RealVideo20BR<'a> { let cbpy = br.read_cb(&self.tables.cbpy_cb)?; let cbp = (cbpy << 2) | (cbpc & 3); if dquant { - let idx = br.read(2)? as usize; - q = ((q as i16) + (H263_DQUANT_TAB[idx] as i16)) as u8; + q = read_dquant(br, q)?; } let binfo = BlockInfo::new(Type::I, cbp, q); return Ok(binfo); @@ -276,8 +282,7 @@ impl<'a> BlockDecoder for RealVideo20BR<'a> { // } let cbp = (cbpy << 2) | (cbpc & 3); if dquant { - let idx = br.read(2)? as usize; - q = ((q as i16) + (H263_DQUANT_TAB[idx] as i16)) as u8; + q = read_dquant(br, q)?; } let mut binfo = BlockInfo::new(Type::P, cbp, q); if !is_4x4 { @@ -312,8 +317,7 @@ impl<'a> BlockDecoder for RealVideo20BR<'a> { } else { 0 }; if dquant { - let idx = br.read(2)? as usize; - q = ((q as i16) + (H263_DQUANT_TAB[idx] as i16)) as u8; + q = read_dquant(br, q)?; } if is_intra {