]> git.nihav.org Git - nihav.git/blame - nihav-itu/src/codecs/h264/mod.rs
core/scale: add options support
[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;
197 dst.truncate(0);
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 }
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);
406 }
407 loop_filter_last(&mut frm, &self.sstate, self.lf_alpha, self.lf_beta);
408 }
409 }
410 },
411 2 => { // slice data partition A
412 //slice header
413 //slice id = read_ue()
414 //cat 2 slice data (all but MB layer residual)
415 return Err(DecoderError::NotImplemented);
416 },
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);
422 },
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);
428 },
429 6 => {}, //SEI
430 7 => {
431 let sps = parse_sps(&src[1..])?;
432 self.sps.push(sps);
433 },
434 8 => {
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();
441 found = true;
442 break;
443 }
444 }
445 if !found {
446 self.pps.push(pps);
447 }
448 },
449 9 => { // access unit delimiter
450 },
451 10 => {}, //end of sequence
452 11 => {}, //end of stream
453 12 => {}, //filler
454 _ => {},
455 };
456
457 Ok(())
458 }
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) {
464 imode as usize
465 } else if !sstate.has_top && !sstate.has_left {
466 IPRED8_DC128
467 } else if !sstate.has_left {
468 IPRED8_DC_TOP
469 } else {
470 IPRED8_DC_LEFT
471 };
472 IPRED_FUNCS16X16[id](frm.data, yoff, frm.stride[0]);
473 },
474 MBType::Intra8x8 => {
475 let mut ictx = IPred8Context::new();
476 for part in 0..4 {
477 let x = (part & 1) * 2;
478 let y = part & 2;
479 let blk4 = x + y * 4;
480
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();
487 im_id as usize
488 } else if !has_top && !has_left {
489 IPRED4_DC128
490 } else if !has_left {
491 IPRED4_DC_TOP
492 } else {
493 IPRED4_DC_LEFT
494 };
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);
500 }
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);
504 }
505 }
506 },
507 MBType::Intra4x4 => {
508 for &(x,y) in I4X4_SCAN.iter() {
509 let x = x as usize;
510 let y = y as usize;
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();
517 im_id as usize
518 } else if !has_top && !has_left {
519 IPRED4_DC128
520 } else if !has_left {
521 IPRED4_DC_TOP
522 } else {
523 IPRED4_DC_LEFT
524 };
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]]
530 } else if has_top {
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]]
533 } else {
534 [0; 4]
535 }
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]]
539 } else {
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]]
542 };
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]);
546 }
547 }
548 },
549 _ => unreachable!(),
550 };
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 {
554 IPRED8_DC128
555 } else if !sstate.has_left {
556 IPRED8_DC_TOP
557 } else {
558 IPRED8_DC_LEFT
559 };
560 for chroma in 1..3 {
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]);
563 }
564 }
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 {
568 for y in 0..4 {
569 for x in 0..4 {
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]);
572 }
573 }
574 yoff += frm.stride[0] * 4;
575 }
576 } else {
577 for y in 0..2 {
578 for x in 0..2 {
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);
581 }
582 }
583 yoff += frm.stride[0] * 8;
584 }
585 }
586 }
587 fn add_chroma(frm: &mut NASimpleVideoFrame<u8>, sstate: &SliceState, mb_info: &CurrentMBInfo) {
588 for chroma in 1..3 {
589 let mut off = frm.offset[chroma] + sstate.mb_x * 8 + sstate.mb_y * 8 * frm.stride[chroma];
590 for y in 0..2 {
591 for x in 0..2 {
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]);
595 }
596 }
597 off += frm.stride[chroma] * 4;
598 }
599 }
600 }
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();
605 let mut xoff = 0;
606 let mut yoff = 0;
607 if mb_type == MBType::Direct || mb_type == MBType::BSkip {
608 sstate.predict_direct_mb(frame_refs, temporal_mv, cur_id);
609 }
610 for part in 0..mb_type.num_parts() {
611 if !mb_type.is_l1(part) {
612 match mb_type {
613 MBType::PSkip => sstate.predict_pskip(),
614 MBType::BSkip | MBType::Direct => {
615 },
616 _ => {
617 sstate.predict(xoff, yoff, pw, ph, 0,
618 mb_info.mv_l0[part], mb_info.ref_l0[part]);
619 },
620 };
621 }
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]);
624 }
625 if pw != 16 {
626 xoff += pw;
627 } else {
628 yoff += ph;
629 }
630 }
631 } else {
632 for part in 0..4 {
633 let sub_type = mb_info.sub_mb_type[part];
634 let mut xoff = (part & 1) * 8;
635 let mut yoff = (part & 2) * 4;
636 let orig_x = xoff;
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]);
642 }
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]);
645 }
646 } else {
647 for sblk in 0..4 {
648 sstate.predict_direct_sub(frame_refs, temporal_mv, cur_id, (xoff / 4) + (sblk & 1) + (yoff / 4) * 4 + (sblk & 2) * 2);
649 }
650 }
651 xoff += pw;
652 if xoff == orig_x + 8 {
653 xoff -= 8;
654 yoff += ph;
655 }
656 }
657 }
658 }
659 }
b7c882c1 660 #[allow(clippy::cognitive_complexity)]
696e4e20
KS
661 fn handle_macroblock(&mut self, mb_info: &mut CurrentMBInfo) {
662 let pps = &self.pps[self.cur_pps];
663
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];
669
670 let tx_bypass = qp_y == 0 && self.sps[self.cur_sps].qpprime_y_zero_transform_bypass;
671
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;
678 }
679 let has_dc = mb_info.mb_type.is_intra16x16() && mb_info.coded[24];
680 if has_dc {
681 idct_luma_dc(&mut mb_info.coeffs[24], qp_y);
682 for i in 0..16 {
683 mb_info.coeffs[i][0] = mb_info.coeffs[24][i];
684 }
685 }
686 if !mb_info.transform_size_8x8 {
687 let quant_dc = !mb_info.mb_type.is_intra16x16();
688 for i in 0..16 {
689 if mb_info.coded[i] {
690 if !tx_bypass {
691 idct(&mut mb_info.coeffs[i], qp_y, quant_dc);
692 }
693 } else if has_dc {
694 if !tx_bypass {
695 idct_dc(&mut mb_info.coeffs[i], qp_y, quant_dc);
696 }
697 mb_info.coded[i] = true;
698 }
699 }
700 } else {
701 for i in 0..4 {
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);
705 }
706 }
707 }
708 for chroma in 0..2 {
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);
712 }
713 for i in 0..4 {
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;
721 }
722 }
723 }
724 if !pps.entropy_coding_mode || mb_info.mb_type.is_skip() || mb_info.mb_type.is_intra() {
725 self.sstate.reset_mb_mv();
726 }
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);
729 }
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);
732 }
733
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);
741 },
742 MBType::Intra4x4 | MBType::Intra8x8 => {
743 Self::pred_intra(&mut frm, &self.sstate, &mb_info);
744 },
745 MBType::PCM => {},
746 MBType::PSkip => {
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);
750 },
751 MBType::P16x16 => {
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);
755 },
756 MBType::P16x8 | MBType::P8x16 => {
757 let (bw, bh, bx, by) = if mb_info.mb_type == MBType::P16x8 {
758 (16, 8, 0, 8)
759 } else {
760 (8, 16, 8, 0)
761 };
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);
768 },
769 MBType::P8x8 | MBType::P8x8Ref0 => {
770 for part in 0..4 {
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];
775
776 match mb_info.sub_mb_type[part] {
777 SubMBType::P8x8 => {
778 do_mc(&mut frm, buf, xpos + bx, ypos + by, 8, 8, mv);
779 },
780 SubMBType::P8x4 => {
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);
784 },
785 SubMBType::P4x8 => {
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);
789 },
790 SubMBType::P4x4 => {
791 for sb_no in 0..4 {
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);
797 }
798 },
799 _ => unreachable!(),
800 };
801 } else {
802 gray_block(&mut frm, xpos + bx, ypos + by, 8, 8);
803 }
804 }
805 },
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);
812 },
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);
818 for part in 0..2 {
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);
825 bx += px;
826 by += py;
827 }
828 },
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);
837 } else {
838 for blk4 in 0..16 {
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);
844 }
845 }
846 self.sstate.apply_to_blk8(|blk8| { blk8.ref_idx[0].set_direct(); blk8.ref_idx[1].set_direct(); });
847 },
848 MBType::B8x8 => {
849 for part in 0..4 {
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;
857 match subtype {
858 SubMBType::Direct8x8 => {
859 for blk in 0..4 {
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);
865 bx += 4;
866 if blk == 1 {
867 bx -= 8;
868 by += 4;
869 }
870 }
871 self.sstate.get_cur_blk8(part).ref_idx[0].set_direct();
872 self.sstate.get_cur_blk8(part).ref_idx[1].set_direct();
873 },
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);
877 },
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);
885 },
886 SubMBType::B4x4(mode) => {
887 for i in 0..4 {
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);
891 bx += 4;
892 if i == 1 {
893 bx -= 8;
894 by += 4;
895 }
896 }
897 },
898 _ => unreachable!(),
899 };
900 }
901 },
902 };
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);
906 }
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);
909 }
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);
912 }
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);
916 }
917 Self::add_chroma(&mut frm, &self.sstate, &mb_info);
918 }
919/*match mb_info.mb_type {
920MBType::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) {
925 row[0] = 255;
926 }
927},
928_ => {},
929};*/
930 }
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();
936 for blk4 in 0..16 {
937 mb.mv[blk4] = self.sstate.get_cur_blk4(blk4).mv;
938 }
939 for blk8 in 0..4 {
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;
942 }
943 mv_info.mbs[mb_pos] = mb;
944 }
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);
950 }
951 }
952 self.sstate.next_mb();
953 }
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);
957 } else {
958 gray_block(frm, xpos, ypos, w, h);
959 }
960 }
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>) {
962 match mode {
963 BMode::L0 => {
964 if let Some(buf) = ref_pic0 {
965 do_mc(frm, buf, xpos, ypos, w, h, mv0);
966 } else {
967 gray_block(frm, xpos, ypos, w, h);
968 }
969 },
970 BMode::L1 => {
971 if let Some(buf) = ref_pic1 {
972 do_mc(frm, buf, xpos, ypos, w, h, mv1);
973 } else {
974 gray_block(frm, xpos, ypos, w, h);
975 }
976 },
977 BMode::Bi => {
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);
982 },
983 (Some(buf0), None) => {
984 do_mc(frm, buf0, xpos, ypos, w, h, mv0);
985 },
986 (None, Some(buf1)) => {
987 do_mc(frm, buf1, xpos, ypos, w, h, mv1);
988 },
989 (None, None) => {
990 gray_block(frm, xpos, ypos, w, h);
991 },
992 };
993 },
994 };
995 }
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
1001 ];
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
1006 ];
1007
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];
1019 mb_info.cbpy = 0;
1020 mb_info.cbpc = 0;
1021
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);
1028 mb_idx += 1;
1029 }
1030 if mb_idx == self.num_mbs || br.tell() >= full_size {
1031 break;
1032 }
1033 }
1034 if br.tell() < full_size {
1035 if self.is_mbaff && ((mb_idx & 1) == 0) {
1036 let _mb_field_decoding = br.read_bool()?;
1037 }
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 {
1042 br.align();
1043 for pix in self.ipcm_buf[..256 + 64 + 64].iter_mut() {
1044 *pix = br.read(8)? as u8;
1045 }
1046 self.sstate.fill_ncoded(16);
1047 } else {
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;
1053 }
1054 }
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 {
1057 (cbpy, cbpc)
1058 } else {
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 {
1062 INTRA_CBP[cbp_id]
1063 } else {
1064 INTER_CBP[cbp_id]
1065 };
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()?;
1068 }
1069 ((cbp & 0xF), (cbp >> 4))
1070 };
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 {
1079 (new_qp + 52) as u8
1080 } else if new_qp >= 52 {
1081 (new_qp - 52) as u8
1082 } else {
1083 new_qp as u8
1084 };
1085 mb_info.coeffs = [[0; 16]; 25];
1086 if self.transform_8x8_mode {
1087 mb_info.clear_coeffs8x8();
1088 }
1089 mb_info.chroma_dc = [[0; 4]; 2];
1090 decode_residual_cavlc(br, &mut self.sstate, &mut mb_info, &self.cavlc_cb)?;
1091 }
1092 }
1093 self.handle_macroblock(&mut mb_info);
1094 }
1095 mb_idx += 1;
1096 }
1097 if let Some(ref mut pic) = self.cur_pic {
1098 pic.cur_mb = mb_idx;
1099 }
1100 Ok(mb_idx == self.num_mbs)
1101 }
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;
1107
1108 let mut mb_info = CurrentMBInfo::default();
1109 mb_info.qp_y = slice_hdr.slice_qp;
1110
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];
1118 mb_info.cbpy = 0;
1119 mb_info.cbpc = 0;
1120 let mb_skip = cabac_decode_mbskip(cabac, &self.sstate, slice_hdr);
1121 if !mb_skip {
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);
1124 }
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;
1133 cabac.reinit()?;
1134 last_qp_diff = false;
1135 } else {
1136 if self.transform_8x8_mode && mb_type == MBType::Intra4x4 {
1137 let mut ctx = 0;
1138 if self.sstate.get_top_mb().transform_8x8 {
1139 ctx += 1;
1140 }
1141 if self.sstate.get_left_mb().transform_8x8 {
1142 ctx += 1;
1143 }
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;
1148 }
1149 }
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 {
1152 (cbpy, cbpc)
1153 } else {
1154 decode_cbp_cabac(cabac, &self.sstate)
1155 };
1156 if self.transform_8x8_mode && cbpy != 0 && mb_info.can_have_8x8_tx(self.sps[self.cur_sps].direct_8x8_inference) {
1157 let mut ctx = 0;
1158 if self.sstate.get_top_mb().transform_8x8 {
1159 ctx += 1;
1160 }
1161 if self.sstate.get_left_mb().transform_8x8 {
1162 ctx += 1;
1163 }
1164 mb_info.transform_size_8x8 = cabac.decode_bit(399 + ctx);
1165 }
1166 if mb_type.is_intra() {
1167 self.sstate.get_cur_mb().cmode = mb_info.chroma_ipred;
1168 }
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 {
1178 (new_qp + 52) as u8
1179 } else if new_qp >= 52 {
1180 (new_qp - 52) as u8
1181 } else {
1182 new_qp as u8
1183 };
1184 mb_info.coeffs = [[0; 16]; 25];
1185 if self.transform_8x8_mode {
1186 mb_info.clear_coeffs8x8();
1187 }
1188 mb_info.chroma_dc = [[0; 4]; 2];
1189 decode_residual_cabac(cabac, &mut self.sstate, &mut mb_info);
1190 } else {
1191 last_qp_diff = false;
1192 }
1193 }
1194 } else {
1195 mb_info.mb_type = skip_type;
1196 mb_info.transform_size_8x8 = false;
1197 last_qp_diff = false;
1198 }
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;
1204 }
1205 return Ok(mb_idx + 1 == self.num_mbs);
1206 }
1207 mb_idx += 1;
1208 }
1209 Err(DecoderError::InvalidData)
1210 }
1211}
1212
1213impl 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();
1219
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();
1226
1227 br.read_skip(4)?;
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)?;
1245 br.read_skip(len)?;
1246 }
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)?;
1254 br.read_skip(len)?;
1255 }
1256 if br.left() > 0 {
1257 match profile {
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;
1271 // parse spsext
1272 br.read_skip(len)?;
1273 }
1274 },
1275 _ => {},
1276 };
1277 }
1278 } else {
1279 return Err(DecoderError::NotImplemented);
1280 }
1281
1282 self.width = vinfo.get_width();
1283 self.height = vinfo.get_height();
1284
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;
1288 }
1289
1290 let num_bufs = if !self.sps.is_empty() {
1291 self.sps[0].num_ref_frames as usize + 1
1292 } else {
1293 3
1294 }.max(16 + 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)?;
1297
1298 Ok(())
1299 } else {
1300println!("???");
1301 Err(DecoderError::InvalidData)
1302 }
1303 }
1304 fn decode(&mut self, supp: &mut NADecoderSupport, pkt: &NAPacket) -> DecoderResult<NAFrameRef> {
1305 let src = pkt.get_buffer();
1306
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!(),
1322 };
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 {
1333 is_ref = true;
1334 }
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,
1339 _ => pic_type,
1340 };
1341 }
1342 br.read_skip(size)?;
1343 }
1344 match self.skip_mode {
1345 FrameSkipMode::IntraOnly => {
1346 skip_decoding = pic_type != FrameType::I;
1347 },
1348 FrameSkipMode::KeyframesOnly => {
1349 if !is_ref {
1350 skip_decoding = true;
1351 }
1352 },
1353 _ => {},
1354 };
1355 br.seek(SeekFrom::Start(0))?;
1356 }
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!(),
1364 };
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)?;
1370 }
1371 } else {
1372//todo NAL detection
1373 unimplemented!();
1374 }
1375
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)));
1381 if cpic.is_ref {
1382 self.frame_refs.add_short_term(cpic.clone(), self.sps[self.cur_sps].num_ref_frames);
1383 }
1384 if let Some(lt_idx) = cpic.long_term {
1385 self.frame_refs.add_long_term(lt_idx, cpic);
1386 }
1387 ret
1388 } else {
1389 (NABufferType::None, FrameType::Skip, None)
1390 };
1391
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));
1396 }
1397 if let Some(dts) = dts {
1398 frm.set_id(dts as i64);
1399 }
1400 frm.set_frame_type(ftype);
1401 Ok(frm.into_ref())
1402 }
1403 fn flush(&mut self) {
1404 }
1405}
1406
1407const DEBLOCK_SKIP_OPTION: &str = "skip_deblock";
1408
1409const 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
1419 ])) },
1420];
1421
1422impl 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;
1432 }
1433 },
1434 (DEBLOCK_SKIP_OPTION, NAValue::Bool(val)) => {
1435 self.deblock_skip = *val;
1436 },
1437 _ => {},
1438 }
1439 }
1440 }
1441 }
1442 }
1443 fn query_option_value(&self, name: &str) -> Option<NAValue> {
1444 match name {
1445 FRAME_SKIP_OPTION => Some(NAValue::String(self.skip_mode.to_string())),
1446 DEBLOCK_SKIP_OPTION => Some(NAValue::Bool(self.deblock_skip)),
1447 _ => None,
1448 }
1449 }
1450}
1451
1452pub fn get_decoder() -> Box<dyn NADecoder + Send> {
1453 Box::new(H264Decoder::new())
1454}
1455
1456#[cfg(test)]
1457mod test {
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;
1463
1464 mod raw_demux;
1465 mod conformance;
1466 use self::raw_demux::RawH264DemuxerCreator;
1467
1468 #[test]
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);
1475
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]]));
1504 }
1505
1506 #[test]
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);
1513
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]]));
1578 }
1579 #[test]
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]]));
1600 }
1601}
1602
1603pub 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)
1606];