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)?;
401 if !self.deblock_skip && self.deblock_mode != 1 {
402 if let Some(ref mut pic) = self.cur_pic {
403 let mut frm = NASimpleVideoFrame::from_video_buf(&mut pic.buf).unwrap();
404 if self.sstate.mb_x != 0 {
405 loop_filter_row(&mut frm, &self.sstate, self.lf_alpha, self.lf_beta);
407 loop_filter_last(&mut frm, &self.sstate, self.lf_alpha, self.lf_beta);
411 2 => { // slice data partition A
413 //slice id = read_ue()
414 //cat 2 slice data (all but MB layer residual)
415 return Err(DecoderError::NotImplemented);
417 3 => { // slice data partition B
418 //slice id = read_ue()
419 //if pps.redundant_pic_cnt_present { redundant_pic_cnt = read_ue() }
420 //cat 3 slice data (MB layer residual)
421 return Err(DecoderError::NotImplemented);
423 4 => { // slice data partition C
424 //slice id = read_ue()
425 //if pps.redundant_pic_cnt_present { redundant_pic_cnt = read_ue() }
426 //cat 4 slice data (MB layer residual)
427 return Err(DecoderError::NotImplemented);
431 let sps = parse_sps(&src[1..])?;
435 validate!(full_size >= 8 + 16);
436 let pps = parse_pps(&src[1..], &self.sps, full_size - 8)?;
437 let mut found = false;
438 for stored_pps in self.pps.iter_mut() {
439 if stored_pps.pic_parameter_set_id == pps.pic_parameter_set_id {
440 *stored_pps = pps.clone();
449 9 => { // access unit delimiter
451 10 => {}, //end of sequence
452 11 => {}, //end of stream
459 fn pred_intra(frm: &mut NASimpleVideoFrame<u8>, sstate: &SliceState, mb_info: &CurrentMBInfo) {
460 let yoff = frm.offset[0] + sstate.mb_x * 16 + sstate.mb_y * 16 * frm.stride[0];
461 match mb_info.mb_type {
462 MBType::Intra16x16(imode, _, _) => {
463 let id = if imode != 2 || (sstate.has_top && sstate.has_left) {
465 } else if !sstate.has_top && !sstate.has_left {
467 } else if !sstate.has_left {
472 IPRED_FUNCS16X16[id](frm.data, yoff, frm.stride[0]);
474 MBType::Intra8x8 => {
475 let mut ictx = IPred8Context::new();
477 let x = (part & 1) * 2;
479 let blk4 = x + y * 4;
481 let cur_yoff = yoff + x * 4 + y * 4 * frm.stride[0];
482 let has_top = y > 0 || sstate.has_top;
483 let has_left = x > 0 || sstate.has_left;
484 let imode = mb_info.ipred[blk4];
485 let id = if imode != IntraPredMode::DC || (has_top && has_left) {
486 let im_id: u8 = imode.into();
488 } else if !has_top && !has_left {
490 } else if !has_left {
495 let mb_idx = sstate.mb_x + sstate.mb_y * sstate.mb_w;
496 let noright = (y == 2 || sstate.mb_x == sstate.mb_w - 1 || mb_idx < sstate.mb_start + sstate.mb_w) && (x == 2);
497 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);
498 if id != IPRED4_DC128 {
499 ictx.fill(frm.data, cur_yoff, frm.stride[0], has_top, has_top && !noright, has_left, has_tl);
501 IPRED_FUNCS8X8_LUMA[id](&mut frm.data[cur_yoff..], frm.stride[0], &ictx);
502 if mb_info.coded[blk4] {
503 add_coeffs8(frm.data, cur_yoff, frm.stride[0], &mb_info.coeffs8x8[part].coeffs);
507 MBType::Intra4x4 => {
508 for &(x,y) in I4X4_SCAN.iter() {
511 let cur_yoff = yoff + x * 4 + y * 4 * frm.stride[0];
512 let has_top = y > 0 || sstate.has_top;
513 let has_left = x > 0 || sstate.has_left;
514 let imode = mb_info.ipred[x + y * 4];
515 let id = if imode != IntraPredMode::DC || (has_top && has_left) {
516 let im_id: u8 = imode.into();
518 } else if !has_top && !has_left {
520 } else if !has_left {
525 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);
526 let tr: [u8; 4] = if y == 0 {
527 if has_top && !noright {
528 let i = cur_yoff - frm.stride[0];
529 [frm.data[i + 4], frm.data[i + 5], frm.data[i + 6], frm.data[i + 7]]
531 let i = cur_yoff - frm.stride[0];
532 [frm.data[i + 3], frm.data[i + 3], frm.data[i + 3], frm.data[i + 3]]
536 } else if (x & 1) == 0 || (x == 1 && y == 2) {
537 let i = cur_yoff - frm.stride[0];
538 [frm.data[i + 4], frm.data[i + 5], frm.data[i + 6], frm.data[i + 7]]
540 let i = cur_yoff - frm.stride[0];
541 [frm.data[i + 3], frm.data[i + 3], frm.data[i + 3], frm.data[i + 3]]
543 IPRED_FUNCS4X4[id](frm.data, cur_yoff, frm.stride[0], &tr);
544 if mb_info.coded[x + y * 4] {
545 add_coeffs(frm.data, cur_yoff, frm.stride[0], &mb_info.coeffs[x + y * 4]);
551 let id = if mb_info.chroma_ipred != 0 || (sstate.has_top && sstate.has_left) {
552 mb_info.chroma_ipred as usize
553 } else if !sstate.has_top && !sstate.has_left {
555 } else if !sstate.has_left {
561 let off = frm.offset[chroma] + sstate.mb_x * 8 + sstate.mb_y * 8 * frm.stride[chroma];
562 IPRED_FUNCS8X8_CHROMA[id](frm.data, off, frm.stride[chroma]);
565 fn add_luma(frm: &mut NASimpleVideoFrame<u8>, sstate: &SliceState, mb_info: &CurrentMBInfo) {
566 let mut yoff = frm.offset[0] + sstate.mb_x * 16 + sstate.mb_y * 16 * frm.stride[0];
567 if !mb_info.transform_size_8x8 {
570 if mb_info.coded[x + y * 4] {
571 add_coeffs(frm.data, yoff + x * 4, frm.stride[0], &mb_info.coeffs[x + y * 4]);
574 yoff += frm.stride[0] * 4;
579 if mb_info.coded[x * 2 + y * 2 * 4] {
580 add_coeffs8(frm.data, yoff + x * 8, frm.stride[0], &mb_info.coeffs8x8[x + y * 2].coeffs);
583 yoff += frm.stride[0] * 8;
587 fn add_chroma(frm: &mut NASimpleVideoFrame<u8>, sstate: &SliceState, mb_info: &CurrentMBInfo) {
589 let mut off = frm.offset[chroma] + sstate.mb_x * 8 + sstate.mb_y * 8 * frm.stride[chroma];
592 let blk_no = 16 + (chroma - 1) * 4 + x + y * 2;
593 if mb_info.coded[blk_no] || mb_info.coeffs[blk_no][0] != 0 {
594 add_coeffs(frm.data, off + x * 4, frm.stride[chroma], &mb_info.coeffs[blk_no]);
597 off += frm.stride[chroma] * 4;
601 fn pred_mv(sstate: &mut SliceState, frame_refs: &FrameRefs, mb_info: &mut CurrentMBInfo, cur_id: u16, temporal_mv: bool) {
602 let mb_type = mb_info.mb_type;
603 if !mb_type.is_4x4() {
604 let (pw, ph) = mb_type.size();
607 if mb_type == MBType::Direct || mb_type == MBType::BSkip {
608 sstate.predict_direct_mb(frame_refs, temporal_mv, cur_id);
610 for part in 0..mb_type.num_parts() {
611 if !mb_type.is_l1(part) {
613 MBType::PSkip => sstate.predict_pskip(),
614 MBType::BSkip | MBType::Direct => {
617 sstate.predict(xoff, yoff, pw, ph, 0,
618 mb_info.mv_l0[part], mb_info.ref_l0[part]);
622 if !mb_type.is_l0(part) && mb_type != MBType::BSkip && mb_type != MBType::Direct {
623 sstate.predict(xoff, yoff, pw, ph, 1, mb_info.mv_l1[part], mb_info.ref_l1[part]);
633 let sub_type = mb_info.sub_mb_type[part];
634 let mut xoff = (part & 1) * 8;
635 let mut yoff = (part & 2) * 4;
637 let (pw, ph) = sub_type.size();
638 for subpart in 0..sub_type.num_parts() {
639 if sub_type != SubMBType::Direct8x8 {
640 if !sub_type.is_l1() {
641 sstate.predict(xoff, yoff, pw, ph, 0, mb_info.mv_l0[part * 4 + subpart], mb_info.ref_l0[part]);
643 if !sub_type.is_l0() {
644 sstate.predict(xoff, yoff, pw, ph, 1, mb_info.mv_l1[part * 4 + subpart], mb_info.ref_l1[part]);
648 sstate.predict_direct_sub(frame_refs, temporal_mv, cur_id, (xoff / 4) + (sblk & 1) + (yoff / 4) * 4 + (sblk & 2) * 2);
652 if xoff == orig_x + 8 {
660 #[allow(clippy::cyclomatic_complexity)]
661 fn handle_macroblock(&mut self, mb_info: &mut CurrentMBInfo) {
662 let pps = &self.pps[self.cur_pps];
664 let qp_y = mb_info.qp_y;
665 let qpr = ((qp_y as i8) + pps.chroma_qp_index_offset).max(0).min(51) as usize;
666 let qp_u = CHROMA_QUANTS[qpr];
667 let qpb = ((qp_y as i8) + pps.second_chroma_qp_index_offset).max(0).min(51) as usize;
668 let qp_v = CHROMA_QUANTS[qpb];
670 let tx_bypass = qp_y == 0 && self.sps[self.cur_sps].qpprime_y_zero_transform_bypass;
672 self.sstate.get_cur_mb().mb_type = mb_info.mb_type.into();
673 if mb_info.mb_type != MBType::PCM {
674 self.sstate.get_cur_mb().qp_y = qp_y;
675 self.sstate.get_cur_mb().qp_u = qp_u;
676 self.sstate.get_cur_mb().qp_v = qp_v;
677 self.sstate.get_cur_mb().transform_8x8 = mb_info.transform_size_8x8;
679 let has_dc = mb_info.mb_type.is_intra16x16() && mb_info.coded[24];
681 idct_luma_dc(&mut mb_info.coeffs[24], qp_y);
683 mb_info.coeffs[i][0] = mb_info.coeffs[24][i];
686 if !mb_info.transform_size_8x8 {
687 let quant_dc = !mb_info.mb_type.is_intra16x16();
689 if mb_info.coded[i] {
691 idct(&mut mb_info.coeffs[i], qp_y, quant_dc);
695 idct_dc(&mut mb_info.coeffs[i], qp_y, quant_dc);
697 mb_info.coded[i] = true;
702 if mb_info.coded[(i & 1) * 2 + (i & 2) * 4] && !tx_bypass {
703 dequant8x8(&mut mb_info.coeffs8x8[i].coeffs, &pps.scaling_list_8x8[!mb_info.mb_type.is_intra() as usize]);
704 idct8x8(&mut mb_info.coeffs8x8[i].coeffs, qp_y);
709 let qp_c = if chroma == 0 { qp_u } else { qp_v };
710 if mb_info.cbpc != 0 {
711 chroma_dc_transform(&mut mb_info.chroma_dc[chroma], qp_c);
714 let blk_no = 16 + chroma * 4 + i;
715 mb_info.coeffs[blk_no][0] = mb_info.chroma_dc[chroma][i];
716 if mb_info.coded[blk_no] {
717 idct(&mut mb_info.coeffs[blk_no], qp_c, false);
718 } else if mb_info.coeffs[blk_no][0] != 0 {
719 idct_dc(&mut mb_info.coeffs[blk_no], qp_c, false);
720 mb_info.coded[blk_no] = true;
724 if !pps.entropy_coding_mode || mb_info.mb_type.is_skip() || mb_info.mb_type.is_intra() {
725 self.sstate.reset_mb_mv();
727 if !mb_info.mb_type.is_intra() {
728 Self::pred_mv(&mut self.sstate, &self.frame_refs, mb_info, self.cur_id, self.temporal_mv);
730 if !pps.constrained_intra_pred && mb_info.mb_type != MBType::Intra4x4 && mb_info.mb_type != MBType::Intra8x8 {
731 self.sstate.fill_ipred(IntraPredMode::DC);
734 let xpos = self.sstate.mb_x * 16;
735 let ypos = self.sstate.mb_y * 16;
736 if let Some(ref mut pic) = self.cur_pic {
737 let mut frm = NASimpleVideoFrame::from_video_buf(&mut pic.buf).unwrap();
738 match mb_info.mb_type {
739 MBType::Intra16x16(_, _, _) => {
740 Self::pred_intra(&mut frm, &self.sstate, &mb_info);
742 MBType::Intra4x4 | MBType::Intra8x8 => {
743 Self::pred_intra(&mut frm, &self.sstate, &mb_info);
747 let mv = self.sstate.get_cur_blk4(0).mv[0];
748 let rpic = self.frame_refs.select_ref_pic(0, 0);
749 Self::do_p_mc(&mut frm, xpos, ypos, 16, 16, mv, rpic);
752 let mv = self.sstate.get_cur_blk4(0).mv[0];
753 let rpic = self.frame_refs.select_ref_pic(0, mb_info.ref_l0[0].index());
754 Self::do_p_mc(&mut frm, xpos, ypos, 16, 16, mv, rpic);
756 MBType::P16x8 | MBType::P8x16 => {
757 let (bw, bh, bx, by) = if mb_info.mb_type == MBType::P16x8 {
762 let mv = self.sstate.get_cur_blk4(0).mv[0];
763 let rpic = self.frame_refs.select_ref_pic(0, mb_info.ref_l0[0].index());
764 Self::do_p_mc(&mut frm, xpos, ypos, bw, bh, mv, rpic);
765 let mv = self.sstate.get_cur_blk4(bx / 4 + by).mv[0];
766 let rpic = self.frame_refs.select_ref_pic(0, mb_info.ref_l0[1].index());
767 Self::do_p_mc(&mut frm, xpos + bx, ypos + by, bw, bh, mv, rpic);
769 MBType::P8x8 | MBType::P8x8Ref0 => {
771 let bx = (part & 1) * 8;
772 let by = (part & 2) * 4;
773 if let Some(buf) = self.frame_refs.select_ref_pic(0, mb_info.ref_l0[part].index()) {
774 let mv = self.sstate.get_cur_blk4(bx / 4 + by).mv[0];
776 match mb_info.sub_mb_type[part] {
778 do_mc(&mut frm, buf, xpos + bx, ypos + by, 8, 8, mv);
781 do_mc(&mut frm, buf.clone(), xpos + bx, ypos + by, 8, 4, mv);
782 let mv = self.sstate.get_cur_blk4(bx / 4 + by + 4).mv[0];
783 do_mc(&mut frm, buf, xpos + bx, ypos + by + 4, 8, 4, mv);
786 do_mc(&mut frm, buf.clone(), xpos + bx, ypos + by, 4, 8, mv);
787 let mv = self.sstate.get_cur_blk4(bx / 4 + by + 1).mv[0];
788 do_mc(&mut frm, buf, xpos + bx + 4, ypos + by, 4, 8, mv);
792 let sxpos = xpos + bx + (sb_no & 1) * 4;
793 let sypos = ypos + by + (sb_no & 2) * 2;
794 let sblk_no = (bx / 4 + (sb_no & 1)) + ((by / 4) + (sb_no >> 1)) * 4;
795 let mv = self.sstate.get_cur_blk4(sblk_no).mv[0];
796 do_mc(&mut frm, buf.clone(), sxpos, sypos, 4, 4, mv);
802 gray_block(&mut frm, xpos + bx, ypos + by, 8, 8);
806 MBType::B16x16(mode) => {
807 let mv0 = self.sstate.get_cur_blk4(0).mv[0];
808 let rpic0 = self.frame_refs.select_ref_pic(0, mb_info.ref_l0[0].index());
809 let mv1 = self.sstate.get_cur_blk4(0).mv[1];
810 let rpic1 = self.frame_refs.select_ref_pic(1, mb_info.ref_l1[0].index());
811 Self::do_b_mc(&mut frm, mode, xpos, ypos, 16, 16, mv0, rpic0, mv1, rpic1, &mut self.avg_buf);
813 MBType::B16x8(mode0, mode1) | MBType::B8x16(mode0, mode1) => {
814 let (pw, ph) = mb_info.mb_type.size();
815 let (px, py) = (pw & 8, ph & 8);
816 let modes = [mode0, mode1];
817 let (mut bx, mut by) = (0, 0);
819 let blk = if part == 0 { 0 } else { (px / 4) + py };
820 let mv0 = self.sstate.get_cur_blk4(blk).mv[0];
821 let rpic0 = self.frame_refs.select_ref_pic(0, mb_info.ref_l0[part].index());
822 let mv1 = self.sstate.get_cur_blk4(blk).mv[1];
823 let rpic1 = self.frame_refs.select_ref_pic(1, mb_info.ref_l1[part].index());
824 Self::do_b_mc(&mut frm, modes[part], xpos + bx, ypos + by, pw, ph, mv0, rpic0, mv1, rpic1, &mut self.avg_buf);
829 MBType::Direct | MBType::BSkip => {
830 let is_16x16 = self.frame_refs.get_colocated_info(self.sstate.mb_x, self.sstate.mb_y).0.mb_type.is_16x16();
831 if is_16x16 || !self.temporal_mv {
832 let mv = self.sstate.get_cur_blk4(0).mv;
833 let ref_idx = self.sstate.get_cur_blk8(0).ref_idx;
834 let rpic0 = self.frame_refs.select_ref_pic(0, ref_idx[0].index());
835 let rpic1 = self.frame_refs.select_ref_pic(1, ref_idx[1].index());
836 Self::do_b_mc(&mut frm, BMode::Bi, xpos, ypos, 16, 16, mv[0], rpic0, mv[1], rpic1, &mut self.avg_buf);
839 let mv = self.sstate.get_cur_blk4(blk4).mv;
840 let ref_idx = self.sstate.get_cur_blk8(blk4_to_blk8(blk4)).ref_idx;
841 let rpic0 = self.frame_refs.select_ref_pic(0, ref_idx[0].index());
842 let rpic1 = self.frame_refs.select_ref_pic(1, ref_idx[1].index());
843 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);
846 self.sstate.apply_to_blk8(|blk8| { blk8.ref_idx[0].set_direct(); blk8.ref_idx[1].set_direct(); });
850 let ridx = self.sstate.get_cur_blk8(part).ref_idx;
851 let rpic0 = self.frame_refs.select_ref_pic(0, ridx[0].index());
852 let rpic1 = self.frame_refs.select_ref_pic(1, ridx[1].index());
853 let subtype = mb_info.sub_mb_type[part];
854 let blk8 = (part & 1) * 2 + (part & 2) * 4;
855 let mut bx = (part & 1) * 8;
856 let mut by = (part & 2) * 4;
858 SubMBType::Direct8x8 => {
860 let mv = self.sstate.get_cur_blk4(bx / 4 + (by / 4) * 4).mv;
861 let ref_idx = self.sstate.get_cur_blk8(bx / 8 + (by / 8) * 2).ref_idx;
862 let rpic0 = self.frame_refs.select_ref_pic(0, ref_idx[0].index());
863 let rpic1 = self.frame_refs.select_ref_pic(1, ref_idx[1].index());
864 Self::do_b_mc(&mut frm, BMode::Bi, xpos + bx, ypos + by, 4, 4, mv[0], rpic0, mv[1], rpic1, &mut self.avg_buf);
871 self.sstate.get_cur_blk8(part).ref_idx[0].set_direct();
872 self.sstate.get_cur_blk8(part).ref_idx[1].set_direct();
874 SubMBType::B8x8(mode) => {
875 let mv = self.sstate.get_cur_blk4(blk8).mv;
876 Self::do_b_mc(&mut frm, mode, xpos + bx, ypos + by, 8, 8, mv[0], rpic0, mv[1], rpic1, &mut self.avg_buf);
878 SubMBType::B8x4(mode) | SubMBType::B4x8(mode) => {
879 let (pw, ph) = subtype.size();
880 let mv = self.sstate.get_cur_blk4(blk8).mv;
881 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);
882 let addr2 = blk8 + (pw & 4) / 4 + (ph & 4);
883 let mv = self.sstate.get_cur_blk4(addr2).mv;
884 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);
886 SubMBType::B4x4(mode) => {
888 let addr2 = blk8 + (i & 1) + (i & 2) * 2;
889 let mv = self.sstate.get_cur_blk4(addr2).mv;
890 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);
903 if mb_info.mb_type == MBType::PCM {
904 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)) {
905 dline[..16].copy_from_slice(src);
907 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)) {
908 dline[..8].copy_from_slice(src);
910 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)) {
911 dline[..8].copy_from_slice(src);
913 } else if !mb_info.mb_type.is_skip() {
914 if mb_info.mb_type != MBType::Intra4x4 && mb_info.mb_type != MBType::Intra8x8 {
915 Self::add_luma(&mut frm, &self.sstate, &mb_info);
917 Self::add_chroma(&mut frm, &self.sstate, &mb_info);
919 /*match mb_info.mb_type {
920 MBType::BSkip | MBType::Direct | MBType::B16x16(_) | MBType::B16x8(_, _) | MBType::B8x16(_, _) | MBType::B8x8 => {
921 let dstride = frm.stride[0];
922 let dst = &mut frm.data[frm.offset[0] + self.sstate.mb_x * 16 + self.sstate.mb_y * 16 * dstride..];
923 for el in dst[..16].iter_mut() { *el = 255; }
924 for row in dst.chunks_mut(dstride).skip(1).take(15) {
931 if let Some(ref mut pic) = self.cur_pic {
932 let mv_info = &mut pic.mv_info;
933 let mb_pos = self.sstate.mb_x + self.sstate.mb_y * mv_info.mb_stride;
934 let mut mb = FrameMBInfo::new();
935 mb.mb_type = mb_info.mb_type.into();
937 mb.mv[blk4] = self.sstate.get_cur_blk4(blk4).mv;
940 mb.ref_poc[blk8] = self.frame_refs.map_refs(self.sstate.get_cur_blk8(blk8).ref_idx);
941 mb.ref_idx[blk8] = self.sstate.get_cur_blk8(blk8).ref_idx;
943 mv_info.mbs[mb_pos] = mb;
945 self.sstate.fill_deblock(self.deblock_mode, self.is_s);
946 if !self.deblock_skip && self.sstate.mb_x + 1 == self.sstate.mb_w && self.deblock_mode != 1 {
947 if let Some(ref mut pic) = self.cur_pic {
948 let mut frm = NASimpleVideoFrame::from_video_buf(&mut pic.buf).unwrap();
949 loop_filter_row(&mut frm, &self.sstate, self.lf_alpha, self.lf_beta);
952 self.sstate.next_mb();
954 fn do_p_mc(frm: &mut NASimpleVideoFrame<u8>, xpos: usize, ypos: usize, w: usize, h: usize, mv: MV, ref_pic: Option<NAVideoBufferRef<u8>>) {
955 if let Some(buf) = ref_pic {
956 do_mc(frm, buf, xpos, ypos, w, h, mv);
958 gray_block(frm, xpos, ypos, w, h);
961 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>) {
964 if let Some(buf) = ref_pic0 {
965 do_mc(frm, buf, xpos, ypos, w, h, mv0);
967 gray_block(frm, xpos, ypos, w, h);
971 if let Some(buf) = ref_pic1 {
972 do_mc(frm, buf, xpos, ypos, w, h, mv1);
974 gray_block(frm, xpos, ypos, w, h);
978 match (ref_pic0, ref_pic1) {
979 (Some(buf0), Some(buf1)) => {
980 do_mc(frm, buf0, xpos, ypos, w, h, mv0);
981 do_mc_avg(frm, buf1, xpos, ypos, w, h, mv1, avg_buf);
983 (Some(buf0), None) => {
984 do_mc(frm, buf0, xpos, ypos, w, h, mv0);
986 (None, Some(buf1)) => {
987 do_mc(frm, buf1, xpos, ypos, w, h, mv1);
990 gray_block(frm, xpos, ypos, w, h);
996 fn decode_slice_cavlc(&mut self, br: &mut BitReader, slice_hdr: &SliceHeader, full_size: usize) -> DecoderResult<bool> {
997 const INTRA_CBP: [u8; 48] = [
998 47, 31, 15, 0, 23, 27, 29, 30, 7, 11, 13, 14, 39, 43, 45, 46,
999 16, 3, 5, 10, 12, 19, 21, 26, 28, 35, 37, 42, 44, 1, 2, 4,
1000 8, 17, 18, 20, 24, 6, 9, 22, 25, 32, 33, 34, 36, 40, 38, 41
1002 const INTER_CBP: [u8; 48] = [
1003 0, 16, 1, 2, 4, 8, 32, 3, 5, 10, 12, 15, 47, 7, 11, 13,
1004 14, 6, 9, 31, 35, 37, 42, 44, 33, 34, 36, 40, 39, 43, 45, 46,
1005 17, 18, 20, 24, 19, 21, 26, 28, 23, 27, 29, 30, 22, 25, 38, 41
1008 let mut mb_idx = slice_hdr.first_mb_in_slice as usize;
1009 let mut mb_info = CurrentMBInfo::default();
1010 mb_info.qp_y = slice_hdr.slice_qp;
1011 let skip_type = if slice_hdr.slice_type.is_p() { MBType::PSkip } else { MBType::BSkip };
1012 while br.tell() < full_size && mb_idx < self.num_mbs {
1013 mb_info.coded = [false; 25];
1014 mb_info.ref_l0 = [ZERO_REF; 4];
1015 mb_info.ref_l1 = [ZERO_REF; 4];
1016 mb_info.mv_l0 = [ZERO_MV; 16];
1017 mb_info.mv_l1 = [ZERO_MV; 16];
1018 mb_info.chroma_dc = [[0; 4]; 2];
1022 if !slice_hdr.slice_type.is_intra() {
1023 let mb_skip_run = br.read_ue()? as usize;
1024 validate!(mb_idx + mb_skip_run <= self.num_mbs);
1025 mb_info.mb_type = skip_type;
1026 for _ in 0..mb_skip_run {
1027 self.handle_macroblock(&mut mb_info);
1030 if mb_idx == self.num_mbs || br.tell() >= full_size {
1034 if br.tell() < full_size {
1035 if self.is_mbaff && ((mb_idx & 1) == 0) {
1036 let _mb_field_decoding = br.read_bool()?;
1038 let mut mb_type = decode_mb_type_cavlc(br, slice_hdr)?;
1039 mb_info.mb_type = mb_type;
1040 mb_info.transform_size_8x8 = false;
1041 if mb_type == MBType::PCM {
1043 for pix in self.ipcm_buf[..256 + 64 + 64].iter_mut() {
1044 *pix = br.read(8)? as u8;
1046 self.sstate.fill_ncoded(16);
1048 if self.transform_8x8_mode && mb_type == MBType::Intra4x4 {
1049 mb_info.transform_size_8x8 = br.read_bool()?;
1050 if mb_info.transform_size_8x8 {
1051 mb_type = MBType::Intra8x8;
1052 mb_info.mb_type = MBType::Intra8x8;
1055 decode_mb_pred_cavlc(br, slice_hdr, mb_type, &mut self.sstate, &mut mb_info)?;
1056 let (cbpy, cbpc) = if let MBType::Intra16x16(_, cbpy, cbpc) = mb_type {
1059 let cbp_id = br.read_ue()? as usize;
1060 validate!(cbp_id < INTRA_CBP.len());
1061 let cbp = if mb_type == MBType::Intra4x4 || mb_type == MBType::Intra8x8 {
1066 if self.transform_8x8_mode && (cbp & 0xF) != 0 && mb_info.can_have_8x8_tx(self.sps[self.cur_sps].direct_8x8_inference) {
1067 mb_info.transform_size_8x8 = br.read_bool()?;
1069 ((cbp & 0xF), (cbp >> 4))
1071 mb_info.cbpy = cbpy;
1072 mb_info.cbpc = cbpc;
1073 self.sstate.get_cur_mb().cbp = (cbpc << 4) | cbpy;
1074 if cbpy != 0 || cbpc != 0 || mb_type.is_intra16x16() {
1075 let mb_qp_delta = br.read_se()?;
1076 validate!(mb_qp_delta >= -26 && mb_qp_delta <= 25);
1077 let new_qp = mb_qp_delta + i32::from(mb_info.qp_y);
1078 mb_info.qp_y = if new_qp < 0 {
1080 } else if new_qp >= 52 {
1085 mb_info.coeffs = [[0; 16]; 25];
1086 if self.transform_8x8_mode {
1087 mb_info.clear_coeffs8x8();
1089 mb_info.chroma_dc = [[0; 4]; 2];
1090 decode_residual_cavlc(br, &mut self.sstate, &mut mb_info, &self.cavlc_cb)?;
1093 self.handle_macroblock(&mut mb_info);
1097 if let Some(ref mut pic) = self.cur_pic {
1098 pic.cur_mb = mb_idx;
1100 Ok(mb_idx == self.num_mbs)
1102 fn decode_slice_cabac(&mut self, cabac: &mut CABAC, slice_hdr: &SliceHeader) -> DecoderResult<bool> {
1103 let mut mb_idx = slice_hdr.first_mb_in_slice as usize;
1104 let mut prev_mb_skipped = false;
1105 let skip_type = if slice_hdr.slice_type.is_p() { MBType::PSkip } else { MBType::BSkip };
1106 let mut last_qp_diff = false;
1108 let mut mb_info = CurrentMBInfo::default();
1109 mb_info.qp_y = slice_hdr.slice_qp;
1111 while mb_idx < self.num_mbs {
1112 mb_info.coded = [false; 25];
1113 mb_info.ref_l0 = [ZERO_REF; 4];
1114 mb_info.ref_l1 = [ZERO_REF; 4];
1115 mb_info.mv_l0 = [ZERO_MV; 16];
1116 mb_info.mv_l1 = [ZERO_MV; 16];
1117 mb_info.chroma_dc = [[0; 4]; 2];
1120 let mb_skip = cabac_decode_mbskip(cabac, &self.sstate, slice_hdr);
1122 if self.is_mbaff && (((mb_idx & 1) == 0) || (prev_mb_skipped && ((mb_idx & 1) == 1))) {
1123 let _mb_field_decoding = cabac.decode_bit(70);
1125 let mut mb_type = cabac_decode_mb_type(cabac, &slice_hdr, &self.sstate);
1126 mb_info.mb_type = mb_type;
1127 mb_info.transform_size_8x8 = false;
1128 if mb_type == MBType::PCM {
1129 let ipcm_size = 256 + 64 + 64;
1130 validate!(cabac.pos + ipcm_size <= cabac.src.len());
1131 self.ipcm_buf[..ipcm_size].copy_from_slice(&cabac.src[cabac.pos..][..ipcm_size]);
1132 cabac.pos += ipcm_size;
1134 last_qp_diff = false;
1136 if self.transform_8x8_mode && mb_type == MBType::Intra4x4 {
1138 if self.sstate.get_top_mb().transform_8x8 {
1141 if self.sstate.get_left_mb().transform_8x8 {
1144 mb_info.transform_size_8x8 = cabac.decode_bit(399 + ctx);
1145 if mb_info.transform_size_8x8 {
1146 mb_type = MBType::Intra8x8;
1147 mb_info.mb_type = MBType::Intra8x8;
1150 decode_mb_pred_cabac(cabac, slice_hdr, mb_type, &mut self.sstate, &mut mb_info);
1151 let (cbpy, cbpc) = if let MBType::Intra16x16(_, cbpy, cbpc) = mb_type {
1154 decode_cbp_cabac(cabac, &self.sstate)
1156 if self.transform_8x8_mode && cbpy != 0 && mb_info.can_have_8x8_tx(self.sps[self.cur_sps].direct_8x8_inference) {
1158 if self.sstate.get_top_mb().transform_8x8 {
1161 if self.sstate.get_left_mb().transform_8x8 {
1164 mb_info.transform_size_8x8 = cabac.decode_bit(399 + ctx);
1166 if mb_type.is_intra() {
1167 self.sstate.get_cur_mb().cmode = mb_info.chroma_ipred;
1169 mb_info.cbpy = cbpy;
1170 mb_info.cbpc = cbpc;
1171 self.sstate.get_cur_mb().cbp = (cbpc << 4) | cbpy;
1172 if cbpy != 0 || cbpc != 0 || mb_type.is_intra16x16() {
1173 let mb_qp_delta = decode_mb_qp_delta_cabac(cabac, last_qp_diff as usize);
1174 validate!(mb_qp_delta >= -26 && mb_qp_delta <= 25);
1175 last_qp_diff = mb_qp_delta != 0;
1176 let new_qp = mb_qp_delta + i32::from(mb_info.qp_y);
1177 mb_info.qp_y = if new_qp < 0 {
1179 } else if new_qp >= 52 {
1184 mb_info.coeffs = [[0; 16]; 25];
1185 if self.transform_8x8_mode {
1186 mb_info.clear_coeffs8x8();
1188 mb_info.chroma_dc = [[0; 4]; 2];
1189 decode_residual_cabac(cabac, &mut self.sstate, &mut mb_info);
1191 last_qp_diff = false;
1195 mb_info.mb_type = skip_type;
1196 mb_info.transform_size_8x8 = false;
1197 last_qp_diff = false;
1199 self.handle_macroblock(&mut mb_info);
1200 prev_mb_skipped = mb_skip;
1201 if !(self.is_mbaff && ((mb_idx & 1) == 0)) && cabac.decode_terminate() {
1202 if let Some(ref mut pic) = self.cur_pic {
1203 pic.cur_mb = mb_idx + 1;
1205 return Ok(mb_idx + 1 == self.num_mbs);
1209 Err(DecoderError::InvalidData)
1213 impl NADecoder for H264Decoder {
1214 fn init(&mut self, supp: &mut NADecoderSupport, info: NACodecInfoRef) -> DecoderResult<()> {
1215 if let NACodecTypeInfo::Video(vinfo) = info.get_properties() {
1216 let fmt = YUV420_FORMAT;
1217 let myinfo = NACodecTypeInfo::Video(NAVideoInfo::new(0, 0, false, fmt));
1218 self.info = NACodecInfo::new_ref(info.get_name(), myinfo, info.get_extradata()).into_ref();
1220 let edata = info.get_extradata().unwrap();
1221 //print!("edata:"); for &el in edata.iter() { print!(" {:02X}", el); } println!();
1222 if edata.len() > 11 && &edata[0..4] == b"avcC" {
1223 let mut mr = MemoryReader::new_read(edata.as_slice());
1224 let mut br = ByteReader::new(&mut mr);
1225 let mut nal_buf = Vec::new();
1228 let version = br.read_byte()?;
1229 validate!(version == 1);
1230 let profile = br.read_byte()?;
1231 let _compatibility = br.read_byte()?;
1232 let _level = br.read_byte()?;
1233 let b = br.read_byte()?;
1234 validate!((b & 0xFC) == 0xFC);
1235 self.nal_len = (b & 3) + 1;
1236 let b = br.read_byte()?;
1237 validate!((b & 0xE0) == 0xE0);
1238 let num_sps = (b & 0x1F) as usize;
1239 for _ in 0..num_sps {
1240 let len = br.read_u16be()? as usize;
1241 let offset = br.tell() as usize;
1242 validate!((br.peek_byte()? & 0x1F) == 7);
1243 let _size = unescape_nal(&edata[offset..][..len], &mut nal_buf);
1244 self.handle_nal(&nal_buf, supp, true)?;
1247 let num_pps = br.read_byte()? as usize;
1248 for _ in 0..num_pps {
1249 let len = br.read_u16be()? as usize;
1250 let offset = br.tell() as usize;
1251 validate!((br.peek_byte()? & 0x1F) == 8);
1252 let _size = unescape_nal(&edata[offset..][..len], &mut nal_buf);
1253 self.handle_nal(&nal_buf, supp, true)?;
1258 100 | 110 | 122 | 144 => {
1259 let b = br.read_byte()?;
1260 validate!((b & 0xFC) == 0xFC);
1261 // b & 3 -> chroma format
1262 let b = br.read_byte()?;
1263 validate!((b & 0xF8) == 0xF8);
1264 // b & 7 -> luma depth minus 8
1265 let b = br.read_byte()?;
1266 validate!((b & 0xF8) == 0xF8);
1267 // b & 7 -> chroma depth minus 8
1268 let num_spsext = br.read_byte()? as usize;
1269 for _ in 0..num_spsext {
1270 let len = br.read_u16be()? as usize;
1279 return Err(DecoderError::NotImplemented);
1282 self.width = vinfo.get_width();
1283 self.height = vinfo.get_height();
1285 if (self.width == 0 || self.height == 0) && !self.sps.is_empty() {
1286 self.width = self.sps[0].pic_width_in_mbs * 16;
1287 self.height = self.sps[0].pic_height_in_mbs * 16;
1290 let num_bufs = if !self.sps.is_empty() {
1291 self.sps[0].num_ref_frames as usize + 1
1295 supp.pool_u8.set_dec_bufs(num_bufs);
1296 supp.pool_u8.prealloc_video(NAVideoInfo::new(self.width, self.height, false, fmt), 4)?;
1301 Err(DecoderError::InvalidData)
1304 fn decode(&mut self, supp: &mut NADecoderSupport, pkt: &NAPacket) -> DecoderResult<NAFrameRef> {
1305 let src = pkt.get_buffer();
1307 let mut mr = MemoryReader::new_read(&src);
1308 let mut br = ByteReader::new(&mut mr);
1309 let mut nal_buf = Vec::with_capacity(src.len());
1310 if self.nal_len > 0 {
1311 let mut skip_decoding = false;
1312 if self.skip_mode != FrameSkipMode::None {
1313 let mut pic_type = FrameType::I;
1314 let mut is_ref = false;
1315 while br.left() > 0 {
1316 let size = match self.nal_len {
1317 1 => br.read_byte()? as usize,
1318 2 => br.read_u16be()? as usize,
1319 3 => br.read_u24be()? as usize,
1320 4 => br.read_u32be()? as usize,
1321 _ => unreachable!(),
1323 validate!(br.left() >= (size as i64));
1324 let offset = br.tell() as usize;
1325 let size = unescape_nal(&src[offset..][..size], &mut nal_buf);
1326 validate!(size > 0);
1327 let nal_ref_idc = nal_buf[0] >> 5;
1328 let nal_unit_type = nal_buf[0] & 0x1F;
1329 if nal_unit_type == 1 || nal_unit_type == 5 {
1330 let mut bitr = BitReader::new(&nal_buf[1..], BitReaderMode::BE);
1331 let (first_mb, slice_type) = parse_slice_header_minimal(&mut bitr)?;
1332 if first_mb == 0 && nal_ref_idc != 0 {
1335 let new_type = slice_type.to_frame_type();
1336 pic_type = match (pic_type, new_type) {
1337 (FrameType::I, _) => new_type,
1338 (_, FrameType::B) => FrameType::B,
1342 br.read_skip(size)?;
1344 match self.skip_mode {
1345 FrameSkipMode::IntraOnly => {
1346 skip_decoding = pic_type != FrameType::I;
1348 FrameSkipMode::KeyframesOnly => {
1350 skip_decoding = true;
1355 br.seek(SeekFrom::Start(0))?;
1357 while br.left() > 0 {
1358 let size = match self.nal_len {
1359 1 => br.read_byte()? as usize,
1360 2 => br.read_u16be()? as usize,
1361 3 => br.read_u24be()? as usize,
1362 4 => br.read_u32be()? as usize,
1363 _ => unreachable!(),
1365 validate!(br.left() >= (size as i64));
1366 let offset = br.tell() as usize;
1367 let _size = unescape_nal(&src[offset..][..size], &mut nal_buf);
1368 self.handle_nal(nal_buf.as_slice(), supp, skip_decoding)?;
1369 br.read_skip(size)?;
1372 //todo NAL detection
1376 let (bufinfo, ftype, dts) = if self.has_pic && self.cur_pic.is_some() {
1377 let mut npic = None;
1378 std::mem::swap(&mut self.cur_pic, &mut npic);
1379 let cpic = npic.unwrap();
1380 let ret = (NABufferType::Video(cpic.buf.clone()), cpic.pic_type, Some(u64::from(cpic.full_id)));
1382 self.frame_refs.add_short_term(cpic.clone(), self.sps[self.cur_sps].num_ref_frames);
1384 if let Some(lt_idx) = cpic.long_term {
1385 self.frame_refs.add_long_term(lt_idx, cpic);
1389 (NABufferType::None, FrameType::Skip, None)
1392 let mut frm = NAFrame::new_from_pkt(pkt, self.info.clone(), bufinfo);
1393 frm.set_keyframe(ftype == FrameType::I);
1394 if let (Some(mydts), None) = (dts, frm.get_dts()) {
1395 frm.set_dts(Some(mydts));
1397 if let Some(dts) = dts {
1398 frm.set_id(dts as i64);
1400 frm.set_frame_type(ftype);
1403 fn flush(&mut self) {
1407 const DEBLOCK_SKIP_OPTION: &str = "skip_deblock";
1409 const DECODER_OPTIONS: &[NAOptionDefinition] = &[
1410 NAOptionDefinition {
1411 name: FRAME_SKIP_OPTION, description: FRAME_SKIP_OPTION_DESC,
1412 opt_type: NAOptionDefinitionType::Bool },
1413 NAOptionDefinition {
1414 name: DEBLOCK_SKIP_OPTION, description: "Loop filter skipping mode",
1415 opt_type: NAOptionDefinitionType::String(Some(&[
1416 FRAME_SKIP_OPTION_VAL_NONE,
1417 FRAME_SKIP_OPTION_VAL_KEYFRAME,
1418 FRAME_SKIP_OPTION_VAL_INTRA
1422 impl NAOptionHandler for H264Decoder {
1423 fn get_supported_options(&self) -> &[NAOptionDefinition] { DECODER_OPTIONS }
1424 fn set_options(&mut self, options: &[NAOption]) {
1425 for option in options.iter() {
1426 for opt_def in DECODER_OPTIONS.iter() {
1427 if opt_def.check(option).is_ok() {
1428 match (option.name, &option.value) {
1429 (FRAME_SKIP_OPTION, NAValue::String(ref str)) => {
1430 if let Ok(smode) = FrameSkipMode::from_str(str) {
1431 self.skip_mode = smode;
1434 (DEBLOCK_SKIP_OPTION, NAValue::Bool(val)) => {
1435 self.deblock_skip = *val;
1443 fn query_option_value(&self, name: &str) -> Option<NAValue> {
1445 FRAME_SKIP_OPTION => Some(NAValue::String(self.skip_mode.to_string())),
1446 DEBLOCK_SKIP_OPTION => Some(NAValue::Bool(self.deblock_skip)),
1452 pub fn get_decoder() -> Box<dyn NADecoder + Send> {
1453 Box::new(H264Decoder::new())
1458 use nihav_core::codecs::RegisteredDecoders;
1459 use nihav_core::demuxers::RegisteredDemuxers;
1460 use nihav_codec_support::test::dec_video::*;
1461 use crate::itu_register_all_decoders;
1462 use nihav_commonfmt::generic_register_all_demuxers;
1466 use self::raw_demux::RawH264DemuxerCreator;
1469 fn test_h264_perframe() {
1470 let mut dmx_reg = RegisteredDemuxers::new();
1471 dmx_reg.add_demuxer(&RawH264DemuxerCreator{});
1472 generic_register_all_demuxers(&mut dmx_reg);
1473 let mut dec_reg = RegisteredDecoders::new();
1474 itu_register_all_decoders(&mut dec_reg);
1476 test_decoding("rawh264", "h264",
1477 "assets/ITU/h264-conformance/CABAST3_Sony_E.jsv",
1478 None, &dmx_reg, &dec_reg, ExpectedTestResult::MD5Frames(vec![
1479 [0x85fc4b44, 0xc9aefdc9, 0x568d0592, 0x2eccf9a0],
1480 [0xbd8d11bc, 0x97acf592, 0x45a3cdbb, 0xa254a882],
1481 [0xbda0e0b9, 0x9fbe1974, 0x1540b244, 0x46a050ca],
1482 [0x471f0057, 0x125ef3b4, 0x4a87515f, 0xba254bbb],
1483 [0x466a7df2, 0xb392c2a4, 0xed66b68b, 0xfdaad2da],
1484 [0x96334b41, 0x41bac7ef, 0xe87154f1, 0xa5fc3551],
1485 [0x0fd4e9b8, 0x4269bbec, 0x00a1978f, 0xe6224851],
1486 [0x68be82af, 0x856615a7, 0x387a253d, 0x8473e6b9],
1487 [0xc4bed119, 0x14ba7fe0, 0x447cb680, 0x555da4c5],
1488 [0x85d127d6, 0x04b85928, 0x26740281, 0x4d848db5],
1489 [0xe44fe461, 0x0d0b64ce, 0xf191179b, 0xabdab686],
1490 [0x347c8edb, 0x847ad11f, 0x8f16b84e, 0xdc915d75],
1491 [0xeb1364a6, 0x91c9d99d, 0x324f5427, 0xcc9f11a2],
1492 [0x7aeb5a3f, 0xebc9c4dd, 0x8f12c8e4, 0x37a2db97],
1493 [0xa11e5c33, 0x656df4c0, 0x1e8b98d8, 0x1736722f],
1494 [0x239f2ef2, 0xe32b0603, 0x448366bb, 0x9331051c],
1495 [0x1815a1b1, 0xfb7e7cf0, 0xd5c7dd5b, 0x0135a8fb],
1496 [0xea3b85dd, 0xa96e7015, 0xa91c576d, 0x5c127ca1],
1497 [0x1c49148f, 0x6d9e7045, 0x093f0b7c, 0x42c2ebaa],
1498 [0x4b4c2863, 0x95709d8c, 0xeb72e251, 0x096632dc],
1499 [0x727418e5, 0x2c015383, 0x59580212, 0x0302dd99],
1500 [0xbe57dfa4, 0xf2aa7d70, 0xa068ee62, 0x77372861],
1501 [0x2faef43a, 0x73da6654, 0xb9d9c22e, 0xc59520bc],
1502 [0x138cff40, 0x3e6c108a, 0xa981e654, 0x903da85b],
1503 [0xa90454f5, 0x7875d5db, 0xbab234bd, 0xe6ce1193]]));
1507 fn test_h264_real1() {
1508 let mut dmx_reg = RegisteredDemuxers::new();
1509 dmx_reg.add_demuxer(&RawH264DemuxerCreator{});
1510 generic_register_all_demuxers(&mut dmx_reg);
1511 let mut dec_reg = RegisteredDecoders::new();
1512 itu_register_all_decoders(&mut dec_reg);
1514 test_decoding("mov", "h264", "assets/ITU/1.mp4",
1515 Some(60), &dmx_reg, &dec_reg,
1516 ExpectedTestResult::MD5Frames(vec![
1517 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
1518 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
1519 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
1520 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
1521 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
1522 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
1523 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
1524 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
1525 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
1526 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
1527 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
1528 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
1529 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
1530 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
1531 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
1532 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
1533 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
1534 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
1535 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
1536 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
1537 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
1538 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
1539 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
1540 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
1541 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
1542 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
1543 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
1544 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
1545 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
1546 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
1547 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
1548 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
1549 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
1550 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
1551 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
1552 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
1553 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
1554 [0xf1c88c12, 0x7da871f5, 0xdaf3153f, 0x66e72d72],
1555 [0x3d4765f1, 0x8ac472f6, 0x7ffd13a6, 0xc7a45dae],
1556 [0x60e5e13a, 0xd2d7f239, 0x1a793d71, 0x19f8c190],
1557 [0xdd80c3e4, 0xb1500149, 0x43925280, 0x9e5f3230],
1558 [0x2adf6e64, 0x39012d45, 0x7a776cb5, 0x3df76e84],
1559 [0x44319007, 0xbc837dd2, 0x486b2703, 0x451d0651],
1560 [0x922386ef, 0xaf101e9b, 0xf2094a40, 0xc8c454c0],
1561 [0x0d81e398, 0x04192a56, 0xa31f39d0, 0x5e0a2deb],
1562 [0xcdd144b3, 0xd1c7743e, 0x5753b0f4, 0xc070efa9],
1563 [0xe1c67e39, 0x6065ddaf, 0x576bf9f1, 0x8e6825aa],
1564 [0xaf817b0d, 0xdc6c345a, 0xf7f289c7, 0x6cc482d8],
1565 [0x81dc4bcb, 0xee4fc5e5, 0x9b87c7ef, 0xdd0fb034],
1566 [0x8b07f523, 0x4168799f, 0x990cb270, 0x858b9f2c],
1567 [0x31855a80, 0xadbcc562, 0xe60628be, 0x5f04be09],
1568 [0x9c614acc, 0xbd08a3f4, 0x91b02c45, 0x41899a83],
1569 [0x89d09064, 0xbff810a3, 0x9c674179, 0x305225a6],
1570 [0xba1fc8d3, 0x15d34fae, 0x565d363b, 0x4f4d0604],
1571 [0x1cb15a1b, 0xa0be111e, 0x45cc801f, 0x01a2c691],
1572 [0xd898be48, 0xd19bf58d, 0xe22fe44f, 0x6a2914fb],
1573 [0xec6712af, 0xa13b55c0, 0x2915a746, 0xb29a5c48],
1574 [0x745798fa, 0x4ef0f882, 0x59335c08, 0xb1d9dbb4],
1575 [0x4045b495, 0xdb3d969c, 0x1f0d9220, 0x5a34067b],
1576 [0x94fee093, 0x78ad89b3, 0xf20e882b, 0x941425db],
1577 [0xc3eb1a78, 0x4b4e098a, 0xcbcf9bb4, 0xfd5b5426]]));
1580 fn test_h264_real2() {
1581 let mut dmx_reg = RegisteredDemuxers::new();
1582 dmx_reg.add_demuxer(&RawH264DemuxerCreator{});
1583 generic_register_all_demuxers(&mut dmx_reg);
1584 let mut dec_reg = RegisteredDecoders::new();
1585 itu_register_all_decoders(&mut dec_reg);
1586 test_decoding("mov", "h264", "assets/ITU/DimpledSpanishCuckoo-mobile.mp4",
1587 Some(10), &dmx_reg, &dec_reg,
1588 ExpectedTestResult::MD5Frames(vec![
1589 [0x1addcb8e, 0xde58b857, 0x17222c32, 0x75455fa8],
1590 [0xae63141a, 0x79435b2e, 0xfe606c48, 0xf676da66],
1591 [0xfdb80404, 0x6a288e23, 0x45cc4106, 0xdd5eb57c],
1592 [0xd603a3ff, 0x872dcb9b, 0x43f7a71c, 0x2ad4eecc],
1593 [0x639ed6a5, 0xbb1cfec6, 0x0ee5443a, 0x1694772a],
1594 [0xf8ef3f48, 0x152de238, 0xb1995f9a, 0xf82ad1d5],
1595 [0x604f6265, 0xb9d82f56, 0x21f00cf4, 0xc69c18a7],
1596 [0xd932c16e, 0x25cbf060, 0xcb66543b, 0xfe8a5019],
1597 [0xf2a3dac0, 0x0f4678dd, 0xf64c8228, 0x47f14676],
1598 [0x267041ee, 0x3b6b8b64, 0x8bfe1697, 0x1fba508b],
1599 [0x9f917e72, 0x75d882a9, 0xa5e3e684, 0x4ed87eff]]));
1603 pub const I4X4_SCAN: [(u8, u8); 16] = [
1604 (0,0), (1,0), (0,1), (1,1), (2,0), (3,0), (2,1), (3,1),
1605 (0,2), (1,2), (0,3), (1,3), (2,2), (3,2), (2,3), (3,3)