rename "str" variable to avoid confusion with the primitive type
[nihav.git] / nihav-itu / src / codecs / h264 / mod.rs
CommitLineData
696e4e20
KS
1/*
2 known bugs and limitations:
696e4e20
KS
3 * wrong slice boundary filtering
4 * not fully correct deblock strength selection for P/B-macroblocks
5 * scaling lists for 4x4 blocks
6*/
7use nihav_core::codecs::*;
8use nihav_core::io::byteio::*;
9use nihav_core::io::bitreader::*;
10use nihav_core::io::intcode::*;
11use nihav_codec_support::codecs::{MV, ZERO_MV};
12
13mod types;
14pub use types::*;
15mod pic_ref;
16pub use pic_ref::*;
4a1ca15c
KS
17#[allow(clippy::identity_op)]
18#[allow(clippy::erasing_op)]
19#[allow(clippy::many_single_char_names)]
20#[allow(clippy::range_plus_one)]
696e4e20
KS
21mod dsp;
22use dsp::*;
23mod cabac;
24use cabac::*;
25mod cabac_coder;
26use cabac_coder::*;
27mod cavlc;
28use cavlc::*;
29mod loopfilter;
30use loopfilter::*;
495b7ec0
KS
31mod mb_recon;
32use mb_recon::*;
696e4e20
KS
33mod sets;
34use sets::*;
35mod slice;
36use slice::*;
37
38trait 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
56impl<'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)]
76pub struct Coeff8x8 {
77 pub coeffs: [i16; 64],
78}
79
80impl Coeff8x8 {
81 fn clear(&mut self) {
82 self.coeffs = [0; 64];
83 }
84}
85
86impl Default for Coeff8x8 {
87 fn default() -> Self {
88 Self {
89 coeffs: [0; 64],
90 }
91 }
92}
93
94#[derive(Clone,Copy,Default)]
95pub 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
115impl 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
143fn 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
157struct 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
2f9923e6 190 mc_dsp: H264MC,
696e4e20
KS
191
192 transform_8x8_mode: bool,
193}
194
195fn unescape_nal(src: &[u8], dst: &mut Vec<u8>) -> usize {
196 let mut off = 0;
197 let mut zrun = 0;
37952415 198 dst.clear();
696e4e20
KS
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
221impl 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
2f9923e6 257 mc_dsp: H264MC::new(avg_buf),
696e4e20
KS
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 {
306println!(" 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;
306c604f 318 self.mc_dsp.set_dimensions(self.width, self.height);
696e4e20
KS
319
320 self.is_mbaff = sps.mb_adaptive_frame_field && !slice_hdr.field_pic;
321 if self.is_mbaff {
322println!("MBAFF");
323 return Err(DecoderError::NotImplemented);
324 }
325 if !sps.frame_mbs_only {
326println!("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 }
696e4e20
KS
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 }
d85f94f7 452 fn pred_mv(sstate: &mut SliceState, frame_refs: &FrameRefs, mb_info: &mut CurrentMBInfo, cur_id: u16, temporal_mv: bool, direct_8x8: bool) {
696e4e20
KS
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 {
d85f94f7 459 sstate.predict_direct_mb(frame_refs, temporal_mv, direct_8x8, cur_id);
696e4e20
KS
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 {
d85f94f7 499 sstate.predict_direct_sub(frame_refs, temporal_mv, direct_8x8, cur_id, (xoff / 4) + (sblk & 1) + (yoff / 4) * 4 + (sblk & 2) * 2);
696e4e20
KS
500 }
501 }
502 xoff += pw;
503 if xoff == orig_x + 8 {
504 xoff -= 8;
505 yoff += ph;
506 }
507 }
508 }
509 }
510 }
b7c882c1 511 #[allow(clippy::cognitive_complexity)]
495b7ec0 512 fn handle_macroblock(&mut self, slice_hdr: &SliceHeader, mb_info: &mut CurrentMBInfo) {
696e4e20
KS
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() {
d85f94f7 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);
696e4e20
KS
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();
495b7ec0
KS
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
696e4e20 594 } else {
495b7ec0
KS
595 0
596 };
42005e25 597 recon_mb(&mut frm, slice_hdr, mb_info, &mut self.sstate, &self.frame_refs, &mut self.mc_dsp, weight_mode);
495b7ec0 598 } else {
696e4e20
KS
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 }
696e4e20
KS
608 }
609/*match mb_info.mb_type {
610MBType::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};*/
22de733b 620 self.sstate.save_ipred_context(&frm);
696e4e20
KS
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 }
22de733b
KS
636 if !self.deblock_skip && self.deblock_mode != 1 {
637 self.sstate.fill_deblock(&self.frame_refs, self.deblock_mode, self.is_s);
696e4e20
KS
638 if let Some(ref mut pic) = self.cur_pic {
639 let mut frm = NASimpleVideoFrame::from_video_buf(&mut pic.buf).unwrap();
22de733b 640 loop_filter_mb(&mut frm, &self.sstate, self.lf_alpha, self.lf_beta);
696e4e20
KS
641 }
642 }
643 self.sstate.next_mb();
644 }
696e4e20
KS
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;
42005e25 658 let mut mb_info = CurrentMBInfo { qp_y: slice_hdr.slice_qp, ..Default::default() };
696e4e20
KS
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 {
495b7ec0 675 self.handle_macroblock(slice_hdr, &mut mb_info);
696e4e20
KS
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 }
495b7ec0 741 self.handle_macroblock(slice_hdr, &mut mb_info);
696e4e20
KS
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
42005e25 756 let mut mb_info = CurrentMBInfo { qp_y: slice_hdr.slice_qp, ..Default::default() };
696e4e20
KS
757
758 while mb_idx < self.num_mbs {
759 mb_info.coded = [false; 25];
760 mb_info.ref_l0 = [ZERO_REF; 4];
761 mb_info.ref_l1 = [ZERO_REF; 4];
762 mb_info.mv_l0 = [ZERO_MV; 16];
763 mb_info.mv_l1 = [ZERO_MV; 16];
764 mb_info.chroma_dc = [[0; 4]; 2];
765 mb_info.cbpy = 0;
766 mb_info.cbpc = 0;
767 let mb_skip = cabac_decode_mbskip(cabac, &self.sstate, slice_hdr);
768 if !mb_skip {
769 if self.is_mbaff && (((mb_idx & 1) == 0) || (prev_mb_skipped && ((mb_idx & 1) == 1))) {
770 let _mb_field_decoding = cabac.decode_bit(70);
771 }
42005e25 772 let mut mb_type = cabac_decode_mb_type(cabac, slice_hdr, &self.sstate);
696e4e20
KS
773 mb_info.mb_type = mb_type;
774 mb_info.transform_size_8x8 = false;
775 if mb_type == MBType::PCM {
776 let ipcm_size = 256 + 64 + 64;
777 validate!(cabac.pos + ipcm_size <= cabac.src.len());
778 self.ipcm_buf[..ipcm_size].copy_from_slice(&cabac.src[cabac.pos..][..ipcm_size]);
779 cabac.pos += ipcm_size;
780 cabac.reinit()?;
781 last_qp_diff = false;
782 } else {
783 if self.transform_8x8_mode && mb_type == MBType::Intra4x4 {
784 let mut ctx = 0;
785 if self.sstate.get_top_mb().transform_8x8 {
786 ctx += 1;
787 }
788 if self.sstate.get_left_mb().transform_8x8 {
789 ctx += 1;
790 }
791 mb_info.transform_size_8x8 = cabac.decode_bit(399 + ctx);
792 if mb_info.transform_size_8x8 {
793 mb_type = MBType::Intra8x8;
794 mb_info.mb_type = MBType::Intra8x8;
795 }
796 }
797 decode_mb_pred_cabac(cabac, slice_hdr, mb_type, &mut self.sstate, &mut mb_info);
798 let (cbpy, cbpc) = if let MBType::Intra16x16(_, cbpy, cbpc) = mb_type {
799 (cbpy, cbpc)
800 } else {
801 decode_cbp_cabac(cabac, &self.sstate)
802 };
803 if self.transform_8x8_mode && cbpy != 0 && mb_info.can_have_8x8_tx(self.sps[self.cur_sps].direct_8x8_inference) {
804 let mut ctx = 0;
805 if self.sstate.get_top_mb().transform_8x8 {
806 ctx += 1;
807 }
808 if self.sstate.get_left_mb().transform_8x8 {
809 ctx += 1;
810 }
811 mb_info.transform_size_8x8 = cabac.decode_bit(399 + ctx);
812 }
813 if mb_type.is_intra() {
814 self.sstate.get_cur_mb().cmode = mb_info.chroma_ipred;
815 }
816 mb_info.cbpy = cbpy;
817 mb_info.cbpc = cbpc;
818 self.sstate.get_cur_mb().cbp = (cbpc << 4) | cbpy;
819 if cbpy != 0 || cbpc != 0 || mb_type.is_intra16x16() {
820 let mb_qp_delta = decode_mb_qp_delta_cabac(cabac, last_qp_diff as usize);
821 validate!(mb_qp_delta >= -26 && mb_qp_delta <= 25);
822 last_qp_diff = mb_qp_delta != 0;
823 let new_qp = mb_qp_delta + i32::from(mb_info.qp_y);
824 mb_info.qp_y = if new_qp < 0 {
825 (new_qp + 52) as u8
826 } else if new_qp >= 52 {
827 (new_qp - 52) as u8
828 } else {
829 new_qp as u8
830 };
831 mb_info.coeffs = [[0; 16]; 25];
832 if self.transform_8x8_mode {
833 mb_info.clear_coeffs8x8();
834 }
835 mb_info.chroma_dc = [[0; 4]; 2];
836 decode_residual_cabac(cabac, &mut self.sstate, &mut mb_info);
837 } else {
838 last_qp_diff = false;
839 }
840 }
841 } else {
842 mb_info.mb_type = skip_type;
843 mb_info.transform_size_8x8 = false;
844 last_qp_diff = false;
845 }
495b7ec0 846 self.handle_macroblock(slice_hdr, &mut mb_info);
696e4e20
KS
847 prev_mb_skipped = mb_skip;
848 if !(self.is_mbaff && ((mb_idx & 1) == 0)) && cabac.decode_terminate() {
849 if let Some(ref mut pic) = self.cur_pic {
850 pic.cur_mb = mb_idx + 1;
851 }
852 return Ok(mb_idx + 1 == self.num_mbs);
853 }
854 mb_idx += 1;
855 }
856 Err(DecoderError::InvalidData)
857 }
858}
859
860impl NADecoder for H264Decoder {
861 fn init(&mut self, supp: &mut NADecoderSupport, info: NACodecInfoRef) -> DecoderResult<()> {
862 if let NACodecTypeInfo::Video(vinfo) = info.get_properties() {
863 let fmt = YUV420_FORMAT;
864 let myinfo = NACodecTypeInfo::Video(NAVideoInfo::new(0, 0, false, fmt));
865 self.info = NACodecInfo::new_ref(info.get_name(), myinfo, info.get_extradata()).into_ref();
866
867 let edata = info.get_extradata().unwrap();
868//print!("edata:"); for &el in edata.iter() { print!(" {:02X}", el); } println!();
869 if edata.len() > 11 && &edata[0..4] == b"avcC" {
870 let mut mr = MemoryReader::new_read(edata.as_slice());
871 let mut br = ByteReader::new(&mut mr);
872 let mut nal_buf = Vec::new();
873
874 br.read_skip(4)?;
875 let version = br.read_byte()?;
876 validate!(version == 1);
877 let profile = br.read_byte()?;
878 let _compatibility = br.read_byte()?;
879 let _level = br.read_byte()?;
880 let b = br.read_byte()?;
881 validate!((b & 0xFC) == 0xFC);
882 self.nal_len = (b & 3) + 1;
883 let b = br.read_byte()?;
884 validate!((b & 0xE0) == 0xE0);
885 let num_sps = (b & 0x1F) as usize;
886 for _ in 0..num_sps {
887 let len = br.read_u16be()? as usize;
888 let offset = br.tell() as usize;
889 validate!((br.peek_byte()? & 0x1F) == 7);
890 let _size = unescape_nal(&edata[offset..][..len], &mut nal_buf);
891 self.handle_nal(&nal_buf, supp, true)?;
892 br.read_skip(len)?;
893 }
894 let num_pps = br.read_byte()? as usize;
895 for _ in 0..num_pps {
896 let len = br.read_u16be()? as usize;
897 let offset = br.tell() as usize;
898 validate!((br.peek_byte()? & 0x1F) == 8);
899 let _size = unescape_nal(&edata[offset..][..len], &mut nal_buf);
900 self.handle_nal(&nal_buf, supp, true)?;
901 br.read_skip(len)?;
902 }
903 if br.left() > 0 {
904 match profile {
905 100 | 110 | 122 | 144 => {
906 let b = br.read_byte()?;
907 validate!((b & 0xFC) == 0xFC);
908 // b & 3 -> chroma format
909 let b = br.read_byte()?;
910 validate!((b & 0xF8) == 0xF8);
911 // b & 7 -> luma depth minus 8
912 let b = br.read_byte()?;
913 validate!((b & 0xF8) == 0xF8);
914 // b & 7 -> chroma depth minus 8
915 let num_spsext = br.read_byte()? as usize;
916 for _ in 0..num_spsext {
917 let len = br.read_u16be()? as usize;
918 // parse spsext
919 br.read_skip(len)?;
920 }
921 },
922 _ => {},
923 };
924 }
925 } else {
926 return Err(DecoderError::NotImplemented);
927 }
928
929 self.width = vinfo.get_width();
930 self.height = vinfo.get_height();
931
932 if (self.width == 0 || self.height == 0) && !self.sps.is_empty() {
933 self.width = self.sps[0].pic_width_in_mbs * 16;
934 self.height = self.sps[0].pic_height_in_mbs * 16;
935 }
936
937 let num_bufs = if !self.sps.is_empty() {
938 self.sps[0].num_ref_frames as usize + 1
939 } else {
940 3
941 }.max(16 + 1);
942 supp.pool_u8.set_dec_bufs(num_bufs);
943 supp.pool_u8.prealloc_video(NAVideoInfo::new(self.width, self.height, false, fmt), 4)?;
944
945 Ok(())
946 } else {
696e4e20
KS
947 Err(DecoderError::InvalidData)
948 }
949 }
950 fn decode(&mut self, supp: &mut NADecoderSupport, pkt: &NAPacket) -> DecoderResult<NAFrameRef> {
951 let src = pkt.get_buffer();
952
953 let mut mr = MemoryReader::new_read(&src);
954 let mut br = ByteReader::new(&mut mr);
955 let mut nal_buf = Vec::with_capacity(src.len());
956 if self.nal_len > 0 {
957 let mut skip_decoding = false;
958 if self.skip_mode != FrameSkipMode::None {
959 let mut pic_type = FrameType::I;
960 let mut is_ref = false;
961 while br.left() > 0 {
962 let size = match self.nal_len {
963 1 => br.read_byte()? as usize,
964 2 => br.read_u16be()? as usize,
965 3 => br.read_u24be()? as usize,
966 4 => br.read_u32be()? as usize,
967 _ => unreachable!(),
968 };
969 validate!(br.left() >= (size as i64));
970 let offset = br.tell() as usize;
971 let size = unescape_nal(&src[offset..][..size], &mut nal_buf);
972 validate!(size > 0);
973 let nal_ref_idc = nal_buf[0] >> 5;
974 let nal_unit_type = nal_buf[0] & 0x1F;
975 if nal_unit_type == 1 || nal_unit_type == 5 {
976 let mut bitr = BitReader::new(&nal_buf[1..], BitReaderMode::BE);
977 let (first_mb, slice_type) = parse_slice_header_minimal(&mut bitr)?;
978 if first_mb == 0 && nal_ref_idc != 0 {
979 is_ref = true;
980 }
981 let new_type = slice_type.to_frame_type();
982 pic_type = match (pic_type, new_type) {
983 (FrameType::I, _) => new_type,
984 (_, FrameType::B) => FrameType::B,
985 _ => pic_type,
986 };
987 }
988 br.read_skip(size)?;
989 }
990 match self.skip_mode {
991 FrameSkipMode::IntraOnly => {
992 skip_decoding = pic_type != FrameType::I;
993 },
994 FrameSkipMode::KeyframesOnly => {
995 if !is_ref {
996 skip_decoding = true;
997 }
998 },
999 _ => {},
1000 };
1001 br.seek(SeekFrom::Start(0))?;
1002 }
1003 while br.left() > 0 {
1004 let size = match self.nal_len {
1005 1 => br.read_byte()? as usize,
1006 2 => br.read_u16be()? as usize,
1007 3 => br.read_u24be()? as usize,
1008 4 => br.read_u32be()? as usize,
1009 _ => unreachable!(),
1010 };
1011 validate!(br.left() >= (size as i64));
1012 let offset = br.tell() as usize;
1013 let _size = unescape_nal(&src[offset..][..size], &mut nal_buf);
1014 self.handle_nal(nal_buf.as_slice(), supp, skip_decoding)?;
1015 br.read_skip(size)?;
1016 }
1017 } else {
1018//todo NAL detection
1019 unimplemented!();
1020 }
1021
1022 let (bufinfo, ftype, dts) = if self.has_pic && self.cur_pic.is_some() {
1023 let mut npic = None;
1024 std::mem::swap(&mut self.cur_pic, &mut npic);
1025 let cpic = npic.unwrap();
1026 let ret = (NABufferType::Video(cpic.buf.clone()), cpic.pic_type, Some(u64::from(cpic.full_id)));
1027 if cpic.is_ref {
1028 self.frame_refs.add_short_term(cpic.clone(), self.sps[self.cur_sps].num_ref_frames);
1029 }
1030 if let Some(lt_idx) = cpic.long_term {
1031 self.frame_refs.add_long_term(lt_idx, cpic);
1032 }
1033 ret
1034 } else {
1035 (NABufferType::None, FrameType::Skip, None)
1036 };
1037
1038 let mut frm = NAFrame::new_from_pkt(pkt, self.info.clone(), bufinfo);
1039 frm.set_keyframe(ftype == FrameType::I);
1040 if let (Some(mydts), None) = (dts, frm.get_dts()) {
1041 frm.set_dts(Some(mydts));
1042 }
1043 if let Some(dts) = dts {
1044 frm.set_id(dts as i64);
1045 }
1046 frm.set_frame_type(ftype);
1047 Ok(frm.into_ref())
1048 }
1049 fn flush(&mut self) {
1050 }
1051}
1052
1053const DEBLOCK_SKIP_OPTION: &str = "skip_deblock";
1054
1055const DECODER_OPTIONS: &[NAOptionDefinition] = &[
1056 NAOptionDefinition {
1057 name: FRAME_SKIP_OPTION, description: FRAME_SKIP_OPTION_DESC,
1058 opt_type: NAOptionDefinitionType::Bool },
1059 NAOptionDefinition {
1060 name: DEBLOCK_SKIP_OPTION, description: "Loop filter skipping mode",
1061 opt_type: NAOptionDefinitionType::String(Some(&[
1062 FRAME_SKIP_OPTION_VAL_NONE,
1063 FRAME_SKIP_OPTION_VAL_KEYFRAME,
1064 FRAME_SKIP_OPTION_VAL_INTRA
1065 ])) },
1066];
1067
1068impl NAOptionHandler for H264Decoder {
1069 fn get_supported_options(&self) -> &[NAOptionDefinition] { DECODER_OPTIONS }
1070 fn set_options(&mut self, options: &[NAOption]) {
1071 for option in options.iter() {
1072 for opt_def in DECODER_OPTIONS.iter() {
1073 if opt_def.check(option).is_ok() {
1074 match (option.name, &option.value) {
405cec9e
KS
1075 (FRAME_SKIP_OPTION, NAValue::String(ref strval)) => {
1076 if let Ok(smode) = FrameSkipMode::from_str(strval) {
696e4e20
KS
1077 self.skip_mode = smode;
1078 }
1079 },
1080 (DEBLOCK_SKIP_OPTION, NAValue::Bool(val)) => {
1081 self.deblock_skip = *val;
1082 },
1083 _ => {},
1084 }
1085 }
1086 }
1087 }
1088 }
1089 fn query_option_value(&self, name: &str) -> Option<NAValue> {
1090 match name {
1091 FRAME_SKIP_OPTION => Some(NAValue::String(self.skip_mode.to_string())),
1092 DEBLOCK_SKIP_OPTION => Some(NAValue::Bool(self.deblock_skip)),
1093 _ => None,
1094 }
1095 }
1096}
1097
1098pub fn get_decoder() -> Box<dyn NADecoder + Send> {
1099 Box::new(H264Decoder::new())
1100}
1101
1102#[cfg(test)]
1103mod test {
1104 use nihav_core::codecs::RegisteredDecoders;
1105 use nihav_core::demuxers::RegisteredDemuxers;
1106 use nihav_codec_support::test::dec_video::*;
1107 use crate::itu_register_all_decoders;
1108 use nihav_commonfmt::generic_register_all_demuxers;
1109
886cde48 1110 // samples if not specified otherwise come from H.264 conformance suite
696e4e20
KS
1111 mod raw_demux;
1112 mod conformance;
1113 use self::raw_demux::RawH264DemuxerCreator;
1114
1115 #[test]
1116 fn test_h264_perframe() {
1117 let mut dmx_reg = RegisteredDemuxers::new();
1118 dmx_reg.add_demuxer(&RawH264DemuxerCreator{});
1119 generic_register_all_demuxers(&mut dmx_reg);
1120 let mut dec_reg = RegisteredDecoders::new();
1121 itu_register_all_decoders(&mut dec_reg);
1122
1123 test_decoding("rawh264", "h264",
1124 "assets/ITU/h264-conformance/CABAST3_Sony_E.jsv",
1125 None, &dmx_reg, &dec_reg, ExpectedTestResult::MD5Frames(vec![
7d251522
KS
1126 [0xb5e5e368, 0x6ac59bfc, 0x82e35b7b, 0xbed17b81],
1127 [0x8343b34d, 0x0de80ae9, 0xe9c08cc9, 0x05161d82],
1128 [0x26e08b9b, 0x84949759, 0x71622124, 0x9bfff254],
1129 [0x940c38bc, 0x559fb990, 0x2b82a7ca, 0x3543188a],
1130 [0x60d7544d, 0x2fc8cc23, 0x4acac90f, 0x44c2a91c],
1131 [0x68d86265, 0x15fc15b9, 0xe4946d83, 0x39d9584d],
1132 [0xaed8e194, 0xa24b3a8a, 0xbed9085d, 0x05d68293],
1133 [0x1cddffac, 0x0ce9d209, 0xc4090b8a, 0xc3008856],
1134 [0x42ee0e5e, 0x4c1c3b64, 0xd91cc00b, 0x88be4b15],
1135 [0x19a70aa8, 0xd8bc987d, 0x51c04849, 0x71191523],
1136 [0x74532da6, 0xecb92919, 0xd39cb150, 0x9ca9933d],
1137 [0x0444b315, 0x2ddfb91a, 0x1e21ce06, 0x0c8613e6],
1138 [0xce209363, 0xf8d8331f, 0x72e0102f, 0x88de3a97],
1139 [0xdbcfa40a, 0x7eed5940, 0xa5c53a66, 0xdfcd3cea],
1140 [0x00796b14, 0x58f16117, 0xb6a5efd1, 0xfb129acd],
1141 [0x7673f569, 0xfccfb96a, 0x1f614c82, 0xf62ea376],
1142 [0x8669d98b, 0x9fdf4e7d, 0xa4083a7f, 0x9b66d296],
1143 [0xf0537976, 0x924229ab, 0xd0f4612f, 0xad4b614e],
1144 [0xbde82067, 0x6cf23a0c, 0xdd29e64d, 0xcaa72ff3],
1145 [0xcfcb544a, 0x1f1a81b0, 0x2217108c, 0x4888d5ef],
1146 [0x3369f874, 0x6a6dde75, 0x46d64780, 0xbf6ced32],
1147 [0x253a1f45, 0x85954311, 0x983dbabe, 0x658f4ce3],
1148 [0xec97b332, 0xa17b26d0, 0xbead22af, 0xa6bd7d8e],
1149 [0x5673d973, 0x78528036, 0xabfe5e13, 0xdcedfb26],
1150 [0xd6110fa9, 0x532d6a30, 0xb7f0aa7c, 0xae7b544b]]));
696e4e20
KS
1151 }
1152
886cde48 1153 // mostly static music video downloaded with youtube-dl
696e4e20
KS
1154 #[test]
1155 fn test_h264_real1() {
1156 let mut dmx_reg = RegisteredDemuxers::new();
1157 dmx_reg.add_demuxer(&RawH264DemuxerCreator{});
1158 generic_register_all_demuxers(&mut dmx_reg);
1159 let mut dec_reg = RegisteredDecoders::new();
1160 itu_register_all_decoders(&mut dec_reg);
1161
1162 test_decoding("mov", "h264", "assets/ITU/1.mp4",
1163 Some(60), &dmx_reg, &dec_reg,
1164 ExpectedTestResult::MD5Frames(vec![
1165 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
1166 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
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],
7d251522
KS
1202 [0xc54f1b6e, 0xaba56a71, 0x8b45132b, 0x3c8bde7f],
1203 [0xe2742374, 0x7b9d6fa6, 0xd57eb3bb, 0x42986664],
1204 [0xa5ebdc2e, 0x9753a46a, 0x631c6359, 0x861ae0e3],
1205 [0x4d2c8769, 0xb9e15141, 0x03274d1f, 0xc15a3733],
1206 [0x17ebec8f, 0xe417571e, 0x75eb2559, 0x2f9b882b],
1207 [0x148e8c97, 0x778f92ba, 0x93646539, 0xeebe643a],
1208 [0xc6770caa, 0x1ac11a57, 0x1388a550, 0x2347758e],
1209 [0x91eb3ae4, 0xaf664462, 0x858d344a, 0xda3baa79],
1210 [0x4de79514, 0x3597aff0, 0x53e1a22f, 0x7875aa4c],
1211 [0xd5afcf7c, 0xa0f4ce82, 0x21a70eb2, 0x3911cde1],
1212 [0x9efa2a08, 0x29019ca6, 0xaba90890, 0xfb982857],
1213 [0xc5755e20, 0x4c66cb54, 0x1194812e, 0x11a9d940],
1214 [0xfd131bbb, 0x0acefb02, 0x6c79b7ab, 0x35bcdd26],
1215 [0xad159db0, 0xfa65ced2, 0xf77e2b22, 0x9e6283a8],
1216 [0xba2059e3, 0xc9f1e5e7, 0x7ea5fbcb, 0xf48d4fc3],
1217 [0xbe794078, 0x64d69f9b, 0x7b6355c5, 0x7dfb5b0f],
1218 [0x6031b77b, 0x712f42fd, 0x30d423df, 0x740e488c],
1219 [0xcc475484, 0x30a664fc, 0x227a9725, 0x4b2bfb18],
1220 [0x44bef2ea, 0xaf1e69e8, 0x832d94a8, 0xffb22712],
1221 [0xe9471e3d, 0x103de80f, 0xdc44136f, 0x67dacaa8],
1222 [0x4df3823d, 0xf6486ca9, 0x016f3114, 0x1c2d0b42],
1223 [0x1171666b, 0x08ca0ced, 0x98719757, 0xbd6b4a86],
1224 [0x9d2fc556, 0x5569fbbd, 0x0ebf629f, 0xd4fdc3b5],
1225 [0x27dbd3c3, 0x803f0230, 0x13f2ff1b, 0xb661b622]]));
696e4e20 1226 }
886cde48 1227 // a sample downloaded from gfycat.com
696e4e20
KS
1228 #[test]
1229 fn test_h264_real2() {
1230 let mut dmx_reg = RegisteredDemuxers::new();
1231 dmx_reg.add_demuxer(&RawH264DemuxerCreator{});
1232 generic_register_all_demuxers(&mut dmx_reg);
1233 let mut dec_reg = RegisteredDecoders::new();
1234 itu_register_all_decoders(&mut dec_reg);
1235 test_decoding("mov", "h264", "assets/ITU/DimpledSpanishCuckoo-mobile.mp4",
1236 Some(10), &dmx_reg, &dec_reg,
1237 ExpectedTestResult::MD5Frames(vec![
7d251522
KS
1238 [0x674c6d60, 0xc7ab918d, 0x9db1beaf, 0xda9f2456],
1239 [0x6a935350, 0x3d463ab2, 0xa3ab3c53, 0x97eb896b],
1240 [0xf6c60411, 0x19ea2c49, 0x3512371a, 0xce6cb26a],
1241 [0xc87afeaa, 0x79899908, 0x152e6320, 0xe689827f],
1242 [0xa3d829e3, 0xb404dd32, 0x11983613, 0xbdf10ee6],
1243 [0x2440ea01, 0x5b9d7fc7, 0x4fa5632b, 0xd2d76090],
1244 [0xd80e8bf9, 0xe9190ab7, 0x2be8fa38, 0xb94182e8],
1245 [0x50b9fd9a, 0x64393126, 0xd03162ec, 0xfb54172a],
1246 [0x80d1f58f, 0x12e454c0, 0x2140ca5c, 0xe19350ba],
1247 [0x26078d38, 0xf6a59d57, 0xcd14eaf8, 0x8eb08259],
1248 [0x31494337, 0x6f8d3f52, 0x4bc9ff92, 0x0c601b1c]]));
696e4e20
KS
1249 }
1250}
1251
1252pub const I4X4_SCAN: [(u8, u8); 16] = [
1253 (0,0), (1,0), (0,1), (1,1), (2,0), (3,0), (2,1), (3,1),
1254 (0,2), (1,2), (0,3), (1,3), (2,2), (3,2), (2,3), (3,3)
1255];