X-Git-Url: https://git.nihav.org/?p=nihav.git;a=blobdiff_plain;f=nihav-codec-support%2Fsrc%2Fcodecs%2Fh263%2Fdecoder.rs;h=bba8c04ce752799a458424e8ae9c050e81115dc1;hp=71c574ca0f3e807aadcc9a81a6dc43a65f4e0e26;hb=379524159c95f1c3639976ccf35f9d47cd9732ac;hpb=8989305f27376e92ec3f0a77cf7edf65a5255183 diff --git a/nihav-codec-support/src/codecs/h263/decoder.rs b/nihav-codec-support/src/codecs/h263/decoder.rs index 71c574c..bba8c04 100644 --- a/nihav-codec-support/src/codecs/h263/decoder.rs +++ b/nihav-codec-support/src/codecs/h263/decoder.rs @@ -119,11 +119,13 @@ struct PredCoeffs { } const ZERO_PRED_COEFFS: PredCoeffs = PredCoeffs { hor: [[1024, 0, 0, 0, 0, 0, 0, 0]; 6], ver: [[1024, 0, 0, 0, 0, 0, 0, 0]; 6] }; +const ZERO_PRED_COEFFS2: PredCoeffs = PredCoeffs { hor: [[0x7FFF, 0, 0, 0, 0, 0, 0, 0]; 6], ver: [[0x7FFF, 0, 0, 0, 0, 0, 0, 0]; 6] }; pub const H263DEC_OPT_USES_GOB: u32 = 0x0001; pub const H263DEC_OPT_SLICE_RESET: u32 = 0x0002; pub const H263DEC_OPT_HAS_B_FRAMES: u32 = 0x0004; pub const H263DEC_OPT_HAS_OBMC: u32 = 0x0008; +pub const H263DEC_OPT_PRED_QUANT: u32 = 0x0010; pub struct H263BaseDecoder { w: usize, @@ -147,6 +149,7 @@ pub struct H263BaseDecoder { blk: [[i16; 64]; 6], obmc_buf: NAVideoBufferRef, obmc_blk: Vec<(Type, BMB)>, + pred_quant: bool, } #[inline] @@ -170,6 +173,7 @@ impl H263BaseDecoder { let slice_reset = (options & H263DEC_OPT_SLICE_RESET) != 0; let may_have_b_frames = (options & H263DEC_OPT_HAS_B_FRAMES) != 0; let has_obmc = (options & H263DEC_OPT_HAS_OBMC) != 0; + let pred_quant = (options & H263DEC_OPT_PRED_QUANT) != 0; let vbuf = alloc_video_buffer(NAVideoInfo::new(64, 64, false, YUV420_FORMAT), 4).unwrap(); let obmc_buf = vbuf.get_vbuf().unwrap(); @@ -183,6 +187,7 @@ impl H263BaseDecoder { pred_coeffs: Vec::new(), is_gob, slice_reset, may_have_b_frames, has_obmc, + pred_quant, mv_data: Vec::new(), blk: [[0; 64]; 6], obmc_buf, @@ -209,7 +214,7 @@ impl H263BaseDecoder { } pub fn get_dimensions(&self) -> (usize, usize) { (self.w, self.h) } - fn decode_intra_mb(&mut self, bd: &mut BlockDecoder, bdsp: &BlockDSP, mb_pos: usize, binfo: &BlockInfo, sstate: &SliceState, apply_acpred: bool) -> DecoderResult<()> { + fn decode_intra_mb(&mut self, bd: &mut dyn BlockDecoder, bdsp: &dyn BlockDSP, mb_pos: usize, binfo: &BlockInfo, sstate: &SliceState, apply_acpred: bool) -> DecoderResult<()> { for i in 0..6 { bd.decode_block_intra(&binfo, &sstate, binfo.get_q(), i, (binfo.cbp & (1 << (5 - i))) != 0, &mut self.blk[i])?; if apply_acpred && (binfo.acpred != ACPredMode::None) { @@ -282,7 +287,112 @@ impl H263BaseDecoder { } Ok(()) } - fn decode_inter_mb(&mut self, bd: &mut BlockDecoder, bdsp: &BlockDSP, binfo: &BlockInfo, sstate: &SliceState) -> DecoderResult<()> { + #[allow(clippy::comparison_chain)] + fn decode_intra_mb_pred_quant(&mut self, bd: &mut dyn BlockDecoder, bdsp: &dyn BlockDSP, mb_pos: usize, binfo: &BlockInfo, sstate: &SliceState, apply_acpred: bool) -> DecoderResult<()> { + for i in 0..6 { + bd.decode_block_intra(&binfo, &sstate, binfo.get_q(), i, (binfo.cbp & (1 << (5 - i))) != 0, &mut self.blk[i])?; + let q = if binfo.get_q() < 8 { + 8 + } else { + i16::from(binfo.get_q() * 2) + }; + let qadd = (q + 1) >> 1; + let quant_gray = 1024 / q; + if apply_acpred && (binfo.acpred != ACPredMode::None) { + let has_b = (i == 1) || (i == 3) || !sstate.first_mb; + let has_a = (i == 2) || (i == 3) || !sstate.first_line; + 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) }; + let dc_a = if has_a && self.pred_coeffs[a_mb].ver[a_blk][0] != 0x7FFF { + self.pred_coeffs[a_mb].ver[a_blk][0] + } else { + quant_gray + }; + let dc_b = if has_b && self.pred_coeffs[b_mb].hor[b_blk][0] != 0x7FFF { + self.pred_coeffs[b_mb].hor[b_blk][0] + } else { + quant_gray + }; + let dc = match binfo.acpred { + ACPredMode::DC => { + if has_a && has_b { + (dc_a + dc_b + 1) >> 1 + } else if has_a { + dc_a + } else if has_b { + dc_b + } else { + quant_gray + } + }, + ACPredMode::Hor => { + if has_b { + for k in 1..8 { + self.blk[i][k * 8] += self.pred_coeffs[b_mb].hor[b_blk][k]; + } + for k in 1..8 { + self.blk[i][k * 8] = clip_ac(self.blk[i][k * 8]); + } + dc_b + } else { + quant_gray + } + }, + ACPredMode::Ver => { + if has_a { + for k in 1..8 { + self.blk[i][k] += self.pred_coeffs[a_mb].ver[a_blk][k]; + } + for k in 1..8 { + self.blk[i][k] = clip_ac(self.blk[i][k]); + } + dc_a + } else { + quant_gray + } + }, + ACPredMode::None => { 0 }, + }; + self.blk[i][0] += dc; + for t in 0..8 { self.pred_coeffs[mb_pos].hor[i][t] = self.blk[i][t * 8]; } + for t in 0..8 { self.pred_coeffs[mb_pos].ver[i][t] = self.blk[i][t]; } + } + if apply_acpred { + let start = if binfo.get_q() < 8 { + self.blk[i][0] <<= 3; + 1 + } else { + 0 + }; + for el in self.blk[i].iter_mut().skip(start) { + if *el > 0 { + *el = *el * q + qadd; + } else if *el < 0 { + *el = *el * q - qadd; + } + } + } + bdsp.idct(&mut self.blk[i]); + } + Ok(()) + } + fn decode_inter_mb(&mut self, bd: &mut dyn BlockDecoder, bdsp: &dyn BlockDSP, binfo: &BlockInfo, sstate: &SliceState) -> DecoderResult<()> { for i in 0..6 { bd.decode_block_inter(&binfo, &sstate, binfo.get_q(), i, ((binfo.cbp >> (5 - i)) & 1) != 0, &mut self.blk[i])?; bdsp.idct(&mut self.blk[i]); @@ -301,6 +411,7 @@ impl H263BaseDecoder { bi.mv_f[blk_no] } } + #[allow(clippy::cognitive_complexity)] fn reconstruct_obmc(&mut self, buf: &mut NAVideoBuffer, slice_start: usize, start: usize, end: usize, slice_end: bool) -> usize { let mut mb_x = start % self.mb_w; let mut mb_y = start / self.mb_w; @@ -404,7 +515,8 @@ impl H263BaseDecoder { } mb_pos } - pub fn parse_frame(&mut self, bd: &mut BlockDecoder, bdsp: &BlockDSP) -> DecoderResult { + #[allow(clippy::cognitive_complexity)] + pub fn parse_frame(&mut self, bd: &mut dyn BlockDecoder, bdsp: &dyn BlockDSP) -> DecoderResult { let pinfo = bd.decode_pichdr()?; let mut mvi = MVInfo::new(); let mut mvi2 = MVInfo::new(); @@ -426,16 +538,16 @@ impl H263BaseDecoder { if capacity < self.num_mb { self.obmc_blk.reserve(self.num_mb - capacity); } - self.obmc_blk.truncate(0); + self.obmc_blk.clear(); } if self.has_b { - self.mv_data.truncate(0); + self.mv_data.clear(); } let save_b_data = pinfo.mode.is_ref() && self.may_have_b_frames; if save_b_data { - self.mv_data.truncate(0); + self.mv_data.clear(); } let is_b = pinfo.mode == Type::B; @@ -468,8 +580,12 @@ impl H263BaseDecoder { 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); + self.pred_coeffs.clear(); + if !self.pred_quant { + self.pred_coeffs.resize(self.mb_w * self.mb_h, ZERO_PRED_COEFFS); + } else { + self.pred_coeffs.resize(self.mb_w * self.mb_h, ZERO_PRED_COEFFS2); + } } sstate.quant = slice.quant; let mut obmc_start = 0; @@ -505,7 +621,11 @@ impl H263BaseDecoder { if save_b_data { self.mv_data.push(BlockMVInfo::Intra); } - self.decode_intra_mb(bd, bdsp, mb_pos, &binfo, &sstate, apply_acpred)?; + if !self.pred_quant { + self.decode_intra_mb(bd, bdsp, mb_pos, &binfo, &sstate, apply_acpred)?; + } else { + self.decode_intra_mb_pred_quant(bd, bdsp, mb_pos, &binfo, &sstate, apply_acpred)?; + } blockdsp::put_blocks(&mut buf, mb_x, mb_y, &self.blk); mvi.set_zero_mv(mb_x); if is_b { @@ -661,7 +781,7 @@ impl H263BaseDecoder { self.ipbs.clear(); } - pub fn get_bframe(&mut self, bdsp: &BlockDSP) -> DecoderResult { + pub fn get_bframe(&mut self, bdsp: &dyn BlockDSP) -> DecoderResult { if !self.has_b || self.ipbs.get_lastref().is_none() || self.ipbs.get_nextref().is_none() { return Err(DecoderError::MissingReference); } @@ -676,12 +796,12 @@ impl H263BaseDecoder { recon_b_frame(b_buf, bck_buf.clone(), fwd_buf.clone(), self.mb_w, self.mb_h, self.b_data.as_slice(), bdsp); } - self.b_data.truncate(0); + self.b_data.clear(); Ok(bufinfo) } } -fn recon_b_mb(buf: &mut NAVideoBuffer, ipbs: &mut IPBShuffler, bdsp: &BlockDSP, mvi: &mut MVInfo, mvi2: &mut MVInfo, mb_pos: usize, mb_w: usize, sstate: &SliceState, binfo: &BlockInfo, mv_data: &[BlockMVInfo], bsdiff: u16, tsdiff: u16) { +fn recon_b_mb(buf: &mut NAVideoBuffer, ipbs: &mut IPBShuffler, bdsp: &dyn BlockDSP, mvi: &mut MVInfo, mvi2: &mut MVInfo, mb_pos: usize, mb_w: usize, sstate: &SliceState, binfo: &BlockInfo, mv_data: &[BlockMVInfo], bsdiff: u16, tsdiff: u16) { let mb_x = mb_pos % mb_w; let mb_y = mb_pos / mb_w; @@ -745,7 +865,7 @@ fn recon_b_mb(buf: &mut NAVideoBuffer, ipbs: &mut IPBShuffler, bdsp: &BlockD } fn recon_b_frame(mut b_buf: NAVideoBufferRef, bck_buf: NAVideoBufferRef, fwd_buf: NAVideoBufferRef, - mb_w: usize, mb_h: usize, b_data: &[BMB], bdsp: &BlockDSP) { + mb_w: usize, mb_h: usize, b_data: &[BMB], bdsp: &dyn BlockDSP) { let mut cbpi = CBPInfo::new(); let mut cur_mb = 0; cbpi.reset(mb_w);