split nihav-codec-support crate from nihav-core
[nihav.git] / nihav-indeo / src / codecs / indeo5.rs
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;
6 use super::ivi::*;
7 use super::ivibr::*;
8
9 fn calc_quant(glob_q: u32, qd: i16) -> usize {
10 let qq = (glob_q as i16) + (qd as i16);
11 if qq < 0 {
12 0
13 } else if qq > 23 {
14 23
15 } else {
16 qq as usize
17 }
18 }
19
20 struct Indeo5Parser {
21 mb_cb: IVICodebook,
22
23 width: usize,
24 height: usize,
25 tile_w: usize,
26 tile_h: usize,
27 luma_bands: usize,
28 chroma_bands: usize,
29
30 is_hpel: [bool; 5],
31 mb_size: [usize; 5],
32 blk_size: [usize; 5],
33 }
34
35 impl Indeo5Parser {
36 fn new() -> Self {
37 Indeo5Parser {
38 mb_cb: IVI_CB_ZERO,
39
40 width: 0,
41 height: 0,
42 tile_w: 0,
43 tile_h: 0,
44 luma_bands: 0,
45 chroma_bands: 0,
46
47 is_hpel: [false; 5],
48 mb_size: [0; 5],
49 blk_size: [0; 5],
50 }
51 }
52 }
53
54 fn skip_extension(br: &mut BitReader) -> DecoderResult<()> {
55 loop {
56 let len = br.read(8)?;
57 if len == 0 { break; }
58 br.skip(len * 8)?;
59 }
60 Ok(())
61 }
62
63 impl IndeoXParser for Indeo5Parser {
64 #[allow(unused_variables)]
65 #[allow(unused_assignments)]
66 fn decode_picture_header(&mut self, br: &mut BitReader) -> DecoderResult<PictureHeader> {
67 let sync = br.read(5)?;
68 validate!(sync == 0x1F);
69 let ftype_idx = br.read(3)?;
70 validate!(ftype_idx < 5);
71 let ftype = INDEO5_FRAME_TYPE[ftype_idx as usize];
72 let fnum = br.read(8)?;
73 if ftype == IVIFrameType::Intra {
74 let gop_flags = br.read(8)?;
75 let hdr_size;
76 if (gop_flags & 0x01) != 0 {
77 hdr_size = br.read(16)?;
78 } else {
79 hdr_size = 0;
80 }
81 if (gop_flags & 0x20) != 0 {
82 br.skip(32)?; // lock word
83 }
84 self.tile_w = 0;
85 self.tile_h = 0;
86 if (gop_flags & 0x40) != 0 {
87 self.tile_w = 64 << br.read(2)?;
88 self.tile_h = self.tile_w;
89 }
90 validate!(self.tile_w < 256);
91 self.luma_bands = (br.read(2)? * 3 + 1) as usize;
92 self.chroma_bands = (br.read(1)? * 3 + 1) as usize;
93 validate!((self.luma_bands == 4) || (self.luma_bands == 1));
94 validate!(self.chroma_bands == 1);
95 let pic_size_idx = br.read(4)? as usize;
96 let w;
97 let h;
98 if pic_size_idx < 15 {
99 w = INDEO5_PICTURE_SIZE_TAB[pic_size_idx][0];
100 h = INDEO5_PICTURE_SIZE_TAB[pic_size_idx][1];
101 } else {
102 h = br.read(13)? as usize;
103 w = br.read(13)? as usize;
104 }
105 validate!((w != 0) && (h != 0));
106 self.width = w;
107 self.height = h;
108
109 validate!((gop_flags & 0x02) == 0);
110 if self.tile_w == 0 {
111 self.tile_w = w;
112 self.tile_h = h;
113 }
114 for b in 0..self.luma_bands+self.chroma_bands {
115 self.is_hpel[b] = br.read_bool()?;
116 let mb_scale = br.read(1)?;
117 self.blk_size[b] = 8 >> br.read(1)?;
118 self.mb_size[b] = self.blk_size[b] << (1 - mb_scale);
119 let ext_tr = br.read_bool()?;
120 validate!(!ext_tr);
121 let end_marker = br.read(2)?;
122 validate!(end_marker == 0);
123 }
124 if (gop_flags & 0x08) != 0 {
125 let align = br.read(3)?;
126 validate!(align == 0);
127 if br.read_bool()? {
128 br.skip(24)?; // transparency color
129 }
130 }
131 br.align();
132 br.skip(23)?;
133 if br.read_bool()? { // gop extension
134 loop {
135 let v = br.read(16)?;
136 if (v & 0x8000) == 0 { break; }
137 }
138 }
139 br.align();
140 }
141 if ftype.is_null() {
142 br.align();
143 return Ok(PictureHeader::new_null(ftype));
144 }
145 let flags = br.read(8)?;
146 let size;
147 if (flags & 0x01) != 0 {
148 size = br.read(24)?;
149 } else {
150 size = 0;
151 }
152 let checksum;
153 if (flags & 0x10) != 0 {
154 checksum = br.read(16)?;
155 } else {
156 checksum = 0;
157 }
158 if (flags & 0x20) != 0 {
159 skip_extension(br)?;
160 }
161 let in_q = (flags & 0x08) != 0;
162 self.mb_cb = br.read_ivi_codebook_desc(true, (flags & 0x40) != 0)?;
163 br.skip(3)?;
164 br.align();
165
166 Ok(PictureHeader::new(ftype, self.width, self.height, self.tile_w, self.tile_h, false, self.luma_bands, self.chroma_bands, in_q))
167 }
168
169 #[allow(unused_variables)]
170 fn decode_band_header(&mut self, br: &mut BitReader, pic_hdr: &PictureHeader, plane_no: usize, band_no: usize) -> DecoderResult<BandHeader> {
171 let band_flags = br.read(8)?;
172
173 if (band_flags & 0x01) != 0 {
174 br.align();
175 return Ok(BandHeader::new_empty(plane_no, band_no));
176 }
177 let inherit_mv = (band_flags & 0x02) != 0;
178 let has_qdelta = (band_flags & 0x04) != 0;
179 let inherit_qd = ((band_flags & 0x08) != 0) || !has_qdelta;
180 let data_size: usize;
181 if (band_flags & 0x80) != 0 {
182 data_size = br.read(24)? as usize;
183 } else {
184 data_size = 0;
185 }
186 validate!(data_size <= ((br.left() / 8) as usize));
187
188 let num_corr: usize;
189 let mut corr_map: [u8; CORR_MAP_SIZE] = [0; CORR_MAP_SIZE];
190 if (band_flags & 0x10) != 0 {
191 num_corr = br.read(8)? as usize;
192 validate!(num_corr*2 <= CORR_MAP_SIZE);
193 for i in 0..num_corr*2 {
194 corr_map[i] = br.read(8)? as u8;
195 }
196 } else {
197 num_corr = 0;
198 }
199 let rvmap_idx;
200 if (band_flags & 0x40) != 0 {
201 rvmap_idx = br.read(3)? as usize;
202 } else {
203 rvmap_idx = 8;
204 }
205 let blk_cb = br.read_ivi_codebook_desc(false, (band_flags & 0x80) != 0)?;
206 if br.read_bool()? {
207 br.skip(16)?; // checksum
208 }
209 let band_q = br.read(5)?;
210 if (band_flags & 0x20) != 0 {
211 skip_extension(br)?;
212 }
213 br.align();
214
215 let tr;
216 let txtype;
217 let band_id = if plane_no == 0 { band_no } else { self.luma_bands };
218 match plane_no {
219 0 => {
220 let scan = INDEO5_SCAN8X8[band_no];
221 let qintra;
222 let qinter;
223 validate!(self.blk_size[band_id] == 8);
224 match band_no {
225 0 => {
226 tr = IVITransformType::Slant(TSize::T8x8, TDir::TwoD);
227 if self.luma_bands == 1 {
228 qintra = INDEO5_Q8_INTRA[0];
229 qinter = INDEO5_Q8_INTER[0];
230 } else {
231 qintra = INDEO5_Q8_INTRA[1];
232 qinter = INDEO5_Q8_INTER[1];
233 }
234 },
235 1 => {
236 tr = IVITransformType::Slant(TSize::T8x8, TDir::Row);
237 qintra = INDEO5_Q8_INTRA[2];
238 qinter = INDEO5_Q8_INTER[2];
239 },
240 2 => {
241 tr = IVITransformType::Slant(TSize::T8x8, TDir::Col);
242 qintra = INDEO5_Q8_INTRA[3];
243 qinter = INDEO5_Q8_INTER[3];
244 },
245 3 => {
246 tr = IVITransformType::None(TSize::T8x8);
247 qintra = INDEO5_Q8_INTRA[4];
248 qinter = INDEO5_Q8_INTER[4];
249 },
250 _ => { unreachable!(); }
251 };
252 txtype = TxType::Transform8(TxParams8x8::new(qintra, qinter, scan));
253 },
254 1 | 2 => {
255 validate!(self.blk_size[band_id] == 4);
256 tr = IVITransformType::Slant(TSize::T4x4, TDir::TwoD);
257 let scan = INDEO5_SCAN4X4;
258 let qintra = INDEO5_Q4_INTRA;
259 let qinter = INDEO5_Q4_INTER;
260 txtype = TxType::Transform4(TxParams4x4::new(qintra, qinter, scan));
261 },
262 _ => { unreachable!(); }
263 };
264
265 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))
266 }
267
268 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<()> {
269 let mut mv_x = 0;
270 let mut mv_y = 0;
271 let band_id = if pic_hdr.luma_bands == 4 { band.band_no + 1 } else { 0 };
272 let mut mb_idx = 0;
273 for mb_y in 0..tile.mb_h {
274 for mb_x in 0..tile.mb_w {
275 let mut mb = MB::new(tile.pos_x + mb_x * band.mb_size, tile.pos_y + mb_y * band.mb_size);
276 if !br.read_bool()? {
277 if pic_hdr.ftype.is_intra() {
278 mb.mtype = MBType::Intra;
279 } else if band.inherit_mv {
280 if let Some(ref tileref) = ref_tile {
281 mb.mtype = tileref.mb[mb_idx].mtype;
282 } else {
283 return Err(DecoderError::MissingReference);
284 }
285 } else {
286 mb.mtype = if br.read_bool()? { MBType::Inter } else { MBType::Intra };
287 }
288 if band.mb_size == band.blk_size {
289 mb.cbp = br.read(1)? as u8;
290 } else {
291 mb.cbp = br.read(4)? as u8;
292 }
293 let q;
294 if band.has_qdelta {
295 if band.inherit_qd {
296 if let Some(ref tileref) = ref_tile {
297 mb.qd = tileref.mb[mb_idx].qd;
298 q = calc_quant(band.quant, mb.qd);
299 } else {
300 return Err(DecoderError::MissingReference);
301 }
302 } else if (mb.cbp != 0) || ((band.plane_no == 0) && (band.band_no == 0) && pic_hdr.in_q) {
303 mb.qd = br.read_ivi_cb_s(&self.mb_cb)? as i16;
304 q = calc_quant(band.quant, mb.qd);
305 } else {
306 q = band.quant as usize;
307 }
308 } else {
309 q = band.quant as usize;
310 }
311
312 if mb.mtype == MBType::Intra {
313 if band.blk_size == 8 {
314 mb.q = INDEO5_QSCALE8_INTRA[band_id][q];
315 } else {
316 mb.q = INDEO5_QSCALE4_INTRA[q];
317 }
318 } else {
319 if band.blk_size == 8 {
320 mb.q = INDEO5_QSCALE8_INTER[band_id][q];
321 } else {
322 mb.q = INDEO5_QSCALE4_INTER[q];
323 }
324 }
325
326 if mb.mtype != MBType::Intra {
327 if band.inherit_mv {
328 if let Some(ref tileref) = ref_tile {
329 let mx = tileref.mb[mb_idx].mv_x;
330 let my = tileref.mb[mb_idx].mv_y;
331 if mv_scale == 0 {
332 mb.mv_x = mx;
333 mb.mv_y = my;
334 } else {
335 mb.mv_x = scale_mv(mx, mv_scale);
336 mb.mv_y = scale_mv(my, mv_scale);
337 }
338 }
339 } else {
340 mv_y += br.read_ivi_cb_s(&self.mb_cb)?;
341 mv_x += br.read_ivi_cb_s(&self.mb_cb)?;
342 mb.mv_x = mv_x;
343 mb.mv_y = mv_y;
344 }
345 }
346 } else {
347 validate!(!pic_hdr.ftype.is_intra());
348 mb.mtype = MBType::Inter;
349 mb.cbp = 0;
350 mb.qd = 0;
351 if (band.plane_no == 0) && (band.band_no == 0) && pic_hdr.in_q {
352 mb.qd = br.read_ivi_cb_s(&self.mb_cb)? as i16;
353 let q = calc_quant(band.quant, mb.qd);
354 if mb.mtype == MBType::Intra {
355 if band.blk_size == 8 {
356 mb.q = INDEO5_QSCALE8_INTRA[band_id][q];
357 } else {
358 mb.q = INDEO5_QSCALE4_INTRA[q];
359 }
360 } else {
361 if band.blk_size == 8 {
362 mb.q = INDEO5_QSCALE8_INTER[band_id][q];
363 } else {
364 mb.q = INDEO5_QSCALE4_INTER[q];
365 }
366 }
367 }
368 if band.inherit_mv {
369 if let Some(ref tileref) = ref_tile {
370 let mx = tileref.mb[mb_idx].mv_x;
371 let my = tileref.mb[mb_idx].mv_y;
372 if mv_scale == 0 {
373 mb.mv_x = mx;
374 mb.mv_y = my;
375 } else {
376 mb.mv_x = scale_mv(mx, mv_scale);
377 mb.mv_y = scale_mv(my, mv_scale);
378 }
379 }
380 }
381 }
382 tile.mb[mb_idx] = mb;
383 mb_idx += 1;
384 }
385 }
386 br.align();
387 Ok(())
388 }
389
390 fn recombine_plane(&mut self, src: &[i16], sstride: usize, dst: &mut [u8], dstride: usize, w: usize, h: usize) {
391 let mut idx0 = 0;
392 let mut idx1 = w / 2;
393 let mut idx2 = (h / 2) * sstride;
394 let mut idx3 = idx2 + idx1;
395 let mut bidx1 = idx1;
396 let mut bidx3 = idx3;
397 let mut oidx0 = 0;
398 let mut oidx1 = dstride;
399 let filt_lo = |a: i16, b: i16| a + b;
400 let filt_hi = |a: i16, b: i16, c: i16| a - b * 6 + c;
401
402 for _ in 0..(h/2) {
403 let mut b0_1 = src[idx0];
404 let mut b0_2 = src[idx0 + sstride];
405 let mut b1_1 = src[bidx1];
406 let mut b1_2 = src[idx1];
407 let mut b1_3 = filt_hi(b1_1, b1_2, src[idx1 + sstride]);
408 let mut b2_1;
409 let mut b2_2 = src[idx2];
410 let mut b2_3 = b2_2;
411 let mut b2_4;
412 let mut b2_5 = src[idx2 + sstride];
413 let mut b2_6 = b2_5;
414 let mut b3_1;
415 let mut b3_2 = src[bidx3];
416 let mut b3_3 = b3_2;
417 let mut b3_4;
418 let mut b3_5 = src[idx3];
419 let mut b3_6 = b3_5;
420 let mut b3_8 = filt_hi(b3_2, b3_5, src[idx3 + sstride]);
421 let mut b3_9 = b3_8;
422 let mut b3_7;
423
424 for x in 0..(w/2) {
425 b2_1 = b2_2;
426 b2_2 = b2_3;
427 b2_4 = b2_5;
428 b2_5 = b2_6;
429 b3_1 = b3_2;
430 b3_2 = b3_3;
431 b3_4 = b3_5;
432 b3_5 = b3_6;
433 b3_7 = b3_8;
434 b3_8 = b3_9;
435
436 let tmp0 = b0_1;
437 let tmp1 = b0_2;
438 b0_1 = src[idx0 + x + 1];
439 b0_2 = src[idx0 + x + 1 + sstride];
440 let mut p0 = tmp0 << 4;
441 let mut p1 = (tmp0 + b0_1) << 3;
442 let mut p2 = (tmp0 + tmp1) << 3;
443 let mut p3 = (tmp0 + tmp1 + b0_1 + b0_2) << 2;
444
445 let tmp0 = b1_1;
446 let tmp1 = b1_2;
447 let tmp2 = filt_lo(tmp0, tmp1);
448 let tmp3 = filt_hi(tmp0, tmp1, b1_3);
449 b1_2 = src[ idx1 + x + 1];
450 b1_1 = src[bidx1 + x + 1];
451 b1_3 = filt_hi(b1_1, b1_2, src[idx1 + x + 1 + sstride]);
452 p0 += tmp2 << 3;
453 p1 += (tmp2 + b1_1 + b1_2) << 2;
454 p2 += tmp3 << 2;
455 p3 += (tmp3 + b1_3) << 1;
456
457 b2_3 = src[idx2 + x + 1];
458 b2_6 = src[idx2 + x + 1 + sstride];
459 let tmp0 = filt_lo(b2_1, b2_2);
460 let tmp1 = filt_hi(b2_1, b2_2, b2_3);
461 p0 += tmp0 << 3;
462 p1 += tmp1 << 2;
463 p2 += (tmp0 + filt_lo(b2_4, b2_5)) << 2;
464 p3 += (tmp1 + filt_hi(b2_4, b2_5, b2_6)) << 1;
465
466 b3_6 = src[idx3 + x + 1];
467 b3_3 = src[bidx3 + x + 1];
468 b3_9 = filt_hi(b3_3, b3_6, src[idx3 + x + 1 + sstride]);
469 let tmp0 = b3_1 + b3_4;
470 let tmp1 = b3_2 + b3_5;
471 let tmp2 = b3_3 + b3_6;
472 p0 += filt_lo(tmp0, tmp1) << 2;
473 p1 += filt_hi(tmp0, tmp1, tmp2) << 1;
474 p2 += filt_lo(b3_7, b3_8) << 1;
475 p3 += filt_hi(b3_7, b3_8, b3_9) << 0;
476
477 dst[oidx0 + x * 2 + 0] = clip8((p0 >> 6) + 128);
478 dst[oidx0 + x * 2 + 1] = clip8((p1 >> 6) + 128);
479 dst[oidx1 + x * 2 + 0] = clip8((p2 >> 6) + 128);
480 dst[oidx1 + x * 2 + 1] = clip8((p3 >> 6) + 128);
481 }
482 bidx1 = idx1;
483 bidx3 = idx3;
484 idx0 += sstride;
485 idx1 += sstride;
486 idx2 += sstride;
487 idx3 += sstride;
488 oidx0 += dstride * 2;
489 oidx1 += dstride * 2;
490 }
491 }
492 }
493
494 struct Indeo5Decoder {
495 info: NACodecInfoRef,
496 dec: IVIDecoder,
497 ip: Indeo5Parser,
498 }
499
500 impl Indeo5Decoder {
501 fn new() -> Self {
502 Indeo5Decoder {
503 info: NACodecInfo::new_dummy(),
504 dec: IVIDecoder::new(),
505 ip: Indeo5Parser::new(),
506 }
507 }
508 }
509
510 impl NADecoder for Indeo5Decoder {
511 fn init(&mut self, _supp: &mut NADecoderSupport, info: NACodecInfoRef) -> DecoderResult<()> {
512 if let NACodecTypeInfo::Video(vinfo) = info.get_properties() {
513 let w = vinfo.get_width();
514 let h = vinfo.get_height();
515 let f = vinfo.is_flipped();
516 let fmt = formats::YUV410_FORMAT;
517 let myinfo = NACodecTypeInfo::Video(NAVideoInfo::new(w, h, f, fmt));
518 self.info = NACodecInfo::new_ref(info.get_name(), myinfo, info.get_extradata()).into_ref();
519 Ok(())
520 } else {
521 Err(DecoderError::InvalidData)
522 }
523 }
524 fn decode(&mut self, _supp: &mut NADecoderSupport, pkt: &NAPacket) -> DecoderResult<NAFrameRef> {
525 let src = pkt.get_buffer();
526 let mut br = BitReader::new(src.as_slice(), BitReaderMode::LE);
527
528 let bufinfo = self.dec.decode_frame(&mut self.ip, &mut br)?;
529 let mut frm = NAFrame::new_from_pkt(pkt, self.info.clone(), bufinfo);
530 frm.set_keyframe(self.dec.is_intra());
531 frm.set_frame_type(self.dec.get_frame_type());
532 Ok(frm.into_ref())
533 }
534 fn flush(&mut self) {
535 self.dec.flush();
536 }
537 }
538
539 const INDEO5_PICTURE_SIZE_TAB: [[usize; 2]; 15] = [
540 [640, 480], [320, 240], [160, 120], [704, 480], [352, 240], [352, 288], [176, 144],
541 [240, 180], [640, 240], [704, 240], [80, 60], [88, 72], [0, 0], [0, 0], [0, 0]
542 ];
543
544 const INDEO5_FRAME_TYPE: [IVIFrameType; 5] = [
545 IVIFrameType::Intra, IVIFrameType::Inter, IVIFrameType::InterScal,
546 IVIFrameType::InterDroppable, IVIFrameType::NULL,
547 ];
548
549 const INDEO5_QUANT8X8_INTRA: [[u16; 64]; 5] = [
550 [
551 0x1a, 0x2e, 0x36, 0x42, 0x46, 0x4a, 0x4e, 0x5a,
552 0x2e, 0x32, 0x3e, 0x42, 0x46, 0x4e, 0x56, 0x6a,
553 0x36, 0x3e, 0x3e, 0x44, 0x4a, 0x54, 0x66, 0x72,
554 0x42, 0x42, 0x44, 0x4a, 0x52, 0x62, 0x6c, 0x7a,
555 0x46, 0x46, 0x4a, 0x52, 0x5e, 0x66, 0x72, 0x8e,
556 0x4a, 0x4e, 0x54, 0x62, 0x66, 0x6e, 0x86, 0xa6,
557 0x4e, 0x56, 0x66, 0x6c, 0x72, 0x86, 0x9a, 0xca,
558 0x5a, 0x6a, 0x72, 0x7a, 0x8e, 0xa6, 0xca, 0xfe,
559 ], [
560 0x26, 0x3a, 0x3e, 0x46, 0x4a, 0x4e, 0x52, 0x5a,
561 0x3a, 0x3e, 0x42, 0x46, 0x4a, 0x4e, 0x56, 0x5e,
562 0x3e, 0x42, 0x46, 0x48, 0x4c, 0x52, 0x5a, 0x62,
563 0x46, 0x46, 0x48, 0x4a, 0x4e, 0x56, 0x5e, 0x66,
564 0x4a, 0x4a, 0x4c, 0x4e, 0x52, 0x5a, 0x62, 0x6a,
565 0x4e, 0x4e, 0x52, 0x56, 0x5a, 0x5e, 0x66, 0x6e,
566 0x52, 0x56, 0x5a, 0x5e, 0x62, 0x66, 0x6a, 0x72,
567 0x5a, 0x5e, 0x62, 0x66, 0x6a, 0x6e, 0x72, 0x76,
568 ], [
569 0x4e, 0xaa, 0xf2, 0xd4, 0xde, 0xc2, 0xd6, 0xc2,
570 0x4e, 0xaa, 0xf2, 0xd4, 0xde, 0xc2, 0xd6, 0xc2,
571 0x4e, 0xaa, 0xf2, 0xd4, 0xde, 0xc2, 0xd6, 0xc2,
572 0x4e, 0xaa, 0xf2, 0xd4, 0xde, 0xc2, 0xd6, 0xc2,
573 0x4e, 0xaa, 0xf2, 0xd4, 0xde, 0xc2, 0xd6, 0xc2,
574 0x4e, 0xaa, 0xf2, 0xd4, 0xde, 0xc2, 0xd6, 0xc2,
575 0x4e, 0xaa, 0xf2, 0xd4, 0xde, 0xc2, 0xd6, 0xc2,
576 0x4e, 0xaa, 0xf2, 0xd4, 0xde, 0xc2, 0xd6, 0xc2,
577 ], [
578 0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e,
579 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
580 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
581 0xd4, 0xd4, 0xd4, 0xd4, 0xd4, 0xd4, 0xd4, 0xd4,
582 0xde, 0xde, 0xde, 0xde, 0xde, 0xde, 0xde, 0xde,
583 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2,
584 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6,
585 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2,
586 ], [
587 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e,
588 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e,
589 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e,
590 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e,
591 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e,
592 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e,
593 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e,
594 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e,
595 ]
596 ];
597 const INDEO5_QUANT8X8_INTER: [[u16; 64]; 5] = [
598 [
599 0x26, 0x3a, 0x3e, 0x46, 0x4a, 0x4e, 0x52, 0x5a,
600 0x3a, 0x3e, 0x42, 0x46, 0x4a, 0x4e, 0x56, 0x5e,
601 0x3e, 0x42, 0x46, 0x48, 0x4c, 0x52, 0x5a, 0x62,
602 0x46, 0x46, 0x48, 0x4a, 0x4e, 0x56, 0x5e, 0x66,
603 0x4a, 0x4a, 0x4c, 0x4e, 0x52, 0x5a, 0x62, 0x6a,
604 0x4e, 0x4e, 0x52, 0x56, 0x5a, 0x5e, 0x66, 0x6e,
605 0x52, 0x56, 0x5a, 0x5e, 0x62, 0x66, 0x6a, 0x72,
606 0x5a, 0x5e, 0x62, 0x66, 0x6a, 0x6e, 0x72, 0x76,
607 ], [
608 0x26, 0x3a, 0x3e, 0x46, 0x4a, 0x4e, 0x52, 0x5a,
609 0x3a, 0x3e, 0x42, 0x46, 0x4a, 0x4e, 0x56, 0x5e,
610 0x3e, 0x42, 0x46, 0x48, 0x4c, 0x52, 0x5a, 0x62,
611 0x46, 0x46, 0x48, 0x4a, 0x4e, 0x56, 0x5e, 0x66,
612 0x4a, 0x4a, 0x4c, 0x4e, 0x52, 0x5a, 0x62, 0x6a,
613 0x4e, 0x4e, 0x52, 0x56, 0x5a, 0x5e, 0x66, 0x6e,
614 0x52, 0x56, 0x5a, 0x5e, 0x62, 0x66, 0x6a, 0x72,
615 0x5a, 0x5e, 0x62, 0x66, 0x6a, 0x6e, 0x72, 0x76,
616 ], [
617 0x4e, 0xaa, 0xf2, 0xd4, 0xde, 0xc2, 0xd6, 0xc2,
618 0x4e, 0xaa, 0xf2, 0xd4, 0xde, 0xc2, 0xd6, 0xc2,
619 0x4e, 0xaa, 0xf2, 0xd4, 0xde, 0xc2, 0xd6, 0xc2,
620 0x4e, 0xaa, 0xf2, 0xd4, 0xde, 0xc2, 0xd6, 0xc2,
621 0x4e, 0xaa, 0xf2, 0xd4, 0xde, 0xc2, 0xd6, 0xc2,
622 0x4e, 0xaa, 0xf2, 0xd4, 0xde, 0xc2, 0xd6, 0xc2,
623 0x4e, 0xaa, 0xf2, 0xd4, 0xde, 0xc2, 0xd6, 0xc2,
624 0x4e, 0xaa, 0xf2, 0xd4, 0xde, 0xc2, 0xd6, 0xc2,
625 ], [
626 0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e,
627 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
628 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
629 0xd4, 0xd4, 0xd4, 0xd4, 0xd4, 0xd4, 0xd4, 0xd4,
630 0xde, 0xde, 0xde, 0xde, 0xde, 0xde, 0xde, 0xde,
631 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2,
632 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6,
633 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2,
634 ], [
635 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e,
636 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e,
637 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e,
638 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e,
639 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e,
640 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e,
641 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e,
642 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e,
643 ]
644 ];
645 const INDEO5_QUANT4X4_INTRA: [u16; 16] = [
646 0x1e, 0x3e, 0x4a, 0x52,
647 0x3e, 0x4a, 0x52, 0x5e,
648 0x4a, 0x52, 0x5e, 0x7a,
649 0x52, 0x5e, 0x7a, 0x92
650 ];
651 const INDEO5_QUANT4X4_INTER: [u16; 16] = [
652 0x1e, 0x3e, 0x4a, 0x52,
653 0x3e, 0x4a, 0x52, 0x56,
654 0x4a, 0x52, 0x56, 0x5e,
655 0x52, 0x56, 0x5e, 0x66
656 ];
657 const INDEO5_Q8_INTRA: [&[u16; 64]; 5] = [
658 &INDEO5_QUANT8X8_INTRA[0], &INDEO5_QUANT8X8_INTRA[1], &INDEO5_QUANT8X8_INTRA[2],
659 &INDEO5_QUANT8X8_INTRA[3], &INDEO5_QUANT8X8_INTRA[4],
660 ];
661 const INDEO5_Q8_INTER: [&[u16; 64]; 5] = [
662 &INDEO5_QUANT8X8_INTER[0], &INDEO5_QUANT8X8_INTER[1], &INDEO5_QUANT8X8_INTER[2],
663 &INDEO5_QUANT8X8_INTER[3], &INDEO5_QUANT8X8_INTER[4],
664 ];
665 const INDEO5_Q4_INTRA: &[u16; 16] = &INDEO5_QUANT4X4_INTRA;
666 const INDEO5_Q4_INTER: &[u16; 16] = &INDEO5_QUANT4X4_INTER;
667
668 const INDEO5_SCAN8X8: [&[usize; 64]; 4] = [
669 &ZIGZAG, &IVI_SCAN_8X8_VER, &IVI_SCAN_8X8_HOR, &IVI_SCAN_8X8_HOR
670 ];
671 const INDEO5_SCAN4X4: &[usize; 16] = &IVI_SCAN_4X4;
672
673 const INDEO5_QSCALE8_INTRA: [[u8; 24]; 5] = [
674 [
675 0x0b, 0x0e, 0x10, 0x12, 0x14, 0x16, 0x17, 0x18, 0x1a, 0x1c, 0x1e, 0x20,
676 0x22, 0x24, 0x27, 0x28, 0x2a, 0x2d, 0x2f, 0x31, 0x34, 0x37, 0x39, 0x3c,
677 ], [
678 0x01, 0x10, 0x12, 0x14, 0x16, 0x18, 0x1b, 0x1e, 0x22, 0x25, 0x28, 0x2c,
679 0x30, 0x34, 0x38, 0x3d, 0x42, 0x47, 0x4c, 0x52, 0x58, 0x5e, 0x65, 0x6c,
680 ], [
681 0x13, 0x22, 0x27, 0x2a, 0x2d, 0x33, 0x36, 0x3c, 0x41, 0x45, 0x49, 0x4e,
682 0x53, 0x58, 0x5d, 0x63, 0x69, 0x6f, 0x75, 0x7c, 0x82, 0x88, 0x8e, 0x95,
683 ], [
684 0x13, 0x1f, 0x21, 0x24, 0x27, 0x29, 0x2d, 0x2f, 0x34, 0x37, 0x3a, 0x3d,
685 0x40, 0x44, 0x48, 0x4c, 0x4f, 0x52, 0x56, 0x5a, 0x5e, 0x62, 0x66, 0x6b,
686 ], [
687 0x31, 0x42, 0x47, 0x47, 0x4d, 0x52, 0x58, 0x58, 0x5d, 0x63, 0x67, 0x6b,
688 0x6f, 0x73, 0x78, 0x7c, 0x80, 0x84, 0x89, 0x8e, 0x93, 0x98, 0x9d, 0xa4,
689 ]
690 ];
691 const INDEO5_QSCALE8_INTER: [[u8; 24]; 5] = [
692 [
693 0x0b, 0x11, 0x13, 0x14, 0x15, 0x16, 0x18, 0x1a, 0x1b, 0x1d, 0x20, 0x22,
694 0x23, 0x25, 0x28, 0x2a, 0x2e, 0x32, 0x35, 0x39, 0x3d, 0x41, 0x44, 0x4a,
695 ], [
696 0x07, 0x14, 0x16, 0x18, 0x1b, 0x1e, 0x22, 0x25, 0x29, 0x2d, 0x31, 0x35,
697 0x3a, 0x3f, 0x44, 0x4a, 0x50, 0x56, 0x5c, 0x63, 0x6a, 0x71, 0x78, 0x7e,
698 ], [
699 0x15, 0x25, 0x28, 0x2d, 0x30, 0x34, 0x3a, 0x3d, 0x42, 0x48, 0x4c, 0x51,
700 0x56, 0x5b, 0x60, 0x65, 0x6b, 0x70, 0x76, 0x7c, 0x82, 0x88, 0x8f, 0x97,
701 ], [
702 0x13, 0x1f, 0x20, 0x22, 0x25, 0x28, 0x2b, 0x2d, 0x30, 0x33, 0x36, 0x39,
703 0x3c, 0x3f, 0x42, 0x45, 0x48, 0x4b, 0x4e, 0x52, 0x56, 0x5a, 0x5e, 0x62,
704 ], [
705 0x3c, 0x52, 0x58, 0x5d, 0x63, 0x68, 0x68, 0x6d, 0x73, 0x78, 0x7c, 0x80,
706 0x84, 0x89, 0x8e, 0x93, 0x98, 0x9d, 0xa3, 0xa9, 0xad, 0xb1, 0xb5, 0xba
707 ]
708 ];
709 const INDEO5_QSCALE4_INTRA: [u8; 24] = [
710 0x01, 0x0b, 0x0b, 0x0d, 0x0d, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x13, 0x14,
711 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20
712 ];
713 const INDEO5_QSCALE4_INTER: [u8; 24] = [
714 0x0b, 0x0d, 0x0d, 0x0e, 0x11, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
715 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23
716 ];
717
718 pub fn get_decoder() -> Box<dyn NADecoder + Send> {
719 Box::new(Indeo5Decoder::new())
720 }
721
722 #[cfg(test)]
723 mod test {
724 use nihav_core::codecs::RegisteredDecoders;
725 use nihav_core::demuxers::RegisteredDemuxers;
726 use nihav_core::test::dec_video::*;
727 use crate::indeo_register_all_codecs;
728 use nihav_commonfmt::generic_register_all_demuxers;
729 #[test]
730 fn test_indeo5() {
731 let mut dmx_reg = RegisteredDemuxers::new();
732 generic_register_all_demuxers(&mut dmx_reg);
733 let mut dec_reg = RegisteredDecoders::new();
734 indeo_register_all_codecs(&mut dec_reg);
735
736 test_decoding("avi", "indeo5", "assets/Indeo/IV5/sample.avi", Some(100),
737 &dmx_reg, &dec_reg, ExpectedTestResult::MD5Frames(vec![
738 [0xd73ef6e2, 0x099dc18f, 0x46450af9, 0x1b390a48],
739 [0xbe3295d6, 0xf4afd9fd, 0x820d35e8, 0x4b593c9a],
740 [0x415e5aed, 0x33afb9a2, 0x14ae9308, 0x53e906d3],
741 [0x7fa94dd3, 0x58582fc3, 0xe39977bc, 0xd88036d5],
742 [0x8eef68f7, 0xace88c0c, 0x3f6e4388, 0xfcd82f46],
743 [0xfe22fcc6, 0x8c4666ab, 0xd9888786, 0x7d9adbc8],
744 [0x37f8b6bc, 0xaea9e94a, 0x05a98f2e, 0x2dce51fa],
745 [0x37492cbd, 0x8fd516fa, 0x48a0bcd1, 0x5eb6584f],
746 [0x6f464159, 0xa2af785b, 0xb440493b, 0x86b21911],
747 [0x3a52de08, 0x9f5762b0, 0xe58a6979, 0x0abb295e],
748 [0xe8f56414, 0x36e76d76, 0xd0927365, 0x15dc5327],
749 [0x0fc17e06, 0x8cb6581c, 0x86eb730d, 0x9bedf951],
750 [0x54fb3627, 0xc02bffc6, 0x87748ee5, 0x8b12d57d],
751 [0x8e4fd3a5, 0x3a7b9cd7, 0x0a4ba1a0, 0x48e10237],
752 [0xce87ea8b, 0x1ec40c98, 0x12c9a682, 0x57d02bf0],
753 [0x7024e691, 0x6bc493ba, 0x617a7a91, 0x65997b4c],
754 [0xb8d53b7c, 0x132ffec9, 0x827cf176, 0x68e97292],
755 [0x12ed76a9, 0x11eced60, 0x473a364f, 0x1e197803],
756 [0x6c23ba3a, 0x12e2f7e3, 0x8fc0c2bc, 0x20726bb2],
757 [0x3307e5e6, 0x3e4fa871, 0x55df1d59, 0xbe055301],
758 [0x8198ee6c, 0x82a33414, 0x9fd8c430, 0x1fca7b93],
759 [0x557662c2, 0xeb3226fc, 0x2a125be4, 0xd475ffa9],
760 [0x850c0326, 0x7a0105e5, 0x37799945, 0x927d1237],
761 [0xe770097e, 0xabd460f4, 0x3d9260e0, 0x5a8132e2],
762 [0xdb6644e7, 0xde6986eb, 0x12cc4916, 0x977d2177],
763 [0xd58ced6c, 0x91c0e7b6, 0x8c5926fc, 0x2dbf3117],
764 [0x6e76dd5f, 0x088884f0, 0x8f94451f, 0xc8df4daf],
765 [0x726b2f8f, 0xd44af9ba, 0x1e188962, 0xd37c1a38],
766 [0x84035565, 0xd2370a8c, 0x8ecb4a3f, 0xd6758196],
767 [0xa1e75a16, 0xc9e230ed, 0x23de50f3, 0x2366967a],
768 [0x690a2a91, 0xfa4acef1, 0xd3de6dd0, 0x973031d9],
769 [0xb392e62a, 0x22b0d3f2, 0x0e975a86, 0x14d6dcb3],
770 [0x5e002202, 0xc80e236e, 0x0b484e02, 0x00035f47],
771 [0x4fc0f301, 0x8ec0d33d, 0xe71a12dd, 0xe799731f],
772 [0x278c9096, 0xec7fa833, 0x2094d81f, 0x52e21165],
773 [0xd55238a8, 0xf040101a, 0x1152b6fe, 0x661c9e64],
774 [0x3699d16e, 0x89d9f2d7, 0x9ad59597, 0x7361ee21],
775 [0x1419c93c, 0x91b75784, 0x18f7121d, 0xec2c6b78],
776 [0x07c435da, 0x05f18557, 0xf28ce1e0, 0x43cadcba],
777 [0x2015269d, 0x52cad948, 0xd6485611, 0x06fe33d7],
778 [0x0cea56f3, 0x82c30841, 0x9b2a8cab, 0x8a6f07cb],
779 [0x81f82aa9, 0x233060d5, 0x00f4171e, 0xe14c0c2a],
780 [0x9b2f8b08, 0x7d091eac, 0x09dcb2c3, 0xa7670405],
781 [0x99c97f75, 0xf91c6b12, 0xfbad7705, 0x1c6e6f27],
782 [0xc762b89c, 0xbf44a194, 0xb2a54dc2, 0xae2103e4],
783 [0xba4f52ed, 0xe35aff77, 0x50d8c9d3, 0xeb382d32],
784 [0x9bc9d9a0, 0x7cb4c594, 0xbc1af6f4, 0x1f718229],
785 [0x5f19eea2, 0x6260982e, 0x393fb360, 0x71abe746],
786 [0xd13f2fcc, 0x88a6a714, 0xf4f53d55, 0xf42b11ba],
787 [0x4208b476, 0xaf06ffce, 0x38e59bfe, 0x588567a2],
788 [0xbedfb7b7, 0x8300a39d, 0x964a3c0f, 0x577d52d7],
789 [0x18e5a6f2, 0x7ec85996, 0x27694f30, 0x7717748a],
790 [0xb5e6d70f, 0xc43261bb, 0xd4e6ae7c, 0xcc11f79c],
791 [0xc808cba7, 0xbb042416, 0x2f01ebe1, 0x7d176a38],
792 [0x03353805, 0x4b6e9d66, 0x25933123, 0x4213aaf7],
793 [0x189a6da5, 0x04a4cbe6, 0xea3c9d09, 0x153fdee2],
794 [0x41f8ac6b, 0xb476356b, 0xc70b67d0, 0x28caf359],
795 [0x4514b6a4, 0x788545ff, 0x4ee9139b, 0xa45bedf9],
796 [0x2a39be04, 0xac9921cb, 0x685c1bf9, 0x904bdab2],
797 [0x2c18f3ef, 0x416c0335, 0x0face768, 0x1b9d5cd2],
798 [0x898cd63f, 0x60af727f, 0x6bdf1be6, 0x0df05cfe],
799 [0x8a06787b, 0x7cee2f8b, 0xdc8aac77, 0x2e0e740a],
800 [0x3d340571, 0xbf1c8d4c, 0xddc23f69, 0xd1903942],
801 [0x7d179e85, 0x54048c4d, 0xba047d33, 0x2e9e5edb],
802 [0x65e26600, 0x87c8421d, 0xa77e2c6c, 0x32b4971a],
803 [0x69041052, 0xa4858c7b, 0x904d84f7, 0xb4ad3dcf],
804 [0x3ea0246d, 0x533e752d, 0x1d55798a, 0x30e17e72],
805 [0x4254a700, 0x07365f23, 0x0f9da313, 0xaecd38ce],
806 [0xa5756d9d, 0x79f31387, 0x0ded3654, 0xa7299663],
807 [0x4ef027c9, 0xeebb1383, 0x26a55289, 0x3746969d],
808 [0xdc6acadf, 0x23e1b6e1, 0x07fcdc26, 0x9914b684],
809 [0x52bb8b80, 0x1a5688ae, 0xd429662d, 0x1cc1485d],
810 [0x76b35f59, 0x24b64e5b, 0xbcbeaee7, 0xf568a832],
811 [0x0756d15f, 0x9cc288bf, 0x9f882a3c, 0xfe7c7161],
812 [0x0503113a, 0x95e716ff, 0x304cf65e, 0x490725e8],
813 [0x7db7ba62, 0x08e4e77d, 0xc9db6413, 0xea3f1a39],
814 [0x7cef6d67, 0xc94867e6, 0x5c674de6, 0x5eb74081],
815 [0x7573b799, 0x069d4f03, 0x63b537a1, 0xdfe25db6],
816 [0xc401e705, 0x834828bc, 0xd99da4a1, 0xd0f3bee8],
817 [0x02817844, 0xada6433e, 0x31761e98, 0x901ccf68],
818 [0x8f9432b4, 0x9f860957, 0xcba54c86, 0x8beb8209],
819 [0x6a46e58c, 0x7d299228, 0x5c001d12, 0xd8db2a00],
820 [0x0c12586d, 0x866d8ca9, 0x849bbb17, 0x5af63ea2],
821 [0xe48671b6, 0xc4377063, 0xc4d03c02, 0x621bd894],
822 [0x5f7f82eb, 0xcdb5abf5, 0x325f2d9d, 0x24a5d200],
823 [0xec6b6fe7, 0x347316c4, 0x6241904a, 0x4e2497a5],
824 [0xf661b7fd, 0xa00e2fc7, 0x90e11456, 0x507fef21],
825 [0x77c7addd, 0x67148dce, 0x1cd27059, 0xefbf4abf],
826 [0x11270d9c, 0xb352779d, 0x81f21055, 0xae93a8b6],
827 [0x3d1f0aaf, 0x3b4aa6d8, 0xca1c160c, 0x6fe4f2bd],
828 [0x17c6bec4, 0x54b568cd, 0xd19c78d6, 0x9a3d897a],
829 [0xc4ab4ca6, 0xbf3b2573, 0xb4d837dd, 0x4dfab799],
830 [0x6fd5645d, 0xa34978b2, 0x6696dd1a, 0x665ca09b],
831 [0x87984bb9, 0xd4d3bc30, 0x7f8bb7a8, 0x2d83b303],
832 [0x21fb5d58, 0x1ee47d1a, 0x97200d83, 0x1d596a88],
833 [0x2656f329, 0x497693be, 0xca971ddf, 0x410d4092],
834 [0xd285c512, 0xfc1ed632, 0x63c43ec2, 0xac5766d1],
835 [0x46fb80ee, 0xcfeecdaa, 0x7237a433, 0x5708ff56],
836 [0x4fccd9c8, 0x7b1a4f31, 0x51516a80, 0x27bf3cae],
837 [0xd649d2f5, 0xebadf1f7, 0x6b34e8ce, 0xb87e82f1],
838 [0x6eb0aec6, 0xfbe9cb51, 0x39e695b4, 0xa6e46e70]]));
839 }
840 }