]> git.nihav.org Git - nihav.git/blob - nihav-indeo/src/codecs/indeo4.rs
indeo4: fix picture header parsing
[nihav.git] / nihav-indeo / src / codecs / indeo4.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 #[inline(always)]
10 fn mclip8(a: i32) -> u8 {
11 if (a as u16) > 255 { !(a >> 16) as u8 }
12 else { a as u8 }
13 }
14
15 struct Indeo4Parser {
16 mb_cb: IVICodebook,
17 blk_cb: IVICodebook,
18 }
19
20 fn calc_quant(glob_q: u32, qd: i16) -> u8 {
21 let q = (glob_q as i16) + qd;
22 if q < 0 {
23 0
24 } else if q > 31 {
25 31
26 } else {
27 q as u8
28 }
29 }
30
31 impl Indeo4Parser {
32 fn new() -> Self {
33 Indeo4Parser {
34 mb_cb: IVI_CB_ZERO,
35 blk_cb: IVI_CB_ZERO,
36 }
37 }
38 }
39
40 impl IndeoXParser for Indeo4Parser {
41 #[allow(unused_variables,unused_assignments)]
42 fn decode_picture_header(&mut self, br: &mut BitReader) -> DecoderResult<PictureHeader> {
43 let sync = br.read(18)?;
44 validate!(sync == 0x3FFF8);
45 let ftype_idx = br.read(3)?;
46 validate!(ftype_idx < 7);
47 let ftype = INDEO4_FRAME_TYPE[ftype_idx as usize];
48 let transparent = br.read_bool()?;
49 br.skip(1)?;
50 let data_size;
51 if br.read_bool()? {
52 data_size = br.read(24)? as usize;
53 } else {
54 data_size = 0;
55 }
56 if ftype.is_null() {
57 return Ok(PictureHeader::new_null(ftype));
58 }
59 if br.read_bool()? {
60 br.skip(32)?; // key lock
61 }
62 let width;
63 let height;
64 let pic_size_idx = br.read(3)?;
65 if pic_size_idx < 7 {
66 width = INDEO4_PICTURE_SIZE_TAB[pic_size_idx as usize][0];
67 height = INDEO4_PICTURE_SIZE_TAB[pic_size_idx as usize][1];
68 } else {
69 height = br.read(16)? as usize;
70 width = br.read(16)? as usize;
71 validate!((width > 0) && ((width & 3) == 0));
72 validate!((height > 0) && ((height & 3) == 0));
73 }
74
75 let slice_w;
76 let slice_h;
77 if br.read_bool()? {
78 let idx = br.read(4)? as usize;
79 slice_h = if idx < 15 { INDEO4_SLICE_SIZE_TAB[idx] } else { height };
80 let idx = br.read(4)? as usize;
81 slice_w = if idx < 15 { INDEO4_SLICE_SIZE_TAB[idx] } else { width };
82 } else {
83 slice_w = width;
84 slice_h = height;
85 }
86 let subsampling = br.read(2)?;
87 validate!(subsampling == 0);
88 let sc_idx = br.read(2)?;
89 match sc_idx {
90 3 => { },
91 2 => { validate!(br.read(2*4)? == 0xFF); }
92 _ => { return Err(DecoderError::InvalidData); }
93 };
94 let luma_bands = if sc_idx == 2 { 4 } else { 1 };
95 let sc_idx = br.read(2)?;
96 match sc_idx {
97 3 => { },
98 2 => { validate!(br.read(2*4)? == 0xFF); }
99 _ => { return Err(DecoderError::InvalidData); }
100 };
101 let chroma_bands = if sc_idx == 2 { 4 } else { 1 };
102 let frame_no;
103 if br.read_bool()? {
104 frame_no = br.read(20)?;
105 } else {
106 frame_no = 0;
107 }
108 if br.read_bool()? {
109 br.skip(8)?; // decTimeEst
110 }
111 let desc_coded = br.read_bool()?;
112 self.mb_cb = br.read_ivi_codebook_desc(true, desc_coded)?;
113 let desc_coded = br.read_bool()?;
114 self.blk_cb = br.read_ivi_codebook_desc(false, desc_coded)?;
115 let rvmap = if br.read_bool()? { br.read(3)? as usize } else { 8 };
116 let in_imf = br.read_bool()?;
117 let in_q = br.read_bool()?;
118 let glob_q = br.read(5)? as u8;
119 if br.read_bool()? {
120 br.skip(3)?;
121 }
122 let checksum = if br.read_bool()? { br.read(16)? } else { 0 };
123 if br.read_bool()? {
124 br.skip(8)?; // pic hdr extension
125 }
126 if br.read_bool()? {
127 println!("bad blocks bits!");
128 }
129 br.align();
130
131 Ok(PictureHeader::new(ftype, width, height, slice_w, slice_h, transparent, luma_bands, chroma_bands, in_q))
132 }
133
134 #[allow(unused_variables,unused_assignments)]
135 fn decode_band_header(&mut self, br: &mut BitReader, pic_hdr: &PictureHeader, plane: usize, band: usize) -> DecoderResult<BandHeader> {
136 let plane_no = br.read(2)? as usize;
137 let band_no = br.read(4)? as usize;
138 validate!(plane_no == plane);
139 validate!(band_no == band);
140 if br.read_bool()? {
141 br.align();
142 return Ok(BandHeader::new_empty(plane_no, band_no));
143 }
144 let hdr_size;
145 if br.read_bool()? {
146 hdr_size = br.read(16)? as usize;
147 } else {
148 hdr_size = 32;
149 }
150 let mv_mode = br.read(2)?;
151 validate!(mv_mode < 2);
152 if br.read_bool()? {
153 br.skip(16)?; //checksum
154 }
155
156 let scale = br.read(2)?;
157 validate!(scale != 3);
158 let mb_size = 16 >> scale;
159 let blk_size = 8 >> (scale >> 1);
160 let inherit_mv = br.read_bool()?;
161 let inherit_qd = br.read_bool()?;
162 let quant = br.read(5)?;
163
164 let tr: IVITransformType;
165 let txtype: TxType;
166 if !br.read_bool()? || pic_hdr.ftype == IVIFrameType::Intra {
167 let tr_id = br.read(5)?;
168 validate!(tr_id < 18);
169 let scan_idx = br.read(4)? as usize;
170 validate!(scan_idx != 15);
171 let qmat_idx = br.read(5)? as usize;
172
173 tr = INDEO4_TRANSFORMS[tr_id as usize];
174 if (scan_idx < 5) || (scan_idx >= 10) {
175 validate!(tr.is_8x8());
176 validate!(qmat_idx < 15);
177 let scan = if scan_idx < 5 { INDEO4_SCANS_8X8[scan_idx] }
178 else { INDEO4_SCANS_8X8[4] };
179 let qidx = INDEO4_Q8X8_IDX[qmat_idx];
180 let qintra = INDEO4_Q8_INTRA[qidx];
181 let qinter = INDEO4_Q8_INTER[qidx];
182 txtype = TxType::Transform8(TxParams8x8::new(qintra, qinter, scan));
183 } else if scan_idx < 10 {
184 validate!(!tr.is_8x8());
185 validate!((15..22).contains(&qmat_idx));
186 let scan = INDEO4_SCANS_4X4[scan_idx - 5];
187 let qidx = INDEO4_Q4X4_IDX[qmat_idx - 15];
188 let qintra = INDEO4_Q4_INTRA[qidx];
189 let qinter = INDEO4_Q4_INTER[qidx];
190 txtype = TxType::Transform4(TxParams4x4::new(qintra, qinter, scan));
191 } else {
192 unreachable!();
193 }
194 } else {
195 tr = IVITransformType::None(TSize::T8x8);
196 txtype = TxType::None;
197 }
198
199 let blk_cb;
200 if br.read_bool()? {
201 blk_cb = br.read_ivi_codebook_desc(false, true)?;
202 } else {
203 blk_cb = self.blk_cb;
204 }
205 let rvmap_idx;
206 if br.read_bool()? {
207 rvmap_idx = br.read(3)? as usize;
208 } else {
209 rvmap_idx = 8;
210 }
211 let num_corr;
212 let mut corr_map: [u8; CORR_MAP_SIZE] = [0; CORR_MAP_SIZE];
213 if br.read_bool()? {
214 num_corr = br.read(8)? as usize;
215 validate!(num_corr*2 <= CORR_MAP_SIZE);
216 for i in 0..num_corr*2 {
217 corr_map[i] = br.read(8)? as u8;
218 }
219 } else {
220 num_corr = 0;
221 }
222
223 br.align();
224 Ok(BandHeader::new(plane_no, band_no, mb_size, blk_size, mv_mode == 1, inherit_mv, false, inherit_qd, quant, rvmap_idx, num_corr, corr_map, blk_cb, tr, txtype))
225 }
226
227 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<()> {
228 let mut mv_x = 0;
229 let mut mv_y = 0;
230 let mut mb_idx = 0;
231
232 for mb_y in 0..tile.mb_h {
233 for mb_x in 0..tile.mb_w {
234 let mut mb = MB::new(tile.pos_x + mb_x * band.mb_size, tile.pos_y + mb_y * band.mb_size);
235 if !br.read_bool()? {
236 if pic_hdr.ftype.is_intra() {
237 mb.mtype = MBType::Intra;
238 } else if band.inherit_mv {
239 if let Some(tileref) = ref_tile {
240 mb.mtype = tileref.mb[mb_idx].mtype;
241 } else {
242 return Err(DecoderError::MissingReference);
243 }
244 } else {
245 if !pic_hdr.ftype.is_bidir() {
246 mb.mtype = if br.read_bool()? { MBType::Inter } else { MBType::Intra };
247 } else {
248 mb.mtype = match br.read(2)? {
249 0 => { MBType::Intra },
250 1 => { MBType::Inter },
251 2 => { MBType::Backward },
252 _ => { MBType::Bidir },
253 };
254 }
255 }
256 if band.mb_size == band.blk_size {
257 mb.cbp = br.read(1)? as u8;
258 } else {
259 mb.cbp = br.read(4)? as u8;
260 }
261 if band.inherit_qd {
262 if let Some(tileref) = ref_tile {
263 mb.qd = tileref.mb[mb_idx].qd;
264 mb.q = calc_quant(band.quant, mb.qd);
265 } else {
266 mb.q = band.quant as u8;
267 }
268 } else if (mb.cbp != 0) || ((band.plane_no == 0) && (band.band_no == 0) && pic_hdr.in_q) {
269 mb.qd = br.read_ivi_cb_s(&self.mb_cb)? as i16;
270 mb.q = calc_quant(band.quant, mb.qd);
271 } else {
272 mb.q = band.quant as u8;
273 }
274
275 if mb.mtype != MBType::Intra {
276 if band.inherit_mv {
277 if let Some(tileref) = ref_tile {
278 let mx = tileref.mb[mb_idx].mv_x;
279 let my = tileref.mb[mb_idx].mv_y;
280 if mv_scale == 0 {
281 mb.mv_x = mx;
282 mb.mv_y = my;
283 } else {
284 mb.mv_x = scale_mv(mx, mv_scale);
285 mb.mv_y = scale_mv(my, mv_scale);
286 }
287 }
288 } else {
289 mv_y += br.read_ivi_cb_s(&self.mb_cb)?;
290 mv_x += br.read_ivi_cb_s(&self.mb_cb)?;
291 mb.mv_x = mv_x;
292 mb.mv_y = mv_y;
293 if mb.mtype == MBType::Backward {
294 mb.mv_x = -mb.mv_x;
295 mb.mv_y = -mb.mv_y;
296 } else if mb.mtype == MBType::Bidir {
297 mv_y += br.read_ivi_cb_s(&self.mb_cb)?;
298 mv_x += br.read_ivi_cb_s(&self.mb_cb)?;
299 mb.mv2_x = -mv_x;
300 mb.mv2_y = -mv_y;
301 }
302 }
303 }
304 } else {
305 validate!(!pic_hdr.ftype.is_intra());
306 mb.mtype = MBType::Inter;
307 mb.cbp = 0;
308 mb.qd = 0;
309 if (band.plane_no == 0) && (band.band_no == 0) && pic_hdr.in_q {
310 mb.qd = br.read_ivi_cb_s(&self.mb_cb)? as i16;
311 mb.q = calc_quant(band.quant, mb.qd);
312 }
313 if band.inherit_mv {
314 if let Some(tileref) = ref_tile {
315 let mx = tileref.mb[mb_idx].mv_x;
316 let my = tileref.mb[mb_idx].mv_y;
317 if mv_scale == 0 {
318 mb.mv_x = mx;
319 mb.mv_y = my;
320 } else {
321 mb.mv_x = scale_mv(mx, mv_scale);
322 mb.mv_y = scale_mv(my, mv_scale);
323 }
324 }
325 }
326 }
327 tile.mb[mb_idx] = mb;
328 mb_idx += 1;
329 }
330 }
331 br.align();
332 Ok(())
333 }
334
335 fn recombine_plane(&mut self, src: &[i16], sstride: usize, dst: &mut [u8], dstride: usize, w: usize, h: usize) {
336 /* let mut idx0 = 0;
337 let mut idx1 = w / 2;
338 let mut idx2 = (h / 2) * sstride;
339 let mut idx3 = idx2 + idx1;
340 let mut oidx0 = 0;
341 let mut oidx1 = dstride;
342
343 for _ in 0..(h/2) {
344 for x in 0..(w/2) {
345 let p0 = src[idx0 + x];
346 let p1 = src[idx1 + x];
347 let p2 = src[idx2 + x];
348 let p3 = src[idx3 + x];
349 let s0 = p0 + p2;
350 let d0 = p0 - p2;
351 let s1 = p1 + p3;
352 let d1 = p1 - p3;
353 dst[oidx0 + x * 2 + 0] = clip8(((s0 + s1 + 2) >> 2) + 128);
354 dst[oidx0 + x * 2 + 1] = clip8(((d0 + d1 + 2) >> 2) + 128);
355 dst[oidx1 + x * 2 + 0] = clip8(((s0 - s1 + 2) >> 2) + 128);
356 dst[oidx1 + x * 2 + 1] = clip8(((d0 - d1 + 2) >> 2) + 128);
357 }
358 idx0 += sstride;
359 idx1 += sstride;
360 idx2 += sstride;
361 idx3 += sstride;
362 oidx0 += dstride * 2;
363 oidx1 += dstride * 2;
364 }*/
365 unsafe {
366 let hw = (w / 2) as isize;
367 let hh = (h / 2) as isize;
368 let mut band0 = src.as_ptr();
369 let mut band1 = band0.offset(hw);
370 let mut band2 = band0.add((h / 2) * sstride);
371 let mut band3 = band2.offset(hw);
372 let mut dst0 = dst.as_mut_ptr();
373 let mut dst1 = dst0.add(dstride);
374 for _ in 0..hh {
375 let mut b0_ptr = band0;
376 let mut b1_ptr = band1;
377 let mut b2_ptr = band2;
378 let mut b3_ptr = band3;
379 let mut d0_ptr = dst0;
380 let mut d1_ptr = dst1;
381 for _ in 0..hw {
382 let p0 = i32::from(*b0_ptr);
383 let p1 = i32::from(*b1_ptr);
384 let p2 = i32::from(*b2_ptr);
385 let p3 = i32::from(*b3_ptr);
386 let s0 = p0.wrapping_add(p2);
387 let s1 = p1.wrapping_add(p3);
388 let d0 = p0.wrapping_sub(p2);
389 let d1 = p1.wrapping_sub(p3);
390 let o0 = s0.wrapping_add(s1).wrapping_add(2);
391 let o1 = d0.wrapping_add(d1).wrapping_add(2);
392 let o2 = s0.wrapping_sub(s1).wrapping_add(2);
393 let o3 = d0.wrapping_sub(d1).wrapping_add(2);
394 *d0_ptr.offset(0) = mclip8((o0 >> 2).wrapping_add(128));
395 *d0_ptr.offset(1) = mclip8((o1 >> 2).wrapping_add(128));
396 *d1_ptr.offset(0) = mclip8((o2 >> 2).wrapping_add(128));
397 *d1_ptr.offset(1) = mclip8((o3 >> 2).wrapping_add(128));
398 b0_ptr = b0_ptr.offset(1);
399 b1_ptr = b1_ptr.offset(1);
400 b2_ptr = b2_ptr.offset(1);
401 b3_ptr = b3_ptr.offset(1);
402 d0_ptr = d0_ptr.offset(2);
403 d1_ptr = d1_ptr.offset(2);
404 }
405 band0 = band0.add(sstride);
406 band1 = band1.add(sstride);
407 band2 = band2.add(sstride);
408 band3 = band3.add(sstride);
409 dst0 = dst0.add(dstride * 2);
410 dst1 = dst1.add(dstride * 2);
411 }
412 }
413 }
414 }
415
416 struct Indeo4Decoder {
417 info: NACodecInfoRef,
418 dec: IVIDecoder,
419 }
420
421 impl Indeo4Decoder {
422 fn new() -> Self {
423 Indeo4Decoder {
424 info: NACodecInfo::new_dummy(),
425 dec: IVIDecoder::new(),
426 }
427 }
428 }
429
430 impl NADecoder for Indeo4Decoder {
431 fn init(&mut self, _supp: &mut NADecoderSupport, info: NACodecInfoRef) -> DecoderResult<()> {
432 if let NACodecTypeInfo::Video(vinfo) = info.get_properties() {
433 let w = vinfo.get_width();
434 let h = vinfo.get_height();
435 let f = vinfo.is_flipped();
436 let fmt = formats::YUV410_FORMAT;
437 let myinfo = NACodecTypeInfo::Video(NAVideoInfo::new(w, h, f, fmt));
438 self.info = NACodecInfo::new_ref(info.get_name(), myinfo, info.get_extradata()).into_ref();
439 Ok(())
440 } else {
441 Err(DecoderError::InvalidData)
442 }
443 }
444 fn decode(&mut self, _supp: &mut NADecoderSupport, pkt: &NAPacket) -> DecoderResult<NAFrameRef> {
445 let src = pkt.get_buffer();
446 let mut br = BitReader::new(src.as_slice(), BitReaderMode::LE);
447
448 let mut ip = Indeo4Parser::new();
449 let bufinfo = self.dec.decode_frame(&mut ip, &mut br)?;
450 let mut frm = NAFrame::new_from_pkt(pkt, self.info.clone(), bufinfo);
451 frm.set_keyframe(self.dec.is_intra());
452 frm.set_frame_type(self.dec.get_frame_type());
453 Ok(frm.into_ref())
454 }
455 fn flush(&mut self) {
456 self.dec.flush();
457 }
458 }
459
460 impl NAOptionHandler for Indeo4Decoder {
461 fn get_supported_options(&self) -> &[NAOptionDefinition] { &[] }
462 fn set_options(&mut self, _options: &[NAOption]) { }
463 fn query_option_value(&self, _name: &str) -> Option<NAValue> { None }
464 }
465
466 const INDEO4_PICTURE_SIZE_TAB: [[usize; 2]; 7] = [
467 [640, 480], [320, 240], [160, 120], [704, 480], [352, 240], [352, 288], [176, 144]
468 ];
469
470 const INDEO4_SLICE_SIZE_TAB: [usize; 15] = [
471 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448, 480
472 ];
473
474 const INDEO4_FRAME_TYPE: [IVIFrameType; 7] = [
475 IVIFrameType::Intra, IVIFrameType::Intra1, IVIFrameType::Inter, IVIFrameType::Bidir,
476 IVIFrameType::InterDroppable, IVIFrameType::NULL, IVIFrameType::NULL2
477 ];
478
479 const INDEO4_TRANSFORMS: [IVITransformType; 18] = [
480 IVITransformType::Haar(TSize::T8x8, TDir::TwoD),
481 IVITransformType::Haar(TSize::T8x8, TDir::Row),
482 IVITransformType::Haar(TSize::T8x8, TDir::Col),
483 IVITransformType::None(TSize::T8x8),
484 IVITransformType::Slant(TSize::T8x8, TDir::TwoD),
485 IVITransformType::Slant(TSize::T8x8, TDir::Row),
486 IVITransformType::Slant(TSize::T8x8, TDir::Col),
487 IVITransformType::DCT(TSize::T8x8, TDir::TwoD),
488 IVITransformType::DCT(TSize::T8x8, TDir::Row),
489 IVITransformType::DCT(TSize::T8x8, TDir::Col),
490 IVITransformType::Haar(TSize::T4x4, TDir::TwoD),
491 IVITransformType::Slant(TSize::T4x4, TDir::TwoD),
492 IVITransformType::None(TSize::T4x4),
493 IVITransformType::Haar(TSize::T4x4, TDir::Row),
494 IVITransformType::Haar(TSize::T4x4, TDir::Col),
495 IVITransformType::Slant(TSize::T4x4, TDir::Row),
496 IVITransformType::Slant(TSize::T4x4, TDir::Col),
497 IVITransformType::DCT(TSize::T4x4, TDir::TwoD),
498 ];
499
500 const INDEO4_SCAN_8X8_ALT: [usize; 64] = [
501 0, 8, 1, 9, 16, 24, 2, 3,
502 17, 25, 10, 11, 32, 40, 48, 56,
503 4, 5, 6, 7, 33, 41, 49, 57,
504 18, 19, 26, 27, 12, 13, 14, 15,
505 34, 35, 43, 42, 50, 51, 59, 58,
506 20, 21, 22, 23, 31, 30, 29, 28,
507 36, 37, 38, 39, 47, 46, 45, 44,
508 52, 53, 54, 55, 63, 62, 61, 60
509 ];
510 const INDEO4_SCAN_4X4_ALT: [usize; 16] = [ 0, 1, 4, 5, 8, 12, 2, 3, 9, 13, 6, 7, 10, 11, 14, 15 ];
511 const INDEO4_SCAN_4X4_VER: [usize; 16] = [ 0, 4, 8, 12, 1, 5, 9, 13, 2, 6, 10, 14, 3, 7, 11, 15 ];
512 const INDEO4_SCAN_4X4_HOR: [usize; 16] = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 ];
513
514 const INDEO4_SCANS_8X8: [&[usize; 64]; 5] = [
515 &ZIGZAG, &INDEO4_SCAN_8X8_ALT, &IVI_SCAN_8X8_HOR, &IVI_SCAN_8X8_VER, &ZIGZAG
516 ];
517 const INDEO4_SCANS_4X4: [&[usize; 16]; 5] = [
518 &IVI_SCAN_4X4, &INDEO4_SCAN_4X4_ALT, &INDEO4_SCAN_4X4_VER, &INDEO4_SCAN_4X4_HOR, &IVI_SCAN_4X4
519 ];
520
521 const INDEO4_Q8X8_IDX: [usize; 15] = [ 0, 1, 0, 2, 1, 3, 0, 4, 1, 5, 0, 1, 6, 7, 8 ];
522 const INDEO4_Q4X4_IDX: [usize; 7] = [ 0, 1, 2, 2, 3, 3, 4 ];
523
524 const INDEO4_QUANT8X8_INTRA: [[u16; 64]; 9] = [
525 [
526 43, 342, 385, 470, 555, 555, 598, 726,
527 342, 342, 470, 513, 555, 598, 726, 769,
528 385, 470, 555, 555, 598, 726, 726, 811,
529 470, 470, 555, 555, 598, 726, 769, 854,
530 470, 555, 555, 598, 683, 726, 854, 1025,
531 555, 555, 598, 683, 726, 854, 1025, 1153,
532 555, 555, 598, 726, 811, 982, 1195, 1451,
533 555, 598, 726, 811, 982, 1195, 1451, 1793
534 ], [
535 86, 1195, 2390, 2390, 4865, 4865, 4865, 4865,
536 1195, 1195, 2390, 2390, 4865, 4865, 4865, 4865,
537 2390, 2390, 4865, 4865, 6827, 6827, 6827, 6827,
538 2390, 2390, 4865, 4865, 6827, 6827, 6827, 6827,
539 4865, 4865, 6827, 6827, 6827, 6827, 6827, 6827,
540 4865, 4865, 6827, 6827, 6827, 6827, 6827, 6827,
541 4865, 4865, 6827, 6827, 6827, 6827, 6827, 6827,
542 4865, 4865, 6827, 6827, 6827, 6827, 6827, 6827
543 ], [
544 235, 1067, 1195, 1323, 1451, 1579, 1707, 1835,
545 235, 1067, 1195, 1323, 1451, 1579, 1707, 1835,
546 235, 1067, 1195, 1323, 1451, 1579, 1707, 1835,
547 235, 1067, 1195, 1323, 1451, 1579, 1707, 1835,
548 235, 1067, 1195, 1323, 1451, 1579, 1707, 1835,
549 235, 1067, 1195, 1323, 1451, 1579, 1707, 1835,
550 235, 1067, 1195, 1323, 1451, 1579, 1707, 1835,
551 235, 1067, 1195, 1323, 1451, 1579, 1707, 1835
552 ], [
553 1707, 1707, 3414, 3414, 3414, 3414, 3414, 3414,
554 1707, 1707, 3414, 3414, 3414, 3414, 3414, 3414,
555 1707, 1707, 3414, 3414, 3414, 3414, 3414, 3414,
556 1707, 1707, 3414, 3414, 3414, 3414, 3414, 3414,
557 1707, 1707, 3414, 3414, 3414, 3414, 3414, 3414,
558 1707, 1707, 3414, 3414, 3414, 3414, 3414, 3414,
559 1707, 1707, 3414, 3414, 3414, 3414, 3414, 3414,
560 1707, 1707, 3414, 3414, 3414, 3414, 3414, 3414
561 ], [
562 897, 897, 897, 897, 897, 897, 897, 897,
563 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067,
564 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238,
565 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409,
566 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579,
567 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750,
568 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921,
569 2091, 2091, 2091, 2091, 2091, 2091, 2091, 2091
570 ], [
571 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
572 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
573 3414, 3414, 3414, 3414, 3414, 3414, 3414, 3414,
574 3414, 3414, 3414, 3414, 3414, 3414, 3414, 3414,
575 3414, 3414, 3414, 3414, 3414, 3414, 3414, 3414,
576 3414, 3414, 3414, 3414, 3414, 3414, 3414, 3414,
577 3414, 3414, 3414, 3414, 3414, 3414, 3414, 3414,
578 3414, 3414, 3414, 3414, 3414, 3414, 3414, 3414
579 ], [
580 2390, 2390, 2390, 2390, 2390, 2390, 2390, 2390,
581 2390, 2390, 2390, 2390, 2390, 2390, 2390, 2390,
582 2390, 2390, 2390, 2390, 2390, 2390, 2390, 2390,
583 2390, 2390, 2390, 2390, 2390, 2390, 2390, 2390,
584 2390, 2390, 2390, 2390, 2390, 2390, 2390, 2390,
585 2390, 2390, 2390, 2390, 2390, 2390, 2390, 2390,
586 2390, 2390, 2390, 2390, 2390, 2390, 2390, 2390,
587 2390, 2390, 2390, 2390, 2390, 2390, 2390, 2390
588 ], [
589 22, 171, 214, 257, 257, 299, 299, 342,
590 171, 171, 257, 257, 299, 299, 342, 385,
591 214, 257, 257, 299, 299, 342, 342, 385,
592 257, 257, 257, 299, 299, 342, 385, 427,
593 257, 257, 299, 299, 342, 385, 427, 513,
594 257, 299, 299, 342, 385, 427, 513, 598,
595 299, 299, 299, 385, 385, 470, 598, 726,
596 299, 299, 385, 385, 470, 598, 726, 897
597 ], [
598 86, 598, 1195, 1195, 2390, 2390, 2390, 2390,
599 598, 598, 1195, 1195, 2390, 2390, 2390, 2390,
600 1195, 1195, 2390, 2390, 3414, 3414, 3414, 3414,
601 1195, 1195, 2390, 2390, 3414, 3414, 3414, 3414,
602 2390, 2390, 3414, 3414, 3414, 3414, 3414, 3414,
603 2390, 2390, 3414, 3414, 3414, 3414, 3414, 3414,
604 2390, 2390, 3414, 3414, 3414, 3414, 3414, 3414,
605 2390, 2390, 3414, 3414, 3414, 3414, 3414, 3414
606 ]
607 ];
608 const INDEO4_QUANT8X8_INTER: [[u16; 64]; 9] = [
609 [
610 427, 427, 470, 427, 427, 427, 470, 470,
611 427, 427, 470, 427, 427, 427, 470, 470,
612 470, 470, 470, 470, 470, 470, 470, 470,
613 427, 427, 470, 470, 427, 427, 470, 470,
614 427, 427, 470, 427, 427, 427, 470, 470,
615 427, 427, 470, 427, 427, 427, 470, 470,
616 470, 470, 470, 470, 470, 470, 470, 470,
617 470, 470, 470, 470, 470, 470, 470, 470
618 ], [
619 1707, 1707, 2433, 2433, 3414, 3414, 3414, 3414,
620 1707, 1707, 2433, 2433, 3414, 3414, 3414, 3414,
621 2433, 2433, 3414, 3414, 4822, 4822, 4822, 4822,
622 2433, 2433, 3414, 3414, 4822, 4822, 4822, 4822,
623 3414, 3414, 4822, 4822, 3414, 3414, 3414, 3414,
624 3414, 3414, 4822, 4822, 3414, 3414, 3414, 3414,
625 3414, 3414, 4822, 4822, 3414, 3414, 3414, 3414,
626 3414, 3414, 4822, 4822, 3414, 3414, 3414, 3414
627 ], [
628 1195, 1195, 1281, 1238, 1195, 1195, 1281, 1281,
629 1195, 1195, 1281, 1238, 1195, 1195, 1281, 1281,
630 1195, 1195, 1281, 1238, 1195, 1195, 1281, 1281,
631 1195, 1195, 1281, 1238, 1195, 1195, 1281, 1281,
632 1195, 1195, 1281, 1238, 1195, 1195, 1281, 1281,
633 1195, 1195, 1281, 1238, 1195, 1195, 1281, 1281,
634 1195, 1195, 1281, 1238, 1195, 1195, 1281, 1281,
635 1195, 1195, 1281, 1238, 1195, 1195, 1281, 1281
636 ], [
637 2433, 2433, 3414, 3414, 2433, 2433, 2433, 2433,
638 2433, 2433, 3414, 3414, 2433, 2433, 2433, 2433,
639 2433, 2433, 3414, 3414, 2433, 2433, 2433, 2433,
640 2433, 2433, 3414, 3414, 2433, 2433, 2433, 2433,
641 2433, 2433, 3414, 3414, 2433, 2433, 2433, 2433,
642 2433, 2433, 3414, 3414, 2433, 2433, 2433, 2433,
643 2433, 2433, 3414, 3414, 2433, 2433, 2433, 2433,
644 2433, 2433, 3414, 3414, 2433, 2433, 2433, 2433
645 ], [
646 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195,
647 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195,
648 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281,
649 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238,
650 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195,
651 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195,
652 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281,
653 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281
654 ], [
655 2433, 2433, 2433, 2433, 2433, 2433, 2433, 2433,
656 2433, 2433, 2433, 2433, 2433, 2433, 2433, 2433,
657 3414, 3414, 3414, 3414, 3414, 3414, 3414, 3414,
658 3414, 3414, 3414, 3414, 3414, 3414, 3414, 3414,
659 2433, 2433, 2433, 2433, 2433, 2433, 2433, 2433,
660 2433, 2433, 2433, 2433, 2433, 2433, 2433, 2433,
661 2433, 2433, 2433, 2433, 2433, 2433, 2433, 2433,
662 2433, 2433, 2433, 2433, 2433, 2433, 2433, 2433
663 ], [
664 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
665 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
666 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
667 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
668 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
669 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
670 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
671 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707
672 ], [
673 86, 171, 171, 214, 214, 214, 214, 257,
674 171, 171, 214, 214, 214, 214, 257, 257,
675 171, 214, 214, 214, 214, 257, 257, 257,
676 214, 214, 214, 214, 257, 257, 257, 299,
677 214, 214, 214, 257, 257, 257, 299, 299,
678 214, 214, 257, 257, 257, 299, 299, 299,
679 214, 257, 257, 257, 299, 299, 299, 342,
680 257, 257, 257, 299, 299, 299, 342, 342
681 ], [
682 854, 854, 1195, 1195, 1707, 1707, 1707, 1707,
683 854, 854, 1195, 1195, 1707, 1707, 1707, 1707,
684 1195, 1195, 1707, 1707, 2390, 2390, 2390, 2390,
685 1195, 1195, 1707, 1707, 2390, 2390, 2390, 2390,
686 1707, 1707, 2390, 2390, 1707, 1707, 1707, 1707,
687 1707, 1707, 2390, 2390, 1707, 1707, 1707, 1707,
688 1707, 1707, 2390, 2390, 1707, 1707, 1707, 1707,
689 1707, 1707, 2390, 2390, 1707, 1707, 1707, 1707
690 ]
691 ];
692 const INDEO4_QUANT4X4_INTRA: [[u16; 16]; 5] = [
693 [
694 22, 214, 257, 299,
695 214, 257, 299, 342,
696 257, 299, 342, 427,
697 299, 342, 427, 513
698 ], [
699 129, 1025, 1451, 1451,
700 1025, 1025, 1451, 1451,
701 1451, 1451, 2049, 2049,
702 1451, 1451, 2049, 2049
703 ], [
704 43, 171, 171, 171,
705 43, 171, 171, 171,
706 43, 171, 171, 171,
707 43, 171, 171, 171
708 ], [
709 43, 43, 43, 43,
710 171, 171, 171, 171,
711 171, 171, 171, 171,
712 171, 171, 171, 171
713 ], [
714 43, 43, 43, 43,
715 43, 43, 43, 43,
716 43, 43, 43, 43,
717 43, 43, 43, 43
718 ]
719 ];
720 const INDEO4_QUANT4X4_INTER: [[u16; 16]; 5] = [
721 [
722 107, 214, 257, 299,
723 214, 257, 299, 299,
724 257, 299, 299, 342,
725 299, 299, 342, 342
726 ], [
727 513, 1025, 1238, 1238,
728 1025, 1025, 1238, 1238,
729 1238, 1238, 1451, 1451,
730 1238, 1238, 1451, 1451
731 ], [
732 43, 171, 171, 171,
733 43, 171, 171, 171,
734 43, 171, 171, 171,
735 43, 171, 171, 171
736 ], [
737 43, 43, 43, 43,
738 171, 171, 171, 171,
739 171, 171, 171, 171,
740 171, 171, 171, 171
741 ], [
742 43, 43, 43, 43,
743 43, 43, 43, 43,
744 43, 43, 43, 43,
745 43, 43, 43, 43
746 ]
747 ];
748 const INDEO4_Q8_INTRA: [&[u16; 64]; 9] = [
749 &INDEO4_QUANT8X8_INTRA[0], &INDEO4_QUANT8X8_INTRA[1], &INDEO4_QUANT8X8_INTRA[2],
750 &INDEO4_QUANT8X8_INTRA[3], &INDEO4_QUANT8X8_INTRA[4], &INDEO4_QUANT8X8_INTRA[5],
751 &INDEO4_QUANT8X8_INTRA[6], &INDEO4_QUANT8X8_INTRA[7], &INDEO4_QUANT8X8_INTRA[8],
752 ];
753 const INDEO4_Q8_INTER: [&[u16; 64]; 9] = [
754 &INDEO4_QUANT8X8_INTER[0], &INDEO4_QUANT8X8_INTER[1], &INDEO4_QUANT8X8_INTER[2],
755 &INDEO4_QUANT8X8_INTER[3], &INDEO4_QUANT8X8_INTER[4], &INDEO4_QUANT8X8_INTER[5],
756 &INDEO4_QUANT8X8_INTER[6], &INDEO4_QUANT8X8_INTER[7], &INDEO4_QUANT8X8_INTER[8],
757 ];
758 const INDEO4_Q4_INTRA: [&[u16; 16]; 5] = [
759 &INDEO4_QUANT4X4_INTRA[0], &INDEO4_QUANT4X4_INTRA[1], &INDEO4_QUANT4X4_INTRA[2],
760 &INDEO4_QUANT4X4_INTRA[3], &INDEO4_QUANT4X4_INTRA[4]
761 ];
762 const INDEO4_Q4_INTER: [&[u16; 16]; 5] = [
763 &INDEO4_QUANT4X4_INTER[0], &INDEO4_QUANT4X4_INTER[1], &INDEO4_QUANT4X4_INTER[2],
764 &INDEO4_QUANT4X4_INTER[3], &INDEO4_QUANT4X4_INTER[4]
765 ];
766
767 pub fn get_decoder() -> Box<dyn NADecoder + Send> {
768 Box::new(Indeo4Decoder::new())
769 }
770
771 #[cfg(test)]
772 mod test {
773 use nihav_core::codecs::RegisteredDecoders;
774 use nihav_core::demuxers::RegisteredDemuxers;
775 use nihav_codec_support::test::dec_video::*;
776 use crate::indeo_register_all_decoders;
777 use nihav_commonfmt::generic_register_all_demuxers;
778 #[test]
779 fn test_indeo4() {
780 let mut dmx_reg = RegisteredDemuxers::new();
781 generic_register_all_demuxers(&mut dmx_reg);
782 let mut dec_reg = RegisteredDecoders::new();
783 indeo_register_all_decoders(&mut dec_reg);
784
785 // sample: https://samples.mplayerhq.hu/V-codecs/IV41/indeo4-avi/volcano.avi
786 test_decoding("avi", "indeo4", "assets/Indeo/IV4/volcano.avi", Some(16),
787 &dmx_reg, &dec_reg, ExpectedTestResult::MD5Frames(vec![
788 [0x194f626b, 0x023fdfd0, 0x9809665a, 0xd68f6f47],
789 [0x194f626b, 0x023fdfd0, 0x9809665a, 0xd68f6f47],
790 [0x194f626b, 0x023fdfd0, 0x9809665a, 0xd68f6f47],
791 [0x194f626b, 0x023fdfd0, 0x9809665a, 0xd68f6f47],
792 [0x46c6719d, 0xe6415ac0, 0x3e4d9799, 0xd2f5747d],
793 [0xe0278b0f, 0x3e4763d5, 0x88033344, 0xc9c2e6de],
794 [0xd962be7f, 0xafc1ac64, 0x0647cdcc, 0xd06465c6],
795 [0xedef0e19, 0xec75eed2, 0x955a2ae2, 0xd6145b4c],
796 [0x89ec8d4b, 0x3d446d74, 0xbd3d681d, 0x2d219dca],
797 [0x89e81643, 0x77fb2f1b, 0x2aa0782f, 0xb1b9b7ef],
798 [0xea283aec, 0x94d7cdf9, 0x961bbb69, 0x2b38162a],
799 [0x1d1b315c, 0x6613c5fa, 0xeff36485, 0x5025fbf2],
800 [0x4145c6a8, 0xd8d513b1, 0x34a5d353, 0x07750cd5],
801 [0xace12feb, 0x468754f3, 0xa72327f5, 0x1a6f6350],
802 [0x4b04dc0e, 0x684533a7, 0x6a4e4b16, 0x0b8a5e68],
803 [0xa3eb64fc, 0x5e02a31b, 0x6b484eae, 0xbb6e6c49],
804 [0x7d4ef46e, 0x6761c447, 0x02e002f5, 0x02d0231c]]));
805 // a sample from Civilization II
806 test_decoding("avi", "indeo4", "assets/Indeo/IV4/HRLDVIK.AVI", Some(8),
807 &dmx_reg, &dec_reg, ExpectedTestResult::MD5Frames(vec![
808 [0x239b8b87, 0x6dbec08c, 0x82bae1f0, 0x868e00c2],
809 [0xe2298beb, 0x4e08866d, 0x00cb6201, 0x6b0a6df3],
810 [0x9d7f4cf0, 0xed33df12, 0x2677be16, 0xce7e99b0],
811 [0x0c8d7489, 0x2b3ac56e, 0x36d75559, 0x70550903],
812 [0xc32b4b78, 0x2fc81737, 0xe4d7722b, 0xbcbbb35e],
813 [0x20bfd5e8, 0x6cfad540, 0xfc6c6b6c, 0xa4f39a7d],
814 [0xc327428d, 0x4e817b56, 0x4376eba2, 0xebafd04a],
815 [0x6a53a6ec, 0x7477a471, 0xd55bc98e, 0x7498de0f],
816 [0x398eba3a, 0x3cf3cce1, 0x90211dfe, 0x82c906f0]]));
817 }
818 }