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