X-Git-Url: https://git.nihav.org/?a=blobdiff_plain;f=nihav-itu%2Fsrc%2Fcodecs%2Fh264%2Fdecoder_mt.rs;h=f66ce2f89cf7e2882bd53c3668d188b253c41e2e;hb=fe64781def821c3900abf44bdfbb38f3b3d21345;hp=27570e511d20b0616703c429628d17ca0bcef60e;hpb=f2cb96fffae1872d6570152983ab52b78623461a;p=nihav.git diff --git a/nihav-itu/src/codecs/h264/decoder_mt.rs b/nihav-itu/src/codecs/h264/decoder_mt.rs index 27570e5..f66ce2f 100644 --- a/nihav-itu/src/codecs/h264/decoder_mt.rs +++ b/nihav-itu/src/codecs/h264/decoder_mt.rs @@ -1,13 +1,11 @@ -/* TODO: - * buffer pool for DSP avg frames -*/ - use nihav_core::codecs::*; use nihav_core::io::bitreader::*; use super::*; use super::dispatch::*; +const AVG_BUF_VINFO: NAVideoInfo = NAVideoInfo { width: 32, height: 32, flipped: false, format: YUV420_FORMAT, bits: 12 }; + pub struct FrameDecoder { pub slices: Vec<(SliceHeader, usize, SliceRefs, Vec)>, pub cur_pic: PictureInfo, @@ -38,18 +36,22 @@ impl FrameDecoder { } validate!(full_size > 0); + let sslice_refs = SimplifiedSliceRefs::new(refs); + let mut br = BitReader::new(&nal[hdr_size / 8..], BitReaderMode::BE); + let mut dst_pic = self.cur_pic.clone(); + let mut dst_frm = NASimpleVideoFrame::from_video_buf(&mut dst_pic.buf).unwrap(); if !self.pps.entropy_coding_mode { br.skip((hdr_size & 7) as u32)?; - self.decode_slice_cavlc(&mut br, full_size - (hdr_size & !7), hdr, refs) + self.decode_slice_cavlc(&mut br, full_size - (hdr_size & !7), hdr, &sslice_refs, &mut dst_frm) } else { let csrc = &nal[(hdr_size + 7) / 8..]; validate!(csrc.len() >= 2); let mut cabac = CABAC::new(csrc, hdr.slice_type, hdr.slice_qp, hdr.cabac_init_idc as usize)?; - self.decode_slice_cabac(&mut cabac, hdr, refs) + self.decode_slice_cabac(&mut cabac, hdr, &sslice_refs, &mut dst_frm) } } - fn decode_slice_cavlc(&mut self, br: &mut BitReader, full_size: usize, slice_hdr: &SliceHeader, refs: &SliceRefs) -> DecoderResult { + fn decode_slice_cavlc(&mut self, br: &mut BitReader, full_size: usize, slice_hdr: &SliceHeader, refs: &SimplifiedSliceRefs, frm: &mut NASimpleVideoFrame) -> DecoderResult { const INTRA_CBP: [u8; 48] = [ 47, 31, 15, 0, 23, 27, 29, 30, 7, 11, 13, 14, 39, 43, 45, 46, 16, 3, 5, 10, 12, 19, 21, 26, 28, 35, 37, 42, 44, 1, 2, 4, @@ -61,7 +63,7 @@ impl FrameDecoder { 17, 18, 20, 24, 19, 21, 26, 28, 23, 27, 29, 30, 22, 25, 38, 41 ]; - let mut mb_idx = slice_hdr.first_mb_in_slice as usize; + let mut mb_idx = slice_hdr.first_mb_in_slice; let mut mb_info = CurrentMBInfo { qp_y: slice_hdr.slice_qp, ..Default::default() }; let skip_type = if slice_hdr.slice_type.is_p() { MBType::PSkip } else { MBType::BSkip }; while br.tell() < full_size && mb_idx < self.num_mbs { @@ -79,7 +81,7 @@ impl FrameDecoder { validate!(mb_idx + mb_skip_run <= self.num_mbs); mb_info.mb_type = skip_type; for _ in 0..mb_skip_run { - self.handle_macroblock(slice_hdr, &mut mb_info, refs)?; + self.handle_macroblock(slice_hdr, &mut mb_info, refs, frm)?; mb_idx += 1; } if mb_idx == self.num_mbs || br.tell() >= full_size { @@ -145,7 +147,7 @@ impl FrameDecoder { decode_residual_cavlc(br, &mut self.sstate, &mut mb_info, &self.cavlc_cb)?; } } - self.handle_macroblock(slice_hdr, &mut mb_info, refs)?; + self.handle_macroblock(slice_hdr, &mut mb_info, refs, frm)?; } mb_idx += 1; if let Ok(disp) = self.dispatch.read() { @@ -154,8 +156,8 @@ impl FrameDecoder { } Ok(mb_idx) } - fn decode_slice_cabac(&mut self, cabac: &mut CABAC, slice_hdr: &SliceHeader, refs: &SliceRefs) -> DecoderResult { - let mut mb_idx = slice_hdr.first_mb_in_slice as usize; + fn decode_slice_cabac(&mut self, cabac: &mut CABAC, slice_hdr: &SliceHeader, refs: &SimplifiedSliceRefs, frm: &mut NASimpleVideoFrame) -> DecoderResult { + let mut mb_idx = slice_hdr.first_mb_in_slice; let mut prev_mb_skipped = false; let skip_type = if slice_hdr.slice_type.is_p() { MBType::PSkip } else { MBType::BSkip }; let mut last_qp_diff = false; @@ -250,7 +252,7 @@ impl FrameDecoder { mb_info.transform_size_8x8 = false; last_qp_diff = false; } - self.handle_macroblock(slice_hdr, &mut mb_info, refs)?; + self.handle_macroblock(slice_hdr, &mut mb_info, refs, frm)?; prev_mb_skipped = mb_skip; if !(self.is_mbaff && ((mb_idx & 1) == 0)) && cabac.decode_terminate() { if let Ok(disp) = self.dispatch.read() { @@ -266,7 +268,7 @@ impl FrameDecoder { Err(DecoderError::InvalidData) } #[allow(clippy::cognitive_complexity)] - fn handle_macroblock(&mut self, slice_hdr: &SliceHeader, mb_info: &mut CurrentMBInfo, refs: &SliceRefs) -> DecoderResult<()> { + fn handle_macroblock(&mut self, slice_hdr: &SliceHeader, mb_info: &mut CurrentMBInfo, refs: &SimplifiedSliceRefs, frm: &mut NASimpleVideoFrame) -> DecoderResult<()> { let qp_y = mb_info.qp_y; let qpr = ((qp_y as i8) + self.pps.chroma_qp_index_offset).max(0).min(51) as usize; let qp_u = CHROMA_QUANTS[qpr]; @@ -291,16 +293,31 @@ impl FrameDecoder { } if !mb_info.transform_size_8x8 { let quant_dc = !mb_info.mb_type.is_intra16x16(); - for i in 0..16 { - if mb_info.coded[i] { - if !tx_bypass { - idct(&mut mb_info.coeffs[i], qp_y, quant_dc); + if quant_dc { + for i in 0..16 { + if mb_info.coded[i] { + if !tx_bypass { + idct(&mut mb_info.coeffs[i], qp_y); + } + } else if has_dc { + if !tx_bypass { + idct_dc(&mut mb_info.coeffs[i], qp_y, quant_dc); + } + mb_info.coded[i] = true; } - } else if has_dc { - if !tx_bypass { - idct_dc(&mut mb_info.coeffs[i], qp_y, quant_dc); + } + } else { + for i in 0..16 { + if mb_info.coded[i] { + if !tx_bypass { + idct_skip_dc(&mut mb_info.coeffs[i], qp_y); + } + } else if has_dc { + if !tx_bypass { + idct_dc(&mut mb_info.coeffs[i], qp_y, quant_dc); + } + mb_info.coded[i] = true; } - mb_info.coded[i] = true; } } } else { @@ -320,7 +337,7 @@ impl FrameDecoder { let blk_no = 16 + chroma * 4 + i; mb_info.coeffs[blk_no][0] = mb_info.chroma_dc[chroma][i]; if mb_info.coded[blk_no] { - idct(&mut mb_info.coeffs[blk_no], qp_c, false); + idct_skip_dc(&mut mb_info.coeffs[blk_no], qp_c); } else if mb_info.coeffs[blk_no][0] != 0 { idct_dc(&mut mb_info.coeffs[blk_no], qp_c, false); mb_info.coded[blk_no] = true; @@ -347,7 +364,6 @@ impl FrameDecoder { let xpos = self.sstate.mb_x * 16; let ypos = self.sstate.mb_y * 16; - let mut frm = NASimpleVideoFrame::from_video_buf(&mut self.cur_pic.buf).unwrap(); if mb_info.mb_type != MBType::PCM { let weight_mode = if self.pps.weighted_pred && slice_hdr.slice_type.is_p() { 1 @@ -356,7 +372,7 @@ impl FrameDecoder { } else { 0 }; - recon_mb_mt(&mut frm, slice_hdr, mb_info, &mut self.sstate, refs, &mut self.mc_dsp, weight_mode, &self.dispatch)?; + recon_mb_mt(frm, slice_hdr, mb_info, &mut self.sstate, refs, &mut self.mc_dsp, weight_mode, &self.dispatch)?; } else { for (dline, src) in frm.data[frm.offset[0] + xpos + ypos * frm.stride[0]..].chunks_mut(frm.stride[0]).take(16).zip(self.ipcm_buf.chunks(16)) { dline[..16].copy_from_slice(src); @@ -368,7 +384,7 @@ impl FrameDecoder { dline[..8].copy_from_slice(src); } } - self.sstate.save_ipred_context(&frm); + self.sstate.save_ipred_context(frm); let mv_info = &mut self.cur_pic.mv_info; let mb_pos = self.sstate.mb_x + self.sstate.mb_y * mv_info.mb_stride; @@ -396,7 +412,7 @@ impl FrameDecoder { Ok(()) } - fn pred_mv(sstate: &mut SliceState, frame_refs: &SliceRefs, mb_info: &mut CurrentMBInfo, cur_id: u16, temporal_mv: bool, direct_8x8: bool) { + fn pred_mv(sstate: &mut SliceState, frame_refs: &SimplifiedSliceRefs, mb_info: &mut CurrentMBInfo, cur_id: u16, temporal_mv: bool, direct_8x8: bool) { let mb_type = mb_info.mb_type; if !mb_type.is_4x4() { let (pw, ph) = mb_type.size(); @@ -472,6 +488,7 @@ struct H264MTDecoder { deblock_skip: bool, max_last_poc: u32, poc_base: u32, + avg_pool: NAVideoBufferPool, } impl H264MTDecoder { @@ -491,6 +508,7 @@ impl H264MTDecoder { deblock_skip: false, max_last_poc: 0, poc_base: 0, + avg_pool: NAVideoBufferPool::new(8), } } fn handle_nal(&mut self, src: Vec, supp: &mut NADecoderSupport, skip_decoding: bool, user_id: u32, time: NATimeInfo) -> DecoderResult<()> { @@ -558,8 +576,13 @@ impl H264MTDecoder { let height = sps.pic_height_in_mbs << 4; let num_mbs = sps.pic_width_in_mbs * sps.pic_height_in_mbs; - let avg_vi = NAVideoInfo { width: 32, height: 32, flipped: false, format: YUV420_FORMAT, bits: 12 }; - let avg_buf = alloc_video_buffer(avg_vi, 4).unwrap().get_vbuf().unwrap(); + let avg_buf = if let Some(buf) = self.avg_pool.get_free() { + buf + } else { + let new_avg_buf = alloc_video_buffer(AVG_BUF_VINFO, 4).unwrap().get_vbuf().unwrap(); + self.avg_pool.add_frame(new_avg_buf.clone()); + new_avg_buf + }; let mut mc_dsp = H264MC::new(avg_buf); mc_dsp.set_dimensions(width, height); @@ -777,7 +800,7 @@ impl NADecoderMT for H264MTDecoder { } let num_bufs = if !self.sps.is_empty() { - self.sps[0].num_ref_frames as usize + 1 + self.sps[0].num_ref_frames + 1 } else { 3 }.max(16 + 1); @@ -789,6 +812,8 @@ impl NADecoderMT for H264MTDecoder { supp.pool_u8.set_dec_bufs(num_bufs + nthreads); supp.pool_u8.prealloc_video(NAVideoInfo::new(width, height, false, fmt), 4)?; + self.avg_pool.prealloc_video(AVG_BUF_VINFO, 4)?; + Ok(()) } else { Err(DecoderError::InvalidData)