]> git.nihav.org Git - nihav.git/blob - nihav-indeo/src/codecs/indeo5.rs
indeo5: fix off-by-one error in recombine_plane()
[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 validate!(data_size >= 4);
184 } else {
185 data_size = 0;
186 }
187 validate!(data_size <= ((br.left() / 8) as usize) + 4);
188
189 let num_corr: usize;
190 let mut corr_map: [u8; CORR_MAP_SIZE] = [0; CORR_MAP_SIZE];
191 if (band_flags & 0x10) != 0 {
192 num_corr = br.read(8)? as usize;
193 validate!(num_corr*2 <= CORR_MAP_SIZE);
194 for i in 0..num_corr*2 {
195 corr_map[i] = br.read(8)? as u8;
196 }
197 } else {
198 num_corr = 0;
199 }
200 let rvmap_idx;
201 if (band_flags & 0x40) != 0 {
202 rvmap_idx = br.read(3)? as usize;
203 } else {
204 rvmap_idx = 8;
205 }
206 let blk_cb = br.read_ivi_codebook_desc(false, (band_flags & 0x80) != 0)?;
207 if br.read_bool()? {
208 br.skip(16)?; // checksum
209 }
210 let band_q = br.read(5)?;
211 if (band_flags & 0x20) != 0 {
212 skip_extension(br)?;
213 }
214 br.align();
215
216 let tr;
217 let txtype;
218 let band_id = if plane_no == 0 { band_no } else { self.luma_bands };
219 match plane_no {
220 0 => {
221 let scan = INDEO5_SCAN8X8[band_no];
222 let qintra;
223 let qinter;
224 validate!(self.blk_size[band_id] == 8);
225 match band_no {
226 0 => {
227 tr = IVITransformType::Slant(TSize::T8x8, TDir::TwoD);
228 if self.luma_bands == 1 {
229 qintra = INDEO5_Q8_INTRA[0];
230 qinter = INDEO5_Q8_INTER[0];
231 } else {
232 qintra = INDEO5_Q8_INTRA[1];
233 qinter = INDEO5_Q8_INTER[1];
234 }
235 },
236 1 => {
237 tr = IVITransformType::Slant(TSize::T8x8, TDir::Row);
238 qintra = INDEO5_Q8_INTRA[2];
239 qinter = INDEO5_Q8_INTER[2];
240 },
241 2 => {
242 tr = IVITransformType::Slant(TSize::T8x8, TDir::Col);
243 qintra = INDEO5_Q8_INTRA[3];
244 qinter = INDEO5_Q8_INTER[3];
245 },
246 3 => {
247 tr = IVITransformType::None(TSize::T8x8);
248 qintra = INDEO5_Q8_INTRA[4];
249 qinter = INDEO5_Q8_INTER[4];
250 },
251 _ => { unreachable!(); }
252 };
253 txtype = TxType::Transform8(TxParams8x8::new(qintra, qinter, scan));
254 },
255 1 | 2 => {
256 validate!(self.blk_size[band_id] == 4);
257 tr = IVITransformType::Slant(TSize::T4x4, TDir::TwoD);
258 let scan = INDEO5_SCAN4X4;
259 let qintra = INDEO5_Q4_INTRA;
260 let qinter = INDEO5_Q4_INTER;
261 txtype = TxType::Transform4(TxParams4x4::new(qintra, qinter, scan));
262 },
263 _ => { unreachable!(); }
264 };
265
266 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))
267 }
268
269 #[allow(clippy::cognitive_complexity)]
270 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<()> {
271 let mut mv_x = 0;
272 let mut mv_y = 0;
273 let band_id = if pic_hdr.luma_bands == 4 { band.band_no + 1 } else { 0 };
274 let mut mb_idx = 0;
275 for mb_y in 0..tile.mb_h {
276 for mb_x in 0..tile.mb_w {
277 let mut mb = MB::new(tile.pos_x + mb_x * band.mb_size, tile.pos_y + mb_y * band.mb_size);
278 if !br.read_bool()? {
279 if pic_hdr.ftype.is_intra() {
280 mb.mtype = MBType::Intra;
281 } else if band.inherit_mv {
282 if let Some(tileref) = ref_tile {
283 mb.mtype = tileref.mb[mb_idx].mtype;
284 } else {
285 return Err(DecoderError::MissingReference);
286 }
287 } else {
288 mb.mtype = if br.read_bool()? { MBType::Inter } else { MBType::Intra };
289 }
290 if band.mb_size == band.blk_size {
291 mb.cbp = br.read(1)? as u8;
292 } else {
293 mb.cbp = br.read(4)? as u8;
294 }
295 let q;
296 if band.has_qdelta {
297 if band.inherit_qd {
298 if let Some(tileref) = ref_tile {
299 mb.qd = tileref.mb[mb_idx].qd;
300 q = calc_quant(band.quant, mb.qd);
301 } else {
302 return Err(DecoderError::MissingReference);
303 }
304 } else if (mb.cbp != 0) || ((band.plane_no == 0) && (band.band_no == 0) && pic_hdr.in_q) {
305 mb.qd = br.read_ivi_cb_s(&self.mb_cb)? as i16;
306 q = calc_quant(band.quant, mb.qd);
307 } else {
308 q = band.quant as usize;
309 }
310 } else {
311 q = band.quant as usize;
312 }
313
314 if mb.mtype == MBType::Intra {
315 if band.blk_size == 8 {
316 mb.q = INDEO5_QSCALE8_INTRA[band_id][q];
317 } else {
318 mb.q = INDEO5_QSCALE4_INTRA[q];
319 }
320 } else {
321 if band.blk_size == 8 {
322 mb.q = INDEO5_QSCALE8_INTER[band_id][q];
323 } else {
324 mb.q = INDEO5_QSCALE4_INTER[q];
325 }
326 }
327
328 if mb.mtype != MBType::Intra {
329 if band.inherit_mv {
330 if let Some(tileref) = ref_tile {
331 let mx = tileref.mb[mb_idx].mv_x;
332 let my = tileref.mb[mb_idx].mv_y;
333 if mv_scale == 0 {
334 mb.mv_x = mx;
335 mb.mv_y = my;
336 } else {
337 mb.mv_x = scale_mv(mx, mv_scale);
338 mb.mv_y = scale_mv(my, mv_scale);
339 }
340 }
341 } else {
342 mv_y += br.read_ivi_cb_s(&self.mb_cb)?;
343 mv_x += br.read_ivi_cb_s(&self.mb_cb)?;
344 mb.mv_x = mv_x;
345 mb.mv_y = mv_y;
346 }
347 }
348 } else {
349 validate!(!pic_hdr.ftype.is_intra());
350 mb.mtype = MBType::Inter;
351 mb.cbp = 0;
352 mb.qd = 0;
353 if (band.plane_no == 0) && (band.band_no == 0) && pic_hdr.in_q {
354 mb.qd = br.read_ivi_cb_s(&self.mb_cb)? as i16;
355 let q = calc_quant(band.quant, mb.qd);
356 if mb.mtype == MBType::Intra {
357 if band.blk_size == 8 {
358 mb.q = INDEO5_QSCALE8_INTRA[band_id][q];
359 } else {
360 mb.q = INDEO5_QSCALE4_INTRA[q];
361 }
362 } else {
363 if band.blk_size == 8 {
364 mb.q = INDEO5_QSCALE8_INTER[band_id][q];
365 } else {
366 mb.q = INDEO5_QSCALE4_INTER[q];
367 }
368 }
369 }
370 if band.inherit_mv {
371 if let Some(tileref) = ref_tile {
372 let mx = tileref.mb[mb_idx].mv_x;
373 let my = tileref.mb[mb_idx].mv_y;
374 if mv_scale == 0 {
375 mb.mv_x = mx;
376 mb.mv_y = my;
377 } else {
378 mb.mv_x = scale_mv(mx, mv_scale);
379 mb.mv_y = scale_mv(my, mv_scale);
380 }
381 }
382 }
383 }
384 tile.mb[mb_idx] = mb;
385 mb_idx += 1;
386 }
387 }
388 br.align();
389 Ok(())
390 }
391
392 fn recombine_plane(&mut self, src: &[i16], sstride: usize, dst: &mut [u8], dstride: usize, w: usize, h: usize) {
393 let mut idx0 = 0;
394 let mut idx1 = w / 2;
395 let mut idx2 = (h / 2) * sstride;
396 let mut idx3 = idx2 + idx1;
397 let mut bidx1 = idx1;
398 let mut bidx3 = idx3;
399 let mut oidx0 = 0;
400 let mut oidx1 = dstride;
401 let filt_lo = |a: i16, b: i16| a + b;
402 let filt_hi = |a: i16, b: i16, c: i16| a - b * 6 + c;
403
404 for _ in 0..(h/2)-1 {
405 let mut b0_1 = src[idx0];
406 let mut b0_2 = src[idx0 + sstride];
407 let mut b1_1 = src[bidx1];
408 let mut b1_2 = src[idx1];
409 let mut b1_3 = filt_hi(b1_1, b1_2, src[idx1 + sstride]);
410 let mut b2_1;
411 let mut b2_2 = src[idx2];
412 let mut b2_3 = b2_2;
413 let mut b2_4;
414 let mut b2_5 = src[idx2 + sstride];
415 let mut b2_6 = b2_5;
416 let mut b3_1;
417 let mut b3_2 = src[bidx3];
418 let mut b3_3 = b3_2;
419 let mut b3_4;
420 let mut b3_5 = src[idx3];
421 let mut b3_6 = b3_5;
422 let mut b3_8 = filt_hi(b3_2, b3_5, src[idx3 + sstride]);
423 let mut b3_9 = b3_8;
424 let mut b3_7;
425
426 for x in 0..(w/2)-1 {
427 b2_1 = b2_2;
428 b2_2 = b2_3;
429 b2_4 = b2_5;
430 b2_5 = b2_6;
431 b3_1 = b3_2;
432 b3_2 = b3_3;
433 b3_4 = b3_5;
434 b3_5 = b3_6;
435 b3_7 = b3_8;
436 b3_8 = b3_9;
437
438 let tmp0 = b0_1;
439 let tmp1 = b0_2;
440 b0_1 = src[idx0 + x + 1];
441 b0_2 = src[idx0 + x + 1 + sstride];
442 let mut p0 = tmp0 << 4;
443 let mut p1 = (tmp0 + b0_1) << 3;
444 let mut p2 = (tmp0 + tmp1) << 3;
445 let mut p3 = (tmp0 + tmp1 + b0_1 + b0_2) << 2;
446
447 let tmp0 = b1_1;
448 let tmp1 = b1_2;
449 let tmp2 = filt_lo(tmp0, tmp1);
450 let tmp3 = filt_hi(tmp0, tmp1, b1_3);
451 b1_2 = src[ idx1 + x + 1];
452 b1_1 = src[bidx1 + x + 1];
453 b1_3 = filt_hi(b1_1, b1_2, src[idx1 + x + 1 + sstride]);
454 p0 += tmp2 << 3;
455 p1 += (tmp2 + b1_1 + b1_2) << 2;
456 p2 += tmp3 << 2;
457 p3 += (tmp3 + b1_3) << 1;
458
459 b2_3 = src[idx2 + x + 1];
460 b2_6 = src[idx2 + x + 1 + sstride];
461 let tmp0 = filt_lo(b2_1, b2_2);
462 let tmp1 = filt_hi(b2_1, b2_2, b2_3);
463 p0 += tmp0 << 3;
464 p1 += tmp1 << 2;
465 p2 += (tmp0 + filt_lo(b2_4, b2_5)) << 2;
466 p3 += (tmp1 + filt_hi(b2_4, b2_5, b2_6)) << 1;
467
468 b3_6 = src[idx3 + x + 1];
469 b3_3 = src[bidx3 + x + 1];
470 b3_9 = filt_hi(b3_3, b3_6, src[idx3 + x + 1 + sstride]);
471 let tmp0 = b3_1 + b3_4;
472 let tmp1 = b3_2 + b3_5;
473 let tmp2 = b3_3 + b3_6;
474 p0 += filt_lo(tmp0, tmp1) << 2;
475 p1 += filt_hi(tmp0, tmp1, tmp2) << 1;
476 p2 += filt_lo(b3_7, b3_8) << 1;
477 p3 += filt_hi(b3_7, b3_8, b3_9) << 0;
478
479 dst[oidx0 + x * 2 + 0] = clip8((p0 >> 6) + 128);
480 dst[oidx0 + x * 2 + 1] = clip8((p1 >> 6) + 128);
481 dst[oidx1 + x * 2 + 0] = clip8((p2 >> 6) + 128);
482 dst[oidx1 + x * 2 + 1] = clip8((p3 >> 6) + 128);
483 }
484 bidx1 = idx1;
485 bidx3 = idx3;
486 idx0 += sstride;
487 idx1 += sstride;
488 idx2 += sstride;
489 idx3 += sstride;
490 oidx0 += dstride * 2;
491 oidx1 += dstride * 2;
492 }
493 }
494 }
495
496 struct Indeo5Decoder {
497 info: NACodecInfoRef,
498 dec: IVIDecoder,
499 ip: Indeo5Parser,
500 }
501
502 impl Indeo5Decoder {
503 fn new(scalable: bool) -> Self {
504 Indeo5Decoder {
505 info: NACodecInfo::new_dummy(),
506 dec: IVIDecoder::new(scalable),
507 ip: Indeo5Parser::new(),
508 }
509 }
510 }
511
512 impl NADecoder for Indeo5Decoder {
513 fn init(&mut self, _supp: &mut NADecoderSupport, info: NACodecInfoRef) -> DecoderResult<()> {
514 if let NACodecTypeInfo::Video(vinfo) = info.get_properties() {
515 let w = vinfo.get_width();
516 let h = vinfo.get_height();
517 let f = vinfo.is_flipped();
518 let fmt = formats::YUV410_FORMAT;
519 let myinfo = NACodecTypeInfo::Video(NAVideoInfo::new(w, h, f, fmt));
520 self.info = NACodecInfo::new_ref(info.get_name(), myinfo, info.get_extradata()).into_ref();
521 Ok(())
522 } else {
523 Err(DecoderError::InvalidData)
524 }
525 }
526 fn decode(&mut self, _supp: &mut NADecoderSupport, pkt: &NAPacket) -> DecoderResult<NAFrameRef> {
527 let src = pkt.get_buffer();
528 let mut br = BitReader::new(src.as_slice(), BitReaderMode::LE);
529
530 let bufinfo = self.dec.decode_frame(&mut self.ip, &mut br)?;
531 let mut frm = NAFrame::new_from_pkt(pkt, self.info.clone(), bufinfo);
532 frm.set_keyframe(self.dec.is_intra());
533 frm.set_frame_type(self.dec.get_frame_type());
534 Ok(frm.into_ref())
535 }
536 fn flush(&mut self) {
537 self.dec.flush();
538 }
539 }
540
541 impl NAOptionHandler for Indeo5Decoder {
542 fn get_supported_options(&self) -> &[NAOptionDefinition] { &[] }
543 fn set_options(&mut self, _options: &[NAOption]) { }
544 fn query_option_value(&self, _name: &str) -> Option<NAValue> { None }
545 }
546
547 const INDEO5_PICTURE_SIZE_TAB: [[usize; 2]; 15] = [
548 [640, 480], [320, 240], [160, 120], [704, 480], [352, 240], [352, 288], [176, 144],
549 [240, 180], [640, 240], [704, 240], [80, 60], [88, 72], [0, 0], [0, 0], [0, 0]
550 ];
551
552 const INDEO5_FRAME_TYPE: [IVIFrameType; 5] = [
553 IVIFrameType::Intra, IVIFrameType::Inter, IVIFrameType::InterScal,
554 IVIFrameType::InterDroppable, IVIFrameType::NULL,
555 ];
556
557 const INDEO5_QUANT8X8_INTRA: [[u16; 64]; 5] = [
558 [
559 0x1a, 0x2e, 0x36, 0x42, 0x46, 0x4a, 0x4e, 0x5a,
560 0x2e, 0x32, 0x3e, 0x42, 0x46, 0x4e, 0x56, 0x6a,
561 0x36, 0x3e, 0x3e, 0x44, 0x4a, 0x54, 0x66, 0x72,
562 0x42, 0x42, 0x44, 0x4a, 0x52, 0x62, 0x6c, 0x7a,
563 0x46, 0x46, 0x4a, 0x52, 0x5e, 0x66, 0x72, 0x8e,
564 0x4a, 0x4e, 0x54, 0x62, 0x66, 0x6e, 0x86, 0xa6,
565 0x4e, 0x56, 0x66, 0x6c, 0x72, 0x86, 0x9a, 0xca,
566 0x5a, 0x6a, 0x72, 0x7a, 0x8e, 0xa6, 0xca, 0xfe,
567 ], [
568 0x26, 0x3a, 0x3e, 0x46, 0x4a, 0x4e, 0x52, 0x5a,
569 0x3a, 0x3e, 0x42, 0x46, 0x4a, 0x4e, 0x56, 0x5e,
570 0x3e, 0x42, 0x46, 0x48, 0x4c, 0x52, 0x5a, 0x62,
571 0x46, 0x46, 0x48, 0x4a, 0x4e, 0x56, 0x5e, 0x66,
572 0x4a, 0x4a, 0x4c, 0x4e, 0x52, 0x5a, 0x62, 0x6a,
573 0x4e, 0x4e, 0x52, 0x56, 0x5a, 0x5e, 0x66, 0x6e,
574 0x52, 0x56, 0x5a, 0x5e, 0x62, 0x66, 0x6a, 0x72,
575 0x5a, 0x5e, 0x62, 0x66, 0x6a, 0x6e, 0x72, 0x76,
576 ], [
577 0x4e, 0xaa, 0xf2, 0xd4, 0xde, 0xc2, 0xd6, 0xc2,
578 0x4e, 0xaa, 0xf2, 0xd4, 0xde, 0xc2, 0xd6, 0xc2,
579 0x4e, 0xaa, 0xf2, 0xd4, 0xde, 0xc2, 0xd6, 0xc2,
580 0x4e, 0xaa, 0xf2, 0xd4, 0xde, 0xc2, 0xd6, 0xc2,
581 0x4e, 0xaa, 0xf2, 0xd4, 0xde, 0xc2, 0xd6, 0xc2,
582 0x4e, 0xaa, 0xf2, 0xd4, 0xde, 0xc2, 0xd6, 0xc2,
583 0x4e, 0xaa, 0xf2, 0xd4, 0xde, 0xc2, 0xd6, 0xc2,
584 0x4e, 0xaa, 0xf2, 0xd4, 0xde, 0xc2, 0xd6, 0xc2,
585 ], [
586 0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e,
587 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
588 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
589 0xd4, 0xd4, 0xd4, 0xd4, 0xd4, 0xd4, 0xd4, 0xd4,
590 0xde, 0xde, 0xde, 0xde, 0xde, 0xde, 0xde, 0xde,
591 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2,
592 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6,
593 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2,
594 ], [
595 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e,
596 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e,
597 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e,
598 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e,
599 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e,
600 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e,
601 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e,
602 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e,
603 ]
604 ];
605 const INDEO5_QUANT8X8_INTER: [[u16; 64]; 5] = [
606 [
607 0x26, 0x3a, 0x3e, 0x46, 0x4a, 0x4e, 0x52, 0x5a,
608 0x3a, 0x3e, 0x42, 0x46, 0x4a, 0x4e, 0x56, 0x5e,
609 0x3e, 0x42, 0x46, 0x48, 0x4c, 0x52, 0x5a, 0x62,
610 0x46, 0x46, 0x48, 0x4a, 0x4e, 0x56, 0x5e, 0x66,
611 0x4a, 0x4a, 0x4c, 0x4e, 0x52, 0x5a, 0x62, 0x6a,
612 0x4e, 0x4e, 0x52, 0x56, 0x5a, 0x5e, 0x66, 0x6e,
613 0x52, 0x56, 0x5a, 0x5e, 0x62, 0x66, 0x6a, 0x72,
614 0x5a, 0x5e, 0x62, 0x66, 0x6a, 0x6e, 0x72, 0x76,
615 ], [
616 0x26, 0x3a, 0x3e, 0x46, 0x4a, 0x4e, 0x52, 0x5a,
617 0x3a, 0x3e, 0x42, 0x46, 0x4a, 0x4e, 0x56, 0x5e,
618 0x3e, 0x42, 0x46, 0x48, 0x4c, 0x52, 0x5a, 0x62,
619 0x46, 0x46, 0x48, 0x4a, 0x4e, 0x56, 0x5e, 0x66,
620 0x4a, 0x4a, 0x4c, 0x4e, 0x52, 0x5a, 0x62, 0x6a,
621 0x4e, 0x4e, 0x52, 0x56, 0x5a, 0x5e, 0x66, 0x6e,
622 0x52, 0x56, 0x5a, 0x5e, 0x62, 0x66, 0x6a, 0x72,
623 0x5a, 0x5e, 0x62, 0x66, 0x6a, 0x6e, 0x72, 0x76,
624 ], [
625 0x4e, 0xaa, 0xf2, 0xd4, 0xde, 0xc2, 0xd6, 0xc2,
626 0x4e, 0xaa, 0xf2, 0xd4, 0xde, 0xc2, 0xd6, 0xc2,
627 0x4e, 0xaa, 0xf2, 0xd4, 0xde, 0xc2, 0xd6, 0xc2,
628 0x4e, 0xaa, 0xf2, 0xd4, 0xde, 0xc2, 0xd6, 0xc2,
629 0x4e, 0xaa, 0xf2, 0xd4, 0xde, 0xc2, 0xd6, 0xc2,
630 0x4e, 0xaa, 0xf2, 0xd4, 0xde, 0xc2, 0xd6, 0xc2,
631 0x4e, 0xaa, 0xf2, 0xd4, 0xde, 0xc2, 0xd6, 0xc2,
632 0x4e, 0xaa, 0xf2, 0xd4, 0xde, 0xc2, 0xd6, 0xc2,
633 ], [
634 0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e,
635 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
636 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
637 0xd4, 0xd4, 0xd4, 0xd4, 0xd4, 0xd4, 0xd4, 0xd4,
638 0xde, 0xde, 0xde, 0xde, 0xde, 0xde, 0xde, 0xde,
639 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2,
640 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6,
641 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2,
642 ], [
643 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e,
644 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e,
645 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e,
646 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e,
647 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e,
648 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e,
649 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e,
650 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e,
651 ]
652 ];
653 const INDEO5_QUANT4X4_INTRA: [u16; 16] = [
654 0x1e, 0x3e, 0x4a, 0x52,
655 0x3e, 0x4a, 0x52, 0x5e,
656 0x4a, 0x52, 0x5e, 0x7a,
657 0x52, 0x5e, 0x7a, 0x92
658 ];
659 const INDEO5_QUANT4X4_INTER: [u16; 16] = [
660 0x1e, 0x3e, 0x4a, 0x52,
661 0x3e, 0x4a, 0x52, 0x56,
662 0x4a, 0x52, 0x56, 0x5e,
663 0x52, 0x56, 0x5e, 0x66
664 ];
665 const INDEO5_Q8_INTRA: [&[u16; 64]; 5] = [
666 &INDEO5_QUANT8X8_INTRA[0], &INDEO5_QUANT8X8_INTRA[1], &INDEO5_QUANT8X8_INTRA[2],
667 &INDEO5_QUANT8X8_INTRA[3], &INDEO5_QUANT8X8_INTRA[4],
668 ];
669 const INDEO5_Q8_INTER: [&[u16; 64]; 5] = [
670 &INDEO5_QUANT8X8_INTER[0], &INDEO5_QUANT8X8_INTER[1], &INDEO5_QUANT8X8_INTER[2],
671 &INDEO5_QUANT8X8_INTER[3], &INDEO5_QUANT8X8_INTER[4],
672 ];
673 const INDEO5_Q4_INTRA: &[u16; 16] = &INDEO5_QUANT4X4_INTRA;
674 const INDEO5_Q4_INTER: &[u16; 16] = &INDEO5_QUANT4X4_INTER;
675
676 const INDEO5_SCAN8X8: [&[usize; 64]; 4] = [
677 &ZIGZAG, &IVI_SCAN_8X8_VER, &IVI_SCAN_8X8_HOR, &IVI_SCAN_8X8_HOR
678 ];
679 const INDEO5_SCAN4X4: &[usize; 16] = &IVI_SCAN_4X4;
680
681 const INDEO5_QSCALE8_INTRA: [[u8; 24]; 5] = [
682 [
683 0x0b, 0x0e, 0x10, 0x12, 0x14, 0x16, 0x17, 0x18, 0x1a, 0x1c, 0x1e, 0x20,
684 0x22, 0x24, 0x27, 0x28, 0x2a, 0x2d, 0x2f, 0x31, 0x34, 0x37, 0x39, 0x3c,
685 ], [
686 0x01, 0x10, 0x12, 0x14, 0x16, 0x18, 0x1b, 0x1e, 0x22, 0x25, 0x28, 0x2c,
687 0x30, 0x34, 0x38, 0x3d, 0x42, 0x47, 0x4c, 0x52, 0x58, 0x5e, 0x65, 0x6c,
688 ], [
689 0x13, 0x22, 0x27, 0x2a, 0x2d, 0x33, 0x36, 0x3c, 0x41, 0x45, 0x49, 0x4e,
690 0x53, 0x58, 0x5d, 0x63, 0x69, 0x6f, 0x75, 0x7c, 0x82, 0x88, 0x8e, 0x95,
691 ], [
692 0x13, 0x1f, 0x21, 0x24, 0x27, 0x29, 0x2d, 0x2f, 0x34, 0x37, 0x3a, 0x3d,
693 0x40, 0x44, 0x48, 0x4c, 0x4f, 0x52, 0x56, 0x5a, 0x5e, 0x62, 0x66, 0x6b,
694 ], [
695 0x31, 0x42, 0x47, 0x47, 0x4d, 0x52, 0x58, 0x58, 0x5d, 0x63, 0x67, 0x6b,
696 0x6f, 0x73, 0x78, 0x7c, 0x80, 0x84, 0x89, 0x8e, 0x93, 0x98, 0x9d, 0xa4,
697 ]
698 ];
699 const INDEO5_QSCALE8_INTER: [[u8; 24]; 5] = [
700 [
701 0x0b, 0x11, 0x13, 0x14, 0x15, 0x16, 0x18, 0x1a, 0x1b, 0x1d, 0x20, 0x22,
702 0x23, 0x25, 0x28, 0x2a, 0x2e, 0x32, 0x35, 0x39, 0x3d, 0x41, 0x44, 0x4a,
703 ], [
704 0x07, 0x14, 0x16, 0x18, 0x1b, 0x1e, 0x22, 0x25, 0x29, 0x2d, 0x31, 0x35,
705 0x3a, 0x3f, 0x44, 0x4a, 0x50, 0x56, 0x5c, 0x63, 0x6a, 0x71, 0x78, 0x7e,
706 ], [
707 0x15, 0x25, 0x28, 0x2d, 0x30, 0x34, 0x3a, 0x3d, 0x42, 0x48, 0x4c, 0x51,
708 0x56, 0x5b, 0x60, 0x65, 0x6b, 0x70, 0x76, 0x7c, 0x82, 0x88, 0x8f, 0x97,
709 ], [
710 0x13, 0x1f, 0x20, 0x22, 0x25, 0x28, 0x2b, 0x2d, 0x30, 0x33, 0x36, 0x39,
711 0x3c, 0x3f, 0x42, 0x45, 0x48, 0x4b, 0x4e, 0x52, 0x56, 0x5a, 0x5e, 0x62,
712 ], [
713 0x3c, 0x52, 0x58, 0x5d, 0x63, 0x68, 0x68, 0x6d, 0x73, 0x78, 0x7c, 0x80,
714 0x84, 0x89, 0x8e, 0x93, 0x98, 0x9d, 0xa3, 0xa9, 0xad, 0xb1, 0xb5, 0xba
715 ]
716 ];
717 const INDEO5_QSCALE4_INTRA: [u8; 24] = [
718 0x01, 0x0b, 0x0b, 0x0d, 0x0d, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x13, 0x14,
719 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20
720 ];
721 const INDEO5_QSCALE4_INTER: [u8; 24] = [
722 0x0b, 0x0d, 0x0d, 0x0e, 0x11, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
723 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23
724 ];
725
726 pub fn get_decoder() -> Box<dyn NADecoder + Send> {
727 Box::new(Indeo5Decoder::new(false))
728 }
729
730 pub fn get_decoder_scalable() -> Box<dyn NADecoder + Send> {
731 Box::new(Indeo5Decoder::new(true))
732 }
733
734 #[cfg(test)]
735 mod test {
736 use nihav_core::codecs::RegisteredDecoders;
737 use nihav_core::demuxers::RegisteredDemuxers;
738 use nihav_codec_support::test::dec_video::*;
739 use crate::indeo_register_all_decoders;
740 use nihav_commonfmt::generic_register_all_demuxers;
741 #[test]
742 fn test_indeo5() {
743 let mut dmx_reg = RegisteredDemuxers::new();
744 generic_register_all_demuxers(&mut dmx_reg);
745 let mut dec_reg = RegisteredDecoders::new();
746 indeo_register_all_decoders(&mut dec_reg);
747
748 // sample: https://samples.mplayerhq.hu/V-codecs/IV50/sample.avi
749 test_decoding("avi", "indeo5", "assets/Indeo/IV5/sample.avi", Some(100),
750 &dmx_reg, &dec_reg, ExpectedTestResult::MD5Frames(vec![
751 [0xcb451428, 0x5c8b1519, 0x96a81eda, 0x0c9cccf0],
752 [0x7554e11f, 0x3b60d661, 0x3bcd14b5, 0x036dcc16],
753 [0x92a20e68, 0x83418e5c, 0x640b6786, 0x9c867622],
754 [0x0b2cde46, 0x67b68ac5, 0xc152edc6, 0xda591ac3],
755 [0x9034354b, 0x81c66b57, 0xcb671505, 0x0062a75f],
756 [0x38606276, 0x547b83df, 0x4a22f079, 0x2afb8362],
757 [0x0d3fe5df, 0xadc8b042, 0x4ee9cb0d, 0xf9b79b11],
758 [0x2b0b1ddb, 0x612a163a, 0x47b5afc8, 0xeb4c79a5],
759 [0x8eadd17e, 0xc4c8c932, 0x57508232, 0x643e1498],
760 [0x0dcc7da2, 0x7b059de2, 0x0ff46dd9, 0x04c11f77],
761 [0xe358728a, 0xe42fc515, 0x8f5cc35f, 0x02973436],
762 [0x66847a32, 0x884b41f0, 0x0c3062bc, 0xb58d923b],
763 [0x555b2711, 0xbcb54b64, 0x5a6141e5, 0xa7b5cc44],
764 [0x0f326348, 0x5d36cb21, 0xe7f8210d, 0x8a43c2c5],
765 [0x4e7b18a3, 0x42146bbb, 0x04c4cf2b, 0x78fe3c0d],
766 [0x220f0721, 0xe681444a, 0x974bf97b, 0x9b658cfe],
767 [0x2d5a5f22, 0x23bd1ed8, 0xed383633, 0x5905422d],
768 [0x982ae872, 0x17b8f765, 0x3d1735af, 0xa2872d9f],
769 [0x743a2819, 0x392d856e, 0xf2ee64ca, 0x63101b79],
770 [0x0c9e0aa7, 0x79414f6b, 0x162c19a6, 0x86d69b96],
771 [0x3eae05ad, 0xbff350bb, 0x97e8a205, 0xfa8e42b2],
772 [0x0ccae893, 0xdfcf9885, 0xef39d053, 0x0a655a73],
773 [0x75e98d11, 0x83fab601, 0xe836a6d2, 0xb2a7c7cb],
774 [0x1565b1ce, 0x8ab813c5, 0xb1658413, 0xeebaf068],
775 [0xe2bb47dd, 0xc3c277a7, 0x8c6bd4be, 0xbbca989d],
776 [0xea97912e, 0xcd224d66, 0x76fd31c2, 0x7a854abf],
777 [0x8eebb842, 0x0534b043, 0xf55a3b65, 0x3868b974],
778 [0x82c55a0b, 0x5d18c3c8, 0xbdc40fd1, 0x5d11f2e2],
779 [0xda46bff0, 0xedc1e115, 0x77cb8b8a, 0xf5fd6ddf],
780 [0x7c9c19e9, 0x4188e742, 0xd8c2cbaf, 0x0ecd1aaa],
781 [0x33145d5b, 0x0c8e2f61, 0x2ab4b213, 0xf1cf9ebe],
782 [0x64f561e1, 0xae2aa75b, 0xe4d56a57, 0xdcc54d10],
783 [0x25545f02, 0x8c271a6a, 0x6b676110, 0xa348628b],
784 [0x8c33d2d7, 0x7dfc25a0, 0xbdb68979, 0xac7ce8f1],
785 [0x8adc7126, 0x71c4d390, 0x4b47aeed, 0x444dbd2b],
786 [0xaab41fbc, 0x2c6de4d8, 0x83b61f31, 0xc68879b1],
787 [0x90961b3a, 0x9a1d4b51, 0xbf34d9d1, 0xe90137a7],
788 [0x2e988439, 0x2d7e67ec, 0x9bfd6405, 0xd851ee32],
789 [0x3b2b45e8, 0x76225018, 0xa2632614, 0x06234ca9],
790 [0xd52dc6af, 0x36c0d185, 0x90f4a9d2, 0x0b024990],
791 [0x5ed3ebb2, 0xb19b49a2, 0xd691c27a, 0x7d52941c],
792 [0xcb22479a, 0x3713b23d, 0x24abe31b, 0x45877b4e],
793 [0x143aa9f1, 0xe7709011, 0xa6ef993b, 0x8e4f33e2],
794 [0xc8b1ad16, 0x820b4f85, 0xe9d1482a, 0x806af90c],
795 [0x4f1eda2b, 0xa73eac8c, 0x8004e66b, 0xa0804e11],
796 [0x668ceb7b, 0xad020ed3, 0x90687534, 0x96eded7e],
797 [0x8bbd77d0, 0x29fc1ae4, 0xc41fb7cf, 0x31b08f08],
798 [0x02d07857, 0x4ed79f55, 0x89cfe082, 0x97167616],
799 [0xd99dbf57, 0x87ef7406, 0x59c9abdf, 0xf664be32],
800 [0x6d2bd834, 0x6b61d6e5, 0x3fd282ce, 0xbc877248],
801 [0xb4dbab3f, 0x7006dded, 0x39608927, 0x9773b83e],
802 [0x6e1f21e8, 0xff1a76c0, 0x197dd40b, 0x3cedee3d],
803 [0x551f64b8, 0x98161c0f, 0xb93103a7, 0xac12366e],
804 [0x6854311c, 0x6bc09f24, 0x226ec3e9, 0x91507815],
805 [0xb106d988, 0x6c9cda70, 0xebf972ce, 0x97b1efa8],
806 [0x91b8c27b, 0x257ff731, 0x1589d60d, 0xcb2b3de9],
807 [0x819d3677, 0xa6afca81, 0x3d2b4ba9, 0xba8cc70f],
808 [0xfb2c67fa, 0x75af7785, 0xde6133b0, 0x1bb59f2c],
809 [0xceb72cd4, 0x8c581ccb, 0x803233f2, 0xb88a174b],
810 [0xe2811f64, 0xa488d42c, 0x3a62a574, 0x918df881],
811 [0x95a66cf8, 0x0529a646, 0x3bc15b00, 0xfb0eedc9],
812 [0x1e90f3ce, 0xa8f81b7f, 0x13d5445c, 0xc969a914],
813 [0x25287783, 0x19869a3d, 0x93672c2a, 0x07a57f5e],
814 [0x44dfacc0, 0x528ae192, 0x141721a9, 0x85b2a3d9],
815 [0x45f13c20, 0x90b07bb5, 0x9a155a2f, 0x3933fb77],
816 [0x40531c62, 0x437c14b6, 0xc03c8d39, 0x35f5ae87],
817 [0x32e58909, 0xdb068147, 0xa967c6cf, 0x33d9416a],
818 [0xa8c44523, 0x12a89332, 0xddd09ccf, 0x7b04c0d2],
819 [0xae00b8b4, 0x589efb18, 0xf8c1dec1, 0xfd9d867f],
820 [0xe2fc1828, 0x5f7a3b28, 0x72de1c32, 0xc01e6ea6],
821 [0x8be4c525, 0xcde70d98, 0xd7f5f5a1, 0xf39faadf],
822 [0x9c744944, 0x00a491f4, 0x665707a9, 0xa93fad9d],
823 [0x036f2525, 0x827ddd36, 0x989c99db, 0x6b9455fc],
824 [0x52c6b5d2, 0xfd4e23f9, 0xb620b0da, 0x462d7566],
825 [0x00ba54e6, 0xfe9021ae, 0xa8c65c37, 0xda979c78],
826 [0x6e11dca0, 0x41887539, 0x2b9781af, 0x94e6b930],
827 [0x086be7db, 0xcce50438, 0x2d94bc75, 0x00f4ebfe],
828 [0xd2216f7c, 0x33321d48, 0x8ce0f144, 0x34c1fd4f],
829 [0x9083c0fc, 0x6cb46451, 0xd8202b2f, 0xae5db326],
830 [0xe894be71, 0x0e1b6c67, 0x70d5e81f, 0x2075d5ff],
831 [0x7f9f10f7, 0x0a8df81d, 0x406cb9cc, 0x524879b5],
832 [0x4c329904, 0x6f939b2c, 0xd49f8bba, 0xad54aee5],
833 [0x92d68b43, 0x2c631f71, 0x98329455, 0x91971f7f],
834 [0x1b06289e, 0x4879af78, 0xc66d7c82, 0xda19e863],
835 [0x399741da, 0xd362b007, 0x8f94e50c, 0xcdd23209],
836 [0xa2063194, 0xc67f368a, 0x83462433, 0xe719c2db],
837 [0x9da0bfd1, 0x8977f90e, 0x7f2f4172, 0xab5213ff],
838 [0x82823c8f, 0xd7cdd62e, 0xac3a59ba, 0x17ef0fb9],
839 [0xb3e51375, 0xfebb3ad3, 0x54ffdda4, 0xfbf44cf9],
840 [0x261f8183, 0x8328012b, 0x47d7e527, 0xc19cca15],
841 [0xef25bfc7, 0x79460e21, 0xeb65f2ef, 0x63731f9f],
842 [0xd14fc8f5, 0x209123ea, 0xf5f1cf21, 0x93f84381],
843 [0xf5375f67, 0x0846d9a1, 0x07aaf802, 0xe753fa08],
844 [0x65a56edd, 0x4ea28e39, 0x10d17a7b, 0xa9445d87],
845 [0xbeb8eb53, 0xd01b9c94, 0xd1d15e41, 0x639307cc],
846 [0xc2272546, 0xd1701452, 0x2fe76cbd, 0xe1dd7697],
847 [0xff6c09f6, 0x1d7804c2, 0x1ca3a2f8, 0x3fffb67b],
848 [0xfe48f3fd, 0x0046ec25, 0x1ed4401a, 0xd67f4ed6],
849 [0x46c3c72f, 0x8398b8c1, 0xe26aff08, 0x0dd1ecbb],
850 [0xc7f49f94, 0xca32d87c, 0x2e063788, 0x0229c6c0],
851 [0xa9ec4820, 0x576c7877, 0xc21211c3, 0x502af3d3]]));
852 }
853 }