2 known bugs and limitations:
3 * weighted motion compensation is not implemented
4 * wrong slice boundary filtering
5 * not fully correct deblock strength selection for P/B-macroblocks
6 * scaling lists for 4x4 blocks
8 use nihav_core::codecs::*;
9 use nihav_core::io::byteio::*;
10 use nihav_core::io::bitreader::*;
11 use nihav_core::io::intcode::*;
12 use nihav_codec_support::codecs::{MV, ZERO_MV};
18 #[allow(clippy::identity_op)]
19 #[allow(clippy::erasing_op)]
20 #[allow(clippy::many_single_char_names)]
21 #[allow(clippy::range_plus_one)]
38 fn read_ue(&mut self) -> DecoderResult<u32>;
39 fn read_te(&mut self, range: u32) -> DecoderResult<u32>;
40 fn read_ue_lim(&mut self, max_val: u32) -> DecoderResult<u32> {
41 let val = self.read_ue()?;
42 validate!(val <= max_val);
45 fn read_se(&mut self) -> DecoderResult<i32> {
46 let val = self.read_ue()?;
48 Ok (((val >> 1) as i32) + 1)
50 Ok (-((val >> 1) as i32))
55 impl<'a> ReadUE for BitReader<'a> {
56 fn read_ue(&mut self) -> DecoderResult<u32> {
57 Ok(self.read_code(UintCodeType::GammaP)? - 1)
59 fn read_te(&mut self, range: u32) -> DecoderResult<u32> {
61 if self.read_bool()? {
67 let val = self.read_ue()?;
68 validate!(val <= range);
76 pub coeffs: [i16; 64],
81 self.coeffs = [0; 64];
85 impl Default for Coeff8x8 {
86 fn default() -> Self {
93 #[derive(Clone,Copy,Default)]
94 pub struct CurrentMBInfo {
96 pub sub_mb_type: [SubMBType; 4],
97 pub ipred: [IntraPredMode; 16],
99 pub luma_ipred: [u8; 16],
101 pub ref_l0: [PicRef; 4],
103 pub ref_l1: [PicRef; 4],
107 pub coeffs: [[i16; 16]; 25],
108 pub coeffs8x8: [Coeff8x8; 4],
109 pub chroma_dc: [[i16; 4]; 2],
110 pub coded: [bool; 25],
111 pub transform_size_8x8: bool,
115 fn clear_coeffs8x8(&mut self) {
116 for c in self.coeffs8x8.iter_mut() {
120 fn can_have_8x8_tx(&self, inference_flag: bool) -> bool {
122 MBType::Intra4x4 | MBType::Intra8x8 | MBType::Intra16x16(_, _, _) | MBType::PCM => false,
123 MBType::P8x8 | MBType::P8x8Ref0 | MBType::B8x8 => {
124 for &sub_id in self.sub_mb_type.iter() {
130 => if !inference_flag { return false; },
136 MBType::Direct => inference_flag,
142 fn get_long_term_id(is_idr: bool, slice_hdr: &SliceHeader) -> Option<usize> {
143 if is_idr && !slice_hdr.long_term_reference {
146 let marking = &slice_hdr.adaptive_ref_pic_marking;
147 for (&op, &arg) in marking.memory_management_control_op.iter().zip(marking.operation_arg.iter()).take(marking.num_ops) {
149 return Some(arg as usize);
157 info: NACodecInfoRef,
162 sps: Vec<SeqParameterSet>,
164 pps: Vec<PicParameterSet>,
167 skip_mode: FrameSkipMode,
172 cavlc_cb: CAVLCTables,
176 cur_pic: Option<PictureInfo>,
179 frame_refs: FrameRefs,
187 ipcm_buf: [u8; 256 + 64 + 64],
189 avg_buf: NAVideoBufferRef<u8>,
191 transform_8x8_mode: bool,
194 fn unescape_nal(src: &[u8], dst: &mut Vec<u8>) -> usize {
198 dst.reserve(src.len());
199 while off < src.len() {
205 if zrun == 2 && off + 1 < src.len() && src[off + 1] == 0x03 {
209 if zrun >= 3 && off + 1 < src.len() && src[off + 1] == 0x01 {
222 let avg_vi = NAVideoInfo { width: 32, height: 32, flipped: false, format: YUV420_FORMAT, bits: 12 };
223 let avg_buf = alloc_video_buffer(avg_vi, 4).unwrap().get_vbuf().unwrap();
225 info: NACodecInfoRef::default(),
230 sps: Vec::with_capacity(1),
232 pps: Vec::with_capacity(3),
235 skip_mode: FrameSkipMode::default(),
240 cavlc_cb: CAVLCTables::new(),
242 sstate: SliceState::new(),
246 frame_refs: FrameRefs::new(),
254 ipcm_buf: [0; 256 + 64 + 64],
258 transform_8x8_mode: false,
261 fn handle_nal(&mut self, src: &[u8], supp: &mut NADecoderSupport, skip_decoding: bool) -> DecoderResult<()> {
262 validate!(!src.is_empty());
263 validate!((src[0] & 0x80) == 0);
264 let nal_ref_idc = src[0] >> 5;
265 let nal_unit_type = src[0] & 0x1F;
267 let mut full_size = src.len() * 8;
268 for &byte in src.iter().rev() {
272 full_size -= (byte.trailing_zeros() + 1) as usize;
276 validate!(full_size > 0);
277 match nal_unit_type {
278 1 | 5 if !skip_decoding => {
279 let is_idr = nal_unit_type == 5;
280 let mut br = BitReader::new(&src[..(full_size + 7)/8], BitReaderMode::BE);
283 let slice_hdr = parse_slice_header(&mut br, &self.sps, &self.pps, is_idr, nal_ref_idc)?;
284 validate!(br.tell() < full_size);
286 if slice_hdr.first_mb_in_slice == 0 {
287 validate!(self.cur_pic.is_none());
288 for (i, pps) in self.pps.iter().enumerate() {
289 if pps.pic_parameter_set_id == slice_hdr.pic_parameter_set_id {
294 for (i, sps) in self.sps.iter().enumerate() {
295 if sps.seq_parameter_set_id == self.pps[self.cur_pps].seq_parameter_set_id {
301 full_id = self.frame_refs.calc_picture_num(&slice_hdr, is_idr, nal_ref_idc, &self.sps[self.cur_sps]);
303 let sps = &self.sps[self.cur_sps];
304 if sps.chroma_format_idc != 1 || sps.bit_depth_luma != 8 || sps.bit_depth_chroma != 8 {
305 println!(" chroma fmt {} bits {}/{}", sps.chroma_format_idc, sps.bit_depth_luma, sps.bit_depth_chroma);
306 return Err(DecoderError::NotImplemented);
308 //let pps = &self.pps[self.cur_pps];
311 self.frame_refs.clear_refs();
314 self.width = sps.pic_width_in_mbs << 4;
315 self.height = sps.pic_height_in_mbs << 4;
316 self.num_mbs = sps.pic_width_in_mbs * sps.pic_height_in_mbs;
318 self.is_mbaff = sps.mb_adaptive_frame_field && !slice_hdr.field_pic;
321 return Err(DecoderError::NotImplemented);
323 if !sps.frame_mbs_only {
325 return Err(DecoderError::NotImplemented);
328 //if slice_hdr.slice_type.is_b() { return Ok(()); }
329 self.cur_id = full_id as u16;
331 if let Some(ref mut pic) = self.cur_pic {
332 validate!(pic.cur_mb == slice_hdr.first_mb_in_slice);
333 let new_type = slice_hdr.slice_type.to_frame_type();
334 pic.pic_type = match (pic.pic_type, new_type) {
335 (FrameType::I, _) => new_type,
336 (_, FrameType::B) => FrameType::B,
339 full_id = pic.full_id;
341 return Ok(());//Err(DecoderError::InvalidData);
343 validate!(self.cur_pps < self.pps.len() && self.pps[self.cur_pps].pic_parameter_set_id == slice_hdr.pic_parameter_set_id);
346 let sps = &self.sps[self.cur_sps];
347 let pps = &self.pps[self.cur_pps];
349 self.temporal_mv = !slice_hdr.direct_spatial_mv_pred;
350 self.is_s = slice_hdr.slice_type == SliceType::SI || slice_hdr.slice_type == SliceType::SP;
351 self.deblock_mode = slice_hdr.disable_deblocking_filter_idc;
352 self.lf_alpha = slice_hdr.slice_alpha_c0_offset;
353 self.lf_beta = slice_hdr.slice_beta_offset;
355 self.frame_refs.select_refs(sps, &slice_hdr, full_id);
357 if slice_hdr.adaptive_ref_pic_marking_mode {
358 self.frame_refs.apply_adaptive_marking(&slice_hdr.adaptive_ref_pic_marking, slice_hdr.frame_num, 1 << self.sps[self.cur_sps].log2_max_frame_num)?;
360 if slice_hdr.first_mb_in_slice == 0 {
361 let ret = supp.pool_u8.get_free();
363 return Err(DecoderError::AllocError);
365 let tmp_vinfo = NAVideoInfo::new(self.width, self.height, false, YUV420_FORMAT);
366 let mut buf = ret.unwrap();
367 if buf.get_info() != tmp_vinfo {
368 supp.pool_u8.reset();
369 supp.pool_u8.prealloc_video(tmp_vinfo, 4)?;
370 let ret = supp.pool_u8.get_free();
372 return Err(DecoderError::AllocError);
376 self.cur_pic = Some(PictureInfo {
377 id: slice_hdr.frame_num,
379 pic_type: slice_hdr.slice_type.to_frame_type(),
382 is_ref: nal_ref_idc != 0,
383 long_term: get_long_term_id(is_idr, &slice_hdr),
384 mv_info: FrameMV::new(sps.pic_width_in_mbs, sps.pic_height_in_mbs),
388 self.transform_8x8_mode = pps.transform_8x8_mode;
390 self.sstate.reset(sps.pic_width_in_mbs, sps.pic_height_in_mbs, slice_hdr.first_mb_in_slice);
391 if !pps.entropy_coding_mode {
392 self.has_pic = self.decode_slice_cavlc(&mut br, &slice_hdr, full_size)?;
395 let start = (br.tell() / 8) as usize;
396 let csrc = &src[start..];
397 validate!(csrc.len() >= 2);
398 let mut cabac = CABAC::new(csrc, slice_hdr.slice_type, slice_hdr.slice_qp, slice_hdr.cabac_init_idc as usize)?;
399 self.has_pic = self.decode_slice_cabac(&mut cabac, &slice_hdr)?;
402 2 => { // slice data partition A
404 //slice id = read_ue()
405 //cat 2 slice data (all but MB layer residual)
406 return Err(DecoderError::NotImplemented);
408 3 => { // slice data partition B
409 //slice id = read_ue()
410 //if pps.redundant_pic_cnt_present { redundant_pic_cnt = read_ue() }
411 //cat 3 slice data (MB layer residual)
412 return Err(DecoderError::NotImplemented);
414 4 => { // slice data partition C
415 //slice id = read_ue()
416 //if pps.redundant_pic_cnt_present { redundant_pic_cnt = read_ue() }
417 //cat 4 slice data (MB layer residual)
418 return Err(DecoderError::NotImplemented);
422 let sps = parse_sps(&src[1..])?;
426 validate!(full_size >= 8 + 16);
427 let pps = parse_pps(&src[1..], &self.sps, full_size - 8)?;
428 let mut found = false;
429 for stored_pps in self.pps.iter_mut() {
430 if stored_pps.pic_parameter_set_id == pps.pic_parameter_set_id {
431 *stored_pps = pps.clone();
440 9 => { // access unit delimiter
442 10 => {}, //end of sequence
443 11 => {}, //end of stream
450 fn pred_intra(frm: &mut NASimpleVideoFrame<u8>, sstate: &SliceState, mb_info: &CurrentMBInfo) {
451 let yoff = frm.offset[0] + sstate.mb_x * 16 + sstate.mb_y * 16 * frm.stride[0];
452 match mb_info.mb_type {
453 MBType::Intra16x16(imode, _, _) => {
454 let id = if imode != 2 || (sstate.has_top && sstate.has_left) {
456 } else if !sstate.has_top && !sstate.has_left {
458 } else if !sstate.has_left {
463 IPRED_FUNCS16X16[id](&mut frm.data[yoff..], frm.stride[0], &sstate.top_line_y[sstate.mb_x * 16..], &sstate.left_y);
465 MBType::Intra8x8 => {
466 let mut ictx = IPred8Context::new();
468 let x = (part & 1) * 2;
470 let blk4 = x + y * 4;
472 let cur_yoff = yoff + x * 4 + y * 4 * frm.stride[0];
473 let has_top = y > 0 || sstate.has_top;
474 let has_left = x > 0 || sstate.has_left;
475 let imode = mb_info.ipred[blk4];
476 let id = if imode != IntraPredMode::DC || (has_top && has_left) {
477 let im_id: u8 = imode.into();
479 } else if !has_top && !has_left {
481 } else if !has_left {
486 let mb_idx = sstate.mb_x + sstate.mb_y * sstate.mb_w;
487 let noright = (y == 2 || sstate.mb_x == sstate.mb_w - 1 || mb_idx < sstate.mb_start + sstate.mb_w) && (x == 2);
488 let has_tl = (has_top && x > 0) || (has_left && y > 0) || (x == 0 && y == 0 && sstate.mb_x > 0 && mb_idx > sstate.mb_start + sstate.mb_w);
489 if id != IPRED4_DC128 {
490 let top = if y == 0 {
491 &sstate.top_line_y[sstate.mb_x * 16 + x * 4..]
493 &frm.data[cur_yoff - frm.stride[0]..]
495 let mut left_buf = [0; 9];
496 let left = if x == 0 {
497 &sstate.left_y[y * 4..]
501 left_buf[0] = sstate.top_line_y[sstate.mb_x * 16 + x * 4 - 1];
503 left_buf[0] = frm.data[cur_yoff - 1 - frm.stride[0]];
507 for (dst, src) in left_buf[1..].iter_mut().zip(frm.data[cur_yoff - 1..].chunks(frm.stride[0])) {
513 ictx.fill(top, left, has_top, has_top && !noright, has_left, has_tl);
515 IPRED_FUNCS8X8_LUMA[id](&mut frm.data[cur_yoff..], frm.stride[0], &ictx);
516 if mb_info.coded[blk4] {
517 add_coeffs8(frm.data, cur_yoff, frm.stride[0], &mb_info.coeffs8x8[part].coeffs);
521 MBType::Intra4x4 => {
522 for &(x,y) in I4X4_SCAN.iter() {
525 let cur_yoff = yoff + x * 4 + y * 4 * frm.stride[0];
526 let has_top = y > 0 || sstate.has_top;
527 let has_left = x > 0 || sstate.has_left;
528 let imode = mb_info.ipred[x + y * 4];
529 let id = if imode != IntraPredMode::DC || (has_top && has_left) {
530 let im_id: u8 = imode.into();
532 } else if !has_top && !has_left {
534 } else if !has_left {
539 let noright = (sstate.mb_x == sstate.mb_w - 1 || sstate.mb_x + sstate.mb_y * sstate.mb_w < sstate.mb_start + sstate.mb_w) && (x == 3);
540 let tr: [u8; 4] = if y == 0 {
541 let tsrc = &sstate.top_line_y[sstate.mb_x * 16 + x * 4..];
542 if has_top && !noright {
543 [tsrc[4], tsrc[5], tsrc[6], tsrc[7]]
549 } else if (x & 1) == 0 || (x == 1 && y == 2) {
550 let i = cur_yoff - frm.stride[0];
551 [frm.data[i + 4], frm.data[i + 5], frm.data[i + 6], frm.data[i + 7]]
553 let i = cur_yoff - frm.stride[0];
554 [frm.data[i + 3], frm.data[i + 3], frm.data[i + 3], frm.data[i + 3]]
556 let mut top = [128; 4];
557 let mut left = [128; 9];
560 top.copy_from_slice(&sstate.top_line_y[sstate.mb_x * 16 + x * 4..][..4]);
563 top.copy_from_slice(&frm.data[cur_yoff - frm.stride[0]..][..4]);
567 for (dst, &src) in left.iter_mut().zip(sstate.left_y[y * 4..].iter()) {
574 left[0] = sstate.left_y[y * 4];
576 left[0] = sstate.top_line_y[sstate.mb_x * 16 + x * 4 - 1];
579 left[0] = frm.data[cur_yoff - frm.stride[0] - 1];
581 for (dst, row) in left[1..].iter_mut().zip(frm.data[cur_yoff - 1..].chunks(frm.stride[0])) {
585 IPRED_FUNCS4X4[id](&mut frm.data[cur_yoff..], frm.stride[0], &top, &left, &tr);
586 if mb_info.coded[x + y * 4] {
587 add_coeffs(frm.data, cur_yoff, frm.stride[0], &mb_info.coeffs[x + y * 4]);
593 let id = if mb_info.chroma_ipred != 0 || (sstate.has_top && sstate.has_left) {
594 mb_info.chroma_ipred as usize
595 } else if !sstate.has_top && !sstate.has_left {
597 } else if !sstate.has_left {
603 let off = frm.offset[chroma] + sstate.mb_x * 8 + sstate.mb_y * 8 * frm.stride[chroma];
604 let top = &sstate.top_line_c[chroma - 1][sstate.mb_x * 8..];
605 IPRED_FUNCS8X8_CHROMA[id](&mut frm.data[off..], frm.stride[chroma], top, &sstate.left_c[chroma - 1]);
608 fn add_luma(frm: &mut NASimpleVideoFrame<u8>, sstate: &SliceState, mb_info: &CurrentMBInfo) {
609 let mut yoff = frm.offset[0] + sstate.mb_x * 16 + sstate.mb_y * 16 * frm.stride[0];
610 if !mb_info.transform_size_8x8 {
613 if mb_info.coded[x + y * 4] {
614 add_coeffs(frm.data, yoff + x * 4, frm.stride[0], &mb_info.coeffs[x + y * 4]);
617 yoff += frm.stride[0] * 4;
622 if mb_info.coded[x * 2 + y * 2 * 4] {
623 add_coeffs8(frm.data, yoff + x * 8, frm.stride[0], &mb_info.coeffs8x8[x + y * 2].coeffs);
626 yoff += frm.stride[0] * 8;
630 fn add_chroma(frm: &mut NASimpleVideoFrame<u8>, sstate: &SliceState, mb_info: &CurrentMBInfo) {
632 let mut off = frm.offset[chroma] + sstate.mb_x * 8 + sstate.mb_y * 8 * frm.stride[chroma];
635 let blk_no = 16 + (chroma - 1) * 4 + x + y * 2;
636 if mb_info.coded[blk_no] || mb_info.coeffs[blk_no][0] != 0 {
637 add_coeffs(frm.data, off + x * 4, frm.stride[chroma], &mb_info.coeffs[blk_no]);
640 off += frm.stride[chroma] * 4;
644 fn pred_mv(sstate: &mut SliceState, frame_refs: &FrameRefs, mb_info: &mut CurrentMBInfo, cur_id: u16, temporal_mv: bool) {
645 let mb_type = mb_info.mb_type;
646 if !mb_type.is_4x4() {
647 let (pw, ph) = mb_type.size();
650 if mb_type == MBType::Direct || mb_type == MBType::BSkip {
651 sstate.predict_direct_mb(frame_refs, temporal_mv, cur_id);
653 for part in 0..mb_type.num_parts() {
654 if !mb_type.is_l1(part) {
656 MBType::PSkip => sstate.predict_pskip(),
657 MBType::BSkip | MBType::Direct => {
660 sstate.predict(xoff, yoff, pw, ph, 0,
661 mb_info.mv_l0[part], mb_info.ref_l0[part]);
665 if !mb_type.is_l0(part) && mb_type != MBType::BSkip && mb_type != MBType::Direct {
666 sstate.predict(xoff, yoff, pw, ph, 1, mb_info.mv_l1[part], mb_info.ref_l1[part]);
676 let sub_type = mb_info.sub_mb_type[part];
677 let mut xoff = (part & 1) * 8;
678 let mut yoff = (part & 2) * 4;
680 let (pw, ph) = sub_type.size();
681 for subpart in 0..sub_type.num_parts() {
682 if sub_type != SubMBType::Direct8x8 {
683 if !sub_type.is_l1() {
684 sstate.predict(xoff, yoff, pw, ph, 0, mb_info.mv_l0[part * 4 + subpart], mb_info.ref_l0[part]);
686 if !sub_type.is_l0() {
687 sstate.predict(xoff, yoff, pw, ph, 1, mb_info.mv_l1[part * 4 + subpart], mb_info.ref_l1[part]);
691 sstate.predict_direct_sub(frame_refs, temporal_mv, cur_id, (xoff / 4) + (sblk & 1) + (yoff / 4) * 4 + (sblk & 2) * 2);
695 if xoff == orig_x + 8 {
703 #[allow(clippy::cognitive_complexity)]
704 fn handle_macroblock(&mut self, mb_info: &mut CurrentMBInfo) {
705 let pps = &self.pps[self.cur_pps];
707 let qp_y = mb_info.qp_y;
708 let qpr = ((qp_y as i8) + pps.chroma_qp_index_offset).max(0).min(51) as usize;
709 let qp_u = CHROMA_QUANTS[qpr];
710 let qpb = ((qp_y as i8) + pps.second_chroma_qp_index_offset).max(0).min(51) as usize;
711 let qp_v = CHROMA_QUANTS[qpb];
713 let tx_bypass = qp_y == 0 && self.sps[self.cur_sps].qpprime_y_zero_transform_bypass;
715 self.sstate.get_cur_mb().mb_type = mb_info.mb_type.into();
716 if mb_info.mb_type != MBType::PCM {
717 self.sstate.get_cur_mb().qp_y = qp_y;
718 self.sstate.get_cur_mb().qp_u = qp_u;
719 self.sstate.get_cur_mb().qp_v = qp_v;
720 self.sstate.get_cur_mb().transform_8x8 = mb_info.transform_size_8x8;
722 let has_dc = mb_info.mb_type.is_intra16x16() && mb_info.coded[24];
724 idct_luma_dc(&mut mb_info.coeffs[24], qp_y);
726 mb_info.coeffs[i][0] = mb_info.coeffs[24][i];
729 if !mb_info.transform_size_8x8 {
730 let quant_dc = !mb_info.mb_type.is_intra16x16();
732 if mb_info.coded[i] {
734 idct(&mut mb_info.coeffs[i], qp_y, quant_dc);
738 idct_dc(&mut mb_info.coeffs[i], qp_y, quant_dc);
740 mb_info.coded[i] = true;
745 if mb_info.coded[(i & 1) * 2 + (i & 2) * 4] && !tx_bypass {
746 dequant8x8(&mut mb_info.coeffs8x8[i].coeffs, &pps.scaling_list_8x8[!mb_info.mb_type.is_intra() as usize]);
747 idct8x8(&mut mb_info.coeffs8x8[i].coeffs, qp_y);
752 let qp_c = if chroma == 0 { qp_u } else { qp_v };
753 if mb_info.cbpc != 0 {
754 chroma_dc_transform(&mut mb_info.chroma_dc[chroma], qp_c);
757 let blk_no = 16 + chroma * 4 + i;
758 mb_info.coeffs[blk_no][0] = mb_info.chroma_dc[chroma][i];
759 if mb_info.coded[blk_no] {
760 idct(&mut mb_info.coeffs[blk_no], qp_c, false);
761 } else if mb_info.coeffs[blk_no][0] != 0 {
762 idct_dc(&mut mb_info.coeffs[blk_no], qp_c, false);
763 mb_info.coded[blk_no] = true;
767 if !pps.entropy_coding_mode || mb_info.mb_type.is_skip() || mb_info.mb_type.is_intra() {
768 self.sstate.reset_mb_mv();
770 if !mb_info.mb_type.is_intra() {
771 Self::pred_mv(&mut self.sstate, &self.frame_refs, mb_info, self.cur_id, self.temporal_mv);
773 if !pps.constrained_intra_pred && mb_info.mb_type != MBType::Intra4x4 && mb_info.mb_type != MBType::Intra8x8 {
774 self.sstate.fill_ipred(IntraPredMode::DC);
777 let xpos = self.sstate.mb_x * 16;
778 let ypos = self.sstate.mb_y * 16;
779 if let Some(ref mut pic) = self.cur_pic {
780 let mut frm = NASimpleVideoFrame::from_video_buf(&mut pic.buf).unwrap();
781 match mb_info.mb_type {
782 MBType::Intra16x16(_, _, _) => {
783 Self::pred_intra(&mut frm, &self.sstate, &mb_info);
785 MBType::Intra4x4 | MBType::Intra8x8 => {
786 Self::pred_intra(&mut frm, &self.sstate, &mb_info);
790 let mv = self.sstate.get_cur_blk4(0).mv[0];
791 let rpic = self.frame_refs.select_ref_pic(0, 0);
792 Self::do_p_mc(&mut frm, xpos, ypos, 16, 16, mv, rpic);
795 let mv = self.sstate.get_cur_blk4(0).mv[0];
796 let rpic = self.frame_refs.select_ref_pic(0, mb_info.ref_l0[0].index());
797 Self::do_p_mc(&mut frm, xpos, ypos, 16, 16, mv, rpic);
799 MBType::P16x8 | MBType::P8x16 => {
800 let (bw, bh, bx, by) = if mb_info.mb_type == MBType::P16x8 {
805 let mv = self.sstate.get_cur_blk4(0).mv[0];
806 let rpic = self.frame_refs.select_ref_pic(0, mb_info.ref_l0[0].index());
807 Self::do_p_mc(&mut frm, xpos, ypos, bw, bh, mv, rpic);
808 let mv = self.sstate.get_cur_blk4(bx / 4 + by).mv[0];
809 let rpic = self.frame_refs.select_ref_pic(0, mb_info.ref_l0[1].index());
810 Self::do_p_mc(&mut frm, xpos + bx, ypos + by, bw, bh, mv, rpic);
812 MBType::P8x8 | MBType::P8x8Ref0 => {
814 let bx = (part & 1) * 8;
815 let by = (part & 2) * 4;
816 if let Some(buf) = self.frame_refs.select_ref_pic(0, mb_info.ref_l0[part].index()) {
817 let mv = self.sstate.get_cur_blk4(bx / 4 + by).mv[0];
819 match mb_info.sub_mb_type[part] {
821 do_mc(&mut frm, buf, xpos + bx, ypos + by, 8, 8, mv);
824 do_mc(&mut frm, buf.clone(), xpos + bx, ypos + by, 8, 4, mv);
825 let mv = self.sstate.get_cur_blk4(bx / 4 + by + 4).mv[0];
826 do_mc(&mut frm, buf, xpos + bx, ypos + by + 4, 8, 4, mv);
829 do_mc(&mut frm, buf.clone(), xpos + bx, ypos + by, 4, 8, mv);
830 let mv = self.sstate.get_cur_blk4(bx / 4 + by + 1).mv[0];
831 do_mc(&mut frm, buf, xpos + bx + 4, ypos + by, 4, 8, mv);
835 let sxpos = xpos + bx + (sb_no & 1) * 4;
836 let sypos = ypos + by + (sb_no & 2) * 2;
837 let sblk_no = (bx / 4 + (sb_no & 1)) + ((by / 4) + (sb_no >> 1)) * 4;
838 let mv = self.sstate.get_cur_blk4(sblk_no).mv[0];
839 do_mc(&mut frm, buf.clone(), sxpos, sypos, 4, 4, mv);
845 gray_block(&mut frm, xpos + bx, ypos + by, 8, 8);
849 MBType::B16x16(mode) => {
850 let mv0 = self.sstate.get_cur_blk4(0).mv[0];
851 let rpic0 = self.frame_refs.select_ref_pic(0, mb_info.ref_l0[0].index());
852 let mv1 = self.sstate.get_cur_blk4(0).mv[1];
853 let rpic1 = self.frame_refs.select_ref_pic(1, mb_info.ref_l1[0].index());
854 Self::do_b_mc(&mut frm, mode, xpos, ypos, 16, 16, mv0, rpic0, mv1, rpic1, &mut self.avg_buf);
856 MBType::B16x8(mode0, mode1) | MBType::B8x16(mode0, mode1) => {
857 let (pw, ph) = mb_info.mb_type.size();
858 let (px, py) = (pw & 8, ph & 8);
859 let modes = [mode0, mode1];
860 let (mut bx, mut by) = (0, 0);
862 let blk = if part == 0 { 0 } else { (px / 4) + py };
863 let mv0 = self.sstate.get_cur_blk4(blk).mv[0];
864 let rpic0 = self.frame_refs.select_ref_pic(0, mb_info.ref_l0[part].index());
865 let mv1 = self.sstate.get_cur_blk4(blk).mv[1];
866 let rpic1 = self.frame_refs.select_ref_pic(1, mb_info.ref_l1[part].index());
867 Self::do_b_mc(&mut frm, modes[part], xpos + bx, ypos + by, pw, ph, mv0, rpic0, mv1, rpic1, &mut self.avg_buf);
872 MBType::Direct | MBType::BSkip => {
873 let is_16x16 = self.frame_refs.get_colocated_info(self.sstate.mb_x, self.sstate.mb_y).0.mb_type.is_16x16();
874 if is_16x16 || !self.temporal_mv {
875 let mv = self.sstate.get_cur_blk4(0).mv;
876 let ref_idx = self.sstate.get_cur_blk8(0).ref_idx;
877 let rpic0 = self.frame_refs.select_ref_pic(0, ref_idx[0].index());
878 let rpic1 = self.frame_refs.select_ref_pic(1, ref_idx[1].index());
879 Self::do_b_mc(&mut frm, BMode::Bi, xpos, ypos, 16, 16, mv[0], rpic0, mv[1], rpic1, &mut self.avg_buf);
882 let mv = self.sstate.get_cur_blk4(blk4).mv;
883 let ref_idx = self.sstate.get_cur_blk8(blk4_to_blk8(blk4)).ref_idx;
884 let rpic0 = self.frame_refs.select_ref_pic(0, ref_idx[0].index());
885 let rpic1 = self.frame_refs.select_ref_pic(1, ref_idx[1].index());
886 Self::do_b_mc(&mut frm, BMode::Bi, xpos + (blk4 & 3) * 4, ypos + (blk4 >> 2) * 4, 4, 4, mv[0], rpic0, mv[1], rpic1, &mut self.avg_buf);
889 self.sstate.apply_to_blk8(|blk8| { blk8.ref_idx[0].set_direct(); blk8.ref_idx[1].set_direct(); });
893 let ridx = self.sstate.get_cur_blk8(part).ref_idx;
894 let rpic0 = self.frame_refs.select_ref_pic(0, ridx[0].index());
895 let rpic1 = self.frame_refs.select_ref_pic(1, ridx[1].index());
896 let subtype = mb_info.sub_mb_type[part];
897 let blk8 = (part & 1) * 2 + (part & 2) * 4;
898 let mut bx = (part & 1) * 8;
899 let mut by = (part & 2) * 4;
901 SubMBType::Direct8x8 => {
903 let mv = self.sstate.get_cur_blk4(bx / 4 + (by / 4) * 4).mv;
904 let ref_idx = self.sstate.get_cur_blk8(bx / 8 + (by / 8) * 2).ref_idx;
905 let rpic0 = self.frame_refs.select_ref_pic(0, ref_idx[0].index());
906 let rpic1 = self.frame_refs.select_ref_pic(1, ref_idx[1].index());
907 Self::do_b_mc(&mut frm, BMode::Bi, xpos + bx, ypos + by, 4, 4, mv[0], rpic0, mv[1], rpic1, &mut self.avg_buf);
914 self.sstate.get_cur_blk8(part).ref_idx[0].set_direct();
915 self.sstate.get_cur_blk8(part).ref_idx[1].set_direct();
917 SubMBType::B8x8(mode) => {
918 let mv = self.sstate.get_cur_blk4(blk8).mv;
919 Self::do_b_mc(&mut frm, mode, xpos + bx, ypos + by, 8, 8, mv[0], rpic0, mv[1], rpic1, &mut self.avg_buf);
921 SubMBType::B8x4(mode) | SubMBType::B4x8(mode) => {
922 let (pw, ph) = subtype.size();
923 let mv = self.sstate.get_cur_blk4(blk8).mv;
924 Self::do_b_mc(&mut frm, mode, xpos + bx, ypos + by, pw, ph, mv[0], rpic0.clone(), mv[1], rpic1.clone(), &mut self.avg_buf);
925 let addr2 = blk8 + (pw & 4) / 4 + (ph & 4);
926 let mv = self.sstate.get_cur_blk4(addr2).mv;
927 Self::do_b_mc(&mut frm, mode, xpos + bx + (pw & 4), ypos + by + (ph & 4), pw, ph, mv[0], rpic0, mv[1], rpic1, &mut self.avg_buf);
929 SubMBType::B4x4(mode) => {
931 let addr2 = blk8 + (i & 1) + (i & 2) * 2;
932 let mv = self.sstate.get_cur_blk4(addr2).mv;
933 Self::do_b_mc(&mut frm, mode, xpos + bx, ypos + by, 4, 4, mv[0], rpic0.clone(), mv[1], rpic1.clone(), &mut self.avg_buf);
946 if mb_info.mb_type == MBType::PCM {
947 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)) {
948 dline[..16].copy_from_slice(src);
950 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)) {
951 dline[..8].copy_from_slice(src);
953 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)) {
954 dline[..8].copy_from_slice(src);
956 } else if !mb_info.mb_type.is_skip() {
957 if mb_info.mb_type != MBType::Intra4x4 && mb_info.mb_type != MBType::Intra8x8 {
958 Self::add_luma(&mut frm, &self.sstate, &mb_info);
960 Self::add_chroma(&mut frm, &self.sstate, &mb_info);
962 /*match mb_info.mb_type {
963 MBType::BSkip | MBType::Direct | MBType::B16x16(_) | MBType::B16x8(_, _) | MBType::B8x16(_, _) | MBType::B8x8 => {
964 let dstride = frm.stride[0];
965 let dst = &mut frm.data[frm.offset[0] + self.sstate.mb_x * 16 + self.sstate.mb_y * 16 * dstride..];
966 for el in dst[..16].iter_mut() { *el = 255; }
967 for row in dst.chunks_mut(dstride).skip(1).take(15) {
973 self.sstate.save_ipred_context(&frm);
975 if let Some(ref mut pic) = self.cur_pic {
976 let mv_info = &mut pic.mv_info;
977 let mb_pos = self.sstate.mb_x + self.sstate.mb_y * mv_info.mb_stride;
978 let mut mb = FrameMBInfo::new();
979 mb.mb_type = mb_info.mb_type.into();
981 mb.mv[blk4] = self.sstate.get_cur_blk4(blk4).mv;
984 mb.ref_poc[blk8] = self.frame_refs.map_refs(self.sstate.get_cur_blk8(blk8).ref_idx);
985 mb.ref_idx[blk8] = self.sstate.get_cur_blk8(blk8).ref_idx;
987 mv_info.mbs[mb_pos] = mb;
989 if !self.deblock_skip && self.deblock_mode != 1 {
990 self.sstate.fill_deblock(&self.frame_refs, self.deblock_mode, self.is_s);
991 if let Some(ref mut pic) = self.cur_pic {
992 let mut frm = NASimpleVideoFrame::from_video_buf(&mut pic.buf).unwrap();
993 loop_filter_mb(&mut frm, &self.sstate, self.lf_alpha, self.lf_beta);
996 self.sstate.next_mb();
998 fn do_p_mc(frm: &mut NASimpleVideoFrame<u8>, xpos: usize, ypos: usize, w: usize, h: usize, mv: MV, ref_pic: Option<NAVideoBufferRef<u8>>) {
999 if let Some(buf) = ref_pic {
1000 do_mc(frm, buf, xpos, ypos, w, h, mv);
1002 gray_block(frm, xpos, ypos, w, h);
1005 fn do_b_mc(frm: &mut NASimpleVideoFrame<u8>, mode: BMode, xpos: usize, ypos: usize, w: usize, h: usize, mv0: MV, ref_pic0: Option<NAVideoBufferRef<u8>>, mv1: MV, ref_pic1: Option<NAVideoBufferRef<u8>>, avg_buf: &mut NAVideoBufferRef<u8>) {
1008 if let Some(buf) = ref_pic0 {
1009 do_mc(frm, buf, xpos, ypos, w, h, mv0);
1011 gray_block(frm, xpos, ypos, w, h);
1015 if let Some(buf) = ref_pic1 {
1016 do_mc(frm, buf, xpos, ypos, w, h, mv1);
1018 gray_block(frm, xpos, ypos, w, h);
1022 match (ref_pic0, ref_pic1) {
1023 (Some(buf0), Some(buf1)) => {
1024 do_mc(frm, buf0, xpos, ypos, w, h, mv0);
1025 do_mc_avg(frm, buf1, xpos, ypos, w, h, mv1, avg_buf);
1027 (Some(buf0), None) => {
1028 do_mc(frm, buf0, xpos, ypos, w, h, mv0);
1030 (None, Some(buf1)) => {
1031 do_mc(frm, buf1, xpos, ypos, w, h, mv1);
1034 gray_block(frm, xpos, ypos, w, h);
1040 fn decode_slice_cavlc(&mut self, br: &mut BitReader, slice_hdr: &SliceHeader, full_size: usize) -> DecoderResult<bool> {
1041 const INTRA_CBP: [u8; 48] = [
1042 47, 31, 15, 0, 23, 27, 29, 30, 7, 11, 13, 14, 39, 43, 45, 46,
1043 16, 3, 5, 10, 12, 19, 21, 26, 28, 35, 37, 42, 44, 1, 2, 4,
1044 8, 17, 18, 20, 24, 6, 9, 22, 25, 32, 33, 34, 36, 40, 38, 41
1046 const INTER_CBP: [u8; 48] = [
1047 0, 16, 1, 2, 4, 8, 32, 3, 5, 10, 12, 15, 47, 7, 11, 13,
1048 14, 6, 9, 31, 35, 37, 42, 44, 33, 34, 36, 40, 39, 43, 45, 46,
1049 17, 18, 20, 24, 19, 21, 26, 28, 23, 27, 29, 30, 22, 25, 38, 41
1052 let mut mb_idx = slice_hdr.first_mb_in_slice as usize;
1053 let mut mb_info = CurrentMBInfo::default();
1054 mb_info.qp_y = slice_hdr.slice_qp;
1055 let skip_type = if slice_hdr.slice_type.is_p() { MBType::PSkip } else { MBType::BSkip };
1056 while br.tell() < full_size && mb_idx < self.num_mbs {
1057 mb_info.coded = [false; 25];
1058 mb_info.ref_l0 = [ZERO_REF; 4];
1059 mb_info.ref_l1 = [ZERO_REF; 4];
1060 mb_info.mv_l0 = [ZERO_MV; 16];
1061 mb_info.mv_l1 = [ZERO_MV; 16];
1062 mb_info.chroma_dc = [[0; 4]; 2];
1066 if !slice_hdr.slice_type.is_intra() {
1067 let mb_skip_run = br.read_ue()? as usize;
1068 validate!(mb_idx + mb_skip_run <= self.num_mbs);
1069 mb_info.mb_type = skip_type;
1070 for _ in 0..mb_skip_run {
1071 self.handle_macroblock(&mut mb_info);
1074 if mb_idx == self.num_mbs || br.tell() >= full_size {
1078 if br.tell() < full_size {
1079 if self.is_mbaff && ((mb_idx & 1) == 0) {
1080 let _mb_field_decoding = br.read_bool()?;
1082 let mut mb_type = decode_mb_type_cavlc(br, slice_hdr)?;
1083 mb_info.mb_type = mb_type;
1084 mb_info.transform_size_8x8 = false;
1085 if mb_type == MBType::PCM {
1087 for pix in self.ipcm_buf[..256 + 64 + 64].iter_mut() {
1088 *pix = br.read(8)? as u8;
1090 self.sstate.fill_ncoded(16);
1092 if self.transform_8x8_mode && mb_type == MBType::Intra4x4 {
1093 mb_info.transform_size_8x8 = br.read_bool()?;
1094 if mb_info.transform_size_8x8 {
1095 mb_type = MBType::Intra8x8;
1096 mb_info.mb_type = MBType::Intra8x8;
1099 decode_mb_pred_cavlc(br, slice_hdr, mb_type, &mut self.sstate, &mut mb_info)?;
1100 let (cbpy, cbpc) = if let MBType::Intra16x16(_, cbpy, cbpc) = mb_type {
1103 let cbp_id = br.read_ue()? as usize;
1104 validate!(cbp_id < INTRA_CBP.len());
1105 let cbp = if mb_type == MBType::Intra4x4 || mb_type == MBType::Intra8x8 {
1110 if self.transform_8x8_mode && (cbp & 0xF) != 0 && mb_info.can_have_8x8_tx(self.sps[self.cur_sps].direct_8x8_inference) {
1111 mb_info.transform_size_8x8 = br.read_bool()?;
1113 ((cbp & 0xF), (cbp >> 4))
1115 mb_info.cbpy = cbpy;
1116 mb_info.cbpc = cbpc;
1117 self.sstate.get_cur_mb().cbp = (cbpc << 4) | cbpy;
1118 if cbpy != 0 || cbpc != 0 || mb_type.is_intra16x16() {
1119 let mb_qp_delta = br.read_se()?;
1120 validate!(mb_qp_delta >= -26 && mb_qp_delta <= 25);
1121 let new_qp = mb_qp_delta + i32::from(mb_info.qp_y);
1122 mb_info.qp_y = if new_qp < 0 {
1124 } else if new_qp >= 52 {
1129 mb_info.coeffs = [[0; 16]; 25];
1130 if self.transform_8x8_mode {
1131 mb_info.clear_coeffs8x8();
1133 mb_info.chroma_dc = [[0; 4]; 2];
1134 decode_residual_cavlc(br, &mut self.sstate, &mut mb_info, &self.cavlc_cb)?;
1137 self.handle_macroblock(&mut mb_info);
1141 if let Some(ref mut pic) = self.cur_pic {
1142 pic.cur_mb = mb_idx;
1144 Ok(mb_idx == self.num_mbs)
1146 fn decode_slice_cabac(&mut self, cabac: &mut CABAC, slice_hdr: &SliceHeader) -> DecoderResult<bool> {
1147 let mut mb_idx = slice_hdr.first_mb_in_slice as usize;
1148 let mut prev_mb_skipped = false;
1149 let skip_type = if slice_hdr.slice_type.is_p() { MBType::PSkip } else { MBType::BSkip };
1150 let mut last_qp_diff = false;
1152 let mut mb_info = CurrentMBInfo::default();
1153 mb_info.qp_y = slice_hdr.slice_qp;
1155 while mb_idx < self.num_mbs {
1156 mb_info.coded = [false; 25];
1157 mb_info.ref_l0 = [ZERO_REF; 4];
1158 mb_info.ref_l1 = [ZERO_REF; 4];
1159 mb_info.mv_l0 = [ZERO_MV; 16];
1160 mb_info.mv_l1 = [ZERO_MV; 16];
1161 mb_info.chroma_dc = [[0; 4]; 2];
1164 let mb_skip = cabac_decode_mbskip(cabac, &self.sstate, slice_hdr);
1166 if self.is_mbaff && (((mb_idx & 1) == 0) || (prev_mb_skipped && ((mb_idx & 1) == 1))) {
1167 let _mb_field_decoding = cabac.decode_bit(70);
1169 let mut mb_type = cabac_decode_mb_type(cabac, &slice_hdr, &self.sstate);
1170 mb_info.mb_type = mb_type;
1171 mb_info.transform_size_8x8 = false;
1172 if mb_type == MBType::PCM {
1173 let ipcm_size = 256 + 64 + 64;
1174 validate!(cabac.pos + ipcm_size <= cabac.src.len());
1175 self.ipcm_buf[..ipcm_size].copy_from_slice(&cabac.src[cabac.pos..][..ipcm_size]);
1176 cabac.pos += ipcm_size;
1178 last_qp_diff = false;
1180 if self.transform_8x8_mode && mb_type == MBType::Intra4x4 {
1182 if self.sstate.get_top_mb().transform_8x8 {
1185 if self.sstate.get_left_mb().transform_8x8 {
1188 mb_info.transform_size_8x8 = cabac.decode_bit(399 + ctx);
1189 if mb_info.transform_size_8x8 {
1190 mb_type = MBType::Intra8x8;
1191 mb_info.mb_type = MBType::Intra8x8;
1194 decode_mb_pred_cabac(cabac, slice_hdr, mb_type, &mut self.sstate, &mut mb_info);
1195 let (cbpy, cbpc) = if let MBType::Intra16x16(_, cbpy, cbpc) = mb_type {
1198 decode_cbp_cabac(cabac, &self.sstate)
1200 if self.transform_8x8_mode && cbpy != 0 && mb_info.can_have_8x8_tx(self.sps[self.cur_sps].direct_8x8_inference) {
1202 if self.sstate.get_top_mb().transform_8x8 {
1205 if self.sstate.get_left_mb().transform_8x8 {
1208 mb_info.transform_size_8x8 = cabac.decode_bit(399 + ctx);
1210 if mb_type.is_intra() {
1211 self.sstate.get_cur_mb().cmode = mb_info.chroma_ipred;
1213 mb_info.cbpy = cbpy;
1214 mb_info.cbpc = cbpc;
1215 self.sstate.get_cur_mb().cbp = (cbpc << 4) | cbpy;
1216 if cbpy != 0 || cbpc != 0 || mb_type.is_intra16x16() {
1217 let mb_qp_delta = decode_mb_qp_delta_cabac(cabac, last_qp_diff as usize);
1218 validate!(mb_qp_delta >= -26 && mb_qp_delta <= 25);
1219 last_qp_diff = mb_qp_delta != 0;
1220 let new_qp = mb_qp_delta + i32::from(mb_info.qp_y);
1221 mb_info.qp_y = if new_qp < 0 {
1223 } else if new_qp >= 52 {
1228 mb_info.coeffs = [[0; 16]; 25];
1229 if self.transform_8x8_mode {
1230 mb_info.clear_coeffs8x8();
1232 mb_info.chroma_dc = [[0; 4]; 2];
1233 decode_residual_cabac(cabac, &mut self.sstate, &mut mb_info);
1235 last_qp_diff = false;
1239 mb_info.mb_type = skip_type;
1240 mb_info.transform_size_8x8 = false;
1241 last_qp_diff = false;
1243 self.handle_macroblock(&mut mb_info);
1244 prev_mb_skipped = mb_skip;
1245 if !(self.is_mbaff && ((mb_idx & 1) == 0)) && cabac.decode_terminate() {
1246 if let Some(ref mut pic) = self.cur_pic {
1247 pic.cur_mb = mb_idx + 1;
1249 return Ok(mb_idx + 1 == self.num_mbs);
1253 Err(DecoderError::InvalidData)
1257 impl NADecoder for H264Decoder {
1258 fn init(&mut self, supp: &mut NADecoderSupport, info: NACodecInfoRef) -> DecoderResult<()> {
1259 if let NACodecTypeInfo::Video(vinfo) = info.get_properties() {
1260 let fmt = YUV420_FORMAT;
1261 let myinfo = NACodecTypeInfo::Video(NAVideoInfo::new(0, 0, false, fmt));
1262 self.info = NACodecInfo::new_ref(info.get_name(), myinfo, info.get_extradata()).into_ref();
1264 let edata = info.get_extradata().unwrap();
1265 //print!("edata:"); for &el in edata.iter() { print!(" {:02X}", el); } println!();
1266 if edata.len() > 11 && &edata[0..4] == b"avcC" {
1267 let mut mr = MemoryReader::new_read(edata.as_slice());
1268 let mut br = ByteReader::new(&mut mr);
1269 let mut nal_buf = Vec::new();
1272 let version = br.read_byte()?;
1273 validate!(version == 1);
1274 let profile = br.read_byte()?;
1275 let _compatibility = br.read_byte()?;
1276 let _level = br.read_byte()?;
1277 let b = br.read_byte()?;
1278 validate!((b & 0xFC) == 0xFC);
1279 self.nal_len = (b & 3) + 1;
1280 let b = br.read_byte()?;
1281 validate!((b & 0xE0) == 0xE0);
1282 let num_sps = (b & 0x1F) as usize;
1283 for _ in 0..num_sps {
1284 let len = br.read_u16be()? as usize;
1285 let offset = br.tell() as usize;
1286 validate!((br.peek_byte()? & 0x1F) == 7);
1287 let _size = unescape_nal(&edata[offset..][..len], &mut nal_buf);
1288 self.handle_nal(&nal_buf, supp, true)?;
1291 let num_pps = br.read_byte()? as usize;
1292 for _ in 0..num_pps {
1293 let len = br.read_u16be()? as usize;
1294 let offset = br.tell() as usize;
1295 validate!((br.peek_byte()? & 0x1F) == 8);
1296 let _size = unescape_nal(&edata[offset..][..len], &mut nal_buf);
1297 self.handle_nal(&nal_buf, supp, true)?;
1302 100 | 110 | 122 | 144 => {
1303 let b = br.read_byte()?;
1304 validate!((b & 0xFC) == 0xFC);
1305 // b & 3 -> chroma format
1306 let b = br.read_byte()?;
1307 validate!((b & 0xF8) == 0xF8);
1308 // b & 7 -> luma depth minus 8
1309 let b = br.read_byte()?;
1310 validate!((b & 0xF8) == 0xF8);
1311 // b & 7 -> chroma depth minus 8
1312 let num_spsext = br.read_byte()? as usize;
1313 for _ in 0..num_spsext {
1314 let len = br.read_u16be()? as usize;
1323 return Err(DecoderError::NotImplemented);
1326 self.width = vinfo.get_width();
1327 self.height = vinfo.get_height();
1329 if (self.width == 0 || self.height == 0) && !self.sps.is_empty() {
1330 self.width = self.sps[0].pic_width_in_mbs * 16;
1331 self.height = self.sps[0].pic_height_in_mbs * 16;
1334 let num_bufs = if !self.sps.is_empty() {
1335 self.sps[0].num_ref_frames as usize + 1
1339 supp.pool_u8.set_dec_bufs(num_bufs);
1340 supp.pool_u8.prealloc_video(NAVideoInfo::new(self.width, self.height, false, fmt), 4)?;
1345 Err(DecoderError::InvalidData)
1348 fn decode(&mut self, supp: &mut NADecoderSupport, pkt: &NAPacket) -> DecoderResult<NAFrameRef> {
1349 let src = pkt.get_buffer();
1351 let mut mr = MemoryReader::new_read(&src);
1352 let mut br = ByteReader::new(&mut mr);
1353 let mut nal_buf = Vec::with_capacity(src.len());
1354 if self.nal_len > 0 {
1355 let mut skip_decoding = false;
1356 if self.skip_mode != FrameSkipMode::None {
1357 let mut pic_type = FrameType::I;
1358 let mut is_ref = false;
1359 while br.left() > 0 {
1360 let size = match self.nal_len {
1361 1 => br.read_byte()? as usize,
1362 2 => br.read_u16be()? as usize,
1363 3 => br.read_u24be()? as usize,
1364 4 => br.read_u32be()? as usize,
1365 _ => unreachable!(),
1367 validate!(br.left() >= (size as i64));
1368 let offset = br.tell() as usize;
1369 let size = unescape_nal(&src[offset..][..size], &mut nal_buf);
1370 validate!(size > 0);
1371 let nal_ref_idc = nal_buf[0] >> 5;
1372 let nal_unit_type = nal_buf[0] & 0x1F;
1373 if nal_unit_type == 1 || nal_unit_type == 5 {
1374 let mut bitr = BitReader::new(&nal_buf[1..], BitReaderMode::BE);
1375 let (first_mb, slice_type) = parse_slice_header_minimal(&mut bitr)?;
1376 if first_mb == 0 && nal_ref_idc != 0 {
1379 let new_type = slice_type.to_frame_type();
1380 pic_type = match (pic_type, new_type) {
1381 (FrameType::I, _) => new_type,
1382 (_, FrameType::B) => FrameType::B,
1386 br.read_skip(size)?;
1388 match self.skip_mode {
1389 FrameSkipMode::IntraOnly => {
1390 skip_decoding = pic_type != FrameType::I;
1392 FrameSkipMode::KeyframesOnly => {
1394 skip_decoding = true;
1399 br.seek(SeekFrom::Start(0))?;
1401 while br.left() > 0 {
1402 let size = match self.nal_len {
1403 1 => br.read_byte()? as usize,
1404 2 => br.read_u16be()? as usize,
1405 3 => br.read_u24be()? as usize,
1406 4 => br.read_u32be()? as usize,
1407 _ => unreachable!(),
1409 validate!(br.left() >= (size as i64));
1410 let offset = br.tell() as usize;
1411 let _size = unescape_nal(&src[offset..][..size], &mut nal_buf);
1412 self.handle_nal(nal_buf.as_slice(), supp, skip_decoding)?;
1413 br.read_skip(size)?;
1416 //todo NAL detection
1420 let (bufinfo, ftype, dts) = if self.has_pic && self.cur_pic.is_some() {
1421 let mut npic = None;
1422 std::mem::swap(&mut self.cur_pic, &mut npic);
1423 let cpic = npic.unwrap();
1424 let ret = (NABufferType::Video(cpic.buf.clone()), cpic.pic_type, Some(u64::from(cpic.full_id)));
1426 self.frame_refs.add_short_term(cpic.clone(), self.sps[self.cur_sps].num_ref_frames);
1428 if let Some(lt_idx) = cpic.long_term {
1429 self.frame_refs.add_long_term(lt_idx, cpic);
1433 (NABufferType::None, FrameType::Skip, None)
1436 let mut frm = NAFrame::new_from_pkt(pkt, self.info.clone(), bufinfo);
1437 frm.set_keyframe(ftype == FrameType::I);
1438 if let (Some(mydts), None) = (dts, frm.get_dts()) {
1439 frm.set_dts(Some(mydts));
1441 if let Some(dts) = dts {
1442 frm.set_id(dts as i64);
1444 frm.set_frame_type(ftype);
1447 fn flush(&mut self) {
1451 const DEBLOCK_SKIP_OPTION: &str = "skip_deblock";
1453 const DECODER_OPTIONS: &[NAOptionDefinition] = &[
1454 NAOptionDefinition {
1455 name: FRAME_SKIP_OPTION, description: FRAME_SKIP_OPTION_DESC,
1456 opt_type: NAOptionDefinitionType::Bool },
1457 NAOptionDefinition {
1458 name: DEBLOCK_SKIP_OPTION, description: "Loop filter skipping mode",
1459 opt_type: NAOptionDefinitionType::String(Some(&[
1460 FRAME_SKIP_OPTION_VAL_NONE,
1461 FRAME_SKIP_OPTION_VAL_KEYFRAME,
1462 FRAME_SKIP_OPTION_VAL_INTRA
1466 impl NAOptionHandler for H264Decoder {
1467 fn get_supported_options(&self) -> &[NAOptionDefinition] { DECODER_OPTIONS }
1468 fn set_options(&mut self, options: &[NAOption]) {
1469 for option in options.iter() {
1470 for opt_def in DECODER_OPTIONS.iter() {
1471 if opt_def.check(option).is_ok() {
1472 match (option.name, &option.value) {
1473 (FRAME_SKIP_OPTION, NAValue::String(ref str)) => {
1474 if let Ok(smode) = FrameSkipMode::from_str(str) {
1475 self.skip_mode = smode;
1478 (DEBLOCK_SKIP_OPTION, NAValue::Bool(val)) => {
1479 self.deblock_skip = *val;
1487 fn query_option_value(&self, name: &str) -> Option<NAValue> {
1489 FRAME_SKIP_OPTION => Some(NAValue::String(self.skip_mode.to_string())),
1490 DEBLOCK_SKIP_OPTION => Some(NAValue::Bool(self.deblock_skip)),
1496 pub fn get_decoder() -> Box<dyn NADecoder + Send> {
1497 Box::new(H264Decoder::new())
1502 use nihav_core::codecs::RegisteredDecoders;
1503 use nihav_core::demuxers::RegisteredDemuxers;
1504 use nihav_codec_support::test::dec_video::*;
1505 use crate::itu_register_all_decoders;
1506 use nihav_commonfmt::generic_register_all_demuxers;
1508 // samples if not specified otherwise come from H.264 conformance suite
1511 use self::raw_demux::RawH264DemuxerCreator;
1514 fn test_h264_perframe() {
1515 let mut dmx_reg = RegisteredDemuxers::new();
1516 dmx_reg.add_demuxer(&RawH264DemuxerCreator{});
1517 generic_register_all_demuxers(&mut dmx_reg);
1518 let mut dec_reg = RegisteredDecoders::new();
1519 itu_register_all_decoders(&mut dec_reg);
1521 test_decoding("rawh264", "h264",
1522 "assets/ITU/h264-conformance/CABAST3_Sony_E.jsv",
1523 None, &dmx_reg, &dec_reg, ExpectedTestResult::MD5Frames(vec![
1524 [0x85fc4b44, 0xc9aefdc9, 0x568d0592, 0x2eccf9a0],
1525 [0xbd8d11bc, 0x97acf592, 0x45a3cdbb, 0xa254a882],
1526 [0xbda0e0b9, 0x9fbe1974, 0x1540b244, 0x46a050ca],
1527 [0x471f0057, 0x125ef3b4, 0x4a87515f, 0xba254bbb],
1528 [0x466a7df2, 0xb392c2a4, 0xed66b68b, 0xfdaad2da],
1529 [0x96334b41, 0x41bac7ef, 0xe87154f1, 0xa5fc3551],
1530 [0x0fd4e9b8, 0x4269bbec, 0x00a1978f, 0xe6224851],
1531 [0x68be82af, 0x856615a7, 0x387a253d, 0x8473e6b9],
1532 [0xc4bed119, 0x14ba7fe0, 0x447cb680, 0x555da4c5],
1533 [0x85d127d6, 0x04b85928, 0x26740281, 0x4d848db5],
1534 [0xe44fe461, 0x0d0b64ce, 0xf191179b, 0xabdab686],
1535 [0x347c8edb, 0x847ad11f, 0x8f16b84e, 0xdc915d75],
1536 [0xeb1364a6, 0x91c9d99d, 0x324f5427, 0xcc9f11a2],
1537 [0x7aeb5a3f, 0xebc9c4dd, 0x8f12c8e4, 0x37a2db97],
1538 [0xa11e5c33, 0x656df4c0, 0x1e8b98d8, 0x1736722f],
1539 [0x239f2ef2, 0xe32b0603, 0x448366bb, 0x9331051c],
1540 [0x1815a1b1, 0xfb7e7cf0, 0xd5c7dd5b, 0x0135a8fb],
1541 [0xea3b85dd, 0xa96e7015, 0xa91c576d, 0x5c127ca1],
1542 [0x1c49148f, 0x6d9e7045, 0x093f0b7c, 0x42c2ebaa],
1543 [0x4b4c2863, 0x95709d8c, 0xeb72e251, 0x096632dc],
1544 [0x727418e5, 0x2c015383, 0x59580212, 0x0302dd99],
1545 [0xbe57dfa4, 0xf2aa7d70, 0xa068ee62, 0x77372861],
1546 [0x2faef43a, 0x73da6654, 0xb9d9c22e, 0xc59520bc],
1547 [0x138cff40, 0x3e6c108a, 0xa981e654, 0x903da85b],
1548 [0xa90454f5, 0x7875d5db, 0xbab234bd, 0xe6ce1193]]));
1551 // mostly static music video downloaded with youtube-dl
1553 fn test_h264_real1() {
1554 let mut dmx_reg = RegisteredDemuxers::new();
1555 dmx_reg.add_demuxer(&RawH264DemuxerCreator{});
1556 generic_register_all_demuxers(&mut dmx_reg);
1557 let mut dec_reg = RegisteredDecoders::new();
1558 itu_register_all_decoders(&mut dec_reg);
1560 test_decoding("mov", "h264", "assets/ITU/1.mp4",
1561 Some(60), &dmx_reg, &dec_reg,
1562 ExpectedTestResult::MD5Frames(vec![
1563 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
1564 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
1565 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
1566 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
1567 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
1568 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
1569 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
1570 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
1571 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
1572 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
1573 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
1574 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
1575 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
1576 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
1577 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
1578 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
1579 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
1580 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
1581 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
1582 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
1583 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
1584 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
1585 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
1586 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
1587 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
1588 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
1589 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
1590 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
1591 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
1592 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
1593 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
1594 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
1595 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
1596 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
1597 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
1598 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
1599 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
1600 [0xf1c88c12, 0x7da871f5, 0xdaf3153f, 0x66e72d72],
1601 [0x3d4765f1, 0x8ac472f6, 0x7ffd13a6, 0xc7a45dae],
1602 [0x60e5e13a, 0xd2d7f239, 0x1a793d71, 0x19f8c190],
1603 [0xdd80c3e4, 0xb1500149, 0x43925280, 0x9e5f3230],
1604 [0x2adf6e64, 0x39012d45, 0x7a776cb5, 0x3df76e84],
1605 [0x44319007, 0xbc837dd2, 0x486b2703, 0x451d0651],
1606 [0x922386ef, 0xaf101e9b, 0xf2094a40, 0xc8c454c0],
1607 [0x0d81e398, 0x04192a56, 0xa31f39d0, 0x5e0a2deb],
1608 [0xcdd144b3, 0xd1c7743e, 0x5753b0f4, 0xc070efa9],
1609 [0xe1c67e39, 0x6065ddaf, 0x576bf9f1, 0x8e6825aa],
1610 [0xaf817b0d, 0xdc6c345a, 0xf7f289c7, 0x6cc482d8],
1611 [0x81dc4bcb, 0xee4fc5e5, 0x9b87c7ef, 0xdd0fb034],
1612 [0x8b07f523, 0x4168799f, 0x990cb270, 0x858b9f2c],
1613 [0x31855a80, 0xadbcc562, 0xe60628be, 0x5f04be09],
1614 [0x9c614acc, 0xbd08a3f4, 0x91b02c45, 0x41899a83],
1615 [0x89d09064, 0xbff810a3, 0x9c674179, 0x305225a6],
1616 [0xba1fc8d3, 0x15d34fae, 0x565d363b, 0x4f4d0604],
1617 [0x1cb15a1b, 0xa0be111e, 0x45cc801f, 0x01a2c691],
1618 [0xd898be48, 0xd19bf58d, 0xe22fe44f, 0x6a2914fb],
1619 [0xec6712af, 0xa13b55c0, 0x2915a746, 0xb29a5c48],
1620 [0x745798fa, 0x4ef0f882, 0x59335c08, 0xb1d9dbb4],
1621 [0x4045b495, 0xdb3d969c, 0x1f0d9220, 0x5a34067b],
1622 [0x94fee093, 0x78ad89b3, 0xf20e882b, 0x941425db],
1623 [0xc3eb1a78, 0x4b4e098a, 0xcbcf9bb4, 0xfd5b5426]]));
1625 // a sample downloaded from gfycat.com
1627 fn test_h264_real2() {
1628 let mut dmx_reg = RegisteredDemuxers::new();
1629 dmx_reg.add_demuxer(&RawH264DemuxerCreator{});
1630 generic_register_all_demuxers(&mut dmx_reg);
1631 let mut dec_reg = RegisteredDecoders::new();
1632 itu_register_all_decoders(&mut dec_reg);
1633 test_decoding("mov", "h264", "assets/ITU/DimpledSpanishCuckoo-mobile.mp4",
1634 Some(10), &dmx_reg, &dec_reg,
1635 ExpectedTestResult::MD5Frames(vec![
1636 [0x1addcb8e, 0xde58b857, 0x17222c32, 0x75455fa8],
1637 [0xae63141a, 0x79435b2e, 0xfe606c48, 0xf676da66],
1638 [0xfdb80404, 0x6a288e23, 0x45cc4106, 0xdd5eb57c],
1639 [0xd603a3ff, 0x872dcb9b, 0x43f7a71c, 0x2ad4eecc],
1640 [0x639ed6a5, 0xbb1cfec6, 0x0ee5443a, 0x1694772a],
1641 [0xf8ef3f48, 0x152de238, 0xb1995f9a, 0xf82ad1d5],
1642 [0x604f6265, 0xb9d82f56, 0x21f00cf4, 0xc69c18a7],
1643 [0xd932c16e, 0x25cbf060, 0xcb66543b, 0xfe8a5019],
1644 [0xf2a3dac0, 0x0f4678dd, 0xf64c8228, 0x47f14676],
1645 [0x267041ee, 0x3b6b8b64, 0x8bfe1697, 0x1fba508b],
1646 [0x9f917e72, 0x75d882a9, 0xa5e3e684, 0x4ed87eff]]));
1650 pub const I4X4_SCAN: [(u8, u8); 16] = [
1651 (0,0), (1,0), (0,1), (1,1), (2,0), (3,0), (2,1), (3,1),
1652 (0,2), (1,2), (0,3), (1,3), (2,2), (3,2), (2,3), (3,3)