98bd34031aad20d432acae4d93297529629af43d
[nihav.git] / nihav-indeo / src / codecs / indeo5.rs
1 use std::rc::Rc;
2 use std::cell::{Ref, RefCell};
3 use nihav_core::io::bitreader::*;
4 use nihav_core::formats;
5 use nihav_core::frame::*;
6 use nihav_core::codecs::*;
7 use super::ivi::*;
8 use super::ivibr::*;
9
10 fn calc_quant(glob_q: u32, qd: i16) -> usize {
11 let qq = (glob_q as i16) + (qd as i16);
12 if qq < 0 {
13 0
14 } else if qq > 23 {
15 23
16 } else {
17 qq as usize
18 }
19 }
20
21 struct Indeo5Parser {
22 mb_cb: IVICodebook,
23
24 width: usize,
25 height: usize,
26 tile_w: usize,
27 tile_h: usize,
28 luma_bands: usize,
29 chroma_bands: usize,
30
31 is_hpel: [bool; 5],
32 mb_size: [usize; 5],
33 blk_size: [usize; 5],
34 }
35
36 impl Indeo5Parser {
37 fn new() -> Self {
38 Indeo5Parser {
39 mb_cb: IVI_CB_ZERO,
40
41 width: 0,
42 height: 0,
43 tile_w: 0,
44 tile_h: 0,
45 luma_bands: 0,
46 chroma_bands: 0,
47
48 is_hpel: [false; 5],
49 mb_size: [0; 5],
50 blk_size: [0; 5],
51 }
52 }
53 }
54
55 fn skip_extension(br: &mut BitReader) -> DecoderResult<()> {
56 loop {
57 let len = br.read(8)?;
58 if len == 0 { break; }
59 br.skip(len * 8)?;
60 }
61 Ok(())
62 }
63
64 impl IndeoXParser for Indeo5Parser {
65 #[allow(unused_variables)]
66 #[allow(unused_assignments)]
67 fn decode_picture_header(&mut self, br: &mut BitReader) -> DecoderResult<PictureHeader> {
68 let sync = br.read(5)?;
69 validate!(sync == 0x1F);
70 let ftype_idx = br.read(3)?;
71 validate!(ftype_idx < 5);
72 let ftype = INDEO5_FRAME_TYPE[ftype_idx as usize];
73 let fnum = br.read(8)?;
74 if ftype == IVIFrameType::Intra {
75 let gop_flags = br.read(8)?;
76 let hdr_size;
77 if (gop_flags & 0x01) != 0 {
78 hdr_size = br.read(16)?;
79 } else {
80 hdr_size = 0;
81 }
82 if (gop_flags & 0x20) != 0 {
83 br.skip(32)?; // lock word
84 }
85 self.tile_w = 0;
86 self.tile_h = 0;
87 if (gop_flags & 0x40) != 0 {
88 self.tile_w = 64 << br.read(2)?;
89 self.tile_h = self.tile_w;
90 }
91 validate!(self.tile_w < 256);
92 self.luma_bands = (br.read(2)? * 3 + 1) as usize;
93 self.chroma_bands = (br.read(1)? * 3 + 1) as usize;
94 validate!((self.luma_bands == 4) || (self.luma_bands == 1));
95 validate!(self.chroma_bands == 1);
96 let pic_size_idx = br.read(4)? as usize;
97 let w;
98 let h;
99 if pic_size_idx < 15 {
100 w = INDEO5_PICTURE_SIZE_TAB[pic_size_idx][0];
101 h = INDEO5_PICTURE_SIZE_TAB[pic_size_idx][1];
102 } else {
103 h = br.read(13)? as usize;
104 w = br.read(13)? as usize;
105 }
106 validate!((w != 0) && (h != 0));
107 self.width = w;
108 self.height = h;
109
110 validate!((gop_flags & 0x02) == 0);
111 if self.tile_w == 0 {
112 self.tile_w = w;
113 self.tile_h = h;
114 }
115 for b in 0..self.luma_bands+self.chroma_bands {
116 self.is_hpel[b] = br.read_bool()?;
117 let mb_scale = br.read(1)?;
118 self.blk_size[b] = 8 >> br.read(1)?;
119 self.mb_size[b] = self.blk_size[b] << (1 - mb_scale);
120 let ext_tr = br.read_bool()?;
121 validate!(!ext_tr);
122 let end_marker = br.read(2)?;
123 validate!(end_marker == 0);
124 }
125 if (gop_flags & 0x08) != 0 {
126 let align = br.read(3)?;
127 validate!(align == 0);
128 if br.read_bool()? {
129 br.skip(24)?; // transparency color
130 }
131 }
132 br.align();
133 br.skip(23)?;
134 if br.read_bool()? { // gop extension
135 loop {
136 let v = br.read(16)?;
137 if (v & 0x8000) == 0 { break; }
138 }
139 }
140 br.align();
141 }
142 if ftype.is_null() {
143 br.align();
144 return Ok(PictureHeader::new_null(ftype));
145 }
146 let flags = br.read(8)?;
147 let size;
148 if (flags & 0x01) != 0 {
149 size = br.read(24)?;
150 } else {
151 size = 0;
152 }
153 let checksum;
154 if (flags & 0x10) != 0 {
155 checksum = br.read(16)?;
156 } else {
157 checksum = 0;
158 }
159 if (flags & 0x20) != 0 {
160 skip_extension(br)?;
161 }
162 let in_q = (flags & 0x08) != 0;
163 self.mb_cb = br.read_ivi_codebook_desc(true, (flags & 0x40) != 0)?;
164 br.skip(3)?;
165 br.align();
166
167 Ok(PictureHeader::new(ftype, self.width, self.height, self.tile_w, self.tile_h, false, self.luma_bands, self.chroma_bands, in_q))
168 }
169
170 #[allow(unused_variables)]
171 fn decode_band_header(&mut self, br: &mut BitReader, pic_hdr: &PictureHeader, plane_no: usize, band_no: usize) -> DecoderResult<BandHeader> {
172 let band_flags = br.read(8)?;
173
174 if (band_flags & 0x01) != 0 {
175 br.align();
176 return Ok(BandHeader::new_empty(plane_no, band_no));
177 }
178 let inherit_mv = (band_flags & 0x02) != 0;
179 let has_qdelta = (band_flags & 0x04) != 0;
180 let inherit_qd = ((band_flags & 0x08) != 0) || !has_qdelta;
181 let data_size: usize;
182 if (band_flags & 0x80) != 0 {
183 data_size = br.read(24)? as usize;
184 } else {
185 data_size = 0;
186 }
187 validate!(data_size <= ((br.left() / 8) as usize));
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 fn decode_mb_info(&mut self, br: &mut BitReader, pic_hdr: &PictureHeader, band: &BandHeader, tile: &mut IVITile, ref_tile: Option<Ref<IVITile>>, mv_scale: u8) -> DecoderResult<()> {
270 let mut mv_x = 0;
271 let mut mv_y = 0;
272 let band_id = if pic_hdr.luma_bands == 4 { band.band_no + 1 } else { 0 };
273 let mut mb_idx = 0;
274 for mb_y in 0..tile.mb_h {
275 for mb_x in 0..tile.mb_w {
276 let mut mb = MB::new(tile.pos_x + mb_x * band.mb_size, tile.pos_y + mb_y * band.mb_size);
277 if !br.read_bool()? {
278 if pic_hdr.ftype.is_intra() {
279 mb.mtype = MBType::Intra;
280 } else if band.inherit_mv {
281 if let Some(ref tileref) = ref_tile {
282 mb.mtype = tileref.mb[mb_idx].mtype;
283 } else {
284 return Err(DecoderError::MissingReference);
285 }
286 } else {
287 mb.mtype = if br.read_bool()? { MBType::Inter } else { MBType::Intra };
288 }
289 if band.mb_size == band.blk_size {
290 mb.cbp = br.read(1)? as u8;
291 } else {
292 mb.cbp = br.read(4)? as u8;
293 }
294 let q;
295 if band.has_qdelta {
296 if band.inherit_qd {
297 if let Some(ref tileref) = ref_tile {
298 mb.qd = tileref.mb[mb_idx].qd;
299 q = calc_quant(band.quant, mb.qd);
300 } else {
301 return Err(DecoderError::MissingReference);
302 }
303 } else if (mb.cbp != 0) || ((band.plane_no == 0) && (band.band_no == 0) && pic_hdr.in_q) {
304 mb.qd = br.read_ivi_cb_s(&self.mb_cb)? as i16;
305 q = calc_quant(band.quant, mb.qd);
306 } else {
307 q = band.quant as usize;
308 }
309 } else {
310 q = band.quant as usize;
311 }
312
313 if mb.mtype == MBType::Intra {
314 if band.blk_size == 8 {
315 mb.q = INDEO5_QSCALE8_INTRA[band_id][q];
316 } else {
317 mb.q = INDEO5_QSCALE4_INTRA[q];
318 }
319 } else {
320 if band.blk_size == 8 {
321 mb.q = INDEO5_QSCALE8_INTER[band_id][q];
322 } else {
323 mb.q = INDEO5_QSCALE4_INTER[q];
324 }
325 }
326
327 if mb.mtype != MBType::Intra {
328 if band.inherit_mv {
329 if let Some(ref tileref) = ref_tile {
330 let mx = tileref.mb[mb_idx].mv_x;
331 let my = tileref.mb[mb_idx].mv_y;
332 if mv_scale == 0 {
333 mb.mv_x = mx;
334 mb.mv_y = my;
335 } else {
336 mb.mv_x = scale_mv(mx, mv_scale);
337 mb.mv_y = scale_mv(my, mv_scale);
338 }
339 }
340 } else {
341 mv_y += br.read_ivi_cb_s(&self.mb_cb)?;
342 mv_x += br.read_ivi_cb_s(&self.mb_cb)?;
343 mb.mv_x = mv_x;
344 mb.mv_y = mv_y;
345 }
346 }
347 } else {
348 validate!(!pic_hdr.ftype.is_intra());
349 mb.mtype = MBType::Inter;
350 mb.cbp = 0;
351 mb.qd = 0;
352 if (band.plane_no == 0) && (band.band_no == 0) && pic_hdr.in_q {
353 mb.qd = br.read_ivi_cb_s(&self.mb_cb)? as i16;
354 let q = calc_quant(band.quant, mb.qd);
355 if mb.mtype == MBType::Intra {
356 if band.blk_size == 8 {
357 mb.q = INDEO5_QSCALE8_INTRA[band_id][q];
358 } else {
359 mb.q = INDEO5_QSCALE4_INTRA[q];
360 }
361 } else {
362 if band.blk_size == 8 {
363 mb.q = INDEO5_QSCALE8_INTER[band_id][q];
364 } else {
365 mb.q = INDEO5_QSCALE4_INTER[q];
366 }
367 }
368 }
369 if band.inherit_mv {
370 if let Some(ref tileref) = ref_tile {
371 let mx = tileref.mb[mb_idx].mv_x;
372 let my = tileref.mb[mb_idx].mv_y;
373 if mv_scale == 0 {
374 mb.mv_x = mx;
375 mb.mv_y = my;
376 } else {
377 mb.mv_x = scale_mv(mx, mv_scale);
378 mb.mv_y = scale_mv(my, mv_scale);
379 }
380 }
381 }
382 }
383 tile.mb[mb_idx] = mb;
384 mb_idx += 1;
385 }
386 }
387 br.align();
388 Ok(())
389 }
390
391 fn recombine_plane(&mut self, src: &[i16], sstride: usize, dst: &mut [u8], dstride: usize, w: usize, h: usize) {
392 let mut idx0 = 0;
393 let mut idx1 = w / 2;
394 let mut idx2 = (h / 2) * sstride;
395 let mut idx3 = idx2 + idx1;
396 let mut bidx1 = idx1;
397 let mut bidx3 = idx3;
398 let mut oidx0 = 0;
399 let mut oidx1 = dstride;
400 let filt_lo = |a: i16, b: i16| a + b;
401 let filt_hi = |a: i16, b: i16, c: i16| a - b * 6 + c;
402
403 for _ in 0..(h/2) {
404 let mut b0_1 = src[idx0];
405 let mut b0_2 = src[idx0 + sstride];
406 let mut b1_1 = src[bidx1];
407 let mut b1_2 = src[idx1];
408 let mut b1_3 = filt_hi(b1_1, b1_2, src[idx1 + sstride]);
409 let mut b2_1;
410 let mut b2_2 = src[idx2];
411 let mut b2_3 = b2_2;
412 let mut b2_4;
413 let mut b2_5 = src[idx2 + sstride];
414 let mut b2_6 = b2_5;
415 let mut b3_1;
416 let mut b3_2 = src[bidx3];
417 let mut b3_3 = b3_2;
418 let mut b3_4;
419 let mut b3_5 = src[idx3];
420 let mut b3_6 = b3_5;
421 let mut b3_8 = filt_hi(b3_2, b3_5, src[idx3 + sstride]);
422 let mut b3_9 = b3_8;
423 let mut b3_7;
424
425 for x in 0..(w/2) {
426 b2_1 = b2_2;
427 b2_2 = b2_3;
428 b2_4 = b2_5;
429 b2_5 = b2_6;
430 b3_1 = b3_2;
431 b3_2 = b3_3;
432 b3_4 = b3_5;
433 b3_5 = b3_6;
434 b3_7 = b3_8;
435 b3_8 = b3_9;
436
437 let tmp0 = b0_1;
438 let tmp1 = b0_2;
439 b0_1 = src[idx0 + x + 1];
440 b0_2 = src[idx0 + x + 1 + sstride];
441 let mut p0 = tmp0 << 4;
442 let mut p1 = (tmp0 + b0_1) << 3;
443 let mut p2 = (tmp0 + tmp1) << 3;
444 let mut p3 = (tmp0 + tmp1 + b0_1 + b0_2) << 2;
445
446 let tmp0 = b1_1;
447 let tmp1 = b1_2;
448 let tmp2 = filt_lo(tmp0, tmp1);
449 let tmp3 = filt_hi(tmp0, tmp1, b1_3);
450 b1_2 = src[ idx1 + x + 1];
451 b1_1 = src[bidx1 + x + 1];
452 b1_3 = filt_hi(b1_1, b1_2, src[idx1 + x + 1 + sstride]);
453 p0 += tmp2 << 3;
454 p1 += (tmp2 + b1_1 + b1_2) << 2;
455 p2 += tmp3 << 2;
456 p3 += (tmp3 + b1_3) << 1;
457
458 b2_3 = src[idx2 + x + 1];
459 b2_6 = src[idx2 + x + 1 + sstride];
460 let tmp0 = filt_lo(b2_1, b2_2);
461 let tmp1 = filt_hi(b2_1, b2_2, b2_3);
462 p0 += tmp0 << 3;
463 p1 += tmp1 << 2;
464 p2 += (tmp0 + filt_lo(b2_4, b2_5)) << 2;
465 p3 += (tmp1 + filt_hi(b2_4, b2_5, b2_6)) << 1;
466
467 b3_6 = src[idx3 + x + 1];
468 b3_3 = src[bidx3 + x + 1];
469 b3_9 = filt_hi(b3_3, b3_6, src[idx3 + x + 1 + sstride]);
470 let tmp0 = b3_1 + b3_4;
471 let tmp1 = b3_2 + b3_5;
472 let tmp2 = b3_3 + b3_6;
473 p0 += filt_lo(tmp0, tmp1) << 2;
474 p1 += filt_hi(tmp0, tmp1, tmp2) << 1;
475 p2 += filt_lo(b3_7, b3_8) << 1;
476 p3 += filt_hi(b3_7, b3_8, b3_9) << 0;
477
478 dst[oidx0 + x * 2 + 0] = clip8((p0 >> 6) + 128);
479 dst[oidx0 + x * 2 + 1] = clip8((p1 >> 6) + 128);
480 dst[oidx1 + x * 2 + 0] = clip8((p2 >> 6) + 128);
481 dst[oidx1 + x * 2 + 1] = clip8((p3 >> 6) + 128);
482 }
483 bidx1 = idx1;
484 bidx3 = idx3;
485 idx0 += sstride;
486 idx1 += sstride;
487 idx2 += sstride;
488 idx3 += sstride;
489 oidx0 += dstride * 2;
490 oidx1 += dstride * 2;
491 }
492 }
493 }
494
495 struct Indeo5Decoder {
496 info: Rc<NACodecInfo>,
497 dec: IVIDecoder,
498 ip: Indeo5Parser,
499 }
500
501 impl Indeo5Decoder {
502 fn new() -> Self {
503 Indeo5Decoder {
504 info: NACodecInfo::new_dummy(),
505 dec: IVIDecoder::new(),
506 ip: Indeo5Parser::new(),
507 }
508 }
509 }
510
511 impl NADecoder for Indeo5Decoder {
512 fn init(&mut self, info: Rc<NACodecInfo>) -> DecoderResult<()> {
513 if let NACodecTypeInfo::Video(vinfo) = info.get_properties() {
514 let w = vinfo.get_width();
515 let h = vinfo.get_height();
516 let f = vinfo.is_flipped();
517 let fmt = formats::YUV410_FORMAT;
518 let myinfo = NACodecTypeInfo::Video(NAVideoInfo::new(w, h, f, fmt));
519 self.info = Rc::new(NACodecInfo::new_ref(info.get_name(), myinfo, info.get_extradata()));
520 Ok(())
521 } else {
522 Err(DecoderError::InvalidData)
523 }
524 }
525 fn decode(&mut self, pkt: &NAPacket) -> DecoderResult<NAFrameRef> {
526 let src = pkt.get_buffer();
527 let mut br = BitReader::new(src.as_slice(), src.len(), BitReaderMode::LE);
528
529 let bufinfo = self.dec.decode_frame(&mut self.ip, &mut br)?;
530 let mut frm = NAFrame::new_from_pkt(pkt, self.info.clone(), bufinfo);
531 frm.set_keyframe(self.dec.is_intra());
532 frm.set_frame_type(self.dec.get_frame_type());
533 Ok(Rc::new(RefCell::new(frm)))
534 }
535 }
536
537 const INDEO5_PICTURE_SIZE_TAB: [[usize; 2]; 15] = [
538 [640, 480], [320, 240], [160, 120], [704, 480], [352, 240], [352, 288], [176, 144],
539 [240, 180], [640, 240], [704, 240], [80, 60], [88, 72], [0, 0], [0, 0], [0, 0]
540 ];
541
542 const INDEO5_FRAME_TYPE: [IVIFrameType; 5] = [
543 IVIFrameType::Intra, IVIFrameType::Inter, IVIFrameType::InterScal,
544 IVIFrameType::InterDroppable, IVIFrameType::NULL,
545 ];
546
547 const INDEO5_QUANT8X8_INTRA: [[u16; 64]; 5] = [
548 [
549 0x1a, 0x2e, 0x36, 0x42, 0x46, 0x4a, 0x4e, 0x5a,
550 0x2e, 0x32, 0x3e, 0x42, 0x46, 0x4e, 0x56, 0x6a,
551 0x36, 0x3e, 0x3e, 0x44, 0x4a, 0x54, 0x66, 0x72,
552 0x42, 0x42, 0x44, 0x4a, 0x52, 0x62, 0x6c, 0x7a,
553 0x46, 0x46, 0x4a, 0x52, 0x5e, 0x66, 0x72, 0x8e,
554 0x4a, 0x4e, 0x54, 0x62, 0x66, 0x6e, 0x86, 0xa6,
555 0x4e, 0x56, 0x66, 0x6c, 0x72, 0x86, 0x9a, 0xca,
556 0x5a, 0x6a, 0x72, 0x7a, 0x8e, 0xa6, 0xca, 0xfe,
557 ], [
558 0x26, 0x3a, 0x3e, 0x46, 0x4a, 0x4e, 0x52, 0x5a,
559 0x3a, 0x3e, 0x42, 0x46, 0x4a, 0x4e, 0x56, 0x5e,
560 0x3e, 0x42, 0x46, 0x48, 0x4c, 0x52, 0x5a, 0x62,
561 0x46, 0x46, 0x48, 0x4a, 0x4e, 0x56, 0x5e, 0x66,
562 0x4a, 0x4a, 0x4c, 0x4e, 0x52, 0x5a, 0x62, 0x6a,
563 0x4e, 0x4e, 0x52, 0x56, 0x5a, 0x5e, 0x66, 0x6e,
564 0x52, 0x56, 0x5a, 0x5e, 0x62, 0x66, 0x6a, 0x72,
565 0x5a, 0x5e, 0x62, 0x66, 0x6a, 0x6e, 0x72, 0x76,
566 ], [
567 0x4e, 0xaa, 0xf2, 0xd4, 0xde, 0xc2, 0xd6, 0xc2,
568 0x4e, 0xaa, 0xf2, 0xd4, 0xde, 0xc2, 0xd6, 0xc2,
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 ], [
576 0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e,
577 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
578 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
579 0xd4, 0xd4, 0xd4, 0xd4, 0xd4, 0xd4, 0xd4, 0xd4,
580 0xde, 0xde, 0xde, 0xde, 0xde, 0xde, 0xde, 0xde,
581 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2,
582 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6,
583 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2,
584 ], [
585 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e,
586 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e,
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 ]
594 ];
595 const INDEO5_QUANT8X8_INTER: [[u16; 64]; 5] = [
596 [
597 0x26, 0x3a, 0x3e, 0x46, 0x4a, 0x4e, 0x52, 0x5a,
598 0x3a, 0x3e, 0x42, 0x46, 0x4a, 0x4e, 0x56, 0x5e,
599 0x3e, 0x42, 0x46, 0x48, 0x4c, 0x52, 0x5a, 0x62,
600 0x46, 0x46, 0x48, 0x4a, 0x4e, 0x56, 0x5e, 0x66,
601 0x4a, 0x4a, 0x4c, 0x4e, 0x52, 0x5a, 0x62, 0x6a,
602 0x4e, 0x4e, 0x52, 0x56, 0x5a, 0x5e, 0x66, 0x6e,
603 0x52, 0x56, 0x5a, 0x5e, 0x62, 0x66, 0x6a, 0x72,
604 0x5a, 0x5e, 0x62, 0x66, 0x6a, 0x6e, 0x72, 0x76,
605 ], [
606 0x26, 0x3a, 0x3e, 0x46, 0x4a, 0x4e, 0x52, 0x5a,
607 0x3a, 0x3e, 0x42, 0x46, 0x4a, 0x4e, 0x56, 0x5e,
608 0x3e, 0x42, 0x46, 0x48, 0x4c, 0x52, 0x5a, 0x62,
609 0x46, 0x46, 0x48, 0x4a, 0x4e, 0x56, 0x5e, 0x66,
610 0x4a, 0x4a, 0x4c, 0x4e, 0x52, 0x5a, 0x62, 0x6a,
611 0x4e, 0x4e, 0x52, 0x56, 0x5a, 0x5e, 0x66, 0x6e,
612 0x52, 0x56, 0x5a, 0x5e, 0x62, 0x66, 0x6a, 0x72,
613 0x5a, 0x5e, 0x62, 0x66, 0x6a, 0x6e, 0x72, 0x76,
614 ], [
615 0x4e, 0xaa, 0xf2, 0xd4, 0xde, 0xc2, 0xd6, 0xc2,
616 0x4e, 0xaa, 0xf2, 0xd4, 0xde, 0xc2, 0xd6, 0xc2,
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 ], [
624 0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e,
625 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
626 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
627 0xd4, 0xd4, 0xd4, 0xd4, 0xd4, 0xd4, 0xd4, 0xd4,
628 0xde, 0xde, 0xde, 0xde, 0xde, 0xde, 0xde, 0xde,
629 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2,
630 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6,
631 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2,
632 ], [
633 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e,
634 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e,
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 ]
642 ];
643 const INDEO5_QUANT4X4_INTRA: [u16; 16] = [
644 0x1e, 0x3e, 0x4a, 0x52,
645 0x3e, 0x4a, 0x52, 0x5e,
646 0x4a, 0x52, 0x5e, 0x7a,
647 0x52, 0x5e, 0x7a, 0x92
648 ];
649 const INDEO5_QUANT4X4_INTER: [u16; 16] = [
650 0x1e, 0x3e, 0x4a, 0x52,
651 0x3e, 0x4a, 0x52, 0x56,
652 0x4a, 0x52, 0x56, 0x5e,
653 0x52, 0x56, 0x5e, 0x66
654 ];
655 const INDEO5_Q8_INTRA: [&[u16; 64]; 5] = [
656 &INDEO5_QUANT8X8_INTRA[0], &INDEO5_QUANT8X8_INTRA[1], &INDEO5_QUANT8X8_INTRA[2],
657 &INDEO5_QUANT8X8_INTRA[3], &INDEO5_QUANT8X8_INTRA[4],
658 ];
659 const INDEO5_Q8_INTER: [&[u16; 64]; 5] = [
660 &INDEO5_QUANT8X8_INTER[0], &INDEO5_QUANT8X8_INTER[1], &INDEO5_QUANT8X8_INTER[2],
661 &INDEO5_QUANT8X8_INTER[3], &INDEO5_QUANT8X8_INTER[4],
662 ];
663 const INDEO5_Q4_INTRA: &[u16; 16] = &INDEO5_QUANT4X4_INTRA;
664 const INDEO5_Q4_INTER: &[u16; 16] = &INDEO5_QUANT4X4_INTER;
665
666 const INDEO5_SCAN8X8: [&[usize; 64]; 4] = [
667 &IVI_ZIGZAG, &IVI_SCAN_8X8_VER, &IVI_SCAN_8X8_HOR, &IVI_SCAN_8X8_HOR
668 ];
669 const INDEO5_SCAN4X4: &[usize; 16] = &IVI_SCAN_4X4;
670
671 const INDEO5_QSCALE8_INTRA: [[u8; 24]; 5] = [
672 [
673 0x0b, 0x0e, 0x10, 0x12, 0x14, 0x16, 0x17, 0x18, 0x1a, 0x1c, 0x1e, 0x20,
674 0x22, 0x24, 0x27, 0x28, 0x2a, 0x2d, 0x2f, 0x31, 0x34, 0x37, 0x39, 0x3c,
675 ], [
676 0x01, 0x10, 0x12, 0x14, 0x16, 0x18, 0x1b, 0x1e, 0x22, 0x25, 0x28, 0x2c,
677 0x30, 0x34, 0x38, 0x3d, 0x42, 0x47, 0x4c, 0x52, 0x58, 0x5e, 0x65, 0x6c,
678 ], [
679 0x13, 0x22, 0x27, 0x2a, 0x2d, 0x33, 0x36, 0x3c, 0x41, 0x45, 0x49, 0x4e,
680 0x53, 0x58, 0x5d, 0x63, 0x69, 0x6f, 0x75, 0x7c, 0x82, 0x88, 0x8e, 0x95,
681 ], [
682 0x13, 0x1f, 0x21, 0x24, 0x27, 0x29, 0x2d, 0x2f, 0x34, 0x37, 0x3a, 0x3d,
683 0x40, 0x44, 0x48, 0x4c, 0x4f, 0x52, 0x56, 0x5a, 0x5e, 0x62, 0x66, 0x6b,
684 ], [
685 0x31, 0x42, 0x47, 0x47, 0x4d, 0x52, 0x58, 0x58, 0x5d, 0x63, 0x67, 0x6b,
686 0x6f, 0x73, 0x78, 0x7c, 0x80, 0x84, 0x89, 0x8e, 0x93, 0x98, 0x9d, 0xa4,
687 ]
688 ];
689 const INDEO5_QSCALE8_INTER: [[u8; 24]; 5] = [
690 [
691 0x0b, 0x11, 0x13, 0x14, 0x15, 0x16, 0x18, 0x1a, 0x1b, 0x1d, 0x20, 0x22,
692 0x23, 0x25, 0x28, 0x2a, 0x2e, 0x32, 0x35, 0x39, 0x3d, 0x41, 0x44, 0x4a,
693 ], [
694 0x07, 0x14, 0x16, 0x18, 0x1b, 0x1e, 0x22, 0x25, 0x29, 0x2d, 0x31, 0x35,
695 0x3a, 0x3f, 0x44, 0x4a, 0x50, 0x56, 0x5c, 0x63, 0x6a, 0x71, 0x78, 0x7e,
696 ], [
697 0x15, 0x25, 0x28, 0x2d, 0x30, 0x34, 0x3a, 0x3d, 0x42, 0x48, 0x4c, 0x51,
698 0x56, 0x5b, 0x60, 0x65, 0x6b, 0x70, 0x76, 0x7c, 0x82, 0x88, 0x8f, 0x97,
699 ], [
700 0x13, 0x1f, 0x20, 0x22, 0x25, 0x28, 0x2b, 0x2d, 0x30, 0x33, 0x36, 0x39,
701 0x3c, 0x3f, 0x42, 0x45, 0x48, 0x4b, 0x4e, 0x52, 0x56, 0x5a, 0x5e, 0x62,
702 ], [
703 0x3c, 0x52, 0x58, 0x5d, 0x63, 0x68, 0x68, 0x6d, 0x73, 0x78, 0x7c, 0x80,
704 0x84, 0x89, 0x8e, 0x93, 0x98, 0x9d, 0xa3, 0xa9, 0xad, 0xb1, 0xb5, 0xba
705 ]
706 ];
707 const INDEO5_QSCALE4_INTRA: [u8; 24] = [
708 0x01, 0x0b, 0x0b, 0x0d, 0x0d, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x13, 0x14,
709 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20
710 ];
711 const INDEO5_QSCALE4_INTER: [u8; 24] = [
712 0x0b, 0x0d, 0x0d, 0x0e, 0x11, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
713 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23
714 ];
715
716 pub fn get_decoder() -> Box<NADecoder> {
717 Box::new(Indeo5Decoder::new())
718 }
719
720 #[cfg(test)]
721 mod test {
722 use nihav_core::codecs::RegisteredDecoders;
723 use nihav_core::demuxers::RegisteredDemuxers;
724 use nihav_core::test::dec_video::*;
725 use crate::codecs::indeo_register_all_codecs;
726 use nihav_commonfmt::demuxers::generic_register_all_demuxers;
727 #[test]
728 fn test_indeo5() {
729 let mut dmx_reg = RegisteredDemuxers::new();
730 generic_register_all_demuxers(&mut dmx_reg);
731 let mut dec_reg = RegisteredDecoders::new();
732 indeo_register_all_codecs(&mut dec_reg);
733
734 test_file_decoding("avi", "assets/Indeo/IV5/sample.avi", /*None*/Some(2), true, false, None, &dmx_reg, &dec_reg);
735 // test_file_decoding("avi", "assets/Indeo/IV5/W32mdl_1.avi", None/*Some(2)*/, true, false, Some("iv5"));
736 //panic!("the end");
737 }
738 }