a0a94a4e3095c91a46de0a137871278474e291f2
[nihav.git] / nihav-itu / src / codecs / h264 / mod.rs
1 /*
2 known bugs and limitations:
3 * wrong slice boundary filtering
4 * not fully correct deblock strength selection for P/B-macroblocks
5 * scaling lists for 4x4 blocks
6 */
7 use nihav_core::codecs::*;
8 use nihav_core::io::byteio::*;
9 use nihav_core::io::bitreader::*;
10 use nihav_core::io::intcode::*;
11 use nihav_codec_support::codecs::{MV, ZERO_MV};
12
13 mod types;
14 pub use types::*;
15 mod pic_ref;
16 pub use pic_ref::*;
17 #[allow(clippy::identity_op)]
18 #[allow(clippy::erasing_op)]
19 #[allow(clippy::many_single_char_names)]
20 #[allow(clippy::range_plus_one)]
21 mod dsp;
22 use dsp::*;
23 mod cabac;
24 use cabac::*;
25 mod cabac_coder;
26 use cabac_coder::*;
27 mod cavlc;
28 use cavlc::*;
29 mod loopfilter;
30 use loopfilter::*;
31 mod mb_recon;
32 use mb_recon::*;
33 mod sets;
34 use sets::*;
35 mod slice;
36 use slice::*;
37
38 trait ReadUE {
39 fn read_ue(&mut self) -> DecoderResult<u32>;
40 fn read_te(&mut self, range: u32) -> DecoderResult<u32>;
41 fn read_ue_lim(&mut self, max_val: u32) -> DecoderResult<u32> {
42 let val = self.read_ue()?;
43 validate!(val <= max_val);
44 Ok(val)
45 }
46 fn read_se(&mut self) -> DecoderResult<i32> {
47 let val = self.read_ue()?;
48 if (val & 1) != 0 {
49 Ok (((val >> 1) as i32) + 1)
50 } else {
51 Ok (-((val >> 1) as i32))
52 }
53 }
54 }
55
56 impl<'a> ReadUE for BitReader<'a> {
57 fn read_ue(&mut self) -> DecoderResult<u32> {
58 Ok(self.read_code(UintCodeType::GammaP)? - 1)
59 }
60 fn read_te(&mut self, range: u32) -> DecoderResult<u32> {
61 if range == 1 {
62 if self.read_bool()? {
63 Ok(0)
64 } else {
65 Ok(1)
66 }
67 } else {
68 let val = self.read_ue()?;
69 validate!(val <= range);
70 Ok(val)
71 }
72 }
73 }
74
75 #[derive(Clone,Copy)]
76 pub struct Coeff8x8 {
77 pub coeffs: [i16; 64],
78 }
79
80 impl Coeff8x8 {
81 fn clear(&mut self) {
82 self.coeffs = [0; 64];
83 }
84 }
85
86 impl Default for Coeff8x8 {
87 fn default() -> Self {
88 Self {
89 coeffs: [0; 64],
90 }
91 }
92 }
93
94 #[derive(Clone,Copy,Default)]
95 pub struct CurrentMBInfo {
96 pub mb_type: MBType,
97 pub sub_mb_type: [SubMBType; 4],
98 pub ipred: [IntraPredMode; 16],
99 pub chroma_ipred: u8,
100 pub luma_ipred: [u8; 16],
101 pub mv_l0: [MV; 16],
102 pub ref_l0: [PicRef; 4],
103 pub mv_l1: [MV; 16],
104 pub ref_l1: [PicRef; 4],
105 pub qp_y: u8,
106 pub cbpy: u8,
107 pub cbpc: u8,
108 pub coeffs: [[i16; 16]; 25],
109 pub coeffs8x8: [Coeff8x8; 4],
110 pub chroma_dc: [[i16; 4]; 2],
111 pub coded: [bool; 25],
112 pub transform_size_8x8: bool,
113 }
114
115 impl CurrentMBInfo {
116 fn clear_coeffs8x8(&mut self) {
117 for c in self.coeffs8x8.iter_mut() {
118 c.clear();
119 }
120 }
121 fn can_have_8x8_tx(&self, inference_flag: bool) -> bool {
122 match self.mb_type {
123 MBType::Intra4x4 | MBType::Intra8x8 | MBType::Intra16x16(_, _, _) | MBType::PCM => false,
124 MBType::P8x8 | MBType::P8x8Ref0 | MBType::B8x8 => {
125 for &sub_id in self.sub_mb_type.iter() {
126 match sub_id {
127 SubMBType::P8x8 |
128 SubMBType::B8x8(_)
129 => {},
130 SubMBType::Direct8x8
131 => if !inference_flag { return false; },
132 _ => return false,
133 };
134 }
135 true
136 },
137 MBType::Direct => inference_flag,
138 _ => true,
139 }
140 }
141 }
142
143 fn get_long_term_id(is_idr: bool, slice_hdr: &SliceHeader) -> Option<usize> {
144 if is_idr && !slice_hdr.long_term_reference {
145 None
146 } else {
147 let marking = &slice_hdr.adaptive_ref_pic_marking;
148 for (&op, &arg) in marking.memory_management_control_op.iter().zip(marking.operation_arg.iter()).take(marking.num_ops) {
149 if op == 6 {
150 return Some(arg as usize);
151 }
152 }
153 None
154 }
155 }
156
157 struct H264Decoder {
158 info: NACodecInfoRef,
159 width: usize,
160 height: usize,
161 num_mbs: usize,
162 nal_len: u8,
163 sps: Vec<SeqParameterSet>,
164 cur_sps: usize,
165 pps: Vec<PicParameterSet>,
166 cur_pps: usize,
167
168 skip_mode: FrameSkipMode,
169 deblock_skip: bool,
170
171 is_mbaff: bool,
172
173 cavlc_cb: CAVLCTables,
174
175 sstate: SliceState,
176
177 cur_pic: Option<PictureInfo>,
178 cur_id: u16,
179 has_pic: bool,
180 frame_refs: FrameRefs,
181
182 temporal_mv: bool,
183 deblock_mode: u8,
184 lf_alpha: i8,
185 lf_beta: i8,
186 is_s: bool,
187
188 ipcm_buf: [u8; 256 + 64 + 64],
189
190 mc_dsp: H264MC,
191
192 transform_8x8_mode: bool,
193 }
194
195 fn unescape_nal(src: &[u8], dst: &mut Vec<u8>) -> usize {
196 let mut off = 0;
197 let mut zrun = 0;
198 dst.clear();
199 dst.reserve(src.len());
200 while off < src.len() {
201 dst.push(src[off]);
202 if src[off] != 0 {
203 zrun = 0;
204 } else {
205 zrun += 1;
206 if zrun == 2 && off + 1 < src.len() && src[off + 1] == 0x03 {
207 zrun = 0;
208 off += 1;
209 }
210 if zrun >= 3 && off + 1 < src.len() && src[off + 1] == 0x01 {
211 off -= 3;
212 dst.truncate(off);
213 break;
214 }
215 }
216 off += 1;
217 }
218 off
219 }
220
221 impl H264Decoder {
222 fn new() -> Self {
223 let avg_vi = NAVideoInfo { width: 32, height: 32, flipped: false, format: YUV420_FORMAT, bits: 12 };
224 let avg_buf = alloc_video_buffer(avg_vi, 4).unwrap().get_vbuf().unwrap();
225 H264Decoder{
226 info: NACodecInfoRef::default(),
227 width: 0,
228 height: 0,
229 num_mbs: 0,
230 nal_len: 0,
231 sps: Vec::with_capacity(1),
232 cur_sps: 0,
233 pps: Vec::with_capacity(3),
234 cur_pps: 0,
235
236 skip_mode: FrameSkipMode::default(),
237 deblock_skip: false,
238
239 is_mbaff: false,
240
241 cavlc_cb: CAVLCTables::new(),
242
243 sstate: SliceState::new(),
244 cur_pic: None,
245 cur_id: 0,
246 has_pic: false,
247 frame_refs: FrameRefs::new(),
248
249 temporal_mv: false,
250 deblock_mode: 0,
251 lf_alpha: 0,
252 lf_beta: 0,
253 is_s: false,
254
255 ipcm_buf: [0; 256 + 64 + 64],
256
257 mc_dsp: H264MC::new(avg_buf),
258
259 transform_8x8_mode: false,
260 }
261 }
262 fn handle_nal(&mut self, src: &[u8], supp: &mut NADecoderSupport, skip_decoding: bool) -> DecoderResult<()> {
263 validate!(!src.is_empty());
264 validate!((src[0] & 0x80) == 0);
265 let nal_ref_idc = src[0] >> 5;
266 let nal_unit_type = src[0] & 0x1F;
267
268 let mut full_size = src.len() * 8;
269 for &byte in src.iter().rev() {
270 if byte == 0 {
271 full_size -= 8;
272 } else {
273 full_size -= (byte.trailing_zeros() + 1) as usize;
274 break;
275 }
276 }
277 validate!(full_size > 0);
278 match nal_unit_type {
279 1 | 5 if !skip_decoding => {
280 let is_idr = nal_unit_type == 5;
281 let mut br = BitReader::new(&src[..(full_size + 7)/8], BitReaderMode::BE);
282 br.skip(8)?;
283
284 let slice_hdr = parse_slice_header(&mut br, &self.sps, &self.pps, is_idr, nal_ref_idc)?;
285 validate!(br.tell() < full_size);
286 let full_id;
287 if slice_hdr.first_mb_in_slice == 0 {
288 validate!(self.cur_pic.is_none());
289 for (i, pps) in self.pps.iter().enumerate() {
290 if pps.pic_parameter_set_id == slice_hdr.pic_parameter_set_id {
291 self.cur_pps = i;
292 break;
293 }
294 }
295 for (i, sps) in self.sps.iter().enumerate() {
296 if sps.seq_parameter_set_id == self.pps[self.cur_pps].seq_parameter_set_id {
297 self.cur_sps = i;
298 break;
299 }
300 }
301
302 full_id = self.frame_refs.calc_picture_num(&slice_hdr, is_idr, nal_ref_idc, &self.sps[self.cur_sps]);
303
304 let sps = &self.sps[self.cur_sps];
305 if sps.chroma_format_idc != 1 || sps.bit_depth_luma != 8 || sps.bit_depth_chroma != 8 {
306 println!(" chroma fmt {} bits {}/{}", sps.chroma_format_idc, sps.bit_depth_luma, sps.bit_depth_chroma);
307 return Err(DecoderError::NotImplemented);
308 }
309 //let pps = &self.pps[self.cur_pps];
310
311 if is_idr {
312 self.frame_refs.clear_refs();
313 }
314
315 self.width = sps.pic_width_in_mbs << 4;
316 self.height = sps.pic_height_in_mbs << 4;
317 self.num_mbs = sps.pic_width_in_mbs * sps.pic_height_in_mbs;
318 self.mc_dsp.set_dimensions(self.width, self.height);
319
320 self.is_mbaff = sps.mb_adaptive_frame_field && !slice_hdr.field_pic;
321 if self.is_mbaff {
322 println!("MBAFF");
323 return Err(DecoderError::NotImplemented);
324 }
325 if !sps.frame_mbs_only {
326 println!("PAFF?");
327 return Err(DecoderError::NotImplemented);
328 }
329
330 //if slice_hdr.slice_type.is_b() { return Ok(()); }
331 self.cur_id = full_id as u16;
332 } else {
333 if let Some(ref mut pic) = self.cur_pic {
334 validate!(pic.cur_mb == slice_hdr.first_mb_in_slice);
335 let new_type = slice_hdr.slice_type.to_frame_type();
336 pic.pic_type = match (pic.pic_type, new_type) {
337 (FrameType::I, _) => new_type,
338 (_, FrameType::B) => FrameType::B,
339 _ => pic.pic_type,
340 };
341 full_id = pic.full_id;
342 } else {
343 return Ok(());//Err(DecoderError::InvalidData);
344 }
345 validate!(self.cur_pps < self.pps.len() && self.pps[self.cur_pps].pic_parameter_set_id == slice_hdr.pic_parameter_set_id);
346 }
347
348 let sps = &self.sps[self.cur_sps];
349 let pps = &self.pps[self.cur_pps];
350
351 self.temporal_mv = !slice_hdr.direct_spatial_mv_pred;
352 self.is_s = slice_hdr.slice_type == SliceType::SI || slice_hdr.slice_type == SliceType::SP;
353 self.deblock_mode = slice_hdr.disable_deblocking_filter_idc;
354 self.lf_alpha = slice_hdr.slice_alpha_c0_offset;
355 self.lf_beta = slice_hdr.slice_beta_offset;
356
357 self.frame_refs.select_refs(sps, &slice_hdr, full_id);
358
359 if slice_hdr.adaptive_ref_pic_marking_mode {
360 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)?;
361 }
362 if slice_hdr.first_mb_in_slice == 0 {
363 let ret = supp.pool_u8.get_free();
364 if ret.is_none() {
365 return Err(DecoderError::AllocError);
366 }
367 let tmp_vinfo = NAVideoInfo::new(self.width, self.height, false, YUV420_FORMAT);
368 let mut buf = ret.unwrap();
369 if buf.get_info() != tmp_vinfo {
370 supp.pool_u8.reset();
371 supp.pool_u8.prealloc_video(tmp_vinfo, 4)?;
372 let ret = supp.pool_u8.get_free();
373 if ret.is_none() {
374 return Err(DecoderError::AllocError);
375 }
376 buf = ret.unwrap();
377 }
378 self.cur_pic = Some(PictureInfo {
379 id: slice_hdr.frame_num,
380 full_id,
381 pic_type: slice_hdr.slice_type.to_frame_type(),
382 buf,
383 cur_mb: 0,
384 is_ref: nal_ref_idc != 0,
385 long_term: get_long_term_id(is_idr, &slice_hdr),
386 mv_info: FrameMV::new(sps.pic_width_in_mbs, sps.pic_height_in_mbs),
387 });
388 }
389
390 self.transform_8x8_mode = pps.transform_8x8_mode;
391
392 self.sstate.reset(sps.pic_width_in_mbs, sps.pic_height_in_mbs, slice_hdr.first_mb_in_slice);
393 if !pps.entropy_coding_mode {
394 self.has_pic = self.decode_slice_cavlc(&mut br, &slice_hdr, full_size)?;
395 } else {
396 br.align();
397 let start = (br.tell() / 8) as usize;
398 let csrc = &src[start..];
399 validate!(csrc.len() >= 2);
400 let mut cabac = CABAC::new(csrc, slice_hdr.slice_type, slice_hdr.slice_qp, slice_hdr.cabac_init_idc as usize)?;
401 self.has_pic = self.decode_slice_cabac(&mut cabac, &slice_hdr)?;
402 }
403 },
404 2 => { // slice data partition A
405 //slice header
406 //slice id = read_ue()
407 //cat 2 slice data (all but MB layer residual)
408 return Err(DecoderError::NotImplemented);
409 },
410 3 => { // slice data partition B
411 //slice id = read_ue()
412 //if pps.redundant_pic_cnt_present { redundant_pic_cnt = read_ue() }
413 //cat 3 slice data (MB layer residual)
414 return Err(DecoderError::NotImplemented);
415 },
416 4 => { // slice data partition C
417 //slice id = read_ue()
418 //if pps.redundant_pic_cnt_present { redundant_pic_cnt = read_ue() }
419 //cat 4 slice data (MB layer residual)
420 return Err(DecoderError::NotImplemented);
421 },
422 6 => {}, //SEI
423 7 => {
424 let sps = parse_sps(&src[1..])?;
425 self.sps.push(sps);
426 },
427 8 => {
428 validate!(full_size >= 8 + 16);
429 let pps = parse_pps(&src[1..], &self.sps, full_size - 8)?;
430 let mut found = false;
431 for stored_pps in self.pps.iter_mut() {
432 if stored_pps.pic_parameter_set_id == pps.pic_parameter_set_id {
433 *stored_pps = pps.clone();
434 found = true;
435 break;
436 }
437 }
438 if !found {
439 self.pps.push(pps);
440 }
441 },
442 9 => { // access unit delimiter
443 },
444 10 => {}, //end of sequence
445 11 => {}, //end of stream
446 12 => {}, //filler
447 _ => {},
448 };
449
450 Ok(())
451 }
452 fn pred_mv(sstate: &mut SliceState, frame_refs: &FrameRefs, mb_info: &mut CurrentMBInfo, cur_id: u16, temporal_mv: bool, direct_8x8: bool) {
453 let mb_type = mb_info.mb_type;
454 if !mb_type.is_4x4() {
455 let (pw, ph) = mb_type.size();
456 let mut xoff = 0;
457 let mut yoff = 0;
458 if mb_type == MBType::Direct || mb_type == MBType::BSkip {
459 sstate.predict_direct_mb(frame_refs, temporal_mv, direct_8x8, cur_id);
460 }
461 for part in 0..mb_type.num_parts() {
462 if !mb_type.is_l1(part) {
463 match mb_type {
464 MBType::PSkip => sstate.predict_pskip(),
465 MBType::BSkip | MBType::Direct => {
466 },
467 _ => {
468 sstate.predict(xoff, yoff, pw, ph, 0,
469 mb_info.mv_l0[part], mb_info.ref_l0[part]);
470 },
471 };
472 }
473 if !mb_type.is_l0(part) && mb_type != MBType::BSkip && mb_type != MBType::Direct {
474 sstate.predict(xoff, yoff, pw, ph, 1, mb_info.mv_l1[part], mb_info.ref_l1[part]);
475 }
476 if pw != 16 {
477 xoff += pw;
478 } else {
479 yoff += ph;
480 }
481 }
482 } else {
483 for part in 0..4 {
484 let sub_type = mb_info.sub_mb_type[part];
485 let mut xoff = (part & 1) * 8;
486 let mut yoff = (part & 2) * 4;
487 let orig_x = xoff;
488 let (pw, ph) = sub_type.size();
489 for subpart in 0..sub_type.num_parts() {
490 if sub_type != SubMBType::Direct8x8 {
491 if !sub_type.is_l1() {
492 sstate.predict(xoff, yoff, pw, ph, 0, mb_info.mv_l0[part * 4 + subpart], mb_info.ref_l0[part]);
493 }
494 if !sub_type.is_l0() {
495 sstate.predict(xoff, yoff, pw, ph, 1, mb_info.mv_l1[part * 4 + subpart], mb_info.ref_l1[part]);
496 }
497 } else {
498 for sblk in 0..4 {
499 sstate.predict_direct_sub(frame_refs, temporal_mv, direct_8x8, cur_id, (xoff / 4) + (sblk & 1) + (yoff / 4) * 4 + (sblk & 2) * 2);
500 }
501 }
502 xoff += pw;
503 if xoff == orig_x + 8 {
504 xoff -= 8;
505 yoff += ph;
506 }
507 }
508 }
509 }
510 }
511 #[allow(clippy::cognitive_complexity)]
512 fn handle_macroblock(&mut self, slice_hdr: &SliceHeader, mb_info: &mut CurrentMBInfo) {
513 let pps = &self.pps[self.cur_pps];
514
515 let qp_y = mb_info.qp_y;
516 let qpr = ((qp_y as i8) + pps.chroma_qp_index_offset).max(0).min(51) as usize;
517 let qp_u = CHROMA_QUANTS[qpr];
518 let qpb = ((qp_y as i8) + pps.second_chroma_qp_index_offset).max(0).min(51) as usize;
519 let qp_v = CHROMA_QUANTS[qpb];
520
521 let tx_bypass = qp_y == 0 && self.sps[self.cur_sps].qpprime_y_zero_transform_bypass;
522
523 self.sstate.get_cur_mb().mb_type = mb_info.mb_type.into();
524 if mb_info.mb_type != MBType::PCM {
525 self.sstate.get_cur_mb().qp_y = qp_y;
526 self.sstate.get_cur_mb().qp_u = qp_u;
527 self.sstate.get_cur_mb().qp_v = qp_v;
528 self.sstate.get_cur_mb().transform_8x8 = mb_info.transform_size_8x8;
529 }
530 let has_dc = mb_info.mb_type.is_intra16x16() && mb_info.coded[24];
531 if has_dc {
532 idct_luma_dc(&mut mb_info.coeffs[24], qp_y);
533 for i in 0..16 {
534 mb_info.coeffs[i][0] = mb_info.coeffs[24][i];
535 }
536 }
537 if !mb_info.transform_size_8x8 {
538 let quant_dc = !mb_info.mb_type.is_intra16x16();
539 for i in 0..16 {
540 if mb_info.coded[i] {
541 if !tx_bypass {
542 idct(&mut mb_info.coeffs[i], qp_y, quant_dc);
543 }
544 } else if has_dc {
545 if !tx_bypass {
546 idct_dc(&mut mb_info.coeffs[i], qp_y, quant_dc);
547 }
548 mb_info.coded[i] = true;
549 }
550 }
551 } else {
552 for i in 0..4 {
553 if mb_info.coded[(i & 1) * 2 + (i & 2) * 4] && !tx_bypass {
554 dequant8x8(&mut mb_info.coeffs8x8[i].coeffs, &pps.scaling_list_8x8[!mb_info.mb_type.is_intra() as usize]);
555 idct8x8(&mut mb_info.coeffs8x8[i].coeffs, qp_y);
556 }
557 }
558 }
559 for chroma in 0..2 {
560 let qp_c = if chroma == 0 { qp_u } else { qp_v };
561 if mb_info.cbpc != 0 {
562 chroma_dc_transform(&mut mb_info.chroma_dc[chroma], qp_c);
563 }
564 for i in 0..4 {
565 let blk_no = 16 + chroma * 4 + i;
566 mb_info.coeffs[blk_no][0] = mb_info.chroma_dc[chroma][i];
567 if mb_info.coded[blk_no] {
568 idct(&mut mb_info.coeffs[blk_no], qp_c, false);
569 } else if mb_info.coeffs[blk_no][0] != 0 {
570 idct_dc(&mut mb_info.coeffs[blk_no], qp_c, false);
571 mb_info.coded[blk_no] = true;
572 }
573 }
574 }
575 if !pps.entropy_coding_mode || mb_info.mb_type.is_skip() || mb_info.mb_type.is_intra() {
576 self.sstate.reset_mb_mv();
577 }
578 if !mb_info.mb_type.is_intra() {
579 Self::pred_mv(&mut self.sstate, &self.frame_refs, mb_info, self.cur_id, self.temporal_mv, self.sps[self.cur_sps].direct_8x8_inference);
580 }
581 if !pps.constrained_intra_pred && mb_info.mb_type != MBType::Intra4x4 && mb_info.mb_type != MBType::Intra8x8 {
582 self.sstate.fill_ipred(IntraPredMode::DC);
583 }
584
585 let xpos = self.sstate.mb_x * 16;
586 let ypos = self.sstate.mb_y * 16;
587 if let Some(ref mut pic) = self.cur_pic {
588 let mut frm = NASimpleVideoFrame::from_video_buf(&mut pic.buf).unwrap();
589 if mb_info.mb_type != MBType::PCM {
590 let weight_mode = if self.pps[self.cur_pps].weighted_pred && slice_hdr.slice_type.is_p() {
591 1
592 } else if slice_hdr.slice_type.is_b() {
593 self.pps[self.cur_pps].weighted_bipred_idc
594 } else {
595 0
596 };
597 recon_mb(&mut frm, slice_hdr, &mb_info, &mut self.sstate, &self.frame_refs, &mut self.mc_dsp, weight_mode);
598 } else {
599 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)) {
600 dline[..16].copy_from_slice(src);
601 }
602 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)) {
603 dline[..8].copy_from_slice(src);
604 }
605 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)) {
606 dline[..8].copy_from_slice(src);
607 }
608 }
609 /*match mb_info.mb_type {
610 MBType::BSkip | MBType::Direct | MBType::B16x16(_) | MBType::B16x8(_, _) | MBType::B8x16(_, _) | MBType::B8x8 => {
611 let dstride = frm.stride[0];
612 let dst = &mut frm.data[frm.offset[0] + self.sstate.mb_x * 16 + self.sstate.mb_y * 16 * dstride..];
613 for el in dst[..16].iter_mut() { *el = 255; }
614 for row in dst.chunks_mut(dstride).skip(1).take(15) {
615 row[0] = 255;
616 }
617 },
618 _ => {},
619 };*/
620 self.sstate.save_ipred_context(&frm);
621 }
622 if let Some(ref mut pic) = self.cur_pic {
623 let mv_info = &mut pic.mv_info;
624 let mb_pos = self.sstate.mb_x + self.sstate.mb_y * mv_info.mb_stride;
625 let mut mb = FrameMBInfo::new();
626 mb.mb_type = mb_info.mb_type.into();
627 for blk4 in 0..16 {
628 mb.mv[blk4] = self.sstate.get_cur_blk4(blk4).mv;
629 }
630 for blk8 in 0..4 {
631 mb.ref_poc[blk8] = self.frame_refs.map_refs(self.sstate.get_cur_blk8(blk8).ref_idx);
632 mb.ref_idx[blk8] = self.sstate.get_cur_blk8(blk8).ref_idx;
633 }
634 mv_info.mbs[mb_pos] = mb;
635 }
636 if !self.deblock_skip && self.deblock_mode != 1 {
637 self.sstate.fill_deblock(&self.frame_refs, self.deblock_mode, self.is_s);
638 if let Some(ref mut pic) = self.cur_pic {
639 let mut frm = NASimpleVideoFrame::from_video_buf(&mut pic.buf).unwrap();
640 loop_filter_mb(&mut frm, &self.sstate, self.lf_alpha, self.lf_beta);
641 }
642 }
643 self.sstate.next_mb();
644 }
645 fn decode_slice_cavlc(&mut self, br: &mut BitReader, slice_hdr: &SliceHeader, full_size: usize) -> DecoderResult<bool> {
646 const INTRA_CBP: [u8; 48] = [
647 47, 31, 15, 0, 23, 27, 29, 30, 7, 11, 13, 14, 39, 43, 45, 46,
648 16, 3, 5, 10, 12, 19, 21, 26, 28, 35, 37, 42, 44, 1, 2, 4,
649 8, 17, 18, 20, 24, 6, 9, 22, 25, 32, 33, 34, 36, 40, 38, 41
650 ];
651 const INTER_CBP: [u8; 48] = [
652 0, 16, 1, 2, 4, 8, 32, 3, 5, 10, 12, 15, 47, 7, 11, 13,
653 14, 6, 9, 31, 35, 37, 42, 44, 33, 34, 36, 40, 39, 43, 45, 46,
654 17, 18, 20, 24, 19, 21, 26, 28, 23, 27, 29, 30, 22, 25, 38, 41
655 ];
656
657 let mut mb_idx = slice_hdr.first_mb_in_slice as usize;
658 let mut mb_info = CurrentMBInfo::default();
659 mb_info.qp_y = slice_hdr.slice_qp;
660 let skip_type = if slice_hdr.slice_type.is_p() { MBType::PSkip } else { MBType::BSkip };
661 while br.tell() < full_size && mb_idx < self.num_mbs {
662 mb_info.coded = [false; 25];
663 mb_info.ref_l0 = [ZERO_REF; 4];
664 mb_info.ref_l1 = [ZERO_REF; 4];
665 mb_info.mv_l0 = [ZERO_MV; 16];
666 mb_info.mv_l1 = [ZERO_MV; 16];
667 mb_info.chroma_dc = [[0; 4]; 2];
668 mb_info.cbpy = 0;
669 mb_info.cbpc = 0;
670
671 if !slice_hdr.slice_type.is_intra() {
672 let mb_skip_run = br.read_ue()? as usize;
673 validate!(mb_idx + mb_skip_run <= self.num_mbs);
674 mb_info.mb_type = skip_type;
675 for _ in 0..mb_skip_run {
676 self.handle_macroblock(slice_hdr, &mut mb_info);
677 mb_idx += 1;
678 }
679 if mb_idx == self.num_mbs || br.tell() >= full_size {
680 break;
681 }
682 }
683 if br.tell() < full_size {
684 if self.is_mbaff && ((mb_idx & 1) == 0) {
685 let _mb_field_decoding = br.read_bool()?;
686 }
687 let mut mb_type = decode_mb_type_cavlc(br, slice_hdr)?;
688 mb_info.mb_type = mb_type;
689 mb_info.transform_size_8x8 = false;
690 if mb_type == MBType::PCM {
691 br.align();
692 for pix in self.ipcm_buf[..256 + 64 + 64].iter_mut() {
693 *pix = br.read(8)? as u8;
694 }
695 self.sstate.fill_ncoded(16);
696 } else {
697 if self.transform_8x8_mode && mb_type == MBType::Intra4x4 {
698 mb_info.transform_size_8x8 = br.read_bool()?;
699 if mb_info.transform_size_8x8 {
700 mb_type = MBType::Intra8x8;
701 mb_info.mb_type = MBType::Intra8x8;
702 }
703 }
704 decode_mb_pred_cavlc(br, slice_hdr, mb_type, &mut self.sstate, &mut mb_info)?;
705 let (cbpy, cbpc) = if let MBType::Intra16x16(_, cbpy, cbpc) = mb_type {
706 (cbpy, cbpc)
707 } else {
708 let cbp_id = br.read_ue()? as usize;
709 validate!(cbp_id < INTRA_CBP.len());
710 let cbp = if mb_type == MBType::Intra4x4 || mb_type == MBType::Intra8x8 {
711 INTRA_CBP[cbp_id]
712 } else {
713 INTER_CBP[cbp_id]
714 };
715 if self.transform_8x8_mode && (cbp & 0xF) != 0 && mb_info.can_have_8x8_tx(self.sps[self.cur_sps].direct_8x8_inference) {
716 mb_info.transform_size_8x8 = br.read_bool()?;
717 }
718 ((cbp & 0xF), (cbp >> 4))
719 };
720 mb_info.cbpy = cbpy;
721 mb_info.cbpc = cbpc;
722 self.sstate.get_cur_mb().cbp = (cbpc << 4) | cbpy;
723 if cbpy != 0 || cbpc != 0 || mb_type.is_intra16x16() {
724 let mb_qp_delta = br.read_se()?;
725 validate!(mb_qp_delta >= -26 && mb_qp_delta <= 25);
726 let new_qp = mb_qp_delta + i32::from(mb_info.qp_y);
727 mb_info.qp_y = if new_qp < 0 {
728 (new_qp + 52) as u8
729 } else if new_qp >= 52 {
730 (new_qp - 52) as u8
731 } else {
732 new_qp as u8
733 };
734 mb_info.coeffs = [[0; 16]; 25];
735 if self.transform_8x8_mode {
736 mb_info.clear_coeffs8x8();
737 }
738 mb_info.chroma_dc = [[0; 4]; 2];
739 decode_residual_cavlc(br, &mut self.sstate, &mut mb_info, &self.cavlc_cb)?;
740 }
741 }
742 self.handle_macroblock(slice_hdr, &mut mb_info);
743 }
744 mb_idx += 1;
745 }
746 if let Some(ref mut pic) = self.cur_pic {
747 pic.cur_mb = mb_idx;
748 }
749 Ok(mb_idx == self.num_mbs)
750 }
751 fn decode_slice_cabac(&mut self, cabac: &mut CABAC, slice_hdr: &SliceHeader) -> DecoderResult<bool> {
752 let mut mb_idx = slice_hdr.first_mb_in_slice as usize;
753 let mut prev_mb_skipped = false;
754 let skip_type = if slice_hdr.slice_type.is_p() { MBType::PSkip } else { MBType::BSkip };
755 let mut last_qp_diff = false;
756
757 let mut mb_info = CurrentMBInfo::default();
758 mb_info.qp_y = slice_hdr.slice_qp;
759
760 while mb_idx < self.num_mbs {
761 mb_info.coded = [false; 25];
762 mb_info.ref_l0 = [ZERO_REF; 4];
763 mb_info.ref_l1 = [ZERO_REF; 4];
764 mb_info.mv_l0 = [ZERO_MV; 16];
765 mb_info.mv_l1 = [ZERO_MV; 16];
766 mb_info.chroma_dc = [[0; 4]; 2];
767 mb_info.cbpy = 0;
768 mb_info.cbpc = 0;
769 let mb_skip = cabac_decode_mbskip(cabac, &self.sstate, slice_hdr);
770 if !mb_skip {
771 if self.is_mbaff && (((mb_idx & 1) == 0) || (prev_mb_skipped && ((mb_idx & 1) == 1))) {
772 let _mb_field_decoding = cabac.decode_bit(70);
773 }
774 let mut mb_type = cabac_decode_mb_type(cabac, &slice_hdr, &self.sstate);
775 mb_info.mb_type = mb_type;
776 mb_info.transform_size_8x8 = false;
777 if mb_type == MBType::PCM {
778 let ipcm_size = 256 + 64 + 64;
779 validate!(cabac.pos + ipcm_size <= cabac.src.len());
780 self.ipcm_buf[..ipcm_size].copy_from_slice(&cabac.src[cabac.pos..][..ipcm_size]);
781 cabac.pos += ipcm_size;
782 cabac.reinit()?;
783 last_qp_diff = false;
784 } else {
785 if self.transform_8x8_mode && mb_type == MBType::Intra4x4 {
786 let mut ctx = 0;
787 if self.sstate.get_top_mb().transform_8x8 {
788 ctx += 1;
789 }
790 if self.sstate.get_left_mb().transform_8x8 {
791 ctx += 1;
792 }
793 mb_info.transform_size_8x8 = cabac.decode_bit(399 + ctx);
794 if mb_info.transform_size_8x8 {
795 mb_type = MBType::Intra8x8;
796 mb_info.mb_type = MBType::Intra8x8;
797 }
798 }
799 decode_mb_pred_cabac(cabac, slice_hdr, mb_type, &mut self.sstate, &mut mb_info);
800 let (cbpy, cbpc) = if let MBType::Intra16x16(_, cbpy, cbpc) = mb_type {
801 (cbpy, cbpc)
802 } else {
803 decode_cbp_cabac(cabac, &self.sstate)
804 };
805 if self.transform_8x8_mode && cbpy != 0 && mb_info.can_have_8x8_tx(self.sps[self.cur_sps].direct_8x8_inference) {
806 let mut ctx = 0;
807 if self.sstate.get_top_mb().transform_8x8 {
808 ctx += 1;
809 }
810 if self.sstate.get_left_mb().transform_8x8 {
811 ctx += 1;
812 }
813 mb_info.transform_size_8x8 = cabac.decode_bit(399 + ctx);
814 }
815 if mb_type.is_intra() {
816 self.sstate.get_cur_mb().cmode = mb_info.chroma_ipred;
817 }
818 mb_info.cbpy = cbpy;
819 mb_info.cbpc = cbpc;
820 self.sstate.get_cur_mb().cbp = (cbpc << 4) | cbpy;
821 if cbpy != 0 || cbpc != 0 || mb_type.is_intra16x16() {
822 let mb_qp_delta = decode_mb_qp_delta_cabac(cabac, last_qp_diff as usize);
823 validate!(mb_qp_delta >= -26 && mb_qp_delta <= 25);
824 last_qp_diff = mb_qp_delta != 0;
825 let new_qp = mb_qp_delta + i32::from(mb_info.qp_y);
826 mb_info.qp_y = if new_qp < 0 {
827 (new_qp + 52) as u8
828 } else if new_qp >= 52 {
829 (new_qp - 52) as u8
830 } else {
831 new_qp as u8
832 };
833 mb_info.coeffs = [[0; 16]; 25];
834 if self.transform_8x8_mode {
835 mb_info.clear_coeffs8x8();
836 }
837 mb_info.chroma_dc = [[0; 4]; 2];
838 decode_residual_cabac(cabac, &mut self.sstate, &mut mb_info);
839 } else {
840 last_qp_diff = false;
841 }
842 }
843 } else {
844 mb_info.mb_type = skip_type;
845 mb_info.transform_size_8x8 = false;
846 last_qp_diff = false;
847 }
848 self.handle_macroblock(slice_hdr, &mut mb_info);
849 prev_mb_skipped = mb_skip;
850 if !(self.is_mbaff && ((mb_idx & 1) == 0)) && cabac.decode_terminate() {
851 if let Some(ref mut pic) = self.cur_pic {
852 pic.cur_mb = mb_idx + 1;
853 }
854 return Ok(mb_idx + 1 == self.num_mbs);
855 }
856 mb_idx += 1;
857 }
858 Err(DecoderError::InvalidData)
859 }
860 }
861
862 impl NADecoder for H264Decoder {
863 fn init(&mut self, supp: &mut NADecoderSupport, info: NACodecInfoRef) -> DecoderResult<()> {
864 if let NACodecTypeInfo::Video(vinfo) = info.get_properties() {
865 let fmt = YUV420_FORMAT;
866 let myinfo = NACodecTypeInfo::Video(NAVideoInfo::new(0, 0, false, fmt));
867 self.info = NACodecInfo::new_ref(info.get_name(), myinfo, info.get_extradata()).into_ref();
868
869 let edata = info.get_extradata().unwrap();
870 //print!("edata:"); for &el in edata.iter() { print!(" {:02X}", el); } println!();
871 if edata.len() > 11 && &edata[0..4] == b"avcC" {
872 let mut mr = MemoryReader::new_read(edata.as_slice());
873 let mut br = ByteReader::new(&mut mr);
874 let mut nal_buf = Vec::new();
875
876 br.read_skip(4)?;
877 let version = br.read_byte()?;
878 validate!(version == 1);
879 let profile = br.read_byte()?;
880 let _compatibility = br.read_byte()?;
881 let _level = br.read_byte()?;
882 let b = br.read_byte()?;
883 validate!((b & 0xFC) == 0xFC);
884 self.nal_len = (b & 3) + 1;
885 let b = br.read_byte()?;
886 validate!((b & 0xE0) == 0xE0);
887 let num_sps = (b & 0x1F) as usize;
888 for _ in 0..num_sps {
889 let len = br.read_u16be()? as usize;
890 let offset = br.tell() as usize;
891 validate!((br.peek_byte()? & 0x1F) == 7);
892 let _size = unescape_nal(&edata[offset..][..len], &mut nal_buf);
893 self.handle_nal(&nal_buf, supp, true)?;
894 br.read_skip(len)?;
895 }
896 let num_pps = br.read_byte()? as usize;
897 for _ in 0..num_pps {
898 let len = br.read_u16be()? as usize;
899 let offset = br.tell() as usize;
900 validate!((br.peek_byte()? & 0x1F) == 8);
901 let _size = unescape_nal(&edata[offset..][..len], &mut nal_buf);
902 self.handle_nal(&nal_buf, supp, true)?;
903 br.read_skip(len)?;
904 }
905 if br.left() > 0 {
906 match profile {
907 100 | 110 | 122 | 144 => {
908 let b = br.read_byte()?;
909 validate!((b & 0xFC) == 0xFC);
910 // b & 3 -> chroma format
911 let b = br.read_byte()?;
912 validate!((b & 0xF8) == 0xF8);
913 // b & 7 -> luma depth minus 8
914 let b = br.read_byte()?;
915 validate!((b & 0xF8) == 0xF8);
916 // b & 7 -> chroma depth minus 8
917 let num_spsext = br.read_byte()? as usize;
918 for _ in 0..num_spsext {
919 let len = br.read_u16be()? as usize;
920 // parse spsext
921 br.read_skip(len)?;
922 }
923 },
924 _ => {},
925 };
926 }
927 } else {
928 return Err(DecoderError::NotImplemented);
929 }
930
931 self.width = vinfo.get_width();
932 self.height = vinfo.get_height();
933
934 if (self.width == 0 || self.height == 0) && !self.sps.is_empty() {
935 self.width = self.sps[0].pic_width_in_mbs * 16;
936 self.height = self.sps[0].pic_height_in_mbs * 16;
937 }
938
939 let num_bufs = if !self.sps.is_empty() {
940 self.sps[0].num_ref_frames as usize + 1
941 } else {
942 3
943 }.max(16 + 1);
944 supp.pool_u8.set_dec_bufs(num_bufs);
945 supp.pool_u8.prealloc_video(NAVideoInfo::new(self.width, self.height, false, fmt), 4)?;
946
947 Ok(())
948 } else {
949 println!("???");
950 Err(DecoderError::InvalidData)
951 }
952 }
953 fn decode(&mut self, supp: &mut NADecoderSupport, pkt: &NAPacket) -> DecoderResult<NAFrameRef> {
954 let src = pkt.get_buffer();
955
956 let mut mr = MemoryReader::new_read(&src);
957 let mut br = ByteReader::new(&mut mr);
958 let mut nal_buf = Vec::with_capacity(src.len());
959 if self.nal_len > 0 {
960 let mut skip_decoding = false;
961 if self.skip_mode != FrameSkipMode::None {
962 let mut pic_type = FrameType::I;
963 let mut is_ref = false;
964 while br.left() > 0 {
965 let size = match self.nal_len {
966 1 => br.read_byte()? as usize,
967 2 => br.read_u16be()? as usize,
968 3 => br.read_u24be()? as usize,
969 4 => br.read_u32be()? as usize,
970 _ => unreachable!(),
971 };
972 validate!(br.left() >= (size as i64));
973 let offset = br.tell() as usize;
974 let size = unescape_nal(&src[offset..][..size], &mut nal_buf);
975 validate!(size > 0);
976 let nal_ref_idc = nal_buf[0] >> 5;
977 let nal_unit_type = nal_buf[0] & 0x1F;
978 if nal_unit_type == 1 || nal_unit_type == 5 {
979 let mut bitr = BitReader::new(&nal_buf[1..], BitReaderMode::BE);
980 let (first_mb, slice_type) = parse_slice_header_minimal(&mut bitr)?;
981 if first_mb == 0 && nal_ref_idc != 0 {
982 is_ref = true;
983 }
984 let new_type = slice_type.to_frame_type();
985 pic_type = match (pic_type, new_type) {
986 (FrameType::I, _) => new_type,
987 (_, FrameType::B) => FrameType::B,
988 _ => pic_type,
989 };
990 }
991 br.read_skip(size)?;
992 }
993 match self.skip_mode {
994 FrameSkipMode::IntraOnly => {
995 skip_decoding = pic_type != FrameType::I;
996 },
997 FrameSkipMode::KeyframesOnly => {
998 if !is_ref {
999 skip_decoding = true;
1000 }
1001 },
1002 _ => {},
1003 };
1004 br.seek(SeekFrom::Start(0))?;
1005 }
1006 while br.left() > 0 {
1007 let size = match self.nal_len {
1008 1 => br.read_byte()? as usize,
1009 2 => br.read_u16be()? as usize,
1010 3 => br.read_u24be()? as usize,
1011 4 => br.read_u32be()? as usize,
1012 _ => unreachable!(),
1013 };
1014 validate!(br.left() >= (size as i64));
1015 let offset = br.tell() as usize;
1016 let _size = unescape_nal(&src[offset..][..size], &mut nal_buf);
1017 self.handle_nal(nal_buf.as_slice(), supp, skip_decoding)?;
1018 br.read_skip(size)?;
1019 }
1020 } else {
1021 //todo NAL detection
1022 unimplemented!();
1023 }
1024
1025 let (bufinfo, ftype, dts) = if self.has_pic && self.cur_pic.is_some() {
1026 let mut npic = None;
1027 std::mem::swap(&mut self.cur_pic, &mut npic);
1028 let cpic = npic.unwrap();
1029 let ret = (NABufferType::Video(cpic.buf.clone()), cpic.pic_type, Some(u64::from(cpic.full_id)));
1030 if cpic.is_ref {
1031 self.frame_refs.add_short_term(cpic.clone(), self.sps[self.cur_sps].num_ref_frames);
1032 }
1033 if let Some(lt_idx) = cpic.long_term {
1034 self.frame_refs.add_long_term(lt_idx, cpic);
1035 }
1036 ret
1037 } else {
1038 (NABufferType::None, FrameType::Skip, None)
1039 };
1040
1041 let mut frm = NAFrame::new_from_pkt(pkt, self.info.clone(), bufinfo);
1042 frm.set_keyframe(ftype == FrameType::I);
1043 if let (Some(mydts), None) = (dts, frm.get_dts()) {
1044 frm.set_dts(Some(mydts));
1045 }
1046 if let Some(dts) = dts {
1047 frm.set_id(dts as i64);
1048 }
1049 frm.set_frame_type(ftype);
1050 Ok(frm.into_ref())
1051 }
1052 fn flush(&mut self) {
1053 }
1054 }
1055
1056 const DEBLOCK_SKIP_OPTION: &str = "skip_deblock";
1057
1058 const DECODER_OPTIONS: &[NAOptionDefinition] = &[
1059 NAOptionDefinition {
1060 name: FRAME_SKIP_OPTION, description: FRAME_SKIP_OPTION_DESC,
1061 opt_type: NAOptionDefinitionType::Bool },
1062 NAOptionDefinition {
1063 name: DEBLOCK_SKIP_OPTION, description: "Loop filter skipping mode",
1064 opt_type: NAOptionDefinitionType::String(Some(&[
1065 FRAME_SKIP_OPTION_VAL_NONE,
1066 FRAME_SKIP_OPTION_VAL_KEYFRAME,
1067 FRAME_SKIP_OPTION_VAL_INTRA
1068 ])) },
1069 ];
1070
1071 impl NAOptionHandler for H264Decoder {
1072 fn get_supported_options(&self) -> &[NAOptionDefinition] { DECODER_OPTIONS }
1073 fn set_options(&mut self, options: &[NAOption]) {
1074 for option in options.iter() {
1075 for opt_def in DECODER_OPTIONS.iter() {
1076 if opt_def.check(option).is_ok() {
1077 match (option.name, &option.value) {
1078 (FRAME_SKIP_OPTION, NAValue::String(ref str)) => {
1079 if let Ok(smode) = FrameSkipMode::from_str(str) {
1080 self.skip_mode = smode;
1081 }
1082 },
1083 (DEBLOCK_SKIP_OPTION, NAValue::Bool(val)) => {
1084 self.deblock_skip = *val;
1085 },
1086 _ => {},
1087 }
1088 }
1089 }
1090 }
1091 }
1092 fn query_option_value(&self, name: &str) -> Option<NAValue> {
1093 match name {
1094 FRAME_SKIP_OPTION => Some(NAValue::String(self.skip_mode.to_string())),
1095 DEBLOCK_SKIP_OPTION => Some(NAValue::Bool(self.deblock_skip)),
1096 _ => None,
1097 }
1098 }
1099 }
1100
1101 pub fn get_decoder() -> Box<dyn NADecoder + Send> {
1102 Box::new(H264Decoder::new())
1103 }
1104
1105 #[cfg(test)]
1106 mod test {
1107 use nihav_core::codecs::RegisteredDecoders;
1108 use nihav_core::demuxers::RegisteredDemuxers;
1109 use nihav_codec_support::test::dec_video::*;
1110 use crate::itu_register_all_decoders;
1111 use nihav_commonfmt::generic_register_all_demuxers;
1112
1113 // samples if not specified otherwise come from H.264 conformance suite
1114 mod raw_demux;
1115 mod conformance;
1116 use self::raw_demux::RawH264DemuxerCreator;
1117
1118 #[test]
1119 fn test_h264_perframe() {
1120 let mut dmx_reg = RegisteredDemuxers::new();
1121 dmx_reg.add_demuxer(&RawH264DemuxerCreator{});
1122 generic_register_all_demuxers(&mut dmx_reg);
1123 let mut dec_reg = RegisteredDecoders::new();
1124 itu_register_all_decoders(&mut dec_reg);
1125
1126 test_decoding("rawh264", "h264",
1127 "assets/ITU/h264-conformance/CABAST3_Sony_E.jsv",
1128 None, &dmx_reg, &dec_reg, ExpectedTestResult::MD5Frames(vec![
1129 [0xb5e5e368, 0x6ac59bfc, 0x82e35b7b, 0xbed17b81],
1130 [0x8343b34d, 0x0de80ae9, 0xe9c08cc9, 0x05161d82],
1131 [0x26e08b9b, 0x84949759, 0x71622124, 0x9bfff254],
1132 [0x940c38bc, 0x559fb990, 0x2b82a7ca, 0x3543188a],
1133 [0x60d7544d, 0x2fc8cc23, 0x4acac90f, 0x44c2a91c],
1134 [0x68d86265, 0x15fc15b9, 0xe4946d83, 0x39d9584d],
1135 [0xaed8e194, 0xa24b3a8a, 0xbed9085d, 0x05d68293],
1136 [0x1cddffac, 0x0ce9d209, 0xc4090b8a, 0xc3008856],
1137 [0x42ee0e5e, 0x4c1c3b64, 0xd91cc00b, 0x88be4b15],
1138 [0x19a70aa8, 0xd8bc987d, 0x51c04849, 0x71191523],
1139 [0x74532da6, 0xecb92919, 0xd39cb150, 0x9ca9933d],
1140 [0x0444b315, 0x2ddfb91a, 0x1e21ce06, 0x0c8613e6],
1141 [0xce209363, 0xf8d8331f, 0x72e0102f, 0x88de3a97],
1142 [0xdbcfa40a, 0x7eed5940, 0xa5c53a66, 0xdfcd3cea],
1143 [0x00796b14, 0x58f16117, 0xb6a5efd1, 0xfb129acd],
1144 [0x7673f569, 0xfccfb96a, 0x1f614c82, 0xf62ea376],
1145 [0x8669d98b, 0x9fdf4e7d, 0xa4083a7f, 0x9b66d296],
1146 [0xf0537976, 0x924229ab, 0xd0f4612f, 0xad4b614e],
1147 [0xbde82067, 0x6cf23a0c, 0xdd29e64d, 0xcaa72ff3],
1148 [0xcfcb544a, 0x1f1a81b0, 0x2217108c, 0x4888d5ef],
1149 [0x3369f874, 0x6a6dde75, 0x46d64780, 0xbf6ced32],
1150 [0x253a1f45, 0x85954311, 0x983dbabe, 0x658f4ce3],
1151 [0xec97b332, 0xa17b26d0, 0xbead22af, 0xa6bd7d8e],
1152 [0x5673d973, 0x78528036, 0xabfe5e13, 0xdcedfb26],
1153 [0xd6110fa9, 0x532d6a30, 0xb7f0aa7c, 0xae7b544b]]));
1154 }
1155
1156 // mostly static music video downloaded with youtube-dl
1157 #[test]
1158 fn test_h264_real1() {
1159 let mut dmx_reg = RegisteredDemuxers::new();
1160 dmx_reg.add_demuxer(&RawH264DemuxerCreator{});
1161 generic_register_all_demuxers(&mut dmx_reg);
1162 let mut dec_reg = RegisteredDecoders::new();
1163 itu_register_all_decoders(&mut dec_reg);
1164
1165 test_decoding("mov", "h264", "assets/ITU/1.mp4",
1166 Some(60), &dmx_reg, &dec_reg,
1167 ExpectedTestResult::MD5Frames(vec![
1168 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
1169 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
1170 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
1171 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
1172 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
1173 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
1174 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
1175 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
1176 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
1177 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
1178 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
1179 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
1180 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
1181 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
1182 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
1183 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
1184 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
1185 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
1186 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
1187 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
1188 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
1189 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
1190 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
1191 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
1192 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
1193 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
1194 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
1195 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
1196 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
1197 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
1198 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
1199 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
1200 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
1201 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
1202 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
1203 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
1204 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
1205 [0xc54f1b6e, 0xaba56a71, 0x8b45132b, 0x3c8bde7f],
1206 [0xe2742374, 0x7b9d6fa6, 0xd57eb3bb, 0x42986664],
1207 [0xa5ebdc2e, 0x9753a46a, 0x631c6359, 0x861ae0e3],
1208 [0x4d2c8769, 0xb9e15141, 0x03274d1f, 0xc15a3733],
1209 [0x17ebec8f, 0xe417571e, 0x75eb2559, 0x2f9b882b],
1210 [0x148e8c97, 0x778f92ba, 0x93646539, 0xeebe643a],
1211 [0xc6770caa, 0x1ac11a57, 0x1388a550, 0x2347758e],
1212 [0x91eb3ae4, 0xaf664462, 0x858d344a, 0xda3baa79],
1213 [0x4de79514, 0x3597aff0, 0x53e1a22f, 0x7875aa4c],
1214 [0xd5afcf7c, 0xa0f4ce82, 0x21a70eb2, 0x3911cde1],
1215 [0x9efa2a08, 0x29019ca6, 0xaba90890, 0xfb982857],
1216 [0xc5755e20, 0x4c66cb54, 0x1194812e, 0x11a9d940],
1217 [0xfd131bbb, 0x0acefb02, 0x6c79b7ab, 0x35bcdd26],
1218 [0xad159db0, 0xfa65ced2, 0xf77e2b22, 0x9e6283a8],
1219 [0xba2059e3, 0xc9f1e5e7, 0x7ea5fbcb, 0xf48d4fc3],
1220 [0xbe794078, 0x64d69f9b, 0x7b6355c5, 0x7dfb5b0f],
1221 [0x6031b77b, 0x712f42fd, 0x30d423df, 0x740e488c],
1222 [0xcc475484, 0x30a664fc, 0x227a9725, 0x4b2bfb18],
1223 [0x44bef2ea, 0xaf1e69e8, 0x832d94a8, 0xffb22712],
1224 [0xe9471e3d, 0x103de80f, 0xdc44136f, 0x67dacaa8],
1225 [0x4df3823d, 0xf6486ca9, 0x016f3114, 0x1c2d0b42],
1226 [0x1171666b, 0x08ca0ced, 0x98719757, 0xbd6b4a86],
1227 [0x9d2fc556, 0x5569fbbd, 0x0ebf629f, 0xd4fdc3b5],
1228 [0x27dbd3c3, 0x803f0230, 0x13f2ff1b, 0xb661b622]]));
1229 }
1230 // a sample downloaded from gfycat.com
1231 #[test]
1232 fn test_h264_real2() {
1233 let mut dmx_reg = RegisteredDemuxers::new();
1234 dmx_reg.add_demuxer(&RawH264DemuxerCreator{});
1235 generic_register_all_demuxers(&mut dmx_reg);
1236 let mut dec_reg = RegisteredDecoders::new();
1237 itu_register_all_decoders(&mut dec_reg);
1238 test_decoding("mov", "h264", "assets/ITU/DimpledSpanishCuckoo-mobile.mp4",
1239 Some(10), &dmx_reg, &dec_reg,
1240 ExpectedTestResult::MD5Frames(vec![
1241 [0x674c6d60, 0xc7ab918d, 0x9db1beaf, 0xda9f2456],
1242 [0x6a935350, 0x3d463ab2, 0xa3ab3c53, 0x97eb896b],
1243 [0xf6c60411, 0x19ea2c49, 0x3512371a, 0xce6cb26a],
1244 [0xc87afeaa, 0x79899908, 0x152e6320, 0xe689827f],
1245 [0xa3d829e3, 0xb404dd32, 0x11983613, 0xbdf10ee6],
1246 [0x2440ea01, 0x5b9d7fc7, 0x4fa5632b, 0xd2d76090],
1247 [0xd80e8bf9, 0xe9190ab7, 0x2be8fa38, 0xb94182e8],
1248 [0x50b9fd9a, 0x64393126, 0xd03162ec, 0xfb54172a],
1249 [0x80d1f58f, 0x12e454c0, 0x2140ca5c, 0xe19350ba],
1250 [0x26078d38, 0xf6a59d57, 0xcd14eaf8, 0x8eb08259],
1251 [0x31494337, 0x6f8d3f52, 0x4bc9ff92, 0x0c601b1c]]));
1252 }
1253 }
1254
1255 pub const I4X4_SCAN: [(u8, u8); 16] = [
1256 (0,0), (1,0), (0,1), (1,1), (2,0), (3,0), (2,1), (3,1),
1257 (0,2), (1,2), (0,3), (1,3), (2,2), (3,2), (2,3), (3,3)
1258 ];