mostly working ITU H.264 decoder
[nihav.git] / nihav-itu / src / codecs / h264 / mod.rs
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 */
8 use nihav_core::codecs::*;
9 use nihav_core::io::byteio::*;
10 use nihav_core::io::bitreader::*;
11 use nihav_core::io::intcode::*;
12 use nihav_codec_support::codecs::{MV, ZERO_MV};
13
14 mod types;
15 pub use types::*;
16 mod pic_ref;
17 pub use pic_ref::*;
18 mod dsp;
19 use dsp::*;
20 mod cabac;
21 use cabac::*;
22 mod cabac_coder;
23 use cabac_coder::*;
24 mod cavlc;
25 use cavlc::*;
26 mod loopfilter;
27 use loopfilter::*;
28 mod sets;
29 use sets::*;
30 mod slice;
31 use slice::*;
32
33 trait ReadUE {
34 fn read_ue(&mut self) -> DecoderResult<u32>;
35 fn read_te(&mut self, range: u32) -> DecoderResult<u32>;
36 fn read_ue_lim(&mut self, max_val: u32) -> DecoderResult<u32> {
37 let val = self.read_ue()?;
38 validate!(val <= max_val);
39 Ok(val)
40 }
41 fn read_se(&mut self) -> DecoderResult<i32> {
42 let val = self.read_ue()?;
43 if (val & 1) != 0 {
44 Ok (((val >> 1) as i32) + 1)
45 } else {
46 Ok (-((val >> 1) as i32))
47 }
48 }
49 }
50
51 impl<'a> ReadUE for BitReader<'a> {
52 fn read_ue(&mut self) -> DecoderResult<u32> {
53 Ok(self.read_code(UintCodeType::GammaP)? - 1)
54 }
55 fn read_te(&mut self, range: u32) -> DecoderResult<u32> {
56 if range == 1 {
57 if self.read_bool()? {
58 Ok(0)
59 } else {
60 Ok(1)
61 }
62 } else {
63 let val = self.read_ue()?;
64 validate!(val <= range);
65 Ok(val)
66 }
67 }
68 }
69
70 #[derive(Clone,Copy)]
71 pub struct Coeff8x8 {
72 pub coeffs: [i16; 64],
73 }
74
75 impl Coeff8x8 {
76 fn clear(&mut self) {
77 self.coeffs = [0; 64];
78 }
79 }
80
81 impl Default for Coeff8x8 {
82 fn default() -> Self {
83 Self {
84 coeffs: [0; 64],
85 }
86 }
87 }
88
89 #[derive(Clone,Copy,Default)]
90 pub struct CurrentMBInfo {
91 pub mb_type: MBType,
92 pub sub_mb_type: [SubMBType; 4],
93 pub ipred: [IntraPredMode; 16],
94 pub chroma_ipred: u8,
95 pub luma_ipred: [u8; 16],
96 pub mv_l0: [MV; 16],
97 pub ref_l0: [PicRef; 4],
98 pub mv_l1: [MV; 16],
99 pub ref_l1: [PicRef; 4],
100 pub qp_y: u8,
101 pub cbpy: u8,
102 pub cbpc: u8,
103 pub coeffs: [[i16; 16]; 25],
104 pub coeffs8x8: [Coeff8x8; 4],
105 pub chroma_dc: [[i16; 4]; 2],
106 pub coded: [bool; 25],
107 pub transform_size_8x8: bool,
108 }
109
110 impl CurrentMBInfo {
111 fn clear_coeffs8x8(&mut self) {
112 for c in self.coeffs8x8.iter_mut() {
113 c.clear();
114 }
115 }
116 fn can_have_8x8_tx(&self, inference_flag: bool) -> bool {
117 match self.mb_type {
118 MBType::Intra4x4 | MBType::Intra8x8 | MBType::Intra16x16(_, _, _) | MBType::PCM => false,
119 MBType::P8x8 | MBType::P8x8Ref0 | MBType::B8x8 => {
120 for &sub_id in self.sub_mb_type.iter() {
121 match sub_id {
122 SubMBType::P8x8 |
123 SubMBType::B8x8(_)
124 => {},
125 SubMBType::Direct8x8
126 => if !inference_flag { return false; },
127 _ => return false,
128 };
129 }
130 true
131 },
132 MBType::Direct => inference_flag,
133 _ => true,
134 }
135 }
136 }
137
138 fn get_long_term_id(is_idr: bool, slice_hdr: &SliceHeader) -> Option<usize> {
139 if is_idr && !slice_hdr.long_term_reference {
140 None
141 } else {
142 let marking = &slice_hdr.adaptive_ref_pic_marking;
143 for (&op, &arg) in marking.memory_management_control_op.iter().zip(marking.operation_arg.iter()).take(marking.num_ops) {
144 if op == 6 {
145 return Some(arg as usize);
146 }
147 }
148 None
149 }
150 }
151
152 struct H264Decoder {
153 info: NACodecInfoRef,
154 width: usize,
155 height: usize,
156 num_mbs: usize,
157 nal_len: u8,
158 sps: Vec<SeqParameterSet>,
159 cur_sps: usize,
160 pps: Vec<PicParameterSet>,
161 cur_pps: usize,
162
163 skip_mode: FrameSkipMode,
164 deblock_skip: bool,
165
166 is_mbaff: bool,
167
168 cavlc_cb: CAVLCTables,
169
170 sstate: SliceState,
171
172 cur_pic: Option<PictureInfo>,
173 cur_id: u16,
174 has_pic: bool,
175 frame_refs: FrameRefs,
176
177 temporal_mv: bool,
178 deblock_mode: u8,
179 lf_alpha: i8,
180 lf_beta: i8,
181 is_s: bool,
182
183 ipcm_buf: [u8; 256 + 64 + 64],
184
185 avg_buf: NAVideoBufferRef<u8>,
186
187 transform_8x8_mode: bool,
188 }
189
190 fn unescape_nal(src: &[u8], dst: &mut Vec<u8>) -> usize {
191 let mut off = 0;
192 let mut zrun = 0;
193 dst.truncate(0);
194 dst.reserve(src.len());
195 while off < src.len() {
196 dst.push(src[off]);
197 if src[off] != 0 {
198 zrun = 0;
199 } else {
200 zrun += 1;
201 if zrun == 2 && off + 1 < src.len() && src[off + 1] == 0x03 {
202 zrun = 0;
203 off += 1;
204 }
205 if zrun >= 3 && off + 1 < src.len() && src[off + 1] == 0x01 {
206 off -= 3;
207 dst.truncate(off);
208 break;
209 }
210 }
211 off += 1;
212 }
213 off
214 }
215
216 impl H264Decoder {
217 fn new() -> Self {
218 let avg_vi = NAVideoInfo { width: 32, height: 32, flipped: false, format: YUV420_FORMAT, bits: 12 };
219 let avg_buf = alloc_video_buffer(avg_vi, 4).unwrap().get_vbuf().unwrap();
220 H264Decoder{
221 info: NACodecInfoRef::default(),
222 width: 0,
223 height: 0,
224 num_mbs: 0,
225 nal_len: 0,
226 sps: Vec::with_capacity(1),
227 cur_sps: 0,
228 pps: Vec::with_capacity(3),
229 cur_pps: 0,
230
231 skip_mode: FrameSkipMode::default(),
232 deblock_skip: false,
233
234 is_mbaff: false,
235
236 cavlc_cb: CAVLCTables::new(),
237
238 sstate: SliceState::new(),
239 cur_pic: None,
240 cur_id: 0,
241 has_pic: false,
242 frame_refs: FrameRefs::new(),
243
244 temporal_mv: false,
245 deblock_mode: 0,
246 lf_alpha: 0,
247 lf_beta: 0,
248 is_s: false,
249
250 ipcm_buf: [0; 256 + 64 + 64],
251
252 avg_buf,
253
254 transform_8x8_mode: false,
255 }
256 }
257 fn handle_nal(&mut self, src: &[u8], supp: &mut NADecoderSupport, skip_decoding: bool) -> DecoderResult<()> {
258 validate!(!src.is_empty());
259 validate!((src[0] & 0x80) == 0);
260 let nal_ref_idc = src[0] >> 5;
261 let nal_unit_type = src[0] & 0x1F;
262
263 let mut full_size = src.len() * 8;
264 for &byte in src.iter().rev() {
265 if byte == 0 {
266 full_size -= 8;
267 } else {
268 full_size -= (byte.trailing_zeros() + 1) as usize;
269 break;
270 }
271 }
272 validate!(full_size > 0);
273 match nal_unit_type {
274 1 | 5 if !skip_decoding => {
275 let is_idr = nal_unit_type == 5;
276 let mut br = BitReader::new(&src[..(full_size + 7)/8], BitReaderMode::BE);
277 br.skip(8)?;
278
279 let slice_hdr = parse_slice_header(&mut br, &self.sps, &self.pps, is_idr, nal_ref_idc)?;
280 validate!(br.tell() < full_size);
281 let full_id;
282 if slice_hdr.first_mb_in_slice == 0 {
283 validate!(self.cur_pic.is_none());
284 for (i, pps) in self.pps.iter().enumerate() {
285 if pps.pic_parameter_set_id == slice_hdr.pic_parameter_set_id {
286 self.cur_pps = i;
287 break;
288 }
289 }
290 for (i, sps) in self.sps.iter().enumerate() {
291 if sps.seq_parameter_set_id == self.pps[self.cur_pps].seq_parameter_set_id {
292 self.cur_sps = i;
293 break;
294 }
295 }
296
297 full_id = self.frame_refs.calc_picture_num(&slice_hdr, is_idr, nal_ref_idc, &self.sps[self.cur_sps]);
298
299 let sps = &self.sps[self.cur_sps];
300 if sps.chroma_format_idc != 1 || sps.bit_depth_luma != 8 || sps.bit_depth_chroma != 8 {
301 println!(" chroma fmt {} bits {}/{}", sps.chroma_format_idc, sps.bit_depth_luma, sps.bit_depth_chroma);
302 return Err(DecoderError::NotImplemented);
303 }
304 //let pps = &self.pps[self.cur_pps];
305
306 if is_idr {
307 self.frame_refs.clear_refs();
308 }
309
310 self.width = sps.pic_width_in_mbs << 4;
311 self.height = sps.pic_height_in_mbs << 4;
312 self.num_mbs = sps.pic_width_in_mbs * sps.pic_height_in_mbs;
313
314 self.is_mbaff = sps.mb_adaptive_frame_field && !slice_hdr.field_pic;
315 if self.is_mbaff {
316 println!("MBAFF");
317 return Err(DecoderError::NotImplemented);
318 }
319 if !sps.frame_mbs_only {
320 println!("PAFF?");
321 return Err(DecoderError::NotImplemented);
322 }
323
324 //if slice_hdr.slice_type.is_b() { return Ok(()); }
325 self.cur_id = full_id as u16;
326 } else {
327 if let Some(ref mut pic) = self.cur_pic {
328 validate!(pic.cur_mb == slice_hdr.first_mb_in_slice);
329 let new_type = slice_hdr.slice_type.to_frame_type();
330 pic.pic_type = match (pic.pic_type, new_type) {
331 (FrameType::I, _) => new_type,
332 (_, FrameType::B) => FrameType::B,
333 _ => pic.pic_type,
334 };
335 full_id = pic.full_id;
336 } else {
337 return Ok(());//Err(DecoderError::InvalidData);
338 }
339 validate!(self.cur_pps < self.pps.len() && self.pps[self.cur_pps].pic_parameter_set_id == slice_hdr.pic_parameter_set_id);
340 }
341
342 let sps = &self.sps[self.cur_sps];
343 let pps = &self.pps[self.cur_pps];
344
345 self.temporal_mv = !slice_hdr.direct_spatial_mv_pred;
346 self.is_s = slice_hdr.slice_type == SliceType::SI || slice_hdr.slice_type == SliceType::SP;
347 self.deblock_mode = slice_hdr.disable_deblocking_filter_idc;
348 self.lf_alpha = slice_hdr.slice_alpha_c0_offset;
349 self.lf_beta = slice_hdr.slice_beta_offset;
350
351 self.frame_refs.select_refs(sps, &slice_hdr, full_id);
352
353 if slice_hdr.adaptive_ref_pic_marking_mode {
354 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)?;
355 }
356 if slice_hdr.first_mb_in_slice == 0 {
357 let ret = supp.pool_u8.get_free();
358 if ret.is_none() {
359 return Err(DecoderError::AllocError);
360 }
361 let tmp_vinfo = NAVideoInfo::new(self.width, self.height, false, YUV420_FORMAT);
362 let mut buf = ret.unwrap();
363 if buf.get_info() != tmp_vinfo {
364 supp.pool_u8.reset();
365 supp.pool_u8.prealloc_video(tmp_vinfo, 4)?;
366 let ret = supp.pool_u8.get_free();
367 if ret.is_none() {
368 return Err(DecoderError::AllocError);
369 }
370 buf = ret.unwrap();
371 }
372 self.cur_pic = Some(PictureInfo {
373 id: slice_hdr.frame_num,
374 full_id,
375 pic_type: slice_hdr.slice_type.to_frame_type(),
376 buf,
377 cur_mb: 0,
378 is_ref: nal_ref_idc != 0,
379 long_term: get_long_term_id(is_idr, &slice_hdr),
380 mv_info: FrameMV::new(sps.pic_width_in_mbs, sps.pic_height_in_mbs),
381 });
382 }
383
384 self.transform_8x8_mode = pps.transform_8x8_mode;
385
386 self.sstate.reset(sps.pic_width_in_mbs, sps.pic_height_in_mbs, slice_hdr.first_mb_in_slice);
387 if !pps.entropy_coding_mode {
388 self.has_pic = self.decode_slice_cavlc(&mut br, &slice_hdr, full_size)?;
389 } else {
390 br.align();
391 let start = (br.tell() / 8) as usize;
392 let csrc = &src[start..];
393 validate!(csrc.len() >= 2);
394 let mut cabac = CABAC::new(csrc, slice_hdr.slice_type, slice_hdr.slice_qp, slice_hdr.cabac_init_idc as usize)?;
395 self.has_pic = self.decode_slice_cabac(&mut cabac, &slice_hdr)?;
396 }
397 if !self.deblock_skip && self.deblock_mode != 1 {
398 if let Some(ref mut pic) = self.cur_pic {
399 let mut frm = NASimpleVideoFrame::from_video_buf(&mut pic.buf).unwrap();
400 if self.sstate.mb_x != 0 {
401 loop_filter_row(&mut frm, &self.sstate, self.lf_alpha, self.lf_beta);
402 }
403 loop_filter_last(&mut frm, &self.sstate, self.lf_alpha, self.lf_beta);
404 }
405 }
406 },
407 2 => { // slice data partition A
408 //slice header
409 //slice id = read_ue()
410 //cat 2 slice data (all but MB layer residual)
411 return Err(DecoderError::NotImplemented);
412 },
413 3 => { // slice data partition B
414 //slice id = read_ue()
415 //if pps.redundant_pic_cnt_present { redundant_pic_cnt = read_ue() }
416 //cat 3 slice data (MB layer residual)
417 return Err(DecoderError::NotImplemented);
418 },
419 4 => { // slice data partition C
420 //slice id = read_ue()
421 //if pps.redundant_pic_cnt_present { redundant_pic_cnt = read_ue() }
422 //cat 4 slice data (MB layer residual)
423 return Err(DecoderError::NotImplemented);
424 },
425 6 => {}, //SEI
426 7 => {
427 let sps = parse_sps(&src[1..])?;
428 self.sps.push(sps);
429 },
430 8 => {
431 validate!(full_size >= 8 + 16);
432 let pps = parse_pps(&src[1..], &self.sps, full_size - 8)?;
433 let mut found = false;
434 for stored_pps in self.pps.iter_mut() {
435 if stored_pps.pic_parameter_set_id == pps.pic_parameter_set_id {
436 *stored_pps = pps.clone();
437 found = true;
438 break;
439 }
440 }
441 if !found {
442 self.pps.push(pps);
443 }
444 },
445 9 => { // access unit delimiter
446 },
447 10 => {}, //end of sequence
448 11 => {}, //end of stream
449 12 => {}, //filler
450 _ => {},
451 };
452
453 Ok(())
454 }
455 fn pred_intra(frm: &mut NASimpleVideoFrame<u8>, sstate: &SliceState, mb_info: &CurrentMBInfo) {
456 let yoff = frm.offset[0] + sstate.mb_x * 16 + sstate.mb_y * 16 * frm.stride[0];
457 match mb_info.mb_type {
458 MBType::Intra16x16(imode, _, _) => {
459 let id = if imode != 2 || (sstate.has_top && sstate.has_left) {
460 imode as usize
461 } else if !sstate.has_top && !sstate.has_left {
462 IPRED8_DC128
463 } else if !sstate.has_left {
464 IPRED8_DC_TOP
465 } else {
466 IPRED8_DC_LEFT
467 };
468 IPRED_FUNCS16X16[id](frm.data, yoff, frm.stride[0]);
469 },
470 MBType::Intra8x8 => {
471 let mut ictx = IPred8Context::new();
472 for part in 0..4 {
473 let x = (part & 1) * 2;
474 let y = part & 2;
475 let blk4 = x + y * 4;
476
477 let cur_yoff = yoff + x * 4 + y * 4 * frm.stride[0];
478 let has_top = y > 0 || sstate.has_top;
479 let has_left = x > 0 || sstate.has_left;
480 let imode = mb_info.ipred[blk4];
481 let id = if imode != IntraPredMode::DC || (has_top && has_left) {
482 let im_id: u8 = imode.into();
483 im_id as usize
484 } else if !has_top && !has_left {
485 IPRED4_DC128
486 } else if !has_left {
487 IPRED4_DC_TOP
488 } else {
489 IPRED4_DC_LEFT
490 };
491 let mb_idx = sstate.mb_x + sstate.mb_y * sstate.mb_w;
492 let noright = (y == 2 || sstate.mb_x == sstate.mb_w - 1 || mb_idx < sstate.mb_start + sstate.mb_w) && (x == 2);
493 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);
494 if id != IPRED4_DC128 {
495 ictx.fill(frm.data, cur_yoff, frm.stride[0], has_top, has_top && !noright, has_left, has_tl);
496 }
497 IPRED_FUNCS8X8_LUMA[id](&mut frm.data[cur_yoff..], frm.stride[0], &ictx);
498 if mb_info.coded[blk4] {
499 add_coeffs8(frm.data, cur_yoff, frm.stride[0], &mb_info.coeffs8x8[part].coeffs);
500 }
501 }
502 },
503 MBType::Intra4x4 => {
504 for &(x,y) in I4X4_SCAN.iter() {
505 let x = x as usize;
506 let y = y as usize;
507 let cur_yoff = yoff + x * 4 + y * 4 * frm.stride[0];
508 let has_top = y > 0 || sstate.has_top;
509 let has_left = x > 0 || sstate.has_left;
510 let imode = mb_info.ipred[x + y * 4];
511 let id = if imode != IntraPredMode::DC || (has_top && has_left) {
512 let im_id: u8 = imode.into();
513 im_id as usize
514 } else if !has_top && !has_left {
515 IPRED4_DC128
516 } else if !has_left {
517 IPRED4_DC_TOP
518 } else {
519 IPRED4_DC_LEFT
520 };
521 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);
522 let tr: [u8; 4] = if y == 0 {
523 if has_top && !noright {
524 let i = cur_yoff - frm.stride[0];
525 [frm.data[i + 4], frm.data[i + 5], frm.data[i + 6], frm.data[i + 7]]
526 } else if has_top {
527 let i = cur_yoff - frm.stride[0];
528 [frm.data[i + 3], frm.data[i + 3], frm.data[i + 3], frm.data[i + 3]]
529 } else {
530 [0; 4]
531 }
532 } else if (x & 1) == 0 || (x == 1 && y == 2) {
533 let i = cur_yoff - frm.stride[0];
534 [frm.data[i + 4], frm.data[i + 5], frm.data[i + 6], frm.data[i + 7]]
535 } else {
536 let i = cur_yoff - frm.stride[0];
537 [frm.data[i + 3], frm.data[i + 3], frm.data[i + 3], frm.data[i + 3]]
538 };
539 IPRED_FUNCS4X4[id](frm.data, cur_yoff, frm.stride[0], &tr);
540 if mb_info.coded[x + y * 4] {
541 add_coeffs(frm.data, cur_yoff, frm.stride[0], &mb_info.coeffs[x + y * 4]);
542 }
543 }
544 },
545 _ => unreachable!(),
546 };
547 let id = if mb_info.chroma_ipred != 0 || (sstate.has_top && sstate.has_left) {
548 mb_info.chroma_ipred as usize
549 } else if !sstate.has_top && !sstate.has_left {
550 IPRED8_DC128
551 } else if !sstate.has_left {
552 IPRED8_DC_TOP
553 } else {
554 IPRED8_DC_LEFT
555 };
556 for chroma in 1..3 {
557 let off = frm.offset[chroma] + sstate.mb_x * 8 + sstate.mb_y * 8 * frm.stride[chroma];
558 IPRED_FUNCS8X8_CHROMA[id](frm.data, off, frm.stride[chroma]);
559 }
560 }
561 fn add_luma(frm: &mut NASimpleVideoFrame<u8>, sstate: &SliceState, mb_info: &CurrentMBInfo) {
562 let mut yoff = frm.offset[0] + sstate.mb_x * 16 + sstate.mb_y * 16 * frm.stride[0];
563 if !mb_info.transform_size_8x8 {
564 for y in 0..4 {
565 for x in 0..4 {
566 if mb_info.coded[x + y * 4] {
567 add_coeffs(frm.data, yoff + x * 4, frm.stride[0], &mb_info.coeffs[x + y * 4]);
568 }
569 }
570 yoff += frm.stride[0] * 4;
571 }
572 } else {
573 for y in 0..2 {
574 for x in 0..2 {
575 if mb_info.coded[x * 2 + y * 2 * 4] {
576 add_coeffs8(frm.data, yoff + x * 8, frm.stride[0], &mb_info.coeffs8x8[x + y * 2].coeffs);
577 }
578 }
579 yoff += frm.stride[0] * 8;
580 }
581 }
582 }
583 fn add_chroma(frm: &mut NASimpleVideoFrame<u8>, sstate: &SliceState, mb_info: &CurrentMBInfo) {
584 for chroma in 1..3 {
585 let mut off = frm.offset[chroma] + sstate.mb_x * 8 + sstate.mb_y * 8 * frm.stride[chroma];
586 for y in 0..2 {
587 for x in 0..2 {
588 let blk_no = 16 + (chroma - 1) * 4 + x + y * 2;
589 if mb_info.coded[blk_no] || mb_info.coeffs[blk_no][0] != 0 {
590 add_coeffs(frm.data, off + x * 4, frm.stride[chroma], &mb_info.coeffs[blk_no]);
591 }
592 }
593 off += frm.stride[chroma] * 4;
594 }
595 }
596 }
597 fn pred_mv(sstate: &mut SliceState, frame_refs: &FrameRefs, mb_info: &mut CurrentMBInfo, cur_id: u16, temporal_mv: bool) {
598 let mb_type = mb_info.mb_type;
599 if !mb_type.is_4x4() {
600 let (pw, ph) = mb_type.size();
601 let mut xoff = 0;
602 let mut yoff = 0;
603 if mb_type == MBType::Direct || mb_type == MBType::BSkip {
604 sstate.predict_direct_mb(frame_refs, temporal_mv, cur_id);
605 }
606 for part in 0..mb_type.num_parts() {
607 if !mb_type.is_l1(part) {
608 match mb_type {
609 MBType::PSkip => sstate.predict_pskip(),
610 MBType::BSkip | MBType::Direct => {
611 },
612 _ => {
613 sstate.predict(xoff, yoff, pw, ph, 0,
614 mb_info.mv_l0[part], mb_info.ref_l0[part]);
615 },
616 };
617 }
618 if !mb_type.is_l0(part) && mb_type != MBType::BSkip && mb_type != MBType::Direct {
619 sstate.predict(xoff, yoff, pw, ph, 1, mb_info.mv_l1[part], mb_info.ref_l1[part]);
620 }
621 if pw != 16 {
622 xoff += pw;
623 } else {
624 yoff += ph;
625 }
626 }
627 } else {
628 for part in 0..4 {
629 let sub_type = mb_info.sub_mb_type[part];
630 let mut xoff = (part & 1) * 8;
631 let mut yoff = (part & 2) * 4;
632 let orig_x = xoff;
633 let (pw, ph) = sub_type.size();
634 for subpart in 0..sub_type.num_parts() {
635 if sub_type != SubMBType::Direct8x8 {
636 if !sub_type.is_l1() {
637 sstate.predict(xoff, yoff, pw, ph, 0, mb_info.mv_l0[part * 4 + subpart], mb_info.ref_l0[part]);
638 }
639 if !sub_type.is_l0() {
640 sstate.predict(xoff, yoff, pw, ph, 1, mb_info.mv_l1[part * 4 + subpart], mb_info.ref_l1[part]);
641 }
642 } else {
643 for sblk in 0..4 {
644 sstate.predict_direct_sub(frame_refs, temporal_mv, cur_id, (xoff / 4) + (sblk & 1) + (yoff / 4) * 4 + (sblk & 2) * 2);
645 }
646 }
647 xoff += pw;
648 if xoff == orig_x + 8 {
649 xoff -= 8;
650 yoff += ph;
651 }
652 }
653 }
654 }
655 }
656 fn handle_macroblock(&mut self, mb_info: &mut CurrentMBInfo) {
657 let pps = &self.pps[self.cur_pps];
658
659 let qp_y = mb_info.qp_y;
660 let qpr = ((qp_y as i8) + pps.chroma_qp_index_offset).max(0).min(51) as usize;
661 let qp_u = CHROMA_QUANTS[qpr];
662 let qpb = ((qp_y as i8) + pps.second_chroma_qp_index_offset).max(0).min(51) as usize;
663 let qp_v = CHROMA_QUANTS[qpb];
664
665 let tx_bypass = qp_y == 0 && self.sps[self.cur_sps].qpprime_y_zero_transform_bypass;
666
667 self.sstate.get_cur_mb().mb_type = mb_info.mb_type.into();
668 if mb_info.mb_type != MBType::PCM {
669 self.sstate.get_cur_mb().qp_y = qp_y;
670 self.sstate.get_cur_mb().qp_u = qp_u;
671 self.sstate.get_cur_mb().qp_v = qp_v;
672 self.sstate.get_cur_mb().transform_8x8 = mb_info.transform_size_8x8;
673 }
674 let has_dc = mb_info.mb_type.is_intra16x16() && mb_info.coded[24];
675 if has_dc {
676 idct_luma_dc(&mut mb_info.coeffs[24], qp_y);
677 for i in 0..16 {
678 mb_info.coeffs[i][0] = mb_info.coeffs[24][i];
679 }
680 }
681 if !mb_info.transform_size_8x8 {
682 let quant_dc = !mb_info.mb_type.is_intra16x16();
683 for i in 0..16 {
684 if mb_info.coded[i] {
685 if !tx_bypass {
686 idct(&mut mb_info.coeffs[i], qp_y, quant_dc);
687 }
688 } else if has_dc {
689 if !tx_bypass {
690 idct_dc(&mut mb_info.coeffs[i], qp_y, quant_dc);
691 }
692 mb_info.coded[i] = true;
693 }
694 }
695 } else {
696 for i in 0..4 {
697 if mb_info.coded[(i & 1) * 2 + (i & 2) * 4] && !tx_bypass {
698 dequant8x8(&mut mb_info.coeffs8x8[i].coeffs, &pps.scaling_list_8x8[!mb_info.mb_type.is_intra() as usize]);
699 idct8x8(&mut mb_info.coeffs8x8[i].coeffs, qp_y);
700 }
701 }
702 }
703 for chroma in 0..2 {
704 let qp_c = if chroma == 0 { qp_u } else { qp_v };
705 if mb_info.cbpc != 0 {
706 chroma_dc_transform(&mut mb_info.chroma_dc[chroma], qp_c);
707 }
708 for i in 0..4 {
709 let blk_no = 16 + chroma * 4 + i;
710 mb_info.coeffs[blk_no][0] = mb_info.chroma_dc[chroma][i];
711 if mb_info.coded[blk_no] {
712 idct(&mut mb_info.coeffs[blk_no], qp_c, false);
713 } else if mb_info.coeffs[blk_no][0] != 0 {
714 idct_dc(&mut mb_info.coeffs[blk_no], qp_c, false);
715 mb_info.coded[blk_no] = true;
716 }
717 }
718 }
719 if !pps.entropy_coding_mode || mb_info.mb_type.is_skip() || mb_info.mb_type.is_intra() {
720 self.sstate.reset_mb_mv();
721 }
722 if !mb_info.mb_type.is_intra() {
723 Self::pred_mv(&mut self.sstate, &self.frame_refs, mb_info, self.cur_id, self.temporal_mv);
724 }
725 if !pps.constrained_intra_pred && mb_info.mb_type != MBType::Intra4x4 && mb_info.mb_type != MBType::Intra8x8 {
726 self.sstate.fill_ipred(IntraPredMode::DC);
727 }
728
729 let xpos = self.sstate.mb_x * 16;
730 let ypos = self.sstate.mb_y * 16;
731 if let Some(ref mut pic) = self.cur_pic {
732 let mut frm = NASimpleVideoFrame::from_video_buf(&mut pic.buf).unwrap();
733 match mb_info.mb_type {
734 MBType::Intra16x16(_, _, _) => {
735 Self::pred_intra(&mut frm, &self.sstate, &mb_info);
736 },
737 MBType::Intra4x4 | MBType::Intra8x8 => {
738 Self::pred_intra(&mut frm, &self.sstate, &mb_info);
739 },
740 MBType::PCM => {},
741 MBType::PSkip => {
742 let mv = self.sstate.get_cur_blk4(0).mv[0];
743 let rpic = self.frame_refs.select_ref_pic(0, 0);
744 Self::do_p_mc(&mut frm, xpos, ypos, 16, 16, mv, rpic);
745 },
746 MBType::P16x16 => {
747 let mv = self.sstate.get_cur_blk4(0).mv[0];
748 let rpic = self.frame_refs.select_ref_pic(0, mb_info.ref_l0[0].index());
749 Self::do_p_mc(&mut frm, xpos, ypos, 16, 16, mv, rpic);
750 },
751 MBType::P16x8 | MBType::P8x16 => {
752 let (bw, bh, bx, by) = if mb_info.mb_type == MBType::P16x8 {
753 (16, 8, 0, 8)
754 } else {
755 (8, 16, 8, 0)
756 };
757 let mv = self.sstate.get_cur_blk4(0).mv[0];
758 let rpic = self.frame_refs.select_ref_pic(0, mb_info.ref_l0[0].index());
759 Self::do_p_mc(&mut frm, xpos, ypos, bw, bh, mv, rpic);
760 let mv = self.sstate.get_cur_blk4(bx / 4 + by).mv[0];
761 let rpic = self.frame_refs.select_ref_pic(0, mb_info.ref_l0[1].index());
762 Self::do_p_mc(&mut frm, xpos + bx, ypos + by, bw, bh, mv, rpic);
763 },
764 MBType::P8x8 | MBType::P8x8Ref0 => {
765 for part in 0..4 {
766 let bx = (part & 1) * 8;
767 let by = (part & 2) * 4;
768 if let Some(buf) = self.frame_refs.select_ref_pic(0, mb_info.ref_l0[part].index()) {
769 let mv = self.sstate.get_cur_blk4(bx / 4 + by).mv[0];
770
771 match mb_info.sub_mb_type[part] {
772 SubMBType::P8x8 => {
773 do_mc(&mut frm, buf, xpos + bx, ypos + by, 8, 8, mv);
774 },
775 SubMBType::P8x4 => {
776 do_mc(&mut frm, buf.clone(), xpos + bx, ypos + by, 8, 4, mv);
777 let mv = self.sstate.get_cur_blk4(bx / 4 + by + 4).mv[0];
778 do_mc(&mut frm, buf, xpos + bx, ypos + by + 4, 8, 4, mv);
779 },
780 SubMBType::P4x8 => {
781 do_mc(&mut frm, buf.clone(), xpos + bx, ypos + by, 4, 8, mv);
782 let mv = self.sstate.get_cur_blk4(bx / 4 + by + 1).mv[0];
783 do_mc(&mut frm, buf, xpos + bx + 4, ypos + by, 4, 8, mv);
784 },
785 SubMBType::P4x4 => {
786 for sb_no in 0..4 {
787 let sxpos = xpos + bx + (sb_no & 1) * 4;
788 let sypos = ypos + by + (sb_no & 2) * 2;
789 let sblk_no = (bx / 4 + (sb_no & 1)) + ((by / 4) + (sb_no >> 1)) * 4;
790 let mv = self.sstate.get_cur_blk4(sblk_no).mv[0];
791 do_mc(&mut frm, buf.clone(), sxpos, sypos, 4, 4, mv);
792 }
793 },
794 _ => unreachable!(),
795 };
796 } else {
797 gray_block(&mut frm, xpos + bx, ypos + by, 8, 8);
798 }
799 }
800 },
801 MBType::B16x16(mode) => {
802 let mv0 = self.sstate.get_cur_blk4(0).mv[0];
803 let rpic0 = self.frame_refs.select_ref_pic(0, mb_info.ref_l0[0].index());
804 let mv1 = self.sstate.get_cur_blk4(0).mv[1];
805 let rpic1 = self.frame_refs.select_ref_pic(1, mb_info.ref_l1[0].index());
806 Self::do_b_mc(&mut frm, mode, xpos, ypos, 16, 16, mv0, rpic0, mv1, rpic1, &mut self.avg_buf);
807 },
808 MBType::B16x8(mode0, mode1) | MBType::B8x16(mode0, mode1) => {
809 let (pw, ph) = mb_info.mb_type.size();
810 let (px, py) = (pw & 8, ph & 8);
811 let modes = [mode0, mode1];
812 let (mut bx, mut by) = (0, 0);
813 for part in 0..2 {
814 let blk = if part == 0 { 0 } else { (px / 4) + py };
815 let mv0 = self.sstate.get_cur_blk4(blk).mv[0];
816 let rpic0 = self.frame_refs.select_ref_pic(0, mb_info.ref_l0[part].index());
817 let mv1 = self.sstate.get_cur_blk4(blk).mv[1];
818 let rpic1 = self.frame_refs.select_ref_pic(1, mb_info.ref_l1[part].index());
819 Self::do_b_mc(&mut frm, modes[part], xpos + bx, ypos + by, pw, ph, mv0, rpic0, mv1, rpic1, &mut self.avg_buf);
820 bx += px;
821 by += py;
822 }
823 },
824 MBType::Direct | MBType::BSkip => {
825 let is_16x16 = self.frame_refs.get_colocated_info(self.sstate.mb_x, self.sstate.mb_y).0.mb_type.is_16x16();
826 if is_16x16 || !self.temporal_mv {
827 let mv = self.sstate.get_cur_blk4(0).mv;
828 let ref_idx = self.sstate.get_cur_blk8(0).ref_idx;
829 let rpic0 = self.frame_refs.select_ref_pic(0, ref_idx[0].index());
830 let rpic1 = self.frame_refs.select_ref_pic(1, ref_idx[1].index());
831 Self::do_b_mc(&mut frm, BMode::Bi, xpos, ypos, 16, 16, mv[0], rpic0, mv[1], rpic1, &mut self.avg_buf);
832 } else {
833 for blk4 in 0..16 {
834 let mv = self.sstate.get_cur_blk4(blk4).mv;
835 let ref_idx = self.sstate.get_cur_blk8(blk4_to_blk8(blk4)).ref_idx;
836 let rpic0 = self.frame_refs.select_ref_pic(0, ref_idx[0].index());
837 let rpic1 = self.frame_refs.select_ref_pic(1, ref_idx[1].index());
838 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);
839 }
840 }
841 self.sstate.apply_to_blk8(|blk8| { blk8.ref_idx[0].set_direct(); blk8.ref_idx[1].set_direct(); });
842 },
843 MBType::B8x8 => {
844 for part in 0..4 {
845 let ridx = self.sstate.get_cur_blk8(part).ref_idx;
846 let rpic0 = self.frame_refs.select_ref_pic(0, ridx[0].index());
847 let rpic1 = self.frame_refs.select_ref_pic(1, ridx[1].index());
848 let subtype = mb_info.sub_mb_type[part];
849 let blk8 = (part & 1) * 2 + (part & 2) * 4;
850 let mut bx = (part & 1) * 8;
851 let mut by = (part & 2) * 4;
852 match subtype {
853 SubMBType::Direct8x8 => {
854 for blk in 0..4 {
855 let mv = self.sstate.get_cur_blk4(bx / 4 + (by / 4) * 4).mv;
856 let ref_idx = self.sstate.get_cur_blk8(bx / 8 + (by / 8) * 2).ref_idx;
857 let rpic0 = self.frame_refs.select_ref_pic(0, ref_idx[0].index());
858 let rpic1 = self.frame_refs.select_ref_pic(1, ref_idx[1].index());
859 Self::do_b_mc(&mut frm, BMode::Bi, xpos + bx, ypos + by, 4, 4, mv[0], rpic0, mv[1], rpic1, &mut self.avg_buf);
860 bx += 4;
861 if blk == 1 {
862 bx -= 8;
863 by += 4;
864 }
865 }
866 self.sstate.get_cur_blk8(part).ref_idx[0].set_direct();
867 self.sstate.get_cur_blk8(part).ref_idx[1].set_direct();
868 },
869 SubMBType::B8x8(mode) => {
870 let mv = self.sstate.get_cur_blk4(blk8).mv;
871 Self::do_b_mc(&mut frm, mode, xpos + bx, ypos + by, 8, 8, mv[0], rpic0, mv[1], rpic1, &mut self.avg_buf);
872 },
873 SubMBType::B8x4(mode) | SubMBType::B4x8(mode) => {
874 let (pw, ph) = subtype.size();
875 let mv = self.sstate.get_cur_blk4(blk8).mv;
876 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);
877 let addr2 = blk8 + (pw & 4) / 4 + (ph & 4);
878 let mv = self.sstate.get_cur_blk4(addr2).mv;
879 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);
880 },
881 SubMBType::B4x4(mode) => {
882 for i in 0..4 {
883 let addr2 = blk8 + (i & 1) + (i & 2) * 2;
884 let mv = self.sstate.get_cur_blk4(addr2).mv;
885 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);
886 bx += 4;
887 if i == 1 {
888 bx -= 8;
889 by += 4;
890 }
891 }
892 },
893 _ => unreachable!(),
894 };
895 }
896 },
897 };
898 if mb_info.mb_type == MBType::PCM {
899 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)) {
900 dline[..16].copy_from_slice(src);
901 }
902 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)) {
903 dline[..8].copy_from_slice(src);
904 }
905 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)) {
906 dline[..8].copy_from_slice(src);
907 }
908 } else if !mb_info.mb_type.is_skip() {
909 if mb_info.mb_type != MBType::Intra4x4 && mb_info.mb_type != MBType::Intra8x8 {
910 Self::add_luma(&mut frm, &self.sstate, &mb_info);
911 }
912 Self::add_chroma(&mut frm, &self.sstate, &mb_info);
913 }
914 /*match mb_info.mb_type {
915 MBType::BSkip | MBType::Direct | MBType::B16x16(_) | MBType::B16x8(_, _) | MBType::B8x16(_, _) | MBType::B8x8 => {
916 let dstride = frm.stride[0];
917 let dst = &mut frm.data[frm.offset[0] + self.sstate.mb_x * 16 + self.sstate.mb_y * 16 * dstride..];
918 for el in dst[..16].iter_mut() { *el = 255; }
919 for row in dst.chunks_mut(dstride).skip(1).take(15) {
920 row[0] = 255;
921 }
922 },
923 _ => {},
924 };*/
925 }
926 if let Some(ref mut pic) = self.cur_pic {
927 let mv_info = &mut pic.mv_info;
928 let mb_pos = self.sstate.mb_x + self.sstate.mb_y * mv_info.mb_stride;
929 let mut mb = FrameMBInfo::new();
930 mb.mb_type = mb_info.mb_type.into();
931 for blk4 in 0..16 {
932 mb.mv[blk4] = self.sstate.get_cur_blk4(blk4).mv;
933 }
934 for blk8 in 0..4 {
935 mb.ref_poc[blk8] = self.frame_refs.map_refs(self.sstate.get_cur_blk8(blk8).ref_idx);
936 mb.ref_idx[blk8] = self.sstate.get_cur_blk8(blk8).ref_idx;
937 }
938 mv_info.mbs[mb_pos] = mb;
939 }
940 self.sstate.fill_deblock(self.deblock_mode, self.is_s);
941 if !self.deblock_skip && self.sstate.mb_x + 1 == self.sstate.mb_w && self.deblock_mode != 1 {
942 if let Some(ref mut pic) = self.cur_pic {
943 let mut frm = NASimpleVideoFrame::from_video_buf(&mut pic.buf).unwrap();
944 loop_filter_row(&mut frm, &self.sstate, self.lf_alpha, self.lf_beta);
945 }
946 }
947 self.sstate.next_mb();
948 }
949 fn do_p_mc(frm: &mut NASimpleVideoFrame<u8>, xpos: usize, ypos: usize, w: usize, h: usize, mv: MV, ref_pic: Option<NAVideoBufferRef<u8>>) {
950 if let Some(buf) = ref_pic {
951 do_mc(frm, buf, xpos, ypos, w, h, mv);
952 } else {
953 gray_block(frm, xpos, ypos, w, h);
954 }
955 }
956 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>) {
957 match mode {
958 BMode::L0 => {
959 if let Some(buf) = ref_pic0 {
960 do_mc(frm, buf, xpos, ypos, w, h, mv0);
961 } else {
962 gray_block(frm, xpos, ypos, w, h);
963 }
964 },
965 BMode::L1 => {
966 if let Some(buf) = ref_pic1 {
967 do_mc(frm, buf, xpos, ypos, w, h, mv1);
968 } else {
969 gray_block(frm, xpos, ypos, w, h);
970 }
971 },
972 BMode::Bi => {
973 match (ref_pic0, ref_pic1) {
974 (Some(buf0), Some(buf1)) => {
975 do_mc(frm, buf0, xpos, ypos, w, h, mv0);
976 do_mc_avg(frm, buf1, xpos, ypos, w, h, mv1, avg_buf);
977 },
978 (Some(buf0), None) => {
979 do_mc(frm, buf0, xpos, ypos, w, h, mv0);
980 },
981 (None, Some(buf1)) => {
982 do_mc(frm, buf1, xpos, ypos, w, h, mv1);
983 },
984 (None, None) => {
985 gray_block(frm, xpos, ypos, w, h);
986 },
987 };
988 },
989 };
990 }
991 fn decode_slice_cavlc(&mut self, br: &mut BitReader, slice_hdr: &SliceHeader, full_size: usize) -> DecoderResult<bool> {
992 const INTRA_CBP: [u8; 48] = [
993 47, 31, 15, 0, 23, 27, 29, 30, 7, 11, 13, 14, 39, 43, 45, 46,
994 16, 3, 5, 10, 12, 19, 21, 26, 28, 35, 37, 42, 44, 1, 2, 4,
995 8, 17, 18, 20, 24, 6, 9, 22, 25, 32, 33, 34, 36, 40, 38, 41
996 ];
997 const INTER_CBP: [u8; 48] = [
998 0, 16, 1, 2, 4, 8, 32, 3, 5, 10, 12, 15, 47, 7, 11, 13,
999 14, 6, 9, 31, 35, 37, 42, 44, 33, 34, 36, 40, 39, 43, 45, 46,
1000 17, 18, 20, 24, 19, 21, 26, 28, 23, 27, 29, 30, 22, 25, 38, 41
1001 ];
1002
1003 let mut mb_idx = slice_hdr.first_mb_in_slice as usize;
1004 let mut mb_info = CurrentMBInfo::default();
1005 mb_info.qp_y = slice_hdr.slice_qp;
1006 let skip_type = if slice_hdr.slice_type.is_p() { MBType::PSkip } else { MBType::BSkip };
1007 while br.tell() < full_size && mb_idx < self.num_mbs {
1008 mb_info.coded = [false; 25];
1009 mb_info.ref_l0 = [ZERO_REF; 4];
1010 mb_info.ref_l1 = [ZERO_REF; 4];
1011 mb_info.mv_l0 = [ZERO_MV; 16];
1012 mb_info.mv_l1 = [ZERO_MV; 16];
1013 mb_info.chroma_dc = [[0; 4]; 2];
1014 mb_info.cbpy = 0;
1015 mb_info.cbpc = 0;
1016
1017 if !slice_hdr.slice_type.is_intra() {
1018 let mb_skip_run = br.read_ue()? as usize;
1019 validate!(mb_idx + mb_skip_run <= self.num_mbs);
1020 mb_info.mb_type = skip_type;
1021 for _ in 0..mb_skip_run {
1022 self.handle_macroblock(&mut mb_info);
1023 mb_idx += 1;
1024 }
1025 if mb_idx == self.num_mbs || br.tell() >= full_size {
1026 break;
1027 }
1028 }
1029 if br.tell() < full_size {
1030 if self.is_mbaff && ((mb_idx & 1) == 0) {
1031 let _mb_field_decoding = br.read_bool()?;
1032 }
1033 let mut mb_type = decode_mb_type_cavlc(br, slice_hdr)?;
1034 mb_info.mb_type = mb_type;
1035 mb_info.transform_size_8x8 = false;
1036 if mb_type == MBType::PCM {
1037 br.align();
1038 for pix in self.ipcm_buf[..256 + 64 + 64].iter_mut() {
1039 *pix = br.read(8)? as u8;
1040 }
1041 self.sstate.fill_ncoded(16);
1042 } else {
1043 if self.transform_8x8_mode && mb_type == MBType::Intra4x4 {
1044 mb_info.transform_size_8x8 = br.read_bool()?;
1045 if mb_info.transform_size_8x8 {
1046 mb_type = MBType::Intra8x8;
1047 mb_info.mb_type = MBType::Intra8x8;
1048 }
1049 }
1050 decode_mb_pred_cavlc(br, slice_hdr, mb_type, &mut self.sstate, &mut mb_info)?;
1051 let (cbpy, cbpc) = if let MBType::Intra16x16(_, cbpy, cbpc) = mb_type {
1052 (cbpy, cbpc)
1053 } else {
1054 let cbp_id = br.read_ue()? as usize;
1055 validate!(cbp_id < INTRA_CBP.len());
1056 let cbp = if mb_type == MBType::Intra4x4 || mb_type == MBType::Intra8x8 {
1057 INTRA_CBP[cbp_id]
1058 } else {
1059 INTER_CBP[cbp_id]
1060 };
1061 if self.transform_8x8_mode && (cbp & 0xF) != 0 && mb_info.can_have_8x8_tx(self.sps[self.cur_sps].direct_8x8_inference) {
1062 mb_info.transform_size_8x8 = br.read_bool()?;
1063 }
1064 ((cbp & 0xF), (cbp >> 4))
1065 };
1066 mb_info.cbpy = cbpy;
1067 mb_info.cbpc = cbpc;
1068 self.sstate.get_cur_mb().cbp = (cbpc << 4) | cbpy;
1069 if cbpy != 0 || cbpc != 0 || mb_type.is_intra16x16() {
1070 let mb_qp_delta = br.read_se()?;
1071 validate!(mb_qp_delta >= -26 && mb_qp_delta <= 25);
1072 let new_qp = mb_qp_delta + i32::from(mb_info.qp_y);
1073 mb_info.qp_y = if new_qp < 0 {
1074 (new_qp + 52) as u8
1075 } else if new_qp >= 52 {
1076 (new_qp - 52) as u8
1077 } else {
1078 new_qp as u8
1079 };
1080 mb_info.coeffs = [[0; 16]; 25];
1081 if self.transform_8x8_mode {
1082 mb_info.clear_coeffs8x8();
1083 }
1084 mb_info.chroma_dc = [[0; 4]; 2];
1085 decode_residual_cavlc(br, &mut self.sstate, &mut mb_info, &self.cavlc_cb)?;
1086 }
1087 }
1088 self.handle_macroblock(&mut mb_info);
1089 }
1090 mb_idx += 1;
1091 }
1092 if let Some(ref mut pic) = self.cur_pic {
1093 pic.cur_mb = mb_idx;
1094 }
1095 Ok(mb_idx == self.num_mbs)
1096 }
1097 fn decode_slice_cabac(&mut self, cabac: &mut CABAC, slice_hdr: &SliceHeader) -> DecoderResult<bool> {
1098 let mut mb_idx = slice_hdr.first_mb_in_slice as usize;
1099 let mut prev_mb_skipped = false;
1100 let skip_type = if slice_hdr.slice_type.is_p() { MBType::PSkip } else { MBType::BSkip };
1101 let mut last_qp_diff = false;
1102
1103 let mut mb_info = CurrentMBInfo::default();
1104 mb_info.qp_y = slice_hdr.slice_qp;
1105
1106 while mb_idx < self.num_mbs {
1107 mb_info.coded = [false; 25];
1108 mb_info.ref_l0 = [ZERO_REF; 4];
1109 mb_info.ref_l1 = [ZERO_REF; 4];
1110 mb_info.mv_l0 = [ZERO_MV; 16];
1111 mb_info.mv_l1 = [ZERO_MV; 16];
1112 mb_info.chroma_dc = [[0; 4]; 2];
1113 mb_info.cbpy = 0;
1114 mb_info.cbpc = 0;
1115 let mb_skip = cabac_decode_mbskip(cabac, &self.sstate, slice_hdr);
1116 if !mb_skip {
1117 if self.is_mbaff && (((mb_idx & 1) == 0) || (prev_mb_skipped && ((mb_idx & 1) == 1))) {
1118 let _mb_field_decoding = cabac.decode_bit(70);
1119 }
1120 let mut mb_type = cabac_decode_mb_type(cabac, &slice_hdr, &self.sstate);
1121 mb_info.mb_type = mb_type;
1122 mb_info.transform_size_8x8 = false;
1123 if mb_type == MBType::PCM {
1124 let ipcm_size = 256 + 64 + 64;
1125 validate!(cabac.pos + ipcm_size <= cabac.src.len());
1126 self.ipcm_buf[..ipcm_size].copy_from_slice(&cabac.src[cabac.pos..][..ipcm_size]);
1127 cabac.pos += ipcm_size;
1128 cabac.reinit()?;
1129 last_qp_diff = false;
1130 } else {
1131 if self.transform_8x8_mode && mb_type == MBType::Intra4x4 {
1132 let mut ctx = 0;
1133 if self.sstate.get_top_mb().transform_8x8 {
1134 ctx += 1;
1135 }
1136 if self.sstate.get_left_mb().transform_8x8 {
1137 ctx += 1;
1138 }
1139 mb_info.transform_size_8x8 = cabac.decode_bit(399 + ctx);
1140 if mb_info.transform_size_8x8 {
1141 mb_type = MBType::Intra8x8;
1142 mb_info.mb_type = MBType::Intra8x8;
1143 }
1144 }
1145 decode_mb_pred_cabac(cabac, slice_hdr, mb_type, &mut self.sstate, &mut mb_info);
1146 let (cbpy, cbpc) = if let MBType::Intra16x16(_, cbpy, cbpc) = mb_type {
1147 (cbpy, cbpc)
1148 } else {
1149 decode_cbp_cabac(cabac, &self.sstate)
1150 };
1151 if self.transform_8x8_mode && cbpy != 0 && mb_info.can_have_8x8_tx(self.sps[self.cur_sps].direct_8x8_inference) {
1152 let mut ctx = 0;
1153 if self.sstate.get_top_mb().transform_8x8 {
1154 ctx += 1;
1155 }
1156 if self.sstate.get_left_mb().transform_8x8 {
1157 ctx += 1;
1158 }
1159 mb_info.transform_size_8x8 = cabac.decode_bit(399 + ctx);
1160 }
1161 if mb_type.is_intra() {
1162 self.sstate.get_cur_mb().cmode = mb_info.chroma_ipred;
1163 }
1164 mb_info.cbpy = cbpy;
1165 mb_info.cbpc = cbpc;
1166 self.sstate.get_cur_mb().cbp = (cbpc << 4) | cbpy;
1167 if cbpy != 0 || cbpc != 0 || mb_type.is_intra16x16() {
1168 let mb_qp_delta = decode_mb_qp_delta_cabac(cabac, last_qp_diff as usize);
1169 validate!(mb_qp_delta >= -26 && mb_qp_delta <= 25);
1170 last_qp_diff = mb_qp_delta != 0;
1171 let new_qp = mb_qp_delta + i32::from(mb_info.qp_y);
1172 mb_info.qp_y = if new_qp < 0 {
1173 (new_qp + 52) as u8
1174 } else if new_qp >= 52 {
1175 (new_qp - 52) as u8
1176 } else {
1177 new_qp as u8
1178 };
1179 mb_info.coeffs = [[0; 16]; 25];
1180 if self.transform_8x8_mode {
1181 mb_info.clear_coeffs8x8();
1182 }
1183 mb_info.chroma_dc = [[0; 4]; 2];
1184 decode_residual_cabac(cabac, &mut self.sstate, &mut mb_info);
1185 } else {
1186 last_qp_diff = false;
1187 }
1188 }
1189 } else {
1190 mb_info.mb_type = skip_type;
1191 mb_info.transform_size_8x8 = false;
1192 last_qp_diff = false;
1193 }
1194 self.handle_macroblock(&mut mb_info);
1195 prev_mb_skipped = mb_skip;
1196 if !(self.is_mbaff && ((mb_idx & 1) == 0)) && cabac.decode_terminate() {
1197 if let Some(ref mut pic) = self.cur_pic {
1198 pic.cur_mb = mb_idx + 1;
1199 }
1200 return Ok(mb_idx + 1 == self.num_mbs);
1201 }
1202 mb_idx += 1;
1203 }
1204 Err(DecoderError::InvalidData)
1205 }
1206 }
1207
1208 impl NADecoder for H264Decoder {
1209 fn init(&mut self, supp: &mut NADecoderSupport, info: NACodecInfoRef) -> DecoderResult<()> {
1210 if let NACodecTypeInfo::Video(vinfo) = info.get_properties() {
1211 let fmt = YUV420_FORMAT;
1212 let myinfo = NACodecTypeInfo::Video(NAVideoInfo::new(0, 0, false, fmt));
1213 self.info = NACodecInfo::new_ref(info.get_name(), myinfo, info.get_extradata()).into_ref();
1214
1215 let edata = info.get_extradata().unwrap();
1216 //print!("edata:"); for &el in edata.iter() { print!(" {:02X}", el); } println!();
1217 if edata.len() > 11 && &edata[0..4] == b"avcC" {
1218 let mut mr = MemoryReader::new_read(edata.as_slice());
1219 let mut br = ByteReader::new(&mut mr);
1220 let mut nal_buf = Vec::new();
1221
1222 br.read_skip(4)?;
1223 let version = br.read_byte()?;
1224 validate!(version == 1);
1225 let profile = br.read_byte()?;
1226 let _compatibility = br.read_byte()?;
1227 let _level = br.read_byte()?;
1228 let b = br.read_byte()?;
1229 validate!((b & 0xFC) == 0xFC);
1230 self.nal_len = (b & 3) + 1;
1231 let b = br.read_byte()?;
1232 validate!((b & 0xE0) == 0xE0);
1233 let num_sps = (b & 0x1F) as usize;
1234 for _ in 0..num_sps {
1235 let len = br.read_u16be()? as usize;
1236 let offset = br.tell() as usize;
1237 validate!((br.peek_byte()? & 0x1F) == 7);
1238 let _size = unescape_nal(&edata[offset..][..len], &mut nal_buf);
1239 self.handle_nal(&nal_buf, supp, true)?;
1240 br.read_skip(len)?;
1241 }
1242 let num_pps = br.read_byte()? as usize;
1243 for _ in 0..num_pps {
1244 let len = br.read_u16be()? as usize;
1245 let offset = br.tell() as usize;
1246 validate!((br.peek_byte()? & 0x1F) == 8);
1247 let _size = unescape_nal(&edata[offset..][..len], &mut nal_buf);
1248 self.handle_nal(&nal_buf, supp, true)?;
1249 br.read_skip(len)?;
1250 }
1251 if br.left() > 0 {
1252 match profile {
1253 100 | 110 | 122 | 144 => {
1254 let b = br.read_byte()?;
1255 validate!((b & 0xFC) == 0xFC);
1256 // b & 3 -> chroma format
1257 let b = br.read_byte()?;
1258 validate!((b & 0xF8) == 0xF8);
1259 // b & 7 -> luma depth minus 8
1260 let b = br.read_byte()?;
1261 validate!((b & 0xF8) == 0xF8);
1262 // b & 7 -> chroma depth minus 8
1263 let num_spsext = br.read_byte()? as usize;
1264 for _ in 0..num_spsext {
1265 let len = br.read_u16be()? as usize;
1266 // parse spsext
1267 br.read_skip(len)?;
1268 }
1269 },
1270 _ => {},
1271 };
1272 }
1273 } else {
1274 return Err(DecoderError::NotImplemented);
1275 }
1276
1277 self.width = vinfo.get_width();
1278 self.height = vinfo.get_height();
1279
1280 if (self.width == 0 || self.height == 0) && !self.sps.is_empty() {
1281 self.width = self.sps[0].pic_width_in_mbs * 16;
1282 self.height = self.sps[0].pic_height_in_mbs * 16;
1283 }
1284
1285 let num_bufs = if !self.sps.is_empty() {
1286 self.sps[0].num_ref_frames as usize + 1
1287 } else {
1288 3
1289 }.max(16 + 1);
1290 supp.pool_u8.set_dec_bufs(num_bufs);
1291 supp.pool_u8.prealloc_video(NAVideoInfo::new(self.width, self.height, false, fmt), 4)?;
1292
1293 Ok(())
1294 } else {
1295 println!("???");
1296 Err(DecoderError::InvalidData)
1297 }
1298 }
1299 fn decode(&mut self, supp: &mut NADecoderSupport, pkt: &NAPacket) -> DecoderResult<NAFrameRef> {
1300 let src = pkt.get_buffer();
1301
1302 let mut mr = MemoryReader::new_read(&src);
1303 let mut br = ByteReader::new(&mut mr);
1304 let mut nal_buf = Vec::with_capacity(src.len());
1305 if self.nal_len > 0 {
1306 let mut skip_decoding = false;
1307 if self.skip_mode != FrameSkipMode::None {
1308 let mut pic_type = FrameType::I;
1309 let mut is_ref = false;
1310 while br.left() > 0 {
1311 let size = match self.nal_len {
1312 1 => br.read_byte()? as usize,
1313 2 => br.read_u16be()? as usize,
1314 3 => br.read_u24be()? as usize,
1315 4 => br.read_u32be()? as usize,
1316 _ => unreachable!(),
1317 };
1318 validate!(br.left() >= (size as i64));
1319 let offset = br.tell() as usize;
1320 let size = unescape_nal(&src[offset..][..size], &mut nal_buf);
1321 validate!(size > 0);
1322 let nal_ref_idc = nal_buf[0] >> 5;
1323 let nal_unit_type = nal_buf[0] & 0x1F;
1324 if nal_unit_type == 1 || nal_unit_type == 5 {
1325 let mut bitr = BitReader::new(&nal_buf[1..], BitReaderMode::BE);
1326 let (first_mb, slice_type) = parse_slice_header_minimal(&mut bitr)?;
1327 if first_mb == 0 && nal_ref_idc != 0 {
1328 is_ref = true;
1329 }
1330 let new_type = slice_type.to_frame_type();
1331 pic_type = match (pic_type, new_type) {
1332 (FrameType::I, _) => new_type,
1333 (_, FrameType::B) => FrameType::B,
1334 _ => pic_type,
1335 };
1336 }
1337 br.read_skip(size)?;
1338 }
1339 match self.skip_mode {
1340 FrameSkipMode::IntraOnly => {
1341 skip_decoding = pic_type != FrameType::I;
1342 },
1343 FrameSkipMode::KeyframesOnly => {
1344 if !is_ref {
1345 skip_decoding = true;
1346 }
1347 },
1348 _ => {},
1349 };
1350 br.seek(SeekFrom::Start(0))?;
1351 }
1352 while br.left() > 0 {
1353 let size = match self.nal_len {
1354 1 => br.read_byte()? as usize,
1355 2 => br.read_u16be()? as usize,
1356 3 => br.read_u24be()? as usize,
1357 4 => br.read_u32be()? as usize,
1358 _ => unreachable!(),
1359 };
1360 validate!(br.left() >= (size as i64));
1361 let offset = br.tell() as usize;
1362 let _size = unescape_nal(&src[offset..][..size], &mut nal_buf);
1363 self.handle_nal(nal_buf.as_slice(), supp, skip_decoding)?;
1364 br.read_skip(size)?;
1365 }
1366 } else {
1367 //todo NAL detection
1368 unimplemented!();
1369 }
1370
1371 let (bufinfo, ftype, dts) = if self.has_pic && self.cur_pic.is_some() {
1372 let mut npic = None;
1373 std::mem::swap(&mut self.cur_pic, &mut npic);
1374 let cpic = npic.unwrap();
1375 let ret = (NABufferType::Video(cpic.buf.clone()), cpic.pic_type, Some(u64::from(cpic.full_id)));
1376 if cpic.is_ref {
1377 self.frame_refs.add_short_term(cpic.clone(), self.sps[self.cur_sps].num_ref_frames);
1378 }
1379 if let Some(lt_idx) = cpic.long_term {
1380 self.frame_refs.add_long_term(lt_idx, cpic);
1381 }
1382 ret
1383 } else {
1384 (NABufferType::None, FrameType::Skip, None)
1385 };
1386
1387 let mut frm = NAFrame::new_from_pkt(pkt, self.info.clone(), bufinfo);
1388 frm.set_keyframe(ftype == FrameType::I);
1389 if let (Some(mydts), None) = (dts, frm.get_dts()) {
1390 frm.set_dts(Some(mydts));
1391 }
1392 if let Some(dts) = dts {
1393 frm.set_id(dts as i64);
1394 }
1395 frm.set_frame_type(ftype);
1396 Ok(frm.into_ref())
1397 }
1398 fn flush(&mut self) {
1399 }
1400 }
1401
1402 const DEBLOCK_SKIP_OPTION: &str = "skip_deblock";
1403
1404 const DECODER_OPTIONS: &[NAOptionDefinition] = &[
1405 NAOptionDefinition {
1406 name: FRAME_SKIP_OPTION, description: FRAME_SKIP_OPTION_DESC,
1407 opt_type: NAOptionDefinitionType::Bool },
1408 NAOptionDefinition {
1409 name: DEBLOCK_SKIP_OPTION, description: "Loop filter skipping mode",
1410 opt_type: NAOptionDefinitionType::String(Some(&[
1411 FRAME_SKIP_OPTION_VAL_NONE,
1412 FRAME_SKIP_OPTION_VAL_KEYFRAME,
1413 FRAME_SKIP_OPTION_VAL_INTRA
1414 ])) },
1415 ];
1416
1417 impl NAOptionHandler for H264Decoder {
1418 fn get_supported_options(&self) -> &[NAOptionDefinition] { DECODER_OPTIONS }
1419 fn set_options(&mut self, options: &[NAOption]) {
1420 for option in options.iter() {
1421 for opt_def in DECODER_OPTIONS.iter() {
1422 if opt_def.check(option).is_ok() {
1423 match (option.name, &option.value) {
1424 (FRAME_SKIP_OPTION, NAValue::String(ref str)) => {
1425 if let Ok(smode) = FrameSkipMode::from_str(str) {
1426 self.skip_mode = smode;
1427 }
1428 },
1429 (DEBLOCK_SKIP_OPTION, NAValue::Bool(val)) => {
1430 self.deblock_skip = *val;
1431 },
1432 _ => {},
1433 }
1434 }
1435 }
1436 }
1437 }
1438 fn query_option_value(&self, name: &str) -> Option<NAValue> {
1439 match name {
1440 FRAME_SKIP_OPTION => Some(NAValue::String(self.skip_mode.to_string())),
1441 DEBLOCK_SKIP_OPTION => Some(NAValue::Bool(self.deblock_skip)),
1442 _ => None,
1443 }
1444 }
1445 }
1446
1447 pub fn get_decoder() -> Box<dyn NADecoder + Send> {
1448 Box::new(H264Decoder::new())
1449 }
1450
1451 #[cfg(test)]
1452 mod test {
1453 use nihav_core::codecs::RegisteredDecoders;
1454 use nihav_core::demuxers::RegisteredDemuxers;
1455 use nihav_codec_support::test::dec_video::*;
1456 use crate::itu_register_all_decoders;
1457 use nihav_commonfmt::generic_register_all_demuxers;
1458
1459 mod raw_demux;
1460 mod conformance;
1461 use self::raw_demux::RawH264DemuxerCreator;
1462
1463 #[test]
1464 fn test_h264_perframe() {
1465 let mut dmx_reg = RegisteredDemuxers::new();
1466 dmx_reg.add_demuxer(&RawH264DemuxerCreator{});
1467 generic_register_all_demuxers(&mut dmx_reg);
1468 let mut dec_reg = RegisteredDecoders::new();
1469 itu_register_all_decoders(&mut dec_reg);
1470
1471 test_decoding("rawh264", "h264",
1472 "assets/ITU/h264-conformance/CABAST3_Sony_E.jsv",
1473 None, &dmx_reg, &dec_reg, ExpectedTestResult::MD5Frames(vec![
1474 [0x85fc4b44, 0xc9aefdc9, 0x568d0592, 0x2eccf9a0],
1475 [0xbd8d11bc, 0x97acf592, 0x45a3cdbb, 0xa254a882],
1476 [0xbda0e0b9, 0x9fbe1974, 0x1540b244, 0x46a050ca],
1477 [0x471f0057, 0x125ef3b4, 0x4a87515f, 0xba254bbb],
1478 [0x466a7df2, 0xb392c2a4, 0xed66b68b, 0xfdaad2da],
1479 [0x96334b41, 0x41bac7ef, 0xe87154f1, 0xa5fc3551],
1480 [0x0fd4e9b8, 0x4269bbec, 0x00a1978f, 0xe6224851],
1481 [0x68be82af, 0x856615a7, 0x387a253d, 0x8473e6b9],
1482 [0xc4bed119, 0x14ba7fe0, 0x447cb680, 0x555da4c5],
1483 [0x85d127d6, 0x04b85928, 0x26740281, 0x4d848db5],
1484 [0xe44fe461, 0x0d0b64ce, 0xf191179b, 0xabdab686],
1485 [0x347c8edb, 0x847ad11f, 0x8f16b84e, 0xdc915d75],
1486 [0xeb1364a6, 0x91c9d99d, 0x324f5427, 0xcc9f11a2],
1487 [0x7aeb5a3f, 0xebc9c4dd, 0x8f12c8e4, 0x37a2db97],
1488 [0xa11e5c33, 0x656df4c0, 0x1e8b98d8, 0x1736722f],
1489 [0x239f2ef2, 0xe32b0603, 0x448366bb, 0x9331051c],
1490 [0x1815a1b1, 0xfb7e7cf0, 0xd5c7dd5b, 0x0135a8fb],
1491 [0xea3b85dd, 0xa96e7015, 0xa91c576d, 0x5c127ca1],
1492 [0x1c49148f, 0x6d9e7045, 0x093f0b7c, 0x42c2ebaa],
1493 [0x4b4c2863, 0x95709d8c, 0xeb72e251, 0x096632dc],
1494 [0x727418e5, 0x2c015383, 0x59580212, 0x0302dd99],
1495 [0xbe57dfa4, 0xf2aa7d70, 0xa068ee62, 0x77372861],
1496 [0x2faef43a, 0x73da6654, 0xb9d9c22e, 0xc59520bc],
1497 [0x138cff40, 0x3e6c108a, 0xa981e654, 0x903da85b],
1498 [0xa90454f5, 0x7875d5db, 0xbab234bd, 0xe6ce1193]]));
1499 }
1500
1501 #[test]
1502 fn test_h264_real1() {
1503 let mut dmx_reg = RegisteredDemuxers::new();
1504 dmx_reg.add_demuxer(&RawH264DemuxerCreator{});
1505 generic_register_all_demuxers(&mut dmx_reg);
1506 let mut dec_reg = RegisteredDecoders::new();
1507 itu_register_all_decoders(&mut dec_reg);
1508
1509 test_decoding("mov", "h264", "assets/ITU/1.mp4",
1510 Some(60), &dmx_reg, &dec_reg,
1511 ExpectedTestResult::MD5Frames(vec![
1512 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
1513 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
1514 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
1515 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
1516 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
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 [0xf1c88c12, 0x7da871f5, 0xdaf3153f, 0x66e72d72],
1550 [0x3d4765f1, 0x8ac472f6, 0x7ffd13a6, 0xc7a45dae],
1551 [0x60e5e13a, 0xd2d7f239, 0x1a793d71, 0x19f8c190],
1552 [0xdd80c3e4, 0xb1500149, 0x43925280, 0x9e5f3230],
1553 [0x2adf6e64, 0x39012d45, 0x7a776cb5, 0x3df76e84],
1554 [0x44319007, 0xbc837dd2, 0x486b2703, 0x451d0651],
1555 [0x922386ef, 0xaf101e9b, 0xf2094a40, 0xc8c454c0],
1556 [0x0d81e398, 0x04192a56, 0xa31f39d0, 0x5e0a2deb],
1557 [0xcdd144b3, 0xd1c7743e, 0x5753b0f4, 0xc070efa9],
1558 [0xe1c67e39, 0x6065ddaf, 0x576bf9f1, 0x8e6825aa],
1559 [0xaf817b0d, 0xdc6c345a, 0xf7f289c7, 0x6cc482d8],
1560 [0x81dc4bcb, 0xee4fc5e5, 0x9b87c7ef, 0xdd0fb034],
1561 [0x8b07f523, 0x4168799f, 0x990cb270, 0x858b9f2c],
1562 [0x31855a80, 0xadbcc562, 0xe60628be, 0x5f04be09],
1563 [0x9c614acc, 0xbd08a3f4, 0x91b02c45, 0x41899a83],
1564 [0x89d09064, 0xbff810a3, 0x9c674179, 0x305225a6],
1565 [0xba1fc8d3, 0x15d34fae, 0x565d363b, 0x4f4d0604],
1566 [0x1cb15a1b, 0xa0be111e, 0x45cc801f, 0x01a2c691],
1567 [0xd898be48, 0xd19bf58d, 0xe22fe44f, 0x6a2914fb],
1568 [0xec6712af, 0xa13b55c0, 0x2915a746, 0xb29a5c48],
1569 [0x745798fa, 0x4ef0f882, 0x59335c08, 0xb1d9dbb4],
1570 [0x4045b495, 0xdb3d969c, 0x1f0d9220, 0x5a34067b],
1571 [0x94fee093, 0x78ad89b3, 0xf20e882b, 0x941425db],
1572 [0xc3eb1a78, 0x4b4e098a, 0xcbcf9bb4, 0xfd5b5426]]));
1573 }
1574 #[test]
1575 fn test_h264_real2() {
1576 let mut dmx_reg = RegisteredDemuxers::new();
1577 dmx_reg.add_demuxer(&RawH264DemuxerCreator{});
1578 generic_register_all_demuxers(&mut dmx_reg);
1579 let mut dec_reg = RegisteredDecoders::new();
1580 itu_register_all_decoders(&mut dec_reg);
1581 test_decoding("mov", "h264", "assets/ITU/DimpledSpanishCuckoo-mobile.mp4",
1582 Some(10), &dmx_reg, &dec_reg,
1583 ExpectedTestResult::MD5Frames(vec![
1584 [0x1addcb8e, 0xde58b857, 0x17222c32, 0x75455fa8],
1585 [0xae63141a, 0x79435b2e, 0xfe606c48, 0xf676da66],
1586 [0xfdb80404, 0x6a288e23, 0x45cc4106, 0xdd5eb57c],
1587 [0xd603a3ff, 0x872dcb9b, 0x43f7a71c, 0x2ad4eecc],
1588 [0x639ed6a5, 0xbb1cfec6, 0x0ee5443a, 0x1694772a],
1589 [0xf8ef3f48, 0x152de238, 0xb1995f9a, 0xf82ad1d5],
1590 [0x604f6265, 0xb9d82f56, 0x21f00cf4, 0xc69c18a7],
1591 [0xd932c16e, 0x25cbf060, 0xcb66543b, 0xfe8a5019],
1592 [0xf2a3dac0, 0x0f4678dd, 0xf64c8228, 0x47f14676],
1593 [0x267041ee, 0x3b6b8b64, 0x8bfe1697, 0x1fba508b],
1594 [0x9f917e72, 0x75d882a9, 0xa5e3e684, 0x4ed87eff]]));
1595 }
1596 }
1597
1598 pub const I4X4_SCAN: [(u8, u8); 16] = [
1599 (0,0), (1,0), (0,1), (1,1), (2,0), (3,0), (2,1), (3,1),
1600 (0,2), (1,2), (0,3), (1,3), (2,2), (3,2), (2,3), (3,3)
1601 ];