h264: rework MB reconstruction and fix loop filtering
[nihav.git] / nihav-itu / src / codecs / h264 / mod.rs
CommitLineData
696e4e20
KS
1/*
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
7*/
8use nihav_core::codecs::*;
9use nihav_core::io::byteio::*;
10use nihav_core::io::bitreader::*;
11use nihav_core::io::intcode::*;
12use nihav_codec_support::codecs::{MV, ZERO_MV};
13
14mod types;
15pub use types::*;
16mod pic_ref;
17pub use pic_ref::*;
4a1ca15c
KS
18#[allow(clippy::identity_op)]
19#[allow(clippy::erasing_op)]
20#[allow(clippy::many_single_char_names)]
21#[allow(clippy::range_plus_one)]
696e4e20
KS
22mod dsp;
23use dsp::*;
24mod cabac;
25use cabac::*;
26mod cabac_coder;
27use cabac_coder::*;
28mod cavlc;
29use cavlc::*;
30mod loopfilter;
31use loopfilter::*;
32mod sets;
33use sets::*;
34mod slice;
35use slice::*;
36
37trait ReadUE {
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);
43 Ok(val)
44 }
45 fn read_se(&mut self) -> DecoderResult<i32> {
46 let val = self.read_ue()?;
47 if (val & 1) != 0 {
48 Ok (((val >> 1) as i32) + 1)
49 } else {
50 Ok (-((val >> 1) as i32))
51 }
52 }
53}
54
55impl<'a> ReadUE for BitReader<'a> {
56 fn read_ue(&mut self) -> DecoderResult<u32> {
57 Ok(self.read_code(UintCodeType::GammaP)? - 1)
58 }
59 fn read_te(&mut self, range: u32) -> DecoderResult<u32> {
60 if range == 1 {
61 if self.read_bool()? {
62 Ok(0)
63 } else {
64 Ok(1)
65 }
66 } else {
67 let val = self.read_ue()?;
68 validate!(val <= range);
69 Ok(val)
70 }
71 }
72}
73
74#[derive(Clone,Copy)]
75pub struct Coeff8x8 {
76 pub coeffs: [i16; 64],
77}
78
79impl Coeff8x8 {
80 fn clear(&mut self) {
81 self.coeffs = [0; 64];
82 }
83}
84
85impl Default for Coeff8x8 {
86 fn default() -> Self {
87 Self {
88 coeffs: [0; 64],
89 }
90 }
91}
92
93#[derive(Clone,Copy,Default)]
94pub struct CurrentMBInfo {
95 pub mb_type: MBType,
96 pub sub_mb_type: [SubMBType; 4],
97 pub ipred: [IntraPredMode; 16],
98 pub chroma_ipred: u8,
99 pub luma_ipred: [u8; 16],
100 pub mv_l0: [MV; 16],
101 pub ref_l0: [PicRef; 4],
102 pub mv_l1: [MV; 16],
103 pub ref_l1: [PicRef; 4],
104 pub qp_y: u8,
105 pub cbpy: u8,
106 pub cbpc: u8,
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,
112}
113
114impl CurrentMBInfo {
115 fn clear_coeffs8x8(&mut self) {
116 for c in self.coeffs8x8.iter_mut() {
117 c.clear();
118 }
119 }
120 fn can_have_8x8_tx(&self, inference_flag: bool) -> bool {
121 match self.mb_type {
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() {
125 match sub_id {
126 SubMBType::P8x8 |
127 SubMBType::B8x8(_)
128 => {},
129 SubMBType::Direct8x8
130 => if !inference_flag { return false; },
131 _ => return false,
132 };
133 }
134 true
135 },
136 MBType::Direct => inference_flag,
137 _ => true,
138 }
139 }
140}
141
142fn get_long_term_id(is_idr: bool, slice_hdr: &SliceHeader) -> Option<usize> {
143 if is_idr && !slice_hdr.long_term_reference {
144 None
145 } else {
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) {
148 if op == 6 {
149 return Some(arg as usize);
150 }
151 }
152 None
153 }
154}
155
156struct H264Decoder {
157 info: NACodecInfoRef,
158 width: usize,
159 height: usize,
160 num_mbs: usize,
161 nal_len: u8,
162 sps: Vec<SeqParameterSet>,
163 cur_sps: usize,
164 pps: Vec<PicParameterSet>,
165 cur_pps: usize,
166
167 skip_mode: FrameSkipMode,
168 deblock_skip: bool,
169
170 is_mbaff: bool,
171
172 cavlc_cb: CAVLCTables,
173
174 sstate: SliceState,
175
176 cur_pic: Option<PictureInfo>,
177 cur_id: u16,
178 has_pic: bool,
179 frame_refs: FrameRefs,
180
181 temporal_mv: bool,
182 deblock_mode: u8,
183 lf_alpha: i8,
184 lf_beta: i8,
185 is_s: bool,
186
187 ipcm_buf: [u8; 256 + 64 + 64],
188
189 avg_buf: NAVideoBufferRef<u8>,
190
191 transform_8x8_mode: bool,
192}
193
194fn unescape_nal(src: &[u8], dst: &mut Vec<u8>) -> usize {
195 let mut off = 0;
196 let mut zrun = 0;
37952415 197 dst.clear();
696e4e20
KS
198 dst.reserve(src.len());
199 while off < src.len() {
200 dst.push(src[off]);
201 if src[off] != 0 {
202 zrun = 0;
203 } else {
204 zrun += 1;
205 if zrun == 2 && off + 1 < src.len() && src[off + 1] == 0x03 {
206 zrun = 0;
207 off += 1;
208 }
209 if zrun >= 3 && off + 1 < src.len() && src[off + 1] == 0x01 {
210 off -= 3;
211 dst.truncate(off);
212 break;
213 }
214 }
215 off += 1;
216 }
217 off
218}
219
220impl H264Decoder {
221 fn new() -> Self {
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();
224 H264Decoder{
225 info: NACodecInfoRef::default(),
226 width: 0,
227 height: 0,
228 num_mbs: 0,
229 nal_len: 0,
230 sps: Vec::with_capacity(1),
231 cur_sps: 0,
232 pps: Vec::with_capacity(3),
233 cur_pps: 0,
234
235 skip_mode: FrameSkipMode::default(),
236 deblock_skip: false,
237
238 is_mbaff: false,
239
240 cavlc_cb: CAVLCTables::new(),
241
242 sstate: SliceState::new(),
243 cur_pic: None,
244 cur_id: 0,
245 has_pic: false,
246 frame_refs: FrameRefs::new(),
247
248 temporal_mv: false,
249 deblock_mode: 0,
250 lf_alpha: 0,
251 lf_beta: 0,
252 is_s: false,
253
254 ipcm_buf: [0; 256 + 64 + 64],
255
256 avg_buf,
257
258 transform_8x8_mode: false,
259 }
260 }
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;
266
267 let mut full_size = src.len() * 8;
268 for &byte in src.iter().rev() {
269 if byte == 0 {
270 full_size -= 8;
271 } else {
272 full_size -= (byte.trailing_zeros() + 1) as usize;
273 break;
274 }
275 }
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);
281 br.skip(8)?;
282
283 let slice_hdr = parse_slice_header(&mut br, &self.sps, &self.pps, is_idr, nal_ref_idc)?;
284 validate!(br.tell() < full_size);
285 let full_id;
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 {
290 self.cur_pps = i;
291 break;
292 }
293 }
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 {
296 self.cur_sps = i;
297 break;
298 }
299 }
300
301 full_id = self.frame_refs.calc_picture_num(&slice_hdr, is_idr, nal_ref_idc, &self.sps[self.cur_sps]);
302
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 {
305println!(" chroma fmt {} bits {}/{}", sps.chroma_format_idc, sps.bit_depth_luma, sps.bit_depth_chroma);
306 return Err(DecoderError::NotImplemented);
307 }
308 //let pps = &self.pps[self.cur_pps];
309
310 if is_idr {
311 self.frame_refs.clear_refs();
312 }
313
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;
317
318 self.is_mbaff = sps.mb_adaptive_frame_field && !slice_hdr.field_pic;
319 if self.is_mbaff {
320println!("MBAFF");
321 return Err(DecoderError::NotImplemented);
322 }
323 if !sps.frame_mbs_only {
324println!("PAFF?");
325 return Err(DecoderError::NotImplemented);
326 }
327
328//if slice_hdr.slice_type.is_b() { return Ok(()); }
329 self.cur_id = full_id as u16;
330 } else {
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,
337 _ => pic.pic_type,
338 };
339 full_id = pic.full_id;
340 } else {
341 return Ok(());//Err(DecoderError::InvalidData);
342 }
343 validate!(self.cur_pps < self.pps.len() && self.pps[self.cur_pps].pic_parameter_set_id == slice_hdr.pic_parameter_set_id);
344 }
345
346 let sps = &self.sps[self.cur_sps];
347 let pps = &self.pps[self.cur_pps];
348
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;
354
355 self.frame_refs.select_refs(sps, &slice_hdr, full_id);
356
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)?;
359 }
360 if slice_hdr.first_mb_in_slice == 0 {
361 let ret = supp.pool_u8.get_free();
362 if ret.is_none() {
363 return Err(DecoderError::AllocError);
364 }
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();
371 if ret.is_none() {
372 return Err(DecoderError::AllocError);
373 }
374 buf = ret.unwrap();
375 }
376 self.cur_pic = Some(PictureInfo {
377 id: slice_hdr.frame_num,
378 full_id,
379 pic_type: slice_hdr.slice_type.to_frame_type(),
380 buf,
381 cur_mb: 0,
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),
385 });
386 }
387
388 self.transform_8x8_mode = pps.transform_8x8_mode;
389
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)?;
393 } else {
394 br.align();
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)?;
400 }
696e4e20
KS
401 },
402 2 => { // slice data partition A
403 //slice header
404 //slice id = read_ue()
405 //cat 2 slice data (all but MB layer residual)
406 return Err(DecoderError::NotImplemented);
407 },
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);
413 },
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);
419 },
420 6 => {}, //SEI
421 7 => {
422 let sps = parse_sps(&src[1..])?;
423 self.sps.push(sps);
424 },
425 8 => {
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();
432 found = true;
433 break;
434 }
435 }
436 if !found {
437 self.pps.push(pps);
438 }
439 },
440 9 => { // access unit delimiter
441 },
442 10 => {}, //end of sequence
443 11 => {}, //end of stream
444 12 => {}, //filler
445 _ => {},
446 };
447
448 Ok(())
449 }
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) {
455 imode as usize
456 } else if !sstate.has_top && !sstate.has_left {
457 IPRED8_DC128
458 } else if !sstate.has_left {
459 IPRED8_DC_TOP
460 } else {
461 IPRED8_DC_LEFT
462 };
22de733b 463 IPRED_FUNCS16X16[id](&mut frm.data[yoff..], frm.stride[0], &sstate.top_line_y[sstate.mb_x * 16..], &sstate.left_y);
696e4e20
KS
464 },
465 MBType::Intra8x8 => {
466 let mut ictx = IPred8Context::new();
467 for part in 0..4 {
468 let x = (part & 1) * 2;
469 let y = part & 2;
470 let blk4 = x + y * 4;
471
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();
478 im_id as usize
479 } else if !has_top && !has_left {
480 IPRED4_DC128
481 } else if !has_left {
482 IPRED4_DC_TOP
483 } else {
484 IPRED4_DC_LEFT
485 };
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 {
22de733b
KS
490 let top = if y == 0 {
491 &sstate.top_line_y[sstate.mb_x * 16 + x * 4..]
492 } else {
493 &frm.data[cur_yoff - frm.stride[0]..]
494 };
495 let mut left_buf = [0; 9];
496 let left = if x == 0 {
497 &sstate.left_y[y * 4..]
498 } else {
499 if has_tl {
500 if y == 0 {
501 left_buf[0] = sstate.top_line_y[sstate.mb_x * 16 + x * 4 - 1];
502 } else {
503 left_buf[0] = frm.data[cur_yoff - 1 - frm.stride[0]];
504 }
505 }
506 if has_left {
507 for (dst, src) in left_buf[1..].iter_mut().zip(frm.data[cur_yoff - 1..].chunks(frm.stride[0])) {
508 *dst = src[0];
509 }
510 }
511 &left_buf
512 };
513 ictx.fill(top, left, has_top, has_top && !noright, has_left, has_tl);
696e4e20
KS
514 }
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);
518 }
519 }
520 },
521 MBType::Intra4x4 => {
522 for &(x,y) in I4X4_SCAN.iter() {
523 let x = x as usize;
524 let y = y as usize;
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();
531 im_id as usize
532 } else if !has_top && !has_left {
533 IPRED4_DC128
534 } else if !has_left {
535 IPRED4_DC_TOP
536 } else {
537 IPRED4_DC_LEFT
538 };
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 {
22de733b 541 let tsrc = &sstate.top_line_y[sstate.mb_x * 16 + x * 4..];
696e4e20 542 if has_top && !noright {
22de733b 543 [tsrc[4], tsrc[5], tsrc[6], tsrc[7]]
696e4e20 544 } else if has_top {
22de733b 545 [tsrc[3]; 4]
696e4e20
KS
546 } else {
547 [0; 4]
548 }
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]]
552 } else {
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]]
555 };
22de733b
KS
556 let mut top = [128; 4];
557 let mut left = [128; 9];
558 if y == 0 {
559 if has_top {
560 top.copy_from_slice(&sstate.top_line_y[sstate.mb_x * 16 + x * 4..][..4]);
561 }
562 } else {
563 top.copy_from_slice(&frm.data[cur_yoff - frm.stride[0]..][..4]);
564 }
565 if x == 0 {
566 if has_left {
567 for (dst, &src) in left.iter_mut().zip(sstate.left_y[y * 4..].iter()) {
568 *dst = src;
569 }
570 }
571 } else {
572 if y == 0 {
573 if x == 0 {
574 left[0] = sstate.left_y[y * 4];
575 } else if has_top {
576 left[0] = sstate.top_line_y[sstate.mb_x * 16 + x * 4 - 1];
577 }
578 } else {
579 left[0] = frm.data[cur_yoff - frm.stride[0] - 1];
580 }
581 for (dst, row) in left[1..].iter_mut().zip(frm.data[cur_yoff - 1..].chunks(frm.stride[0])) {
582 *dst = row[0];
583 }
584 }
585 IPRED_FUNCS4X4[id](&mut frm.data[cur_yoff..], frm.stride[0], &top, &left, &tr);
696e4e20
KS
586 if mb_info.coded[x + y * 4] {
587 add_coeffs(frm.data, cur_yoff, frm.stride[0], &mb_info.coeffs[x + y * 4]);
588 }
589 }
590 },
591 _ => unreachable!(),
592 };
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 {
596 IPRED8_DC128
597 } else if !sstate.has_left {
598 IPRED8_DC_TOP
599 } else {
600 IPRED8_DC_LEFT
601 };
602 for chroma in 1..3 {
603 let off = frm.offset[chroma] + sstate.mb_x * 8 + sstate.mb_y * 8 * frm.stride[chroma];
22de733b
KS
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]);
696e4e20
KS
606 }
607 }
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 {
611 for y in 0..4 {
612 for x in 0..4 {
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]);
615 }
616 }
617 yoff += frm.stride[0] * 4;
618 }
619 } else {
620 for y in 0..2 {
621 for x in 0..2 {
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);
624 }
625 }
626 yoff += frm.stride[0] * 8;
627 }
628 }
629 }
630 fn add_chroma(frm: &mut NASimpleVideoFrame<u8>, sstate: &SliceState, mb_info: &CurrentMBInfo) {
631 for chroma in 1..3 {
632 let mut off = frm.offset[chroma] + sstate.mb_x * 8 + sstate.mb_y * 8 * frm.stride[chroma];
633 for y in 0..2 {
634 for x in 0..2 {
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]);
638 }
639 }
640 off += frm.stride[chroma] * 4;
641 }
642 }
643 }
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();
648 let mut xoff = 0;
649 let mut yoff = 0;
650 if mb_type == MBType::Direct || mb_type == MBType::BSkip {
651 sstate.predict_direct_mb(frame_refs, temporal_mv, cur_id);
652 }
653 for part in 0..mb_type.num_parts() {
654 if !mb_type.is_l1(part) {
655 match mb_type {
656 MBType::PSkip => sstate.predict_pskip(),
657 MBType::BSkip | MBType::Direct => {
658 },
659 _ => {
660 sstate.predict(xoff, yoff, pw, ph, 0,
661 mb_info.mv_l0[part], mb_info.ref_l0[part]);
662 },
663 };
664 }
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]);
667 }
668 if pw != 16 {
669 xoff += pw;
670 } else {
671 yoff += ph;
672 }
673 }
674 } else {
675 for part in 0..4 {
676 let sub_type = mb_info.sub_mb_type[part];
677 let mut xoff = (part & 1) * 8;
678 let mut yoff = (part & 2) * 4;
679 let orig_x = xoff;
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]);
685 }
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]);
688 }
689 } else {
690 for sblk in 0..4 {
691 sstate.predict_direct_sub(frame_refs, temporal_mv, cur_id, (xoff / 4) + (sblk & 1) + (yoff / 4) * 4 + (sblk & 2) * 2);
692 }
693 }
694 xoff += pw;
695 if xoff == orig_x + 8 {
696 xoff -= 8;
697 yoff += ph;
698 }
699 }
700 }
701 }
702 }
b7c882c1 703 #[allow(clippy::cognitive_complexity)]
696e4e20
KS
704 fn handle_macroblock(&mut self, mb_info: &mut CurrentMBInfo) {
705 let pps = &self.pps[self.cur_pps];
706
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];
712
713 let tx_bypass = qp_y == 0 && self.sps[self.cur_sps].qpprime_y_zero_transform_bypass;
714
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;
721 }
722 let has_dc = mb_info.mb_type.is_intra16x16() && mb_info.coded[24];
723 if has_dc {
724 idct_luma_dc(&mut mb_info.coeffs[24], qp_y);
725 for i in 0..16 {
726 mb_info.coeffs[i][0] = mb_info.coeffs[24][i];
727 }
728 }
729 if !mb_info.transform_size_8x8 {
730 let quant_dc = !mb_info.mb_type.is_intra16x16();
731 for i in 0..16 {
732 if mb_info.coded[i] {
733 if !tx_bypass {
734 idct(&mut mb_info.coeffs[i], qp_y, quant_dc);
735 }
736 } else if has_dc {
737 if !tx_bypass {
738 idct_dc(&mut mb_info.coeffs[i], qp_y, quant_dc);
739 }
740 mb_info.coded[i] = true;
741 }
742 }
743 } else {
744 for i in 0..4 {
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);
748 }
749 }
750 }
751 for chroma in 0..2 {
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);
755 }
756 for i in 0..4 {
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;
764 }
765 }
766 }
767 if !pps.entropy_coding_mode || mb_info.mb_type.is_skip() || mb_info.mb_type.is_intra() {
768 self.sstate.reset_mb_mv();
769 }
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);
772 }
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);
775 }
776
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);
784 },
785 MBType::Intra4x4 | MBType::Intra8x8 => {
786 Self::pred_intra(&mut frm, &self.sstate, &mb_info);
787 },
788 MBType::PCM => {},
789 MBType::PSkip => {
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);
793 },
794 MBType::P16x16 => {
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);
798 },
799 MBType::P16x8 | MBType::P8x16 => {
800 let (bw, bh, bx, by) = if mb_info.mb_type == MBType::P16x8 {
801 (16, 8, 0, 8)
802 } else {
803 (8, 16, 8, 0)
804 };
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);
811 },
812 MBType::P8x8 | MBType::P8x8Ref0 => {
813 for part in 0..4 {
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];
818
819 match mb_info.sub_mb_type[part] {
820 SubMBType::P8x8 => {
821 do_mc(&mut frm, buf, xpos + bx, ypos + by, 8, 8, mv);
822 },
823 SubMBType::P8x4 => {
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);
827 },
828 SubMBType::P4x8 => {
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);
832 },
833 SubMBType::P4x4 => {
834 for sb_no in 0..4 {
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);
840 }
841 },
842 _ => unreachable!(),
843 };
844 } else {
845 gray_block(&mut frm, xpos + bx, ypos + by, 8, 8);
846 }
847 }
848 },
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);
855 },
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);
861 for part in 0..2 {
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);
868 bx += px;
869 by += py;
870 }
871 },
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);
880 } else {
881 for blk4 in 0..16 {
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);
887 }
888 }
889 self.sstate.apply_to_blk8(|blk8| { blk8.ref_idx[0].set_direct(); blk8.ref_idx[1].set_direct(); });
890 },
891 MBType::B8x8 => {
892 for part in 0..4 {
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;
900 match subtype {
901 SubMBType::Direct8x8 => {
902 for blk in 0..4 {
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);
908 bx += 4;
909 if blk == 1 {
910 bx -= 8;
911 by += 4;
912 }
913 }
914 self.sstate.get_cur_blk8(part).ref_idx[0].set_direct();
915 self.sstate.get_cur_blk8(part).ref_idx[1].set_direct();
916 },
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);
920 },
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);
928 },
929 SubMBType::B4x4(mode) => {
930 for i in 0..4 {
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);
934 bx += 4;
935 if i == 1 {
936 bx -= 8;
937 by += 4;
938 }
939 }
940 },
941 _ => unreachable!(),
942 };
943 }
944 },
945 };
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);
949 }
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);
952 }
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);
955 }
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);
959 }
960 Self::add_chroma(&mut frm, &self.sstate, &mb_info);
961 }
962/*match mb_info.mb_type {
963MBType::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) {
968 row[0] = 255;
969 }
970},
971_ => {},
972};*/
22de733b 973 self.sstate.save_ipred_context(&frm);
696e4e20
KS
974 }
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();
980 for blk4 in 0..16 {
981 mb.mv[blk4] = self.sstate.get_cur_blk4(blk4).mv;
982 }
983 for blk8 in 0..4 {
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;
986 }
987 mv_info.mbs[mb_pos] = mb;
988 }
22de733b
KS
989 if !self.deblock_skip && self.deblock_mode != 1 {
990 self.sstate.fill_deblock(&self.frame_refs, self.deblock_mode, self.is_s);
696e4e20
KS
991 if let Some(ref mut pic) = self.cur_pic {
992 let mut frm = NASimpleVideoFrame::from_video_buf(&mut pic.buf).unwrap();
22de733b 993 loop_filter_mb(&mut frm, &self.sstate, self.lf_alpha, self.lf_beta);
696e4e20
KS
994 }
995 }
996 self.sstate.next_mb();
997 }
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);
1001 } else {
1002 gray_block(frm, xpos, ypos, w, h);
1003 }
1004 }
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>) {
1006 match mode {
1007 BMode::L0 => {
1008 if let Some(buf) = ref_pic0 {
1009 do_mc(frm, buf, xpos, ypos, w, h, mv0);
1010 } else {
1011 gray_block(frm, xpos, ypos, w, h);
1012 }
1013 },
1014 BMode::L1 => {
1015 if let Some(buf) = ref_pic1 {
1016 do_mc(frm, buf, xpos, ypos, w, h, mv1);
1017 } else {
1018 gray_block(frm, xpos, ypos, w, h);
1019 }
1020 },
1021 BMode::Bi => {
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);
1026 },
1027 (Some(buf0), None) => {
1028 do_mc(frm, buf0, xpos, ypos, w, h, mv0);
1029 },
1030 (None, Some(buf1)) => {
1031 do_mc(frm, buf1, xpos, ypos, w, h, mv1);
1032 },
1033 (None, None) => {
1034 gray_block(frm, xpos, ypos, w, h);
1035 },
1036 };
1037 },
1038 };
1039 }
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
1045 ];
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
1050 ];
1051
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];
1063 mb_info.cbpy = 0;
1064 mb_info.cbpc = 0;
1065
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);
1072 mb_idx += 1;
1073 }
1074 if mb_idx == self.num_mbs || br.tell() >= full_size {
1075 break;
1076 }
1077 }
1078 if br.tell() < full_size {
1079 if self.is_mbaff && ((mb_idx & 1) == 0) {
1080 let _mb_field_decoding = br.read_bool()?;
1081 }
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 {
1086 br.align();
1087 for pix in self.ipcm_buf[..256 + 64 + 64].iter_mut() {
1088 *pix = br.read(8)? as u8;
1089 }
1090 self.sstate.fill_ncoded(16);
1091 } else {
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;
1097 }
1098 }
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 {
1101 (cbpy, cbpc)
1102 } else {
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 {
1106 INTRA_CBP[cbp_id]
1107 } else {
1108 INTER_CBP[cbp_id]
1109 };
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()?;
1112 }
1113 ((cbp & 0xF), (cbp >> 4))
1114 };
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 {
1123 (new_qp + 52) as u8
1124 } else if new_qp >= 52 {
1125 (new_qp - 52) as u8
1126 } else {
1127 new_qp as u8
1128 };
1129 mb_info.coeffs = [[0; 16]; 25];
1130 if self.transform_8x8_mode {
1131 mb_info.clear_coeffs8x8();
1132 }
1133 mb_info.chroma_dc = [[0; 4]; 2];
1134 decode_residual_cavlc(br, &mut self.sstate, &mut mb_info, &self.cavlc_cb)?;
1135 }
1136 }
1137 self.handle_macroblock(&mut mb_info);
1138 }
1139 mb_idx += 1;
1140 }
1141 if let Some(ref mut pic) = self.cur_pic {
1142 pic.cur_mb = mb_idx;
1143 }
1144 Ok(mb_idx == self.num_mbs)
1145 }
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;
1151
1152 let mut mb_info = CurrentMBInfo::default();
1153 mb_info.qp_y = slice_hdr.slice_qp;
1154
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];
1162 mb_info.cbpy = 0;
1163 mb_info.cbpc = 0;
1164 let mb_skip = cabac_decode_mbskip(cabac, &self.sstate, slice_hdr);
1165 if !mb_skip {
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);
1168 }
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;
1177 cabac.reinit()?;
1178 last_qp_diff = false;
1179 } else {
1180 if self.transform_8x8_mode && mb_type == MBType::Intra4x4 {
1181 let mut ctx = 0;
1182 if self.sstate.get_top_mb().transform_8x8 {
1183 ctx += 1;
1184 }
1185 if self.sstate.get_left_mb().transform_8x8 {
1186 ctx += 1;
1187 }
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;
1192 }
1193 }
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 {
1196 (cbpy, cbpc)
1197 } else {
1198 decode_cbp_cabac(cabac, &self.sstate)
1199 };
1200 if self.transform_8x8_mode && cbpy != 0 && mb_info.can_have_8x8_tx(self.sps[self.cur_sps].direct_8x8_inference) {
1201 let mut ctx = 0;
1202 if self.sstate.get_top_mb().transform_8x8 {
1203 ctx += 1;
1204 }
1205 if self.sstate.get_left_mb().transform_8x8 {
1206 ctx += 1;
1207 }
1208 mb_info.transform_size_8x8 = cabac.decode_bit(399 + ctx);
1209 }
1210 if mb_type.is_intra() {
1211 self.sstate.get_cur_mb().cmode = mb_info.chroma_ipred;
1212 }
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 {
1222 (new_qp + 52) as u8
1223 } else if new_qp >= 52 {
1224 (new_qp - 52) as u8
1225 } else {
1226 new_qp as u8
1227 };
1228 mb_info.coeffs = [[0; 16]; 25];
1229 if self.transform_8x8_mode {
1230 mb_info.clear_coeffs8x8();
1231 }
1232 mb_info.chroma_dc = [[0; 4]; 2];
1233 decode_residual_cabac(cabac, &mut self.sstate, &mut mb_info);
1234 } else {
1235 last_qp_diff = false;
1236 }
1237 }
1238 } else {
1239 mb_info.mb_type = skip_type;
1240 mb_info.transform_size_8x8 = false;
1241 last_qp_diff = false;
1242 }
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;
1248 }
1249 return Ok(mb_idx + 1 == self.num_mbs);
1250 }
1251 mb_idx += 1;
1252 }
1253 Err(DecoderError::InvalidData)
1254 }
1255}
1256
1257impl 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();
1263
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();
1270
1271 br.read_skip(4)?;
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)?;
1289 br.read_skip(len)?;
1290 }
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)?;
1298 br.read_skip(len)?;
1299 }
1300 if br.left() > 0 {
1301 match profile {
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;
1315 // parse spsext
1316 br.read_skip(len)?;
1317 }
1318 },
1319 _ => {},
1320 };
1321 }
1322 } else {
1323 return Err(DecoderError::NotImplemented);
1324 }
1325
1326 self.width = vinfo.get_width();
1327 self.height = vinfo.get_height();
1328
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;
1332 }
1333
1334 let num_bufs = if !self.sps.is_empty() {
1335 self.sps[0].num_ref_frames as usize + 1
1336 } else {
1337 3
1338 }.max(16 + 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)?;
1341
1342 Ok(())
1343 } else {
1344println!("???");
1345 Err(DecoderError::InvalidData)
1346 }
1347 }
1348 fn decode(&mut self, supp: &mut NADecoderSupport, pkt: &NAPacket) -> DecoderResult<NAFrameRef> {
1349 let src = pkt.get_buffer();
1350
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!(),
1366 };
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 {
1377 is_ref = true;
1378 }
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,
1383 _ => pic_type,
1384 };
1385 }
1386 br.read_skip(size)?;
1387 }
1388 match self.skip_mode {
1389 FrameSkipMode::IntraOnly => {
1390 skip_decoding = pic_type != FrameType::I;
1391 },
1392 FrameSkipMode::KeyframesOnly => {
1393 if !is_ref {
1394 skip_decoding = true;
1395 }
1396 },
1397 _ => {},
1398 };
1399 br.seek(SeekFrom::Start(0))?;
1400 }
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!(),
1408 };
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)?;
1414 }
1415 } else {
1416//todo NAL detection
1417 unimplemented!();
1418 }
1419
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)));
1425 if cpic.is_ref {
1426 self.frame_refs.add_short_term(cpic.clone(), self.sps[self.cur_sps].num_ref_frames);
1427 }
1428 if let Some(lt_idx) = cpic.long_term {
1429 self.frame_refs.add_long_term(lt_idx, cpic);
1430 }
1431 ret
1432 } else {
1433 (NABufferType::None, FrameType::Skip, None)
1434 };
1435
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));
1440 }
1441 if let Some(dts) = dts {
1442 frm.set_id(dts as i64);
1443 }
1444 frm.set_frame_type(ftype);
1445 Ok(frm.into_ref())
1446 }
1447 fn flush(&mut self) {
1448 }
1449}
1450
1451const DEBLOCK_SKIP_OPTION: &str = "skip_deblock";
1452
1453const 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
1463 ])) },
1464];
1465
1466impl 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;
1476 }
1477 },
1478 (DEBLOCK_SKIP_OPTION, NAValue::Bool(val)) => {
1479 self.deblock_skip = *val;
1480 },
1481 _ => {},
1482 }
1483 }
1484 }
1485 }
1486 }
1487 fn query_option_value(&self, name: &str) -> Option<NAValue> {
1488 match name {
1489 FRAME_SKIP_OPTION => Some(NAValue::String(self.skip_mode.to_string())),
1490 DEBLOCK_SKIP_OPTION => Some(NAValue::Bool(self.deblock_skip)),
1491 _ => None,
1492 }
1493 }
1494}
1495
1496pub fn get_decoder() -> Box<dyn NADecoder + Send> {
1497 Box::new(H264Decoder::new())
1498}
1499
1500#[cfg(test)]
1501mod test {
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;
1507
886cde48 1508 // samples if not specified otherwise come from H.264 conformance suite
696e4e20
KS
1509 mod raw_demux;
1510 mod conformance;
1511 use self::raw_demux::RawH264DemuxerCreator;
1512
1513 #[test]
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);
1520
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]]));
1549 }
1550
886cde48 1551 // mostly static music video downloaded with youtube-dl
696e4e20
KS
1552 #[test]
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);
1559
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]]));
1624 }
886cde48 1625 // a sample downloaded from gfycat.com
696e4e20
KS
1626 #[test]
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]]));
1647 }
1648}
1649
1650pub 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)
1653];