1 use nihav_core::io::bitreader::*;
2 use nihav_core::formats;
3 use nihav_core::frame::*;
4 use nihav_core::codecs::*;
5 use nihav_codec_support::codecs::ZIGZAG;
9 fn calc_quant(glob_q: u32, qd: i16) -> usize {
10 let qq = (glob_q as i16) + qd;
54 fn skip_extension(br: &mut BitReader) -> DecoderResult<()> {
56 let len = br.read(8)?;
57 if len == 0 { break; }
63 impl IndeoXParser for Indeo5Parser {
64 fn decode_picture_header(&mut self, br: &mut BitReader) -> DecoderResult<PictureHeader> {
65 let sync = br.read(5)?;
66 validate!(sync == 0x1F);
67 let ftype_idx = br.read(3)?;
68 validate!(ftype_idx < 5);
69 let ftype = INDEO5_FRAME_TYPE[ftype_idx as usize];
70 let _fnum = br.read(8)?;
71 if ftype == IVIFrameType::Intra {
72 let gop_flags = br.read(8)?;
73 let _hdr_size = if (gop_flags & 0x01) != 0 { br.read(16)? } else { 0 };
74 if (gop_flags & 0x20) != 0 {
75 br.skip(32)?; // lock word
79 if (gop_flags & 0x40) != 0 {
80 self.tile_w = 64 << br.read(2)?;
81 self.tile_h = self.tile_w;
83 validate!(self.tile_w < 256);
84 self.luma_bands = (br.read(2)? * 3 + 1) as usize;
85 self.chroma_bands = (br.read(1)? * 3 + 1) as usize;
86 validate!((self.luma_bands == 4) || (self.luma_bands == 1));
87 validate!(self.chroma_bands == 1);
88 let pic_size_idx = br.read(4)? as usize;
91 if pic_size_idx < 15 {
92 w = INDEO5_PICTURE_SIZE_TAB[pic_size_idx][0];
93 h = INDEO5_PICTURE_SIZE_TAB[pic_size_idx][1];
95 h = br.read(13)? as usize;
96 w = br.read(13)? as usize;
98 validate!((w != 0) && (h != 0));
102 validate!((gop_flags & 0x02) == 0);
103 if self.tile_w == 0 {
107 for b in 0..self.luma_bands+self.chroma_bands {
108 self.is_hpel[b] = br.read_bool()?;
109 let mb_scale = br.read(1)?;
110 self.blk_size[b] = 8 >> br.read(1)?;
111 self.mb_size[b] = self.blk_size[b] << (1 - mb_scale);
112 let ext_tr = br.read_bool()?;
114 let end_marker = br.read(2)?;
115 validate!(end_marker == 0);
117 if (gop_flags & 0x08) != 0 {
118 let align = br.read(3)?;
119 validate!(align == 0);
121 br.skip(24)?; // transparency color
126 if br.read_bool()? { // gop extension
128 let v = br.read(16)?;
129 if (v & 0x8000) == 0 { break; }
136 return Ok(PictureHeader::new_null(ftype));
138 let flags = br.read(8)?;
139 let _size = if (flags & 0x01) != 0 { br.read(24)? } else { 0 };
140 let _checksum = if (flags & 0x10) != 0 { br.read(16)? } else { 0 };
141 if (flags & 0x20) != 0 {
144 let in_q = (flags & 0x08) != 0;
145 self.mb_cb = br.read_ivi_codebook_desc(true, (flags & 0x40) != 0)?;
149 Ok(PictureHeader::new(ftype, self.width, self.height, self.tile_w, self.tile_h, false, self.luma_bands, self.chroma_bands, in_q))
152 fn decode_band_header(&mut self, br: &mut BitReader, _pic_hdr: &PictureHeader, plane_no: usize, band_no: usize) -> DecoderResult<BandHeader> {
153 let band_flags = br.read(8)?;
155 if (band_flags & 0x01) != 0 {
157 return Ok(BandHeader::new_empty(plane_no, band_no));
159 let inherit_mv = (band_flags & 0x02) != 0;
160 let has_qdelta = (band_flags & 0x04) != 0;
161 let inherit_qd = ((band_flags & 0x08) != 0) || !has_qdelta;
162 let data_size: usize;
163 if (band_flags & 0x80) != 0 {
164 data_size = br.read(24)? as usize;
165 validate!(data_size >= 4);
169 validate!(data_size <= ((br.left() / 8) as usize) + 4);
172 let mut corr_map: [u8; CORR_MAP_SIZE] = [0; CORR_MAP_SIZE];
173 if (band_flags & 0x10) != 0 {
174 num_corr = br.read(8)? as usize;
175 validate!(num_corr*2 <= CORR_MAP_SIZE);
176 for el in corr_map[..num_corr*2].iter_mut() {
177 *el = br.read(8)? as u8;
182 let rvmap_idx = if (band_flags & 0x40) != 0 { br.read(3)? as usize } else { 8 };
183 let blk_cb = br.read_ivi_codebook_desc(false, (band_flags & 0x80) != 0)?;
185 br.skip(16)?; // checksum
187 let band_q = br.read(5)?;
188 if (band_flags & 0x20) != 0 {
195 let band_id = if plane_no == 0 { band_no } else { self.luma_bands };
198 let scan = INDEO5_SCAN8X8[band_no];
201 validate!(self.blk_size[band_id] == 8);
204 tr = IVITransformType::Slant(TSize::T8x8, TDir::TwoD);
205 if self.luma_bands == 1 {
206 qintra = INDEO5_Q8_INTRA[0];
207 qinter = INDEO5_Q8_INTER[0];
209 qintra = INDEO5_Q8_INTRA[1];
210 qinter = INDEO5_Q8_INTER[1];
214 tr = IVITransformType::Slant(TSize::T8x8, TDir::Row);
215 qintra = INDEO5_Q8_INTRA[2];
216 qinter = INDEO5_Q8_INTER[2];
219 tr = IVITransformType::Slant(TSize::T8x8, TDir::Col);
220 qintra = INDEO5_Q8_INTRA[3];
221 qinter = INDEO5_Q8_INTER[3];
224 tr = IVITransformType::None(TSize::T8x8);
225 qintra = INDEO5_Q8_INTRA[4];
226 qinter = INDEO5_Q8_INTER[4];
228 _ => { unreachable!(); }
230 txtype = TxType::Transform8(TxParams8x8::new(qintra, qinter, scan));
233 validate!(self.blk_size[band_id] == 4);
234 tr = IVITransformType::Slant(TSize::T4x4, TDir::TwoD);
235 let scan = INDEO5_SCAN4X4;
236 let qintra = INDEO5_Q4_INTRA;
237 let qinter = INDEO5_Q4_INTER;
238 txtype = TxType::Transform4(TxParams4x4::new(qintra, qinter, scan));
240 _ => { unreachable!(); }
243 Ok(BandHeader::new(plane_no, band_no, self.mb_size[band_id], self.blk_size[band_id], self.is_hpel[band_id], inherit_mv, has_qdelta, inherit_qd, band_q, rvmap_idx, num_corr, corr_map, blk_cb, tr, txtype))
246 #[allow(clippy::cognitive_complexity)]
247 #[allow(clippy::collapsible_else_if)]
248 fn decode_mb_info(&mut self, br: &mut BitReader, pic_hdr: &PictureHeader, band: &BandHeader, tile: &mut IVITile, ref_tile: Option<&IVITile>, mv_scale: u8) -> DecoderResult<()> {
251 let band_id = if pic_hdr.luma_bands == 4 { band.band_no + 1 } else { 0 };
253 for mb_y in 0..tile.mb_h {
254 for mb_x in 0..tile.mb_w {
255 let mut mb = MB::new(tile.pos_x + mb_x * band.mb_size, tile.pos_y + mb_y * band.mb_size);
256 if !br.read_bool()? {
257 if pic_hdr.ftype.is_intra() {
258 mb.mtype = MBType::Intra;
259 } else if band.inherit_mv {
260 if let Some(tileref) = ref_tile {
261 mb.mtype = tileref.mb[mb_idx].mtype;
263 return Err(DecoderError::MissingReference);
266 mb.mtype = if br.read_bool()? { MBType::Inter } else { MBType::Intra };
268 if band.mb_size == band.blk_size {
269 mb.cbp = br.read(1)? as u8;
271 mb.cbp = br.read(4)? as u8;
276 if let Some(tileref) = ref_tile {
277 mb.qd = tileref.mb[mb_idx].qd;
278 q = calc_quant(band.quant, mb.qd);
280 return Err(DecoderError::MissingReference);
282 } else if (mb.cbp != 0) || ((band.plane_no == 0) && (band.band_no == 0) && pic_hdr.in_q) {
283 mb.qd = br.read_ivi_cb_s(&self.mb_cb)? as i16;
284 q = calc_quant(band.quant, mb.qd);
286 q = band.quant as usize;
289 q = band.quant as usize;
292 if mb.mtype == MBType::Intra {
293 if band.blk_size == 8 {
294 mb.q = INDEO5_QSCALE8_INTRA[band_id][q];
296 mb.q = INDEO5_QSCALE4_INTRA[q];
299 if band.blk_size == 8 {
300 mb.q = INDEO5_QSCALE8_INTER[band_id][q];
302 mb.q = INDEO5_QSCALE4_INTER[q];
306 if mb.mtype != MBType::Intra {
308 if let Some(tileref) = ref_tile {
309 let mx = tileref.mb[mb_idx].mv_x;
310 let my = tileref.mb[mb_idx].mv_y;
315 mb.mv_x = scale_mv(mx, mv_scale);
316 mb.mv_y = scale_mv(my, mv_scale);
320 mv_y += br.read_ivi_cb_s(&self.mb_cb)?;
321 mv_x += br.read_ivi_cb_s(&self.mb_cb)?;
327 validate!(!pic_hdr.ftype.is_intra());
328 mb.mtype = MBType::Inter;
331 if (band.plane_no == 0) && (band.band_no == 0) && pic_hdr.in_q {
332 mb.qd = br.read_ivi_cb_s(&self.mb_cb)? as i16;
333 let q = calc_quant(band.quant, mb.qd);
334 if mb.mtype == MBType::Intra {
335 if band.blk_size == 8 {
336 mb.q = INDEO5_QSCALE8_INTRA[band_id][q];
338 mb.q = INDEO5_QSCALE4_INTRA[q];
341 if band.blk_size == 8 {
342 mb.q = INDEO5_QSCALE8_INTER[band_id][q];
344 mb.q = INDEO5_QSCALE4_INTER[q];
349 if let Some(tileref) = ref_tile {
350 let mx = tileref.mb[mb_idx].mv_x;
351 let my = tileref.mb[mb_idx].mv_y;
356 mb.mv_x = scale_mv(mx, mv_scale);
357 mb.mv_y = scale_mv(my, mv_scale);
362 tile.mb[mb_idx] = mb;
370 #[allow(clippy::identity_op)]
371 fn recombine_plane(&mut self, src: &[i16], sstride: usize, dst: &mut [u8], dstride: usize, w: usize, h: usize) {
373 let mut idx1 = w / 2;
374 let mut idx2 = (h / 2) * sstride;
375 let mut idx3 = idx2 + idx1;
376 let mut bidx1 = idx1;
377 let mut bidx3 = idx3;
379 let mut oidx1 = dstride;
380 let filt_lo = |a: i16, b: i16| a + b;
381 let filt_hi = |a: i16, b: i16, c: i16| a - b * 6 + c;
383 for _ in 0..(h/2)-1 {
384 let mut b0_1 = src[idx0];
385 let mut b0_2 = src[idx0 + sstride];
386 let mut b1_1 = src[bidx1];
387 let mut b1_2 = src[idx1];
388 let mut b1_3 = filt_hi(b1_1, b1_2, src[idx1 + sstride]);
390 let mut b2_2 = src[idx2];
393 let mut b2_5 = src[idx2 + sstride];
396 let mut b3_2 = src[bidx3];
399 let mut b3_5 = src[idx3];
401 let mut b3_8 = filt_hi(b3_2, b3_5, src[idx3 + sstride]);
405 for x in 0..(w/2)-1 {
419 b0_1 = src[idx0 + x + 1];
420 b0_2 = src[idx0 + x + 1 + sstride];
421 let mut p0 = tmp0 << 4;
422 let mut p1 = (tmp0 + b0_1) << 3;
423 let mut p2 = (tmp0 + tmp1) << 3;
424 let mut p3 = (tmp0 + tmp1 + b0_1 + b0_2) << 2;
428 let tmp2 = filt_lo(tmp0, tmp1);
429 let tmp3 = filt_hi(tmp0, tmp1, b1_3);
430 b1_2 = src[ idx1 + x + 1];
431 b1_1 = src[bidx1 + x + 1];
432 b1_3 = filt_hi(b1_1, b1_2, src[idx1 + x + 1 + sstride]);
434 p1 += (tmp2 + b1_1 + b1_2) << 2;
436 p3 += (tmp3 + b1_3) << 1;
438 b2_3 = src[idx2 + x + 1];
439 b2_6 = src[idx2 + x + 1 + sstride];
440 let tmp0 = filt_lo(b2_1, b2_2);
441 let tmp1 = filt_hi(b2_1, b2_2, b2_3);
444 p2 += (tmp0 + filt_lo(b2_4, b2_5)) << 2;
445 p3 += (tmp1 + filt_hi(b2_4, b2_5, b2_6)) << 1;
447 b3_6 = src[idx3 + x + 1];
448 b3_3 = src[bidx3 + x + 1];
449 b3_9 = filt_hi(b3_3, b3_6, src[idx3 + x + 1 + sstride]);
450 let tmp0 = b3_1 + b3_4;
451 let tmp1 = b3_2 + b3_5;
452 let tmp2 = b3_3 + b3_6;
453 p0 += filt_lo(tmp0, tmp1) << 2;
454 p1 += filt_hi(tmp0, tmp1, tmp2) << 1;
455 p2 += filt_lo(b3_7, b3_8) << 1;
456 p3 += filt_hi(b3_7, b3_8, b3_9) << 0;
458 dst[oidx0 + x * 2 + 0] = clip8((p0 >> 6) + 128);
459 dst[oidx0 + x * 2 + 1] = clip8((p1 >> 6) + 128);
460 dst[oidx1 + x * 2 + 0] = clip8((p2 >> 6) + 128);
461 dst[oidx1 + x * 2 + 1] = clip8((p3 >> 6) + 128);
469 oidx0 += dstride * 2;
470 oidx1 += dstride * 2;
475 struct Indeo5Decoder {
476 info: NACodecInfoRef,
482 fn new(scalable: bool) -> Self {
484 info: NACodecInfo::new_dummy(),
485 dec: IVIDecoder::new(scalable),
486 ip: Indeo5Parser::new(),
491 impl NADecoder for Indeo5Decoder {
492 fn init(&mut self, _supp: &mut NADecoderSupport, info: NACodecInfoRef) -> DecoderResult<()> {
493 if let NACodecTypeInfo::Video(vinfo) = info.get_properties() {
494 let w = vinfo.get_width();
495 let h = vinfo.get_height();
496 let f = vinfo.is_flipped();
497 let fmt = formats::YUV410_FORMAT;
498 let myinfo = NACodecTypeInfo::Video(NAVideoInfo::new(w, h, f, fmt));
499 self.info = NACodecInfo::new_ref(info.get_name(), myinfo, info.get_extradata()).into_ref();
502 Err(DecoderError::InvalidData)
505 fn decode(&mut self, _supp: &mut NADecoderSupport, pkt: &NAPacket) -> DecoderResult<NAFrameRef> {
506 let src = pkt.get_buffer();
507 let mut br = BitReader::new(src.as_slice(), BitReaderMode::LE);
509 let bufinfo = self.dec.decode_frame(&mut self.ip, &mut br)?;
510 let mut frm = NAFrame::new_from_pkt(pkt, self.info.clone(), bufinfo);
511 frm.set_keyframe(self.dec.is_intra());
512 frm.set_frame_type(self.dec.get_frame_type());
515 fn flush(&mut self) {
520 impl NAOptionHandler for Indeo5Decoder {
521 fn get_supported_options(&self) -> &[NAOptionDefinition] { &[] }
522 fn set_options(&mut self, _options: &[NAOption]) { }
523 fn query_option_value(&self, _name: &str) -> Option<NAValue> { None }
526 const INDEO5_PICTURE_SIZE_TAB: [[usize; 2]; 15] = [
527 [640, 480], [320, 240], [160, 120], [704, 480], [352, 240], [352, 288], [176, 144],
528 [240, 180], [640, 240], [704, 240], [80, 60], [88, 72], [0, 0], [0, 0], [0, 0]
531 const INDEO5_FRAME_TYPE: [IVIFrameType; 5] = [
532 IVIFrameType::Intra, IVIFrameType::Inter, IVIFrameType::InterScal,
533 IVIFrameType::InterDroppable, IVIFrameType::NULL,
536 const INDEO5_QUANT8X8_INTRA: [[u16; 64]; 5] = [
538 0x1a, 0x2e, 0x36, 0x42, 0x46, 0x4a, 0x4e, 0x5a,
539 0x2e, 0x32, 0x3e, 0x42, 0x46, 0x4e, 0x56, 0x6a,
540 0x36, 0x3e, 0x3e, 0x44, 0x4a, 0x54, 0x66, 0x72,
541 0x42, 0x42, 0x44, 0x4a, 0x52, 0x62, 0x6c, 0x7a,
542 0x46, 0x46, 0x4a, 0x52, 0x5e, 0x66, 0x72, 0x8e,
543 0x4a, 0x4e, 0x54, 0x62, 0x66, 0x6e, 0x86, 0xa6,
544 0x4e, 0x56, 0x66, 0x6c, 0x72, 0x86, 0x9a, 0xca,
545 0x5a, 0x6a, 0x72, 0x7a, 0x8e, 0xa6, 0xca, 0xfe,
547 0x26, 0x3a, 0x3e, 0x46, 0x4a, 0x4e, 0x52, 0x5a,
548 0x3a, 0x3e, 0x42, 0x46, 0x4a, 0x4e, 0x56, 0x5e,
549 0x3e, 0x42, 0x46, 0x48, 0x4c, 0x52, 0x5a, 0x62,
550 0x46, 0x46, 0x48, 0x4a, 0x4e, 0x56, 0x5e, 0x66,
551 0x4a, 0x4a, 0x4c, 0x4e, 0x52, 0x5a, 0x62, 0x6a,
552 0x4e, 0x4e, 0x52, 0x56, 0x5a, 0x5e, 0x66, 0x6e,
553 0x52, 0x56, 0x5a, 0x5e, 0x62, 0x66, 0x6a, 0x72,
554 0x5a, 0x5e, 0x62, 0x66, 0x6a, 0x6e, 0x72, 0x76,
556 0x4e, 0xaa, 0xf2, 0xd4, 0xde, 0xc2, 0xd6, 0xc2,
557 0x4e, 0xaa, 0xf2, 0xd4, 0xde, 0xc2, 0xd6, 0xc2,
558 0x4e, 0xaa, 0xf2, 0xd4, 0xde, 0xc2, 0xd6, 0xc2,
559 0x4e, 0xaa, 0xf2, 0xd4, 0xde, 0xc2, 0xd6, 0xc2,
560 0x4e, 0xaa, 0xf2, 0xd4, 0xde, 0xc2, 0xd6, 0xc2,
561 0x4e, 0xaa, 0xf2, 0xd4, 0xde, 0xc2, 0xd6, 0xc2,
562 0x4e, 0xaa, 0xf2, 0xd4, 0xde, 0xc2, 0xd6, 0xc2,
563 0x4e, 0xaa, 0xf2, 0xd4, 0xde, 0xc2, 0xd6, 0xc2,
565 0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e,
566 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
567 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
568 0xd4, 0xd4, 0xd4, 0xd4, 0xd4, 0xd4, 0xd4, 0xd4,
569 0xde, 0xde, 0xde, 0xde, 0xde, 0xde, 0xde, 0xde,
570 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2,
571 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6,
572 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2,
574 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e,
575 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e,
576 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e,
577 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e,
578 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e,
579 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e,
580 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e,
581 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e,
584 const INDEO5_QUANT8X8_INTER: [[u16; 64]; 5] = [
586 0x26, 0x3a, 0x3e, 0x46, 0x4a, 0x4e, 0x52, 0x5a,
587 0x3a, 0x3e, 0x42, 0x46, 0x4a, 0x4e, 0x56, 0x5e,
588 0x3e, 0x42, 0x46, 0x48, 0x4c, 0x52, 0x5a, 0x62,
589 0x46, 0x46, 0x48, 0x4a, 0x4e, 0x56, 0x5e, 0x66,
590 0x4a, 0x4a, 0x4c, 0x4e, 0x52, 0x5a, 0x62, 0x6a,
591 0x4e, 0x4e, 0x52, 0x56, 0x5a, 0x5e, 0x66, 0x6e,
592 0x52, 0x56, 0x5a, 0x5e, 0x62, 0x66, 0x6a, 0x72,
593 0x5a, 0x5e, 0x62, 0x66, 0x6a, 0x6e, 0x72, 0x76,
595 0x26, 0x3a, 0x3e, 0x46, 0x4a, 0x4e, 0x52, 0x5a,
596 0x3a, 0x3e, 0x42, 0x46, 0x4a, 0x4e, 0x56, 0x5e,
597 0x3e, 0x42, 0x46, 0x48, 0x4c, 0x52, 0x5a, 0x62,
598 0x46, 0x46, 0x48, 0x4a, 0x4e, 0x56, 0x5e, 0x66,
599 0x4a, 0x4a, 0x4c, 0x4e, 0x52, 0x5a, 0x62, 0x6a,
600 0x4e, 0x4e, 0x52, 0x56, 0x5a, 0x5e, 0x66, 0x6e,
601 0x52, 0x56, 0x5a, 0x5e, 0x62, 0x66, 0x6a, 0x72,
602 0x5a, 0x5e, 0x62, 0x66, 0x6a, 0x6e, 0x72, 0x76,
604 0x4e, 0xaa, 0xf2, 0xd4, 0xde, 0xc2, 0xd6, 0xc2,
605 0x4e, 0xaa, 0xf2, 0xd4, 0xde, 0xc2, 0xd6, 0xc2,
606 0x4e, 0xaa, 0xf2, 0xd4, 0xde, 0xc2, 0xd6, 0xc2,
607 0x4e, 0xaa, 0xf2, 0xd4, 0xde, 0xc2, 0xd6, 0xc2,
608 0x4e, 0xaa, 0xf2, 0xd4, 0xde, 0xc2, 0xd6, 0xc2,
609 0x4e, 0xaa, 0xf2, 0xd4, 0xde, 0xc2, 0xd6, 0xc2,
610 0x4e, 0xaa, 0xf2, 0xd4, 0xde, 0xc2, 0xd6, 0xc2,
611 0x4e, 0xaa, 0xf2, 0xd4, 0xde, 0xc2, 0xd6, 0xc2,
613 0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e,
614 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
615 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
616 0xd4, 0xd4, 0xd4, 0xd4, 0xd4, 0xd4, 0xd4, 0xd4,
617 0xde, 0xde, 0xde, 0xde, 0xde, 0xde, 0xde, 0xde,
618 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2,
619 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6,
620 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2,
622 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e,
623 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e,
624 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e,
625 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e,
626 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e,
627 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e,
628 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e,
629 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e,
632 const INDEO5_QUANT4X4_INTRA: [u16; 16] = [
633 0x1e, 0x3e, 0x4a, 0x52,
634 0x3e, 0x4a, 0x52, 0x5e,
635 0x4a, 0x52, 0x5e, 0x7a,
636 0x52, 0x5e, 0x7a, 0x92
638 const INDEO5_QUANT4X4_INTER: [u16; 16] = [
639 0x1e, 0x3e, 0x4a, 0x52,
640 0x3e, 0x4a, 0x52, 0x56,
641 0x4a, 0x52, 0x56, 0x5e,
642 0x52, 0x56, 0x5e, 0x66
644 const INDEO5_Q8_INTRA: [&[u16; 64]; 5] = [
645 &INDEO5_QUANT8X8_INTRA[0], &INDEO5_QUANT8X8_INTRA[1], &INDEO5_QUANT8X8_INTRA[2],
646 &INDEO5_QUANT8X8_INTRA[3], &INDEO5_QUANT8X8_INTRA[4],
648 const INDEO5_Q8_INTER: [&[u16; 64]; 5] = [
649 &INDEO5_QUANT8X8_INTER[0], &INDEO5_QUANT8X8_INTER[1], &INDEO5_QUANT8X8_INTER[2],
650 &INDEO5_QUANT8X8_INTER[3], &INDEO5_QUANT8X8_INTER[4],
652 const INDEO5_Q4_INTRA: &[u16; 16] = &INDEO5_QUANT4X4_INTRA;
653 const INDEO5_Q4_INTER: &[u16; 16] = &INDEO5_QUANT4X4_INTER;
655 const INDEO5_SCAN8X8: [&[usize; 64]; 4] = [
656 &ZIGZAG, &IVI_SCAN_8X8_VER, &IVI_SCAN_8X8_HOR, &IVI_SCAN_8X8_HOR
658 const INDEO5_SCAN4X4: &[usize; 16] = &IVI_SCAN_4X4;
660 const INDEO5_QSCALE8_INTRA: [[u8; 24]; 5] = [
662 0x0b, 0x0e, 0x10, 0x12, 0x14, 0x16, 0x17, 0x18, 0x1a, 0x1c, 0x1e, 0x20,
663 0x22, 0x24, 0x27, 0x28, 0x2a, 0x2d, 0x2f, 0x31, 0x34, 0x37, 0x39, 0x3c,
665 0x01, 0x10, 0x12, 0x14, 0x16, 0x18, 0x1b, 0x1e, 0x22, 0x25, 0x28, 0x2c,
666 0x30, 0x34, 0x38, 0x3d, 0x42, 0x47, 0x4c, 0x52, 0x58, 0x5e, 0x65, 0x6c,
668 0x13, 0x22, 0x27, 0x2a, 0x2d, 0x33, 0x36, 0x3c, 0x41, 0x45, 0x49, 0x4e,
669 0x53, 0x58, 0x5d, 0x63, 0x69, 0x6f, 0x75, 0x7c, 0x82, 0x88, 0x8e, 0x95,
671 0x13, 0x1f, 0x21, 0x24, 0x27, 0x29, 0x2d, 0x2f, 0x34, 0x37, 0x3a, 0x3d,
672 0x40, 0x44, 0x48, 0x4c, 0x4f, 0x52, 0x56, 0x5a, 0x5e, 0x62, 0x66, 0x6b,
674 0x31, 0x42, 0x47, 0x47, 0x4d, 0x52, 0x58, 0x58, 0x5d, 0x63, 0x67, 0x6b,
675 0x6f, 0x73, 0x78, 0x7c, 0x80, 0x84, 0x89, 0x8e, 0x93, 0x98, 0x9d, 0xa4,
678 const INDEO5_QSCALE8_INTER: [[u8; 24]; 5] = [
680 0x0b, 0x11, 0x13, 0x14, 0x15, 0x16, 0x18, 0x1a, 0x1b, 0x1d, 0x20, 0x22,
681 0x23, 0x25, 0x28, 0x2a, 0x2e, 0x32, 0x35, 0x39, 0x3d, 0x41, 0x44, 0x4a,
683 0x07, 0x14, 0x16, 0x18, 0x1b, 0x1e, 0x22, 0x25, 0x29, 0x2d, 0x31, 0x35,
684 0x3a, 0x3f, 0x44, 0x4a, 0x50, 0x56, 0x5c, 0x63, 0x6a, 0x71, 0x78, 0x7e,
686 0x15, 0x25, 0x28, 0x2d, 0x30, 0x34, 0x3a, 0x3d, 0x42, 0x48, 0x4c, 0x51,
687 0x56, 0x5b, 0x60, 0x65, 0x6b, 0x70, 0x76, 0x7c, 0x82, 0x88, 0x8f, 0x97,
689 0x13, 0x1f, 0x20, 0x22, 0x25, 0x28, 0x2b, 0x2d, 0x30, 0x33, 0x36, 0x39,
690 0x3c, 0x3f, 0x42, 0x45, 0x48, 0x4b, 0x4e, 0x52, 0x56, 0x5a, 0x5e, 0x62,
692 0x3c, 0x52, 0x58, 0x5d, 0x63, 0x68, 0x68, 0x6d, 0x73, 0x78, 0x7c, 0x80,
693 0x84, 0x89, 0x8e, 0x93, 0x98, 0x9d, 0xa3, 0xa9, 0xad, 0xb1, 0xb5, 0xba
696 const INDEO5_QSCALE4_INTRA: [u8; 24] = [
697 0x01, 0x0b, 0x0b, 0x0d, 0x0d, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x13, 0x14,
698 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20
700 const INDEO5_QSCALE4_INTER: [u8; 24] = [
701 0x0b, 0x0d, 0x0d, 0x0e, 0x11, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
702 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23
705 pub fn get_decoder() -> Box<dyn NADecoder + Send> {
706 Box::new(Indeo5Decoder::new(false))
709 pub fn get_decoder_scalable() -> Box<dyn NADecoder + Send> {
710 Box::new(Indeo5Decoder::new(true))
715 use nihav_core::codecs::RegisteredDecoders;
716 use nihav_core::demuxers::RegisteredDemuxers;
717 use nihav_codec_support::test::dec_video::*;
718 use crate::indeo_register_all_decoders;
719 use nihav_commonfmt::generic_register_all_demuxers;
722 let mut dmx_reg = RegisteredDemuxers::new();
723 generic_register_all_demuxers(&mut dmx_reg);
724 let mut dec_reg = RegisteredDecoders::new();
725 indeo_register_all_decoders(&mut dec_reg);
727 // sample: https://samples.mplayerhq.hu/V-codecs/IV50/sample.avi
728 test_decoding("avi", "indeo5", "assets/Indeo/IV5/sample.avi", Some(100),
729 &dmx_reg, &dec_reg, ExpectedTestResult::MD5Frames(vec![
730 [0xcb451428, 0x5c8b1519, 0x96a81eda, 0x0c9cccf0],
731 [0x7554e11f, 0x3b60d661, 0x3bcd14b5, 0x036dcc16],
732 [0x92a20e68, 0x83418e5c, 0x640b6786, 0x9c867622],
733 [0x0b2cde46, 0x67b68ac5, 0xc152edc6, 0xda591ac3],
734 [0x9034354b, 0x81c66b57, 0xcb671505, 0x0062a75f],
735 [0x38606276, 0x547b83df, 0x4a22f079, 0x2afb8362],
736 [0x0d3fe5df, 0xadc8b042, 0x4ee9cb0d, 0xf9b79b11],
737 [0x2b0b1ddb, 0x612a163a, 0x47b5afc8, 0xeb4c79a5],
738 [0x8eadd17e, 0xc4c8c932, 0x57508232, 0x643e1498],
739 [0x0dcc7da2, 0x7b059de2, 0x0ff46dd9, 0x04c11f77],
740 [0xe358728a, 0xe42fc515, 0x8f5cc35f, 0x02973436],
741 [0x66847a32, 0x884b41f0, 0x0c3062bc, 0xb58d923b],
742 [0x555b2711, 0xbcb54b64, 0x5a6141e5, 0xa7b5cc44],
743 [0x0f326348, 0x5d36cb21, 0xe7f8210d, 0x8a43c2c5],
744 [0x4e7b18a3, 0x42146bbb, 0x04c4cf2b, 0x78fe3c0d],
745 [0x220f0721, 0xe681444a, 0x974bf97b, 0x9b658cfe],
746 [0x2d5a5f22, 0x23bd1ed8, 0xed383633, 0x5905422d],
747 [0x982ae872, 0x17b8f765, 0x3d1735af, 0xa2872d9f],
748 [0x743a2819, 0x392d856e, 0xf2ee64ca, 0x63101b79],
749 [0x0c9e0aa7, 0x79414f6b, 0x162c19a6, 0x86d69b96],
750 [0x3eae05ad, 0xbff350bb, 0x97e8a205, 0xfa8e42b2],
751 [0x0ccae893, 0xdfcf9885, 0xef39d053, 0x0a655a73],
752 [0x75e98d11, 0x83fab601, 0xe836a6d2, 0xb2a7c7cb],
753 [0x1565b1ce, 0x8ab813c5, 0xb1658413, 0xeebaf068],
754 [0xe2bb47dd, 0xc3c277a7, 0x8c6bd4be, 0xbbca989d],
755 [0xea97912e, 0xcd224d66, 0x76fd31c2, 0x7a854abf],
756 [0x8eebb842, 0x0534b043, 0xf55a3b65, 0x3868b974],
757 [0x82c55a0b, 0x5d18c3c8, 0xbdc40fd1, 0x5d11f2e2],
758 [0xda46bff0, 0xedc1e115, 0x77cb8b8a, 0xf5fd6ddf],
759 [0x7c9c19e9, 0x4188e742, 0xd8c2cbaf, 0x0ecd1aaa],
760 [0x33145d5b, 0x0c8e2f61, 0x2ab4b213, 0xf1cf9ebe],
761 [0x64f561e1, 0xae2aa75b, 0xe4d56a57, 0xdcc54d10],
762 [0x25545f02, 0x8c271a6a, 0x6b676110, 0xa348628b],
763 [0x8c33d2d7, 0x7dfc25a0, 0xbdb68979, 0xac7ce8f1],
764 [0x8adc7126, 0x71c4d390, 0x4b47aeed, 0x444dbd2b],
765 [0xaab41fbc, 0x2c6de4d8, 0x83b61f31, 0xc68879b1],
766 [0x90961b3a, 0x9a1d4b51, 0xbf34d9d1, 0xe90137a7],
767 [0x2e988439, 0x2d7e67ec, 0x9bfd6405, 0xd851ee32],
768 [0x3b2b45e8, 0x76225018, 0xa2632614, 0x06234ca9],
769 [0xd52dc6af, 0x36c0d185, 0x90f4a9d2, 0x0b024990],
770 [0x5ed3ebb2, 0xb19b49a2, 0xd691c27a, 0x7d52941c],
771 [0xcb22479a, 0x3713b23d, 0x24abe31b, 0x45877b4e],
772 [0x143aa9f1, 0xe7709011, 0xa6ef993b, 0x8e4f33e2],
773 [0xc8b1ad16, 0x820b4f85, 0xe9d1482a, 0x806af90c],
774 [0x4f1eda2b, 0xa73eac8c, 0x8004e66b, 0xa0804e11],
775 [0x668ceb7b, 0xad020ed3, 0x90687534, 0x96eded7e],
776 [0x8bbd77d0, 0x29fc1ae4, 0xc41fb7cf, 0x31b08f08],
777 [0x02d07857, 0x4ed79f55, 0x89cfe082, 0x97167616],
778 [0xd99dbf57, 0x87ef7406, 0x59c9abdf, 0xf664be32],
779 [0x6d2bd834, 0x6b61d6e5, 0x3fd282ce, 0xbc877248],
780 [0xb4dbab3f, 0x7006dded, 0x39608927, 0x9773b83e],
781 [0x6e1f21e8, 0xff1a76c0, 0x197dd40b, 0x3cedee3d],
782 [0x551f64b8, 0x98161c0f, 0xb93103a7, 0xac12366e],
783 [0x6854311c, 0x6bc09f24, 0x226ec3e9, 0x91507815],
784 [0xb106d988, 0x6c9cda70, 0xebf972ce, 0x97b1efa8],
785 [0x91b8c27b, 0x257ff731, 0x1589d60d, 0xcb2b3de9],
786 [0x819d3677, 0xa6afca81, 0x3d2b4ba9, 0xba8cc70f],
787 [0xfb2c67fa, 0x75af7785, 0xde6133b0, 0x1bb59f2c],
788 [0xceb72cd4, 0x8c581ccb, 0x803233f2, 0xb88a174b],
789 [0xe2811f64, 0xa488d42c, 0x3a62a574, 0x918df881],
790 [0x95a66cf8, 0x0529a646, 0x3bc15b00, 0xfb0eedc9],
791 [0x1e90f3ce, 0xa8f81b7f, 0x13d5445c, 0xc969a914],
792 [0x25287783, 0x19869a3d, 0x93672c2a, 0x07a57f5e],
793 [0x44dfacc0, 0x528ae192, 0x141721a9, 0x85b2a3d9],
794 [0x45f13c20, 0x90b07bb5, 0x9a155a2f, 0x3933fb77],
795 [0x40531c62, 0x437c14b6, 0xc03c8d39, 0x35f5ae87],
796 [0x32e58909, 0xdb068147, 0xa967c6cf, 0x33d9416a],
797 [0xa8c44523, 0x12a89332, 0xddd09ccf, 0x7b04c0d2],
798 [0xae00b8b4, 0x589efb18, 0xf8c1dec1, 0xfd9d867f],
799 [0xe2fc1828, 0x5f7a3b28, 0x72de1c32, 0xc01e6ea6],
800 [0x8be4c525, 0xcde70d98, 0xd7f5f5a1, 0xf39faadf],
801 [0x9c744944, 0x00a491f4, 0x665707a9, 0xa93fad9d],
802 [0x036f2525, 0x827ddd36, 0x989c99db, 0x6b9455fc],
803 [0x52c6b5d2, 0xfd4e23f9, 0xb620b0da, 0x462d7566],
804 [0x00ba54e6, 0xfe9021ae, 0xa8c65c37, 0xda979c78],
805 [0x6e11dca0, 0x41887539, 0x2b9781af, 0x94e6b930],
806 [0x086be7db, 0xcce50438, 0x2d94bc75, 0x00f4ebfe],
807 [0xd2216f7c, 0x33321d48, 0x8ce0f144, 0x34c1fd4f],
808 [0x9083c0fc, 0x6cb46451, 0xd8202b2f, 0xae5db326],
809 [0xe894be71, 0x0e1b6c67, 0x70d5e81f, 0x2075d5ff],
810 [0x7f9f10f7, 0x0a8df81d, 0x406cb9cc, 0x524879b5],
811 [0x4c329904, 0x6f939b2c, 0xd49f8bba, 0xad54aee5],
812 [0x92d68b43, 0x2c631f71, 0x98329455, 0x91971f7f],
813 [0x1b06289e, 0x4879af78, 0xc66d7c82, 0xda19e863],
814 [0x399741da, 0xd362b007, 0x8f94e50c, 0xcdd23209],
815 [0xa2063194, 0xc67f368a, 0x83462433, 0xe719c2db],
816 [0x9da0bfd1, 0x8977f90e, 0x7f2f4172, 0xab5213ff],
817 [0x82823c8f, 0xd7cdd62e, 0xac3a59ba, 0x17ef0fb9],
818 [0xb3e51375, 0xfebb3ad3, 0x54ffdda4, 0xfbf44cf9],
819 [0x261f8183, 0x8328012b, 0x47d7e527, 0xc19cca15],
820 [0xef25bfc7, 0x79460e21, 0xeb65f2ef, 0x63731f9f],
821 [0xd14fc8f5, 0x209123ea, 0xf5f1cf21, 0x93f84381],
822 [0xf5375f67, 0x0846d9a1, 0x07aaf802, 0xe753fa08],
823 [0x65a56edd, 0x4ea28e39, 0x10d17a7b, 0xa9445d87],
824 [0xbeb8eb53, 0xd01b9c94, 0xd1d15e41, 0x639307cc],
825 [0xc2272546, 0xd1701452, 0x2fe76cbd, 0xe1dd7697],
826 [0xff6c09f6, 0x1d7804c2, 0x1ca3a2f8, 0x3fffb67b],
827 [0xfe48f3fd, 0x0046ec25, 0x1ed4401a, 0xd67f4ed6],
828 [0x46c3c72f, 0x8398b8c1, 0xe26aff08, 0x0dd1ecbb],
829 [0xc7f49f94, 0xca32d87c, 0x2e063788, 0x0229c6c0],
830 [0xa9ec4820, 0x576c7877, 0xc21211c3, 0x502af3d3]]));
833 fn test_indeo5_scalable() {
834 let mut dmx_reg = RegisteredDemuxers::new();
835 crate::indeo_register_all_demuxers(&mut dmx_reg);
836 let mut dec_reg = RegisteredDecoders::new();
837 indeo_register_all_decoders(&mut dec_reg);
839 // sample is a trailer for Heart of Darkness game
840 test_decoding("ivf", "indeo5s", "assets/Indeo/TRAILERIIE.IVF", Some(31),
841 &dmx_reg, &dec_reg, ExpectedTestResult::MD5Frames(vec![
842 [0xd6c5b653, 0x082e25e6, 0x90c0c112, 0xfa7f46c8],
843 [0x75e96cdb, 0x198cdb95, 0xde228898, 0x3cf68cfc],
844 [0xb1bed823, 0xad632d3e, 0x2e509143, 0x5e59e911],
845 [0xe3e7e2f0, 0xb8c7d968, 0xcb0b9273, 0xb7e48207],
846 [0xc6ef6975, 0xe0cc0b05, 0x983f7888, 0x64c9b89f],
847 [0xda936fad, 0xa170c0f2, 0x889a3e0c, 0xfef1a626],
848 [0xa85ccb32, 0x2c6847c4, 0x3259f48d, 0xe7e1b47b],
849 [0xedbb8256, 0x1e889428, 0xbc268e66, 0xf41d15f1],
850 [0xd6869899, 0x5121410d, 0xb12dfc96, 0x7dc67a24],
851 [0x9a594172, 0x3d9269c7, 0x1a7277fd, 0xe597dd01],
852 [0x3af07da6, 0x1968872d, 0xf7fc190e, 0x5c61c184],
853 [0xd8eec91e, 0x1aa55dfe, 0x9703a2ce, 0x1ce30990],
854 [0xea4821ae, 0x44ab9f2f, 0xa882bccb, 0xcae50f58],
855 [0x6ddfb989, 0x1affb8ad, 0x7bb2d74a, 0xc28e1a1d],
856 [0x4c9aa98d, 0xb6b2ddd2, 0xfb533baf, 0xc2d90242],
857 [0x332c8e68, 0x47a942ea, 0x6ced7891, 0x7667ad97],
858 [0x940ad339, 0x448ea27c, 0x3b7d0328, 0x4a4cf19f],
859 [0x08a60746, 0x399949ef, 0xce81ef06, 0xbc1d7d6b],
860 [0x4b5e51d0, 0xe26d32f1, 0xb1872663, 0xa70c6e65],
861 [0x428fb122, 0xf3a55f40, 0xdc4316d7, 0xe2765f76],
862 [0xcce4fa35, 0xb47d9848, 0xcbe7fef4, 0x5285022b],
863 [0xde30af92, 0x28a04fe2, 0x317f6be8, 0xde5c161c],
864 [0xe1f00bf7, 0xab2d4e91, 0x9eb674e6, 0x3b863314],
865 [0xac944130, 0xa5d1171a, 0xe8a0b591, 0x09d7652d],
866 [0x17c17612, 0x7cd40f67, 0x7aec3009, 0x2405b862],
867 [0x1d88eb87, 0x44496fb8, 0x58665011, 0xc545f745],
868 [0x04c32cce, 0x38eca98f, 0xd6227880, 0xc7d0f2bf],
869 [0x76d9dcb8, 0x92a35e1a, 0x2b968e96, 0x2c362e4a],
870 [0xda4904e7, 0x2d9d0a74, 0x63932049, 0x7bf9f0de],
871 [0x4f18931c, 0x61b9046f, 0xf5eac763, 0x0c1826d5],
872 [0x823d8746, 0x17debe43, 0xe256fda4, 0xdd1a6832],
873 [0x0bb4b91d, 0xf66f1c19, 0x166ee91a, 0x69379e27]]));