X-Git-Url: https://git.nihav.org/?a=blobdiff_plain;f=nihav-itu%2Fsrc%2Fcodecs%2Fh264%2Fdecoder_st.rs;h=94b3977c0622d3c046219fba2844f53b97e92f3e;hb=fe64781def821c3900abf44bdfbb38f3b3d21345;hp=3cffc6a278c04f3dae0d6e27513b3e7d9f54d353;hpb=56a17e69f584e41c2bfd2cb808b812be6b8796e5;p=nihav.git diff --git a/nihav-itu/src/codecs/h264/decoder_st.rs b/nihav-itu/src/codecs/h264/decoder_st.rs index 3cffc6a..94b3977 100644 --- a/nihav-itu/src/codecs/h264/decoder_st.rs +++ b/nihav-itu/src/codecs/h264/decoder_st.rs @@ -1,3 +1,5 @@ +use std::sync::Arc; + use nihav_core::codecs::*; use nihav_core::io::bitreader::*; @@ -9,9 +11,9 @@ struct H264Decoder { height: usize, num_mbs: usize, nal_len: u8, - sps: Vec, + sps: Vec>, cur_sps: usize, - pps: Vec, + pps: Vec>, cur_pps: usize, skip_mode: FrameSkipMode, @@ -104,7 +106,7 @@ impl H264Decoder { let mut br = BitReader::new(&src[..(full_size + 7)/8], BitReaderMode::BE); br.skip(8)?; - let slice_hdr = parse_slice_header(&mut br, &self.sps, &self.pps, is_idr, nal_ref_idc)?; + let slice_hdr = parse_slice_header(&mut br, self.sps.as_slice(), self.pps.as_slice(), is_idr, nal_ref_idc)?; validate!(br.tell() < full_size); let full_id; if slice_hdr.first_mb_in_slice == 0 { @@ -201,27 +203,38 @@ println!("PAFF?"); self.cur_pic = Some(PictureInfo { id: slice_hdr.frame_num, full_id, + user_id: full_id, + time: NATimeInfo::new(None, None, None, 0, 0), pic_type: slice_hdr.slice_type.to_frame_type(), buf, cur_mb: 0, is_ref: nal_ref_idc != 0, + is_idr, long_term: get_long_term_id(is_idr, &slice_hdr), - mv_info: FrameMV::new(sps.pic_width_in_mbs, sps.pic_height_in_mbs), + mv_info: NABufferRef::new(FrameMV::new(sps.pic_width_in_mbs, sps.pic_height_in_mbs)), }); } self.transform_8x8_mode = pps.transform_8x8_mode; self.sstate.reset(sps.pic_width_in_mbs, sps.pic_height_in_mbs, slice_hdr.first_mb_in_slice); + + let mut dst_pic = if let Some(ref pic) = self.cur_pic { + pic.clone() + } else { + return Err(DecoderError::InvalidData); + }; + let mut dst_frm = NASimpleVideoFrame::from_video_buf(&mut dst_pic.buf).unwrap(); + let dst_mv_info = &mut dst_pic.mv_info; if !pps.entropy_coding_mode { - self.has_pic = self.decode_slice_cavlc(&mut br, &slice_hdr, full_size)?; + self.has_pic = self.decode_slice_cavlc(&mut br, &slice_hdr, full_size, &mut dst_frm, dst_mv_info)?; } else { br.align(); - let start = (br.tell() / 8) as usize; + let start = br.tell() / 8; let csrc = &src[start..]; validate!(csrc.len() >= 2); let mut cabac = CABAC::new(csrc, slice_hdr.slice_type, slice_hdr.slice_qp, slice_hdr.cabac_init_idc as usize)?; - self.has_pic = self.decode_slice_cabac(&mut cabac, &slice_hdr)?; + self.has_pic = self.decode_slice_cabac(&mut cabac, &slice_hdr, &mut dst_frm, dst_mv_info)?; } }, 2 => { // slice data partition A @@ -245,7 +258,7 @@ println!("PAFF?"); 6 => {}, //SEI 7 => { let sps = parse_sps(&src[1..])?; - self.sps.push(sps); + self.sps.push(Arc::new(sps)); }, 8 => { validate!(full_size >= 8 + 16); @@ -253,7 +266,7 @@ println!("PAFF?"); let mut found = false; for stored_pps in self.pps.iter_mut() { if stored_pps.pic_parameter_set_id == pps.pic_parameter_set_id { - *stored_pps = pps.clone(); + *stored_pps = Arc::clone(&pps); found = true; break; } @@ -272,7 +285,7 @@ println!("PAFF?"); 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(); @@ -332,7 +345,7 @@ println!("PAFF?"); } } #[allow(clippy::cognitive_complexity)] - fn handle_macroblock(&mut self, slice_hdr: &SliceHeader, mb_info: &mut CurrentMBInfo) { + fn handle_macroblock(&mut self, slice_hdr: &SliceHeader, mb_info: &mut CurrentMBInfo, slice_refs: &SimplifiedSliceRefs, frm: &mut NASimpleVideoFrame, mv_info: &mut FrameMV) { let pps = &self.pps[self.cur_pps]; let qp_y = mb_info.qp_y; @@ -357,25 +370,40 @@ println!("PAFF?"); mb_info.coeffs[i][0] = mb_info.coeffs[24][i]; } } - 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 !tx_bypass { + if !mb_info.transform_size_8x8 { + let quant_dc = !mb_info.mb_type.is_intra16x16(); + if quant_dc { + for (coded, coeffs) in mb_info.coded[..16].iter_mut().zip(mb_info.coeffs[..16].iter_mut()) { + if *coded { + idct(coeffs, qp_y); + } else if has_dc { + idct_dc(coeffs, qp_y, quant_dc); + *coded = true; + } } - } else if has_dc { - if !tx_bypass { - idct_dc(&mut mb_info.coeffs[i], qp_y, quant_dc); + } else { + for (coded, coeffs) in mb_info.coded[..16].iter_mut().zip(mb_info.coeffs[..16].iter_mut()) { + if *coded { + idct_skip_dc(coeffs, qp_y); + } else if has_dc { + idct_dc(coeffs, qp_y, quant_dc); + *coded = true; + } + } + } + } else { + for i in 0..4 { + if mb_info.coded[(i & 1) * 2 + (i & 2) * 4] { + dequant8x8(&mut mb_info.coeffs8x8[i].coeffs, &pps.scaling_list_8x8[!mb_info.mb_type.is_intra() as usize]); + idct8x8(&mut mb_info.coeffs8x8[i].coeffs, qp_y); } - mb_info.coded[i] = true; } } - } else { - for i in 0..4 { - if mb_info.coded[(i & 1) * 2 + (i & 2) * 4] && !tx_bypass { - dequant8x8(&mut mb_info.coeffs8x8[i].coeffs, &pps.scaling_list_8x8[!mb_info.mb_type.is_intra() as usize]); - idct8x8(&mut mb_info.coeffs8x8[i].coeffs, qp_y); + } else if !mb_info.transform_size_8x8 { + for i in 0..16 { + if !mb_info.coded[i] && has_dc { + mb_info.coded[i] = true; } } } @@ -388,7 +416,7 @@ println!("PAFF?"); 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; @@ -399,7 +427,7 @@ println!("PAFF?"); self.sstate.reset_mb_mv(); } if !mb_info.mb_type.is_intra() { - Self::pred_mv(&mut self.sstate, &self.frame_refs.cur_refs, mb_info, self.cur_id, self.temporal_mv, self.sps[self.cur_sps].direct_8x8_inference); + Self::pred_mv(&mut self.sstate, slice_refs, mb_info, self.cur_id, self.temporal_mv, self.sps[self.cur_sps].direct_8x8_inference); } if !pps.constrained_intra_pred && mb_info.mb_type != MBType::Intra4x4 && mb_info.mb_type != MBType::Intra8x8 { self.sstate.fill_ipred(IntraPredMode::DC); @@ -407,28 +435,27 @@ println!("PAFF?"); let xpos = self.sstate.mb_x * 16; let ypos = self.sstate.mb_y * 16; - if let Some(ref mut pic) = self.cur_pic { - let mut frm = NASimpleVideoFrame::from_video_buf(&mut pic.buf).unwrap(); - if mb_info.mb_type != MBType::PCM { - let weight_mode = if self.pps[self.cur_pps].weighted_pred && slice_hdr.slice_type.is_p() { - 1 - } else if slice_hdr.slice_type.is_b() { - self.pps[self.cur_pps].weighted_bipred_idc - } else { - 0 - }; - recon_mb(&mut frm, slice_hdr, mb_info, &mut self.sstate, &self.frame_refs.cur_refs, &mut self.mc_dsp, weight_mode); - } 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); - } - for (dline, src) in frm.data[frm.offset[1] + xpos/2 + ypos/2 * frm.stride[1]..].chunks_mut(frm.stride[1]).take(8).zip(self.ipcm_buf[256..].chunks(8)) { - dline[..8].copy_from_slice(src); - } - for (dline, src) in frm.data[frm.offset[2] + xpos/2 + ypos/2 * frm.stride[2]..].chunks_mut(frm.stride[2]).take(8).zip(self.ipcm_buf[256 + 64..].chunks(8)) { - dline[..8].copy_from_slice(src); - } + + if mb_info.mb_type != MBType::PCM { + let weight_mode = if self.pps[self.cur_pps].weighted_pred && slice_hdr.slice_type.is_p() { + 1 + } else if slice_hdr.slice_type.is_b() { + self.pps[self.cur_pps].weighted_bipred_idc + } else { + 0 + }; + recon_mb(frm, slice_hdr, mb_info, &mut self.sstate, slice_refs, &mut self.mc_dsp, weight_mode); + } 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); + } + for (dline, src) in frm.data[frm.offset[1] + xpos/2 + ypos/2 * frm.stride[1]..].chunks_mut(frm.stride[1]).take(8).zip(self.ipcm_buf[256..].chunks(8)) { + dline[..8].copy_from_slice(src); + } + for (dline, src) in frm.data[frm.offset[2] + xpos/2 + ypos/2 * frm.stride[2]..].chunks_mut(frm.stride[2]).take(8).zip(self.ipcm_buf[256 + 64..].chunks(8)) { + dline[..8].copy_from_slice(src); } + } /*match mb_info.mb_type { MBType::BSkip | MBType::Direct | MBType::B16x16(_) | MBType::B16x8(_, _) | MBType::B8x16(_, _) | MBType::B8x8 => { let dstride = frm.stride[0]; @@ -440,32 +467,27 @@ MBType::BSkip | MBType::Direct | MBType::B16x16(_) | MBType::B16x8(_, _) | MBTyp }, _ => {}, };*/ - self.sstate.save_ipred_context(&frm); + self.sstate.save_ipred_context(frm); + + let mb_pos = self.sstate.mb_x + self.sstate.mb_y * mv_info.mb_stride; + let mut mb = FrameMBInfo::new(); + mb.mb_type = mb_info.mb_type.into(); + for blk4 in 0..16 { + mb.mv[blk4] = self.sstate.get_cur_blk4(blk4).mv; } - if let Some(ref mut pic) = self.cur_pic { - let mv_info = &mut pic.mv_info; - let mb_pos = self.sstate.mb_x + self.sstate.mb_y * mv_info.mb_stride; - let mut mb = FrameMBInfo::new(); - mb.mb_type = mb_info.mb_type.into(); - for blk4 in 0..16 { - mb.mv[blk4] = self.sstate.get_cur_blk4(blk4).mv; - } - for blk8 in 0..4 { - mb.ref_poc[blk8] = self.frame_refs.cur_refs.map_refs(self.sstate.get_cur_blk8(blk8).ref_idx); - mb.ref_idx[blk8] = self.sstate.get_cur_blk8(blk8).ref_idx; - } - mv_info.mbs[mb_pos] = mb; + for blk8 in 0..4 { + mb.ref_poc[blk8] = slice_refs.map_refs(self.sstate.get_cur_blk8(blk8).ref_idx); + mb.ref_idx[blk8] = self.sstate.get_cur_blk8(blk8).ref_idx; } + mv_info.mbs[mb_pos] = mb; + if !self.deblock_skip && self.deblock_mode != 1 { - self.sstate.fill_deblock(&self.frame_refs.cur_refs, self.deblock_mode, self.is_s); - if let Some(ref mut pic) = self.cur_pic { - let mut frm = NASimpleVideoFrame::from_video_buf(&mut pic.buf).unwrap(); - loop_filter_mb(&mut frm, &self.sstate, self.lf_alpha, self.lf_beta); - } + self.sstate.fill_deblock(slice_refs, self.deblock_mode, self.is_s); + loop_filter_mb(frm, &self.sstate, self.lf_alpha, self.lf_beta); } self.sstate.next_mb(); } - fn decode_slice_cavlc(&mut self, br: &mut BitReader, slice_hdr: &SliceHeader, full_size: usize) -> DecoderResult { + fn decode_slice_cavlc(&mut self, br: &mut BitReader, slice_hdr: &SliceHeader, full_size: usize, frm: &mut NASimpleVideoFrame, mv_info: &mut FrameMV) -> 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, @@ -477,9 +499,13 @@ _ => {}, 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 }; + + let slice_refs = self.frame_refs.cur_refs.clone(); + let sslice_refs = SimplifiedSliceRefs::new(&slice_refs); + while br.tell() < full_size && mb_idx < self.num_mbs { mb_info.coded = [false; 25]; mb_info.ref_l0 = [ZERO_REF; 4]; @@ -495,7 +521,7 @@ _ => {}, 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); + self.handle_macroblock(slice_hdr, &mut mb_info, &sslice_refs, frm, mv_info); mb_idx += 1; } if mb_idx == self.num_mbs || br.tell() >= full_size { @@ -561,7 +587,7 @@ _ => {}, decode_residual_cavlc(br, &mut self.sstate, &mut mb_info, &self.cavlc_cb)?; } } - self.handle_macroblock(slice_hdr, &mut mb_info); + self.handle_macroblock(slice_hdr, &mut mb_info, &sslice_refs, frm, mv_info); } mb_idx += 1; } @@ -570,14 +596,17 @@ _ => {}, } Ok(mb_idx == self.num_mbs) } - fn decode_slice_cabac(&mut self, cabac: &mut CABAC, slice_hdr: &SliceHeader) -> 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, frm: &mut NASimpleVideoFrame, mv_info: &mut FrameMV) -> 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; let mut mb_info = CurrentMBInfo { qp_y: slice_hdr.slice_qp, ..Default::default() }; + let slice_refs = self.frame_refs.cur_refs.clone(); + let sslice_refs = SimplifiedSliceRefs::new(&slice_refs); + while mb_idx < self.num_mbs { mb_info.coded = [false; 25]; mb_info.ref_l0 = [ZERO_REF; 4]; @@ -666,7 +695,7 @@ _ => {}, mb_info.transform_size_8x8 = false; last_qp_diff = false; } - self.handle_macroblock(slice_hdr, &mut mb_info); + self.handle_macroblock(slice_hdr, &mut mb_info, &sslice_refs, frm, mv_info); prev_mb_skipped = mb_skip; if !(self.is_mbaff && ((mb_idx & 1) == 0)) && cabac.decode_terminate() { if let Some(ref mut pic) = self.cur_pic { @@ -758,7 +787,7 @@ impl NADecoder for H264Decoder { } 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);