1 use nihav_core::formats;
2 use nihav_core::codecs::*;
3 use nihav_core::io::byteio::*;
12 #[derive(Clone, Copy)]
27 const DEFAULT_PIXEL: u8 = 0x40;
30 fn new() -> Self { Buffers { width: 0, height: 0, cw: 0, ch: 0, sbuf: Vec::new(), dbuf: Vec::new() } }
37 fn alloc(&mut self, w: usize, h: usize) {
40 self.cw = ((w >> 2) + 3) & !3;
41 self.ch = ((h >> 2) + 3) & !3;
42 self.sbuf.resize(w * h + self.cw * self.ch * 2, DEFAULT_PIXEL);
43 self.dbuf.resize(w * h + self.cw * self.ch * 2, DEFAULT_PIXEL);
45 fn flip(&mut self) { std::mem::swap(&mut self.sbuf, &mut self.dbuf); }
46 fn get_stride(&mut self, planeno: usize) -> usize {
47 if planeno == 0 { self.width } else { self.cw }
49 fn get_offset(&mut self, planeno: usize) -> usize {
51 1 => self.width * self.height,
52 2 => self.width * self.height + self.cw * self.ch,
56 fn fill_framebuf(&mut self, fbuf: &mut NAVideoBuffer<u8>) {
58 let mut soff = self.get_offset(planeno);
59 let mut doff = fbuf.get_offset(planeno);
60 let sstride = self.get_stride(planeno);
61 let dstride = fbuf.get_stride(planeno);
62 let width = if planeno == 0 { self.width } else { self.width >> 2 };
63 let height = if planeno == 0 { self.height } else { self.height >> 2 };
64 let src = self.dbuf.as_slice();
65 let dst = fbuf.get_data_mut().unwrap();
68 dst[doff + x] = src[soff + x] * 2;
75 fn copy_block(&mut self, doff: usize, soff: usize, stride: usize, w: usize, h: usize) {
79 self.dbuf[didx..][..w].copy_from_slice(&self.sbuf[sidx..][..w]);
84 fn fill_block(&mut self, doff: usize, stride: usize, w: usize, h: usize, topline: bool) {
86 let mut buf: [u8; 8] = [0; 8];
89 for i in 0..w { self.dbuf[didx + i] = DEFAULT_PIXEL; }
93 for i in 0..w { buf[i] = self.dbuf[didx - stride + i]; }
95 self.dbuf[didx..][..w].copy_from_slice(&buf[..w]);
102 #[allow(unused_variables)]
103 fn apply_delta4x4(bufs: &mut Buffers, off: usize, stride: usize,
104 deltas: &[u8], topline: bool, first_line: bool) {
105 let dst = &mut bufs.dbuf[off..][..4];
106 for i in 0..4 { dst[i] = dst[i].wrapping_add(deltas[i]) & 0x7F; }
109 #[allow(unused_variables)]
110 fn apply_delta4x8(bufs: &mut Buffers, off: usize, stride: usize,
111 deltas: &[u8], topline: bool, first_line: bool) {
112 let dst = &mut bufs.dbuf[off..][..stride + 4];
113 for i in 0..4 { dst[i + stride] = dst[i].wrapping_add(deltas[i]) & 0x7F; }
115 for i in 0..4 { dst[i] = (dst[i + stride] + dst[i]) >> 1; }
117 for i in 0..4 { dst[i] = dst[i + stride]; }
121 #[allow(unused_variables)]
122 fn apply_delta4x8m11(bufs: &mut Buffers, off: usize, stride: usize,
123 deltas: &[u8], topline: bool, first_line: bool) {
124 let dst = &mut bufs.dbuf[off..][..stride + 4];
125 for i in 0..4 { dst[i] = dst[i] .wrapping_add(deltas[i]) & 0x7F; }
126 for i in 0..4 { dst[i + stride] = dst[i + stride].wrapping_add(deltas[i]) & 0x7F; }
129 #[allow(unused_variables)]
130 fn apply_delta8x8p(bufs: &mut Buffers, off: usize, stride: usize,
131 deltas: &[u8], topline: bool, first_line: bool) {
132 let dst = &mut bufs.dbuf[off..][..stride + 8];
133 for i in 0..8 { dst[i] = dst[i] .wrapping_add(deltas[i >> 1]) & 0x7F; }
134 for i in 0..8 { dst[i + stride] = dst[i + stride].wrapping_add(deltas[i >> 1]) & 0x7F; }
137 fn apply_delta8x8i(bufs: &mut Buffers, off: usize, stride: usize,
138 deltas: &[u8], topline: bool, firstline: bool) {
139 let dst = &mut bufs.dbuf[off..][..stride + 8];
141 for i in 0..8 { dst[i + stride] = dst[i ].wrapping_add(deltas[i >> 1]) & 0x7F; }
143 for i in 0..8 { dst[i + stride] = dst[i & !1].wrapping_add(deltas[i >> 1]) & 0x7F; }
146 for i in 0..8 { dst[i] = (dst[i + stride] + dst[i]) >> 1; }
148 for i in 0..8 { dst[i] = dst[i + stride]; }
152 fn copy_line_top(bufs: &mut Buffers, off: usize, stride: usize, bw: usize, topline: bool) {
153 let mut buf: [u8; 8] = [0; 8];
155 let src = &bufs.dbuf[(off - stride)..(off - stride + bw)];
156 buf[..bw].copy_from_slice(&src[..bw]);
158 for i in 0..bw { buf[i] = DEFAULT_PIXEL; }
160 let dst = &mut bufs.dbuf[off..][..bw];
161 dst.copy_from_slice(&buf[..bw]);
164 fn copy_line_top4x4(bufs: &mut Buffers, off: usize, stride: usize, topline: bool) {
165 copy_line_top(bufs, off, stride, 4, topline);
168 fn copy_line_top4x8(bufs: &mut Buffers, off: usize, stride: usize, topline: bool) {
169 copy_line_top(bufs, off, stride, 4, topline);
170 copy_line_top(bufs, off + stride, stride, 4, false);
173 fn copy_line_top8x8(bufs: &mut Buffers, off: usize, stride: usize, topline: bool) {
174 let mut buf: [u8; 8] = [0; 8];
176 let src = &bufs.dbuf[(off - stride)..(off - stride + 8)];
177 for i in 0..8 { buf[i] = src[i & !1]; }
179 for i in 0..8 { buf[i] = DEFAULT_PIXEL; }
181 let dst = &mut bufs.dbuf[off..][..8];
182 dst.copy_from_slice(&buf[..8]);
185 fn fill_block8x8(bufs: &mut Buffers, doff: usize, stride: usize, h: usize, topline: bool, firstline: bool) {
187 let mut buf: [u8; 8] = [0; 8];
189 for i in 0..8 { buf[i] = DEFAULT_PIXEL; }
191 for i in 0..8 { buf[i] = bufs.dbuf[doff - stride + i]; }
193 if topline && !firstline {
194 for i in 0..4 { buf[i * 2 + 1] = buf[i * 2]; }
195 for i in 0..8 { bufs.dbuf[doff + i] = (bufs.dbuf[doff - stride + i] + buf[i]) >> 1; }
198 let start = if !topline { 0 } else { 1 };
203 bufs.dbuf[didx..][..8].copy_from_slice(&buf[..8]);
208 struct Indeo3Decoder {
209 info: NACodecInfoRef,
218 requant_tab: [[u8; 128]; 8],
221 #[derive(Clone,Copy)]
233 fn new(w: u16, h: u16) -> Self {
234 IV3Cell { x: 0, y: 0, w, h, d: 20, vqt: false, mv: None }
236 fn split_h(&self) -> (Self, Self) {
237 let h1 = if self.h > 2 { ((self.h + 2) >> 2) << 1 } else { 1 };
238 let h2 = self.h - h1;
239 let mut cell1 = *self;
242 let mut cell2 = *self;
248 fn split_w(&self, stripw: u16) -> (Self, Self) {
249 let w1 = if self.w > stripw {
250 if self.w > stripw * 2 { stripw * 2 } else { stripw }
252 if self.w > 2 { ((self.w + 2) >> 2) << 1 } else { 1 }
254 let w2 = self.w - w1;
255 let mut cell1 = *self;
258 let mut cell2 = *self;
264 fn no_mv(&self) -> bool { self.mv.is_none() }
267 struct CellDecParams {
273 apply_delta: fn (&mut Buffers, usize, usize, &[u8], bool, bool),
274 copy_line_top: fn (&mut Buffers, usize, usize, bool),
277 const FRMH_TAG: u32 = ((b'F' as u32) << 24) | ((b'R' as u32) << 16)
278 | ((b'M' as u32) << 8) | (b'H' as u32);
280 const H_SPLIT: u8 = 0;
281 const V_SPLIT: u8 = 1;
282 const SKIP_OR_TREE: u8 = 2;
286 const REQUANT_OFF: [i32; 8] = [ 0, 1, 0, 4, 4, 1, 0, 1 ];
288 let dummy_info = NACodecInfo::new_dummy();
290 let mut requant_tab = [[0u8; 128]; 8];
292 let step = (i as i32) + 2;
293 let start = if (i == 3) || (i == 4) { -3 } else { step / 2 };
296 requant_tab[i][j] = (((j as i32) + start) / step * step + REQUANT_OFF[i]) as u8;
297 if requant_tab[i][j] < 128 {
298 last = requant_tab[i][j];
300 requant_tab[i][j] = last;
304 requant_tab[1][7] = 10;
305 requant_tab[1][119] = 118;
306 requant_tab[1][120] = 118;
307 requant_tab[4][8] = 10;
309 Indeo3Decoder { info: dummy_info, bpos: 0, bbuf: 0, width: 0, height: 0,
310 mvs: Vec::new(), altquant: [0; 16],
311 vq_offset: 0, bufs: Buffers::new(), requant_tab }
314 fn br_reset(&mut self) {
319 fn get_2bits(&mut self, br: &mut ByteReader) -> DecoderResult<u8> {
321 self.bbuf = br.read_byte()?;
325 Ok((self.bbuf >> self.bpos) & 0x3)
328 #[allow(clippy::cognitive_complexity)]
329 fn decode_cell_data(&mut self, br: &mut ByteReader, cell: IV3Cell,
330 off: usize, stride: usize, params: CellDecParams, vq_idx: u8) -> DecoderResult<()> {
331 let blk_w = cell.w * 4 / params.bw;
332 let blk_h = cell.h * 4 / params.bh;
333 let scale: usize = if params.bh == 4 { 1 } else { 2 };
335 validate!((((cell.w * 4) % params.bw) == 0) && (((cell.h * 4) % params.bh) == 0));
337 let mut run_blocks = 0;
338 let mut run_skip = false;
340 let mut didx: usize = ((cell.x*4) as usize) + ((cell.y * 4) as usize) * stride + off;
346 let mv = cell.mv.unwrap();
347 let mx = i16::from(mv.x);
348 let my = i16::from(mv.y);
349 let l = (cell.x as i16) * 4 + mx;
350 let t = (cell.y as i16) * 4 + my;
351 let r = ((cell.x + cell.w) as i16) * 4 + mx;
352 let b = ((cell.y + cell.h) as i16) * 4 + my;
355 validate!(r <= (self.width as i16));
356 validate!(b <= (self.height as i16));
357 sidx = (l as usize) + (t as usize) * stride + off;
360 let requant_tab = &self.requant_tab[(vq_idx & 7) as usize];
363 for x in 0..(cell.w as usize) * 4 {
364 self.bufs.dbuf[didx + x - stride] = requant_tab[self.bufs.dbuf[didx + x - stride] as usize];
368 for x in 0..(cell.w as usize) * 4 {
369 self.bufs.sbuf[sidx + x] = requant_tab[self.bufs.sbuf[sidx + x] as usize];
374 let mut xoff: usize = 0;
377 if !run_skip || !cell.no_mv() {
378 if !(params.bw == 8 && cell.no_mv()) {
380 self.bufs.copy_block(didx + xoff, sidx + xoff, stride,
381 params.bw as usize, params.bh as usize);
383 self.bufs.fill_block(didx + xoff, stride,
384 params.bw as usize, params.bh as usize,
385 (cell.y == 0) && (y == 0));
388 fill_block8x8(&mut self.bufs,
389 didx + xoff, stride, 8,
390 y == 0, (cell.y == 0) && (y == 0));
395 let mut line: usize = 0;
397 let c = br.read_byte()?;
399 let delta_tab = if params.hq {
400 IVI3_DELTA_CBS[params.tab[line & 1]]
402 IVI3_DELTA_CBS[params.tab[1]]
406 if (c as usize) < delta_tab.data.len()/2 {
407 idx1 = br.read_byte()? as usize;
408 validate!(idx1 < delta_tab.data.len() / 2);
411 let tmp = (c as usize) - delta_tab.data.len()/2;
412 idx1 = tmp / (delta_tab.quad_radix as usize);
413 idx2 = tmp % (delta_tab.quad_radix as usize);
414 if params.swap_q[line & 1] {
415 mem::swap(&mut idx1, &mut idx2);
418 let deltas: [u8; 4] = [delta_tab.data[idx1 * 2] as u8,
419 delta_tab.data[idx1 * 2 + 1] as u8,
420 delta_tab.data[idx2 * 2 + 0] as u8,
421 delta_tab.data[idx2 * 2 + 1] as u8];
422 let topline = (cell.y == 0) && (y == 0) && (line == 0);
423 let first_line = (y == 0) && (line == 0);
425 (params.copy_line_top)(&mut self.bufs,
426 didx + xoff + line * scale * stride,
429 self.bufs.copy_block(didx + xoff + line * scale * stride,
430 sidx + xoff + line * scale * stride,
431 stride, params.bw as usize, scale);
433 (params.apply_delta)(&mut self.bufs,
434 didx + xoff + line * scale * stride,
435 stride, &deltas, topline, first_line);
438 let mut tocopy: usize = 0;
439 let mut do_copy = true;
440 if c == 0xF8 { return Err(DecoderError::InvalidData); }
444 validate!(line == 0);
446 do_copy = !cell.no_mv();
449 validate!(line == 0);
451 do_copy = !cell.no_mv();
454 let c = br.read_byte()?;
455 validate!((c < 64) && ((c & 0x1F) != 0));
456 run_blocks = (c & 0x1F) - 1;
457 run_skip = (c & 0x20) != 0;
459 if params.bw == 4 && cell.no_mv() && run_skip {
469 let nl = 257 - i16::from(c) - (line as i16);
471 tocopy = nl as usize;
474 if !(params.bh == 8 && cell.no_mv()) {
476 self.bufs.copy_block(didx + xoff + line * scale * stride,
477 sidx + xoff + line * scale * stride,
478 stride, params.bw as usize,
481 self.bufs.fill_block(didx + xoff + line * scale * stride,
482 stride, params.bw as usize,
484 (cell.y == 0) && (y == 0) && (line == 0));
487 fill_block8x8(&mut self.bufs,
488 didx + xoff + line * 2 * stride,
490 (y == 0) && (line == 0),
491 (cell.y == 0) && (y == 0) && (line == 0));
498 xoff += params.bw as usize;
500 didx += stride * (params.bh as usize);
501 sidx += stride * (params.bh as usize);
506 fn copy_cell(&mut self, cell: IV3Cell, off: usize, stride: usize) -> DecoderResult<()> {
507 if cell.no_mv() { return Err(DecoderError::InvalidData); }
508 let mv = cell.mv.unwrap();
509 let mx = i16::from(mv.x);
510 let my = i16::from(mv.y);
511 let l = (cell.x as i16) * 4 + mx;
512 let t = (cell.y as i16) * 4 + my;
513 let r = ((cell.x + cell.w) as i16) * 4 + mx;
514 let b = ((cell.y + cell.h) as i16) * 4 + my;
517 validate!(r <= (self.width as i16));
518 validate!(b <= (self.height as i16));
519 let sidx: usize = off + (l as usize) + (t as usize) * stride;
520 let didx: usize = off + ((cell.x * 4) as usize) + ((cell.y * 4) as usize) * stride;
521 self.bufs.copy_block(didx, sidx, stride, (cell.w * 4) as usize, (cell.h * 4) as usize);
525 fn decode_cell(&mut self, br: &mut ByteReader, cell: IV3Cell, off: usize,
526 stride: usize, intra: bool) -> DecoderResult<()> {
527 let code = br.read_byte()?;
528 let mode = code >> 4;
529 let vq_idx = code & 0xF;
531 let mut idx1: usize = vq_idx as usize;
532 let mut idx2: usize = vq_idx as usize;
533 if (mode == 1) || (mode == 4) {
534 let c = self.altquant[vq_idx as usize];
535 idx1 = (c >> 4) as usize;
536 idx2 = (c & 0xF) as usize;
538 idx1 += self.vq_offset as usize;
539 idx2 += self.vq_offset as usize;
541 validate!((idx1 < 24) && (idx2 < 24));
543 let mut cp = CellDecParams {
546 swap_q: [idx2 >= 16, idx1 >= 16],
548 apply_delta: apply_delta4x4,
549 copy_line_top: copy_line_top4x4,
551 if (mode == 0) || (mode == 1) {
555 } else if (mode == 3) || (mode == 4) {
556 if !cell.no_mv() { return Err(DecoderError::InvalidData); }
560 cp.apply_delta = apply_delta4x8;
561 cp.copy_line_top = copy_line_top4x8;
562 } else if mode == 10 {
565 cp.apply_delta = apply_delta8x8p;
567 cp.apply_delta = apply_delta8x8i;
571 cp.copy_line_top = copy_line_top8x8;
572 } else if mode == 11 {
573 if cell.no_mv() { return Err(DecoderError::InvalidData); }
577 cp.apply_delta = apply_delta4x8m11;
578 cp.copy_line_top = copy_line_top4x8;
580 return Err(DecoderError::InvalidData);
582 self.decode_cell_data(br, cell, off, stride, cp, vq_idx)
585 fn parse_tree(&mut self, br: &mut ByteReader, cell: IV3Cell, off: usize,
586 stride: usize, stripw: u16, intra: bool) -> DecoderResult<()> {
587 let op = self.get_2bits(br)?;
589 validate!(cell.h > 1);
590 validate!(cell.d > 0);
591 let (cell1, cell2) = cell.split_h();
592 self.parse_tree(br, cell1, off, stride, stripw, intra)?;
593 self.parse_tree(br, cell2, off, stride, stripw, intra)?;
595 } else if op == V_SPLIT {
596 validate!(cell.w > 1);
597 validate!(cell.d > 0);
598 let (cell1, cell2) = cell.split_w(stripw);
599 self.parse_tree(br, cell1, off, stride, stripw, intra)?;
600 self.parse_tree(br, cell2, off, stride, stripw, intra)?;
602 } else if op == SKIP_OR_TREE {
604 let mut newcell = cell;
607 self.parse_tree(br, newcell, off, stride, stripw, intra)
610 let code = self.get_2bits(br)?;
612 if code == 1 { return Err(DecoderError::NotImplemented); }
613 self.copy_cell(cell, off, stride)
617 let mut newcell = cell;
620 let mv_idx = br.read_byte()? as usize;
621 validate!(mv_idx < self.mvs.len());
622 newcell.mv = Some(self.mvs[mv_idx]);
623 self.parse_tree(br, newcell, off, stride, stripw, intra)
625 self.decode_cell(br, cell, off, stride, intra)
630 fn decode_plane_intra(&mut self, br: &mut ByteReader, planeno: usize,
631 start: u64, end: u64) -> DecoderResult<()> {
632 let offs = self.bufs.get_offset(planeno);
633 let stride = self.bufs.get_stride(planeno);
634 br.seek(SeekFrom::Start(start))?;
636 let nvec = br.read_u32le()?;
637 validate!(nvec == 0); // for intra there should be no mc_vecs
640 let x = br.read_byte()? as i8;
641 let y = br.read_byte()? as i8;
642 self.mvs.push(MV{ x, y });
645 let (cellwidth, cellheight) = if planeno == 0 {
646 (self.bufs.width >> 2, self.bufs.height >> 2)
648 (((self.bufs.width >> 2) + 3) >> 2, ((self.bufs.height >> 2) + 3) >> 2)
650 let cell = IV3Cell::new(cellwidth as u16, cellheight as u16);
652 self.parse_tree(br, cell, offs, stride, if planeno > 0 { 10 } else { 40 }, true)?;
653 validate!(br.tell() <= end);
657 fn decode_plane_inter(&mut self, br: &mut ByteReader, planeno: usize,
658 start: u64, end: u64) -> DecoderResult<()> {
659 let offs = self.bufs.get_offset(planeno);
660 let stride = self.bufs.get_stride(planeno);
661 br.seek(SeekFrom::Start(start))?;
663 let nvec = br.read_u32le()?;
664 validate!(nvec <= 256); // for intra there should be no mc_vecs
667 let y = br.read_byte()? as i8;
668 let x = br.read_byte()? as i8;
669 self.mvs.push(MV{ x, y });
672 let (cellwidth, cellheight) = if planeno == 0 {
673 (self.bufs.width >> 2, self.bufs.height >> 2)
675 (((self.bufs.width >> 2) + 3) >> 2, ((self.bufs.height >> 2) + 3) >> 2)
677 let cell = IV3Cell::new(cellwidth as u16, cellheight as u16);
679 self.parse_tree(br, cell, offs, stride, if planeno > 0 { 10 } else { 40 }, false)?;
680 validate!(br.tell() <= end);
685 const FLAG_KEYFRAME: u16 = 1 << 2;
686 const FLAG_NONREF: u16 = 1 << 8;
688 impl NADecoder for Indeo3Decoder {
689 fn init(&mut self, _supp: &mut NADecoderSupport, info: NACodecInfoRef) -> DecoderResult<()> {
690 if let NACodecTypeInfo::Video(vinfo) = info.get_properties() {
691 let w = vinfo.get_width();
692 let h = vinfo.get_height();
693 let fmt = formats::YUV410_FORMAT;
694 let myinfo = NACodecTypeInfo::Video(NAVideoInfo::new(w, h, false, fmt));
695 self.info = NACodecInfo::new_ref(info.get_name(), myinfo, info.get_extradata()).into_ref();
699 Err(DecoderError::InvalidData)
702 fn decode(&mut self, _supp: &mut NADecoderSupport, pkt: &NAPacket) -> DecoderResult<NAFrameRef> {
703 let src = pkt.get_buffer();
704 let mut mr = MemoryReader::new_read(&src);
705 let mut br = ByteReader::new(&mut mr);
706 let frameno = br.read_u32le()?;
707 let hdr_2 = br.read_u32le()?;
708 let check = br.read_u32le()?;
709 let size = br.read_u32le()?;
711 let data_start = br.tell();
713 if (frameno ^ hdr_2 ^ size ^ FRMH_TAG) != check {
714 return Err(DecoderError::InvalidData);
716 if i64::from(size) > br.left() { return Err(DecoderError::InvalidData); }
717 let ver = br.read_u16le()?;
718 if ver != 32 { return Err(DecoderError::NotImplemented); }
719 let flags = br.read_u16le()?;
720 let size2 = br.read_u32le()?;
722 let mut frm = NAFrame::new_from_pkt(pkt, self.info.clone(), NABufferType::None);
723 frm.set_keyframe(false);
724 frm.set_frame_type(FrameType::Skip);
725 return Ok(frm.into_ref());
727 validate!(((size2 + 7) >> 3) <= size);
728 let cb = br.read_byte()?;
731 let height = br.read_u16le()?;
732 let width = br.read_u16le()?;
733 validate!((width >= 16) && (width <= 640));
734 validate!((height >= 16) && (height <= 640));
735 validate!(((width & 3) == 0) && ((height & 3) == 0));
737 if (self.bufs.width != (width as usize)) || (self.bufs.height != (height as usize)) {
738 self.bufs.alloc(width as usize, height as usize);
739 vinfo = NAVideoInfo::new(width as usize, height as usize, false, formats::YUV410_FORMAT);
741 vinfo = self.info.get_properties().get_video_info().unwrap();
744 self.height = height;
746 let yoff = br.read_u32le()?;
747 let uoff = br.read_u32le()?;
748 let voff = br.read_u32le()?;
749 if yoff > size { return Err(DecoderError::InvalidData); }
750 if uoff > size { return Err(DecoderError::InvalidData); }
751 if voff > size { return Err(DecoderError::InvalidData); }
754 br.read_buf(&mut self.altquant)?;
756 let mut yend = src.len() as u32;//size;
757 if (uoff < yend) && (uoff > yoff) { yend = uoff; }
758 if (voff < yend) && (voff > yoff) { yend = voff; }
760 if (yoff < uend) && (yoff > uoff) { uend = yoff; }
761 if (voff < uend) && (voff > uoff) { uend = voff; }
763 if (yoff < vend) && (yoff > voff) { vend = yoff; }
764 if (uoff < vend) && (uoff > voff) { vend = uoff; }
766 let intraframe = (flags & FLAG_KEYFRAME) != 0;
767 let bufinfo = alloc_video_buffer(vinfo, 4)?;
768 let mut buf = bufinfo.get_vbuf().unwrap();
769 let ystart = data_start + u64::from(yoff);
770 let ustart = data_start + u64::from(uoff);
771 let vstart = data_start + u64::from(voff);
772 let yendpos = data_start + u64::from(yend);
773 let uendpos = data_start + u64::from(uend);
774 let vendpos = data_start + u64::from(vend);
776 self.decode_plane_intra(&mut br, 0, ystart, yendpos)?;
777 self.decode_plane_intra(&mut br, 1, vstart, vendpos)?;
778 self.decode_plane_intra(&mut br, 2, ustart, uendpos)?;
780 self.decode_plane_inter(&mut br, 0, ystart, yendpos)?;
781 self.decode_plane_inter(&mut br, 1, vstart, vendpos)?;
782 self.decode_plane_inter(&mut br, 2, ustart, uendpos)?;
784 self.bufs.fill_framebuf(&mut buf);
785 if (flags & FLAG_NONREF) == 0 { self.bufs.flip(); }
786 let mut frm = NAFrame::new_from_pkt(pkt, self.info.clone(), bufinfo);
787 frm.set_keyframe(intraframe);
788 frm.set_frame_type(if intraframe { FrameType::I } else { FrameType::P });
791 fn flush(&mut self) {
796 impl NAOptionHandler for Indeo3Decoder {
797 fn get_supported_options(&self) -> &[NAOptionDefinition] { &[] }
798 fn set_options(&mut self, _options: &[NAOption]) { }
799 fn query_option_value(&self, _name: &str) -> Option<NAValue> { None }
802 pub fn get_decoder() -> Box<dyn NADecoder + Send> {
803 Box::new(Indeo3Decoder::new())
808 use nihav_core::codecs::RegisteredDecoders;
809 use nihav_core::demuxers::RegisteredDemuxers;
810 use nihav_codec_support::test::dec_video::*;
811 use crate::indeo_register_all_decoders;
812 use nihav_commonfmt::generic_register_all_demuxers;
815 let mut dmx_reg = RegisteredDemuxers::new();
816 generic_register_all_demuxers(&mut dmx_reg);
817 let mut dec_reg = RegisteredDecoders::new();
818 indeo_register_all_decoders(&mut dec_reg);
820 // sample: https://samples.mplayerhq.hu/V-codecs/IV32/iv32_example.avi
821 test_decoding("avi", "indeo3", "assets/Indeo/iv32_example.avi", Some(10),
822 &dmx_reg, &dec_reg, ExpectedTestResult::MD5Frames(vec![
823 [0x90be698e, 0x326db071, 0x08e8c6a5, 0x39349acc],
824 [0x25d677fc, 0x63f96aaa, 0xd412ca98, 0x61416313],
825 [0xc4368250, 0x63e7b6bc, 0xffcff950, 0x11f13239],
826 [0x7e869758, 0x027abc2e, 0x25204bca, 0x93fbaa03],
827 [0x5a1e822c, 0x2b1a4cd5, 0x72059843, 0xe5689ad1],
828 [0x3a971cce, 0x5ec22135, 0x1a45f802, 0x0f5f9264],
829 [0x0a65f782, 0xd8767cf3, 0x878b4b8d, 0xfc94c88b],
830 [0x4ac70139, 0x3300eac1, 0xba84b068, 0x47f5ff29],
831 [0x3e8c8ec4, 0x9421b38c, 0x580abbbd, 0x92792d19],
832 [0x9096ee9b, 0x8dd9fb14, 0x981e31e3, 0x3ffd7d29],
833 [0x22dc71ec, 0x3d8f6f7e, 0x1a198982, 0x41d17ecc]]));
837 const DT_1_1: IviDeltaCB = IviDeltaCB{ quad_radix: 7, data: &[
838 0, 0, 2, 2, -2, -2, -1, 3,
839 1, -3, 3, -1, -3, 1, 4, 4,
840 -4, -4, 1, 5, -1, -5, 5, 1,
841 -5, -1, -4, 4, 4, -4, -2, 6,
842 2, -6, 6, -2, -6, 2, 4, 9,
843 -4, -9, 9, 4, -9, -4, 9, 9,
844 -9, -9, 1, 10, -1, -10, 10, 1,
845 -10, -1, -5, 8, 5, -8, 8, -5,
846 -8, 5, 9, 15, -9, -15, 15, 9,
847 -15, -9, -3, 12, 3, -12, 12, -3,
848 -12, 3, 4, 16, -4, -16, 16, 4,
849 -16, -4, 16, 16, -16, -16, 0, 18,
850 0, -18, 18, 0, -18, 0, -12, 12,
851 12, -12, -9, 16, 9, -16, 16, -9,
852 -16, 9, 11, 27, -11, -27, 27, 11,
853 -27, -11, 19, 28, -19, -28, 28, 19,
854 -28, -19, -6, 22, 6, -22, 22, -6,
855 -22, 6, 4, 29, -4, -29, 29, 4,
856 -29, -4, 30, 30, -30, -30, -2, 33,
857 2, -33, 33, -2, -33, 2, -18, 23,
858 18, -23, 23, -18, -23, 18, -15, 30,
859 15, -30, 30, -15, -30, 15, 22, 46,
860 -22, -46, 46, 22, -46, -22, 13, 47,
861 -13, -47, 47, 13, -47, -13, 35, 49,
862 -35, -49, 49, 35, -49, -35, -11, 41,
863 11, -41, 41, -11, -41, 11, 4, 51,
864 -4, -51, 51, 4, -51, -4, 54, 54,
865 -54, -54, -34, 34, 34, -34, -29, 42,
866 29, -42, 42, -29, -42, 29, -6, 60,
867 6, -60, 60, -6, -60, 6, 27, 76,
868 -27, -76, 76, 27, -76, -27, 43, 77,
869 -43, -77, 77, 43, -77, -43, -24, 55,
870 24, -55, 55, -24, -55, 24, 14, 79,
871 -14, -79, 79, 14, -79, -14, 63, 83,
872 -63, -83, 83, 63, -83, -63, -20, 74,
873 20, -74, 74, -20, -74, 20, 2, 88,
874 -2, -88, 88, 2, -88, -2, 93, 93,
875 -93, -93, -52, 61, 52, -61, 61, -52,
876 -61, 52, 52, 120, -52, -120, 120, 52,
877 -120, -52, -45, 75, 45, -75, 75, -45,
878 -75, 45, 75, 125, -75, -125, 125, 75,
879 -125, -75, 33, 122, -33, -122, 122, 33,
880 -122, -33, -13, 103, 13, -103, 103, -13,
881 -103, 13, -40, 96, 40, -96, 96, -40,
882 -96, 40, -34, 127, 34, -127, 127, -34,
883 -127, 34, -89, 89, 89, -89, -78, 105,
884 78, -105, 105, -78, -105, 78, 12, 12,
885 -12, -12, 23, 23, -23, -23, 42, 42,
886 -42, -42, 73, 73, -73, -73,
889 const DT_1_2: IviDeltaCB = IviDeltaCB{ quad_radix: 9, data: &[
890 0, 0, 3, 3, -3, -3, -1, 4,
891 1, -4, 4, -1, -4, 1, 7, 7,
892 -7, -7, 2, 8, -2, -8, 8, 2,
893 -8, -2, -2, 9, 2, -9, 9, -2,
894 -9, 2, -6, 6, 6, -6, 6, 13,
895 -6, -13, 13, 6, -13, -6, 13, 13,
896 -13, -13, 1, 14, -1, -14, 14, 1,
897 -14, -1, -8, 12, 8, -12, 12, -8,
898 -12, 8, 14, 23, -14, -23, 23, 14,
899 -23, -14, -5, 18, 5, -18, 18, -5,
900 -18, 5, 6, 24, -6, -24, 24, 6,
901 -24, -6, 24, 24, -24, -24, -1, 27,
902 1, -27, 27, -1, -27, 1, -17, 17,
903 17, -17, -13, 23, 13, -23, 23, -13,
904 -23, 13, 16, 40, -16, -40, 40, 16,
905 -40, -16, 28, 41, -28, -41, 41, 28,
906 -41, -28, -9, 33, 9, -33, 33, -9,
907 -33, 9, 6, 43, -6, -43, 43, 6,
908 -43, -6, 46, 46, -46, -46, -4, 50,
909 4, -50, 50, -4, -50, 4, -27, 34,
910 27, -34, 34, -27, -34, 27, -22, 45,
911 22, -45, 45, -22, -45, 22, 34, 69,
912 -34, -69, 69, 34, -69, -34, 19, 70,
913 -19, -70, 70, 19, -70, -19, 53, 73,
914 -53, -73, 73, 53, -73, -53, -17, 62,
915 17, -62, 62, -17, -62, 17, 5, 77,
916 -5, -77, 77, 5, -77, -5, 82, 82,
917 -82, -82, -51, 51, 51, -51, -43, 64,
918 43, -64, 64, -43, -64, 43, -10, 90,
919 10, -90, 90, -10, -90, 10, 41, 114,
920 -41, -114, 114, 41, -114, -41, 64, 116,
921 -64, -116, 116, 64, -116, -64, -37, 82,
922 37, -82, 82, -37, -82, 37, 22, 119,
923 -22, -119, 119, 22, -119, -22, 95, 124,
924 -95, -124, 124, 95, -124, -95, -30, 111,
925 30, -111, 111, -30, -111, 30, -78, 92,
926 78, -92, 92, -78, -92, 78, -68, 113,
927 68, -113, 113, -68, -113, 68, 18, 18,
928 -18, -18, 34, 34, -34, -34, 63, 63,
929 -63, -63, 109, 109, -109, -109,
932 const DT_1_3: IviDeltaCB = IviDeltaCB{ quad_radix: 10, data: &[
933 0, 0, 4, 4, -4, -4, -1, 5,
934 1, -5, 5, -1, -5, 1, 3, 10,
935 -3, -10, 10, 3, -10, -3, 9, 9,
936 -9, -9, -7, 7, 7, -7, -3, 12,
937 3, -12, 12, -3, -12, 3, 8, 17,
938 -8, -17, 17, 8, -17, -8, 17, 17,
939 -17, -17, 1, 19, -1, -19, 19, 1,
940 -19, -1, -11, 16, 11, -16, 16, -11,
941 -16, 11, -6, 23, 6, -23, 23, -6,
942 -23, 6, 18, 31, -18, -31, 31, 18,
943 -31, -18, 8, 32, -8, -32, 32, 8,
944 -32, -8, 33, 33, -33, -33, -1, 36,
945 1, -36, 36, -1, -36, 1, -23, 23,
946 23, -23, -17, 31, 17, -31, 31, -17,
947 -31, 17, 21, 54, -21, -54, 54, 21,
948 -54, -21, 37, 55, -37, -55, 55, 37,
949 -55, -37, -12, 44, 12, -44, 44, -12,
950 -44, 12, 8, 57, -8, -57, 57, 8,
951 -57, -8, 61, 61, -61, -61, -5, 66,
952 5, -66, 66, -5, -66, 5, -36, 45,
953 36, -45, 45, -36, -45, 36, -29, 60,
954 29, -60, 60, -29, -60, 29, 45, 92,
955 -45, -92, 92, 45, -92, -45, 25, 93,
956 -25, -93, 93, 25, -93, -25, 71, 97,
957 -71, -97, 97, 71, -97, -71, -22, 83,
958 22, -83, 83, -22, -83, 22, 7, 102,
959 -7, -102, 102, 7, -102, -7, 109, 109,
960 -109, -109, -68, 68, 68, -68, -57, 85,
961 57, -85, 85, -57, -85, 57, -13, 120,
962 13, -120, 120, -13, -120, 13, -49, 110,
963 49, -110, 110, -49, -110, 49, -104, 123,
964 104, -123, 123, -104, -123, 104, 24, 24,
965 -24, -24, 46, 46, -46, -46, 84, 84,
969 const DT_1_4: IviDeltaCB = IviDeltaCB{ quad_radix: 11, data: &[
970 0, 0, 5, 5, -5, -5, -2, 7,
971 2, -7, 7, -2, -7, 2, 11, 11,
972 -11, -11, 3, 13, -3, -13, 13, 3,
973 -13, -3, -9, 9, 9, -9, -4, 15,
974 4, -15, 15, -4, -15, 4, 11, 22,
975 -11, -22, 22, 11, -22, -11, 21, 21,
976 -21, -21, 2, 24, -2, -24, 24, 2,
977 -24, -2, -14, 20, 14, -20, 20, -14,
978 -20, 14, 23, 38, -23, -38, 38, 23,
979 -38, -23, -8, 29, 8, -29, 29, -8,
980 -29, 8, 11, 39, -11, -39, 39, 11,
981 -39, -11, 41, 41, -41, -41, -1, 45,
982 1, -45, 45, -1, -45, 1, -29, 29,
983 29, -29, -22, 39, 22, -39, 39, -22,
984 -39, 22, 27, 67, -27, -67, 67, 27,
985 -67, -27, 47, 69, -47, -69, 69, 47,
986 -69, -47, -15, 56, 15, -56, 56, -15,
987 -56, 15, 11, 71, -11, -71, 71, 11,
988 -71, -11, 76, 76, -76, -76, -6, 83,
989 6, -83, 83, -6, -83, 6, -45, 57,
990 45, -57, 57, -45, -57, 45, -36, 75,
991 36, -75, 75, -36, -75, 36, 56, 115,
992 -56, -115, 115, 56, -115, -56, 31, 117,
993 -31, -117, 117, 31, -117, -31, 88, 122,
994 -88, -122, 122, 88, -122, -88, -28, 104,
995 28, -104, 104, -28, -104, 28, -85, 85,
996 85, -85, -72, 106, 72, -106, 106, -72,
997 -106, 72, 30, 30, -30, -30, 58, 58,
998 -58, -58, 105, 105, -105, -105,
1001 const DT_1_5: IviDeltaCB = IviDeltaCB{ quad_radix: 12, data: &[
1002 0, 0, 6, 6, -6, -6, -2, 8,
1003 2, -8, 8, -2, -8, 2, 13, 13,
1004 -13, -13, 4, 15, -4, -15, 15, 4,
1005 -15, -4, -11, 11, 11, -11, -5, 18,
1006 5, -18, 18, -5, -18, 5, 13, 26,
1007 -13, -26, 26, 13, -26, -13, 26, 26,
1008 -26, -26, 2, 29, -2, -29, 29, 2,
1009 -29, -2, -16, 24, 16, -24, 24, -16,
1010 -24, 16, 28, 46, -28, -46, 46, 28,
1011 -46, -28, -9, 35, 9, -35, 35, -9,
1012 -35, 9, 13, 47, -13, -47, 47, 13,
1013 -47, -13, 49, 49, -49, -49, -1, 54,
1014 1, -54, 54, -1, -54, 1, -35, 35,
1015 35, -35, -26, 47, 26, -47, 47, -26,
1016 -47, 26, 32, 81, -32, -81, 81, 32,
1017 -81, -32, 56, 83, -56, -83, 83, 56,
1018 -83, -56, -18, 67, 18, -67, 67, -18,
1019 -67, 18, 13, 86, -13, -86, 86, 13,
1020 -86, -13, 91, 91, -91, -91, -7, 99,
1021 7, -99, 99, -7, -99, 7, -54, 68,
1022 54, -68, 68, -54, -68, 54, -44, 90,
1023 44, -90, 90, -44, -90, 44, -33, 124,
1024 33, -124, 124, -33, -124, 33, -103, 103,
1025 103, -103, -86, 127, 86, -127, 127, -86,
1026 -127, 86, 37, 37, -37, -37, 69, 69,
1030 const DT_1_6: IviDeltaCB = IviDeltaCB{ quad_radix: 12, data: &[
1031 0, 0, 7, 7, -7, -7, -3, 10,
1032 3, -10, 10, -3, -10, 3, 16, 16,
1033 -16, -16, 5, 18, -5, -18, 18, 5,
1034 -18, -5, -13, 13, 13, -13, -6, 21,
1035 6, -21, 21, -6, -21, 6, 15, 30,
1036 -15, -30, 30, 15, -30, -15, 30, 30,
1037 -30, -30, 2, 34, -2, -34, 34, 2,
1038 -34, -2, -19, 28, 19, -28, 28, -19,
1039 -28, 19, 32, 54, -32, -54, 54, 32,
1040 -54, -32, -11, 41, 11, -41, 41, -11,
1041 -41, 11, 15, 55, -15, -55, 55, 15,
1042 -55, -15, 57, 57, -57, -57, -1, 63,
1043 1, -63, 63, -1, -63, 1, -40, 40,
1044 40, -40, -30, 55, 30, -55, 55, -30,
1045 -55, 30, 37, 94, -37, -94, 94, 37,
1046 -94, -37, 65, 96, -65, -96, 96, 65,
1047 -96, -65, -21, 78, 21, -78, 78, -21,
1048 -78, 21, 15, 100, -15, -100, 100, 15,
1049 -100, -15, 106, 106, -106, -106, -8, 116,
1050 8, -116, 116, -8, -116, 8, -63, 79,
1051 63, -79, 79, -63, -79, 63, -51, 105,
1052 51, -105, 105, -51, -105, 51, -120, 120,
1053 120, -120, 43, 43, -43, -43, 80, 80,
1057 const DT_1_7: IviDeltaCB = IviDeltaCB{ quad_radix: 12, data: &[
1058 0, 0, 8, 8, -8, -8, -3, 11,
1059 3, -11, 11, -3, -11, 3, 18, 18,
1060 -18, -18, 5, 20, -5, -20, 20, 5,
1061 -20, -5, -15, 15, 15, -15, -7, 24,
1062 7, -24, 24, -7, -24, 7, 17, 35,
1063 -17, -35, 35, 17, -35, -17, 34, 34,
1064 -34, -34, 3, 38, -3, -38, 38, 3,
1065 -38, -3, -22, 32, 22, -32, 32, -22,
1066 -32, 22, 37, 61, -37, -61, 61, 37,
1067 -61, -37, -13, 47, 13, -47, 47, -13,
1068 -47, 13, 17, 63, -17, -63, 63, 17,
1069 -63, -17, 65, 65, -65, -65, -1, 72,
1070 1, -72, 72, -1, -72, 1, -46, 46,
1071 46, -46, -35, 63, 35, -63, 63, -35,
1072 -63, 35, 43, 107, -43, -107, 107, 43,
1073 -107, -43, 75, 110, -75, -110, 110, 75,
1074 -110, -75, -24, 89, 24, -89, 89, -24,
1075 -89, 24, 17, 114, -17, -114, 114, 17,
1076 -114, -17, 121, 121, -121, -121, -72, 91,
1077 72, -91, 91, -72, -91, 72, -58, 120,
1078 58, -120, 120, -58, -120, 58, 49, 49,
1079 -49, -49, 92, 92, -92, -92,
1082 const DT_1_8: IviDeltaCB = IviDeltaCB{ quad_radix: 13, data: &[
1083 0, 0, 9, 9, -9, -9, -3, 12,
1084 3, -12, 12, -3, -12, 3, 20, 20,
1085 -20, -20, 6, 23, -6, -23, 23, 6,
1086 -23, -6, -17, 17, 17, -17, -7, 27,
1087 7, -27, 27, -7, -27, 7, 19, 39,
1088 -19, -39, 39, 19, -39, -19, 39, 39,
1089 -39, -39, 3, 43, -3, -43, 43, 3,
1090 -43, -3, -24, 36, 24, -36, 36, -24,
1091 -36, 24, 42, 69, -42, -69, 69, 42,
1092 -69, -42, -14, 53, 14, -53, 53, -14,
1093 -53, 14, 19, 71, -19, -71, 71, 19,
1094 -71, -19, 73, 73, -73, -73, -2, 80,
1095 2, -80, 80, -2, -80, 2, -52, 52,
1096 52, -52, -39, 70, 39, -70, 70, -39,
1097 -70, 39, 48, 121, -48, -121, 121, 48,
1098 -121, -48, 84, 124, -84, -124, 124, 84,
1099 -124, -84, -27, 100, 27, -100, 100, -27,
1100 -100, 27, -81, 102, 81, -102, 102, -81,
1101 -102, 81, 55, 55, -55, -55, 104, 104,
1105 const DT_2_1: IviDeltaCB = IviDeltaCB{ quad_radix: 7, data: &[
1106 0, 0, 2, 2, -2, -2, 0, 2,
1107 0, -2, 2, 0, -2, 0, 4, 4,
1108 -4, -4, 0, 4, 0, -4, 4, 0,
1109 -4, 0, -4, 4, 4, -4, -2, 6,
1110 2, -6, 6, -2, -6, 2, 4, 8,
1111 -4, -8, 8, 4, -8, -4, 8, 8,
1112 -8, -8, 0, 10, 0, -10, 10, 0,
1113 -10, 0, -4, 8, 4, -8, 8, -4,
1114 -8, 4, 8, 14, -8, -14, 14, 8,
1115 -14, -8, -2, 12, 2, -12, 12, -2,
1116 -12, 2, 4, 16, -4, -16, 16, 4,
1117 -16, -4, 16, 16, -16, -16, 0, 18,
1118 0, -18, 18, 0, -18, 0, -12, 12,
1119 12, -12, -8, 16, 8, -16, 16, -8,
1120 -16, 8, 10, 26, -10, -26, 26, 10,
1121 -26, -10, 18, 28, -18, -28, 28, 18,
1122 -28, -18, -6, 22, 6, -22, 22, -6,
1123 -22, 6, 4, 28, -4, -28, 28, 4,
1124 -28, -4, 30, 30, -30, -30, -2, 32,
1125 2, -32, 32, -2, -32, 2, -18, 22,
1126 18, -22, 22, -18, -22, 18, -14, 30,
1127 14, -30, 30, -14, -30, 14, 22, 46,
1128 -22, -46, 46, 22, -46, -22, 12, 46,
1129 -12, -46, 46, 12, -46, -12, 34, 48,
1130 -34, -48, 48, 34, -48, -34, -10, 40,
1131 10, -40, 40, -10, -40, 10, 4, 50,
1132 -4, -50, 50, 4, -50, -4, 54, 54,
1133 -54, -54, -34, 34, 34, -34, -28, 42,
1134 28, -42, 42, -28, -42, 28, -6, 60,
1135 6, -60, 60, -6, -60, 6, 26, 76,
1136 -26, -76, 76, 26, -76, -26, 42, 76,
1137 -42, -76, 76, 42, -76, -42, -24, 54,
1138 24, -54, 54, -24, -54, 24, 14, 78,
1139 -14, -78, 78, 14, -78, -14, 62, 82,
1140 -62, -82, 82, 62, -82, -62, -20, 74,
1141 20, -74, 74, -20, -74, 20, 2, 88,
1142 -2, -88, 88, 2, -88, -2, 92, 92,
1143 -92, -92, -52, 60, 52, -60, 60, -52,
1144 -60, 52, 52, 118, -52, -118, 118, 52,
1145 -118, -52, -44, 74, 44, -74, 74, -44,
1146 -74, 44, 74, 118, -74, -118, 118, 74,
1147 -118, -74, 32, 118, -32, -118, 118, 32,
1148 -118, -32, -12, 102, 12, -102, 102, -12,
1149 -102, 12, -40, 96, 40, -96, 96, -40,
1150 -96, 40, -34, 118, 34, -118, 118, -34,
1151 -118, 34, -88, 88, 88, -88, -78, 104,
1152 78, -104, 104, -78, -104, 78, 12, 12,
1153 -12, -12, 22, 22, -22, -22, 42, 42,
1154 -42, -42, 72, 72, -72, -72,
1157 const DT_2_2: IviDeltaCB = IviDeltaCB{ quad_radix: 9, data: &[
1158 0, 0, 3, 3, -3, -3, 0, 3,
1159 0, -3, 3, 0, -3, 0, 6, 6,
1160 -6, -6, 3, 9, -3, -9, 9, 3,
1161 -9, -3, -3, 9, 3, -9, 9, -3,
1162 -9, 3, -6, 6, 6, -6, 6, 12,
1163 -6, -12, 12, 6, -12, -6, 12, 12,
1164 -12, -12, 0, 15, 0, -15, 15, 0,
1165 -15, 0, -9, 12, 9, -12, 12, -9,
1166 -12, 9, 15, 24, -15, -24, 24, 15,
1167 -24, -15, -6, 18, 6, -18, 18, -6,
1168 -18, 6, 6, 24, -6, -24, 24, 6,
1169 -24, -6, 24, 24, -24, -24, 0, 27,
1170 0, -27, 27, 0, -27, 0, -18, 18,
1171 18, -18, -12, 24, 12, -24, 24, -12,
1172 -24, 12, 15, 39, -15, -39, 39, 15,
1173 -39, -15, 27, 42, -27, -42, 42, 27,
1174 -42, -27, -9, 33, 9, -33, 33, -9,
1175 -33, 9, 6, 42, -6, -42, 42, 6,
1176 -42, -6, 45, 45, -45, -45, -3, 51,
1177 3, -51, 51, -3, -51, 3, -27, 33,
1178 27, -33, 33, -27, -33, 27, -21, 45,
1179 21, -45, 45, -21, -45, 21, 33, 69,
1180 -33, -69, 69, 33, -69, -33, 18, 69,
1181 -18, -69, 69, 18, -69, -18, 54, 72,
1182 -54, -72, 72, 54, -72, -54, -18, 63,
1183 18, -63, 63, -18, -63, 18, 6, 78,
1184 -6, -78, 78, 6, -78, -6, 81, 81,
1185 -81, -81, -51, 51, 51, -51, -42, 63,
1186 42, -63, 63, -42, -63, 42, -9, 90,
1187 9, -90, 90, -9, -90, 9, 42, 114,
1188 -42, -114, 114, 42, -114, -42, 63, 117,
1189 -63, -117, 117, 63, -117, -63, -36, 81,
1190 36, -81, 81, -36, -81, 36, 21, 120,
1191 -21, -120, 120, 21, -120, -21, 96, 123,
1192 -96, -123, 123, 96, -123, -96, -30, 111,
1193 30, -111, 111, -30, -111, 30, -78, 93,
1194 78, -93, 93, -78, -93, 78, -69, 114,
1195 69, -114, 114, -69, -114, 69, 18, 18,
1196 -18, -18, 33, 33, -33, -33, 63, 63,
1197 -63, -63, 108, 108, -108, -108,
1200 const DT_2_3: IviDeltaCB = IviDeltaCB{ quad_radix: 10, data: &[
1201 0, 0, 4, 4, -4, -4, 0, 4,
1202 0, -4, 4, 0, -4, 0, 4, 8,
1203 -4, -8, 8, 4, -8, -4, 8, 8,
1204 -8, -8, -8, 8, 8, -8, -4, 12,
1205 4, -12, 12, -4, -12, 4, 8, 16,
1206 -8, -16, 16, 8, -16, -8, 16, 16,
1207 -16, -16, 0, 20, 0, -20, 20, 0,
1208 -20, 0, -12, 16, 12, -16, 16, -12,
1209 -16, 12, -4, 24, 4, -24, 24, -4,
1210 -24, 4, 16, 32, -16, -32, 32, 16,
1211 -32, -16, 8, 32, -8, -32, 32, 8,
1212 -32, -8, 32, 32, -32, -32, 0, 36,
1213 0, -36, 36, 0, -36, 0, -24, 24,
1214 24, -24, -16, 32, 16, -32, 32, -16,
1215 -32, 16, 20, 52, -20, -52, 52, 20,
1216 -52, -20, 36, 56, -36, -56, 56, 36,
1217 -56, -36, -12, 44, 12, -44, 44, -12,
1218 -44, 12, 8, 56, -8, -56, 56, 8,
1219 -56, -8, 60, 60, -60, -60, -4, 64,
1220 4, -64, 64, -4, -64, 4, -36, 44,
1221 36, -44, 44, -36, -44, 36, -28, 60,
1222 28, -60, 60, -28, -60, 28, 44, 92,
1223 -44, -92, 92, 44, -92, -44, 24, 92,
1224 -24, -92, 92, 24, -92, -24, 72, 96,
1225 -72, -96, 96, 72, -96, -72, -20, 84,
1226 20, -84, 84, -20, -84, 20, 8, 100,
1227 -8, -100, 100, 8, -100, -8, 108, 108,
1228 -108, -108, -68, 68, 68, -68, -56, 84,
1229 56, -84, 84, -56, -84, 56, -12, 120,
1230 12, -120, 120, -12, -120, 12, -48, 108,
1231 48, -108, 108, -48, -108, 48, -104, 124,
1232 104, -124, 124, -104, -124, 104, 24, 24,
1233 -24, -24, 44, 44, -44, -44, 84, 84,
1237 const DT_2_4: IviDeltaCB = IviDeltaCB{ quad_radix: 11, data: &[
1238 0, 0, 5, 5, -5, -5, 0, 5,
1239 0, -5, 5, 0, -5, 0, 10, 10,
1240 -10, -10, 5, 15, -5, -15, 15, 5,
1241 -15, -5, -10, 10, 10, -10, -5, 15,
1242 5, -15, 15, -5, -15, 5, 10, 20,
1243 -10, -20, 20, 10, -20, -10, 20, 20,
1244 -20, -20, 0, 25, 0, -25, 25, 0,
1245 -25, 0, -15, 20, 15, -20, 20, -15,
1246 -20, 15, 25, 40, -25, -40, 40, 25,
1247 -40, -25, -10, 30, 10, -30, 30, -10,
1248 -30, 10, 10, 40, -10, -40, 40, 10,
1249 -40, -10, 40, 40, -40, -40, 0, 45,
1250 0, -45, 45, 0, -45, 0, -30, 30,
1251 30, -30, -20, 40, 20, -40, 40, -20,
1252 -40, 20, 25, 65, -25, -65, 65, 25,
1253 -65, -25, 45, 70, -45, -70, 70, 45,
1254 -70, -45, -15, 55, 15, -55, 55, -15,
1255 -55, 15, 10, 70, -10, -70, 70, 10,
1256 -70, -10, 75, 75, -75, -75, -5, 85,
1257 5, -85, 85, -5, -85, 5, -45, 55,
1258 45, -55, 55, -45, -55, 45, -35, 75,
1259 35, -75, 75, -35, -75, 35, 55, 115,
1260 -55, -115, 115, 55, -115, -55, 30, 115,
1261 -30, -115, 115, 30, -115, -30, 90, 120,
1262 -90, -120, 120, 90, -120, -90, -30, 105,
1263 30, -105, 105, -30, -105, 30, -85, 85,
1264 85, -85, -70, 105, 70, -105, 105, -70,
1265 -105, 70, 30, 30, -30, -30, 60, 60,
1266 -60, -60, 105, 105, -105, -105,
1269 const DT_2_5: IviDeltaCB = IviDeltaCB{ quad_radix: 12, data: &[
1270 0, 0, 6, 6, -6, -6, 0, 6,
1271 0, -6, 6, 0, -6, 0, 12, 12,
1272 -12, -12, 6, 12, -6, -12, 12, 6,
1273 -12, -6, -12, 12, 12, -12, -6, 18,
1274 6, -18, 18, -6, -18, 6, 12, 24,
1275 -12, -24, 24, 12, -24, -12, 24, 24,
1276 -24, -24, 0, 30, 0, -30, 30, 0,
1277 -30, 0, -18, 24, 18, -24, 24, -18,
1278 -24, 18, 30, 48, -30, -48, 48, 30,
1279 -48, -30, -6, 36, 6, -36, 36, -6,
1280 -36, 6, 12, 48, -12, -48, 48, 12,
1281 -48, -12, 48, 48, -48, -48, 0, 54,
1282 0, -54, 54, 0, -54, 0, -36, 36,
1283 36, -36, -24, 48, 24, -48, 48, -24,
1284 -48, 24, 30, 78, -30, -78, 78, 30,
1285 -78, -30, 54, 84, -54, -84, 84, 54,
1286 -84, -54, -18, 66, 18, -66, 66, -18,
1287 -66, 18, 12, 84, -12, -84, 84, 12,
1288 -84, -12, 90, 90, -90, -90, -6, 96,
1289 6, -96, 96, -6, -96, 6, -54, 66,
1290 54, -66, 66, -54, -66, 54, -42, 90,
1291 42, -90, 90, -42, -90, 42, -30, 126,
1292 30, -126, 126, -30, -126, 30, -102, 102,
1293 102, -102, -84, 126, 84, -126, 126, -84,
1294 -126, 84, 36, 36, -36, -36, 66, 66,
1298 const DT_2_6: IviDeltaCB = IviDeltaCB{ quad_radix: 12, data: &[
1299 0, 0, 7, 7, -7, -7, 0, 7,
1300 0, -7, 7, 0, -7, 0, 14, 14,
1301 -14, -14, 7, 21, -7, -21, 21, 7,
1302 -21, -7, -14, 14, 14, -14, -7, 21,
1303 7, -21, 21, -7, -21, 7, 14, 28,
1304 -14, -28, 28, 14, -28, -14, 28, 28,
1305 -28, -28, 0, 35, 0, -35, 35, 0,
1306 -35, 0, -21, 28, 21, -28, 28, -21,
1307 -28, 21, 35, 56, -35, -56, 56, 35,
1308 -56, -35, -14, 42, 14, -42, 42, -14,
1309 -42, 14, 14, 56, -14, -56, 56, 14,
1310 -56, -14, 56, 56, -56, -56, 0, 63,
1311 0, -63, 63, 0, -63, 0, -42, 42,
1312 42, -42, -28, 56, 28, -56, 56, -28,
1313 -56, 28, 35, 91, -35, -91, 91, 35,
1314 -91, -35, 63, 98, -63, -98, 98, 63,
1315 -98, -63, -21, 77, 21, -77, 77, -21,
1316 -77, 21, 14, 98, -14, -98, 98, 14,
1317 -98, -14, 105, 105, -105, -105, -7, 119,
1318 7, -119, 119, -7, -119, 7, -63, 77,
1319 63, -77, 77, -63, -77, 63, -49, 105,
1320 49, -105, 105, -49, -105, 49, -119, 119,
1321 119, -119, 42, 42, -42, -42, 77, 77,
1325 const DT_2_7: IviDeltaCB = IviDeltaCB{ quad_radix: 12, data: &[
1326 0, 0, 8, 8, -8, -8, 0, 8,
1327 0, -8, 8, 0, -8, 0, 16, 16,
1328 -16, -16, 8, 16, -8, -16, 16, 8,
1329 -16, -8, -16, 16, 16, -16, -8, 24,
1330 8, -24, 24, -8, -24, 8, 16, 32,
1331 -16, -32, 32, 16, -32, -16, 32, 32,
1332 -32, -32, 0, 40, 0, -40, 40, 0,
1333 -40, 0, -24, 32, 24, -32, 32, -24,
1334 -32, 24, 40, 64, -40, -64, 64, 40,
1335 -64, -40, -16, 48, 16, -48, 48, -16,
1336 -48, 16, 16, 64, -16, -64, 64, 16,
1337 -64, -16, 64, 64, -64, -64, 0, 72,
1338 0, -72, 72, 0, -72, 0, -48, 48,
1339 48, -48, -32, 64, 32, -64, 64, -32,
1340 -64, 32, 40, 104, -40, -104, 104, 40,
1341 -104, -40, 72, 112, -72, -112, 112, 72,
1342 -112, -72, -24, 88, 24, -88, 88, -24,
1343 -88, 24, 16, 112, -16, -112, 112, 16,
1344 -112, -16, 120, 120, -120, -120, -72, 88,
1345 72, -88, 88, -72, -88, 72, -56, 120,
1346 56, -120, 120, -56, -120, 56, 48, 48,
1347 -48, -48, 88, 88, -88, -88,
1350 const DT_2_8: IviDeltaCB = IviDeltaCB{ quad_radix: 13, data: &[
1351 0, 0, 9, 9, -9, -9, 0, 9,
1352 0, -9, 9, 0, -9, 0, 18, 18,
1353 -18, -18, 9, 27, -9, -27, 27, 9,
1354 -27, -9, -18, 18, 18, -18, -9, 27,
1355 9, -27, 27, -9, -27, 9, 18, 36,
1356 -18, -36, 36, 18, -36, -18, 36, 36,
1357 -36, -36, 0, 45, 0, -45, 45, 0,
1358 -45, 0, -27, 36, 27, -36, 36, -27,
1359 -36, 27, 45, 72, -45, -72, 72, 45,
1360 -72, -45, -18, 54, 18, -54, 54, -18,
1361 -54, 18, 18, 72, -18, -72, 72, 18,
1362 -72, -18, 72, 72, -72, -72, 0, 81,
1363 0, -81, 81, 0, -81, 0, -54, 54,
1364 54, -54, -36, 72, 36, -72, 72, -36,
1365 -72, 36, 45, 117, -45, -117, 117, 45,
1366 -117, -45, 81, 126, -81, -126, 126, 81,
1367 -126, -81, -27, 99, 27, -99, 99, -27,
1368 -99, 27, -81, 99, 81, -99, 99, -81,
1369 -99, 81, 54, 54, -54, -54, 108, 108,
1373 const DT_3_1: IviDeltaCB = IviDeltaCB{ quad_radix: 11, data: &[
1374 0, 0, 2, 2, -2, -2, 0, 3,
1375 0, -3, 3, 0, -3, 0, 6, 6,
1376 -6, -6, 0, 7, 0, -7, 7, 0,
1377 -7, 0, -5, 5, 5, -5, 5, -5,
1378 -5, 5, 6, 11, -6, -11, 11, 6,
1379 -11, -6, 0, 8, 0, -8, 8, 0,
1380 -8, 0, 11, 11, -11, -11, 0, 12,
1381 0, -12, 12, 0, -12, 0, 12, 17,
1382 -12, -17, 17, 12, -17, -12, 17, 17,
1383 -17, -17, 6, 18, -6, -18, 18, 6,
1384 -18, -6, -8, 11, 8, -11, 11, -8,
1385 -11, 8, 0, 15, 0, -15, 15, 0,
1386 -15, 0, 0, 20, 0, -20, 20, 0,
1387 -20, 0, 18, 25, -18, -25, 25, 18,
1388 -25, -18, 11, 25, -11, -25, 25, 11,
1389 -25, -11, 25, 25, -25, -25, -14, 14,
1390 14, -14, 14, -14, -14, 14, 0, 26,
1391 0, -26, 26, 0, -26, 0, -11, 18,
1392 11, -18, 18, -11, -18, 11, -7, 22,
1393 7, -22, 22, -7, -22, 7, 26, 34,
1394 -26, -34, 34, 26, -34, -26, 18, 34,
1395 -18, -34, 34, 18, -34, -18, 34, 34,
1396 -34, -34, 11, 35, -11, -35, 35, 11,
1397 -35, -11, 0, 29, 0, -29, 29, 0,
1398 -29, 0, -19, 22, 19, -22, 22, -19,
1399 -22, 19, -15, 26, 15, -26, 26, -15,
1400 -26, 15, 0, 37, 0, -37, 37, 0,
1401 -37, 0, 27, 44, -27, -44, 44, 27,
1402 -44, -27, 36, 44, -36, -44, 44, 36,
1403 -44, -36, 18, 44, -18, -44, 44, 18,
1404 -44, -18, -10, 33, 10, -33, 33, -10,
1405 -33, 10, 45, 45, -45, -45, 0, 0,
1408 const DT_3_2: IviDeltaCB = IviDeltaCB{ quad_radix: 13, data: &[
1409 0, 0, 0, 2, 0, -2, 2, 0,
1410 -2, 0, 2, 2, -2, -2, 6, 6,
1411 -6, -6, 0, 6, 0, -6, 6, 0,
1412 -6, 0, -4, 4, 4, -4, 10, -6,
1413 -10, 6, 0, -12, 0, 12, -6, -12,
1414 6, -12, -6, 12, 6, 12, -14, 0,
1415 14, 0, 12, 12, -12, -12, 0, -18,
1416 0, 18, 14, -12, -14, 12, -18, -6,
1417 18, -6, -18, 6, 18, 6, -10, -18,
1418 10, -18, -10, 18, 10, 18, -22, 0,
1419 22, 0, 0, -24, 0, 24, -22, -12,
1420 22, -12, -22, 12, 22, 12, -8, -24,
1421 8, -24, -8, 24, 8, 24, -26, -6,
1422 26, -6, -26, 6, 26, 6, -28, 0,
1423 28, 0, 20, 20, -20, -20, -14, -26,
1424 14, 26, -30, -12, 30, 12, -10, -32,
1425 10, 32, -18, -32, 18, 32, -26, -26,
1426 26, 26, -34, -20, 34, 20, -38, -12,
1427 38, 12, -32, -32, 32, 32, 32, 32,
1428 -22, -40, -34, -34, 34, 34,
1431 const DT_3_3: IviDeltaCB = IviDeltaCB{ quad_radix: 13, data: &[
1432 0, 0, 0, 2, 0, -2, 2, 0,
1433 -2, 0, 4, 4, -4, -4, 10, 10,
1434 -10, -10, 0, 10, 0, -10, 10, 0,
1435 -10, 0, -6, 6, 6, -6, 14, -8,
1436 -14, 8, -18, 0, 18, 0, 10, -16,
1437 -10, 16, 0, -24, 0, 24, -24, -8,
1438 24, -8, -24, 8, 24, 8, 18, 18,
1439 -18, -18, 20, -16, -20, 16, -14, -26,
1440 14, -26, -14, 26, 14, 26, -30, 0,
1441 30, 0, 0, -34, 0, 34, -34, -8,
1442 34, -8, -34, 8, 34, 8, -30, -18,
1443 30, -18, -30, 18, 30, 18, -10, -34,
1444 10, -34, -10, 34, 10, 34, -20, -34,
1445 20, 34, -40, 0, 40, 0, 30, 30,
1446 -30, -30, -40, -18, 40, 18, 0, -44,
1447 0, 44, -16, -44, 16, 44, -36, -36,
1448 -36, -36, 36, 36, -26, -44, 26, 44,
1449 -46, -26, 46, 26, -52, -18, 52, 18,
1450 -20, -54, -44, -44, 44, 44, -32, -54,
1451 -46, -46, -46, -46, 46, 46,
1454 const DT_3_4: IviDeltaCB = IviDeltaCB{ quad_radix: 13, data: &[
1455 0, 0, 0, 4, 0, -4, 4, 0,
1456 -4, 0, 4, 4, -4, -4, 12, 12,
1457 -12, -12, 0, 12, 0, -12, 12, 0,
1458 -12, 0, -8, 8, 8, -8, 8, -16,
1459 -8, 16, 0, -24, 0, 24, -24, -8,
1460 24, -8, -24, 8, 24, 8, 20, -16,
1461 -20, 16, -28, 0, 28, 0, -16, -24,
1462 16, -24, -16, 24, 16, 24, 0, -32,
1463 0, 32, -28, -16, 28, -16, -28, 16,
1464 28, 16, -8, -32, 8, -32, -32, -8,
1465 32, -8, -32, 8, 32, 8, -8, 32,
1466 8, 32, 24, 24, -24, -24, 24, -24,
1467 -24, 24, -20, -32, 20, 32, -40, 0,
1468 40, 0, -40, -16, 40, 16, 0, -44,
1469 0, -44, -44, 0, 44, 0, 0, 44,
1470 0, 44, -32, -32, 32, 32, -16, -44,
1471 16, 44, -24, -44, -44, -24, 44, 24,
1472 24, 44, -48, -16, 48, 16, -36, -36,
1473 -36, -36, 36, 36, 36, 36, -20, -52,
1474 40, 40, -40, -40, -32, -52,
1477 const DT_3_5: IviDeltaCB = IviDeltaCB{ quad_radix: 13, data: &[
1478 0, 0, 2, 2, -2, -2, 6, 6,
1479 -6, -6, 12, 12, -12, -12, 20, 20,
1480 -20, -20, 32, 32, -32, -32, 46, 46,
1481 -46, -46, 0, 0, 0, 0, 0, 0,
1482 0, 0, 0, 0, 0, 0, 0, 0,
1483 0, 0, 0, 0, 0, 0, 0, 0,
1484 0, 0, 0, 0, 0, 0, 0, 0,
1485 0, 0, 0, 0, 0, 0, 0, 0,
1486 0, 0, 0, 0, 0, 0, 0, 0,
1487 0, 0, 0, 0, 0, 0, 0, 0,
1488 0, 0, 0, 0, 0, 0, 0, 0,
1489 0, 0, 0, 0, 0, 0, 0, 0,
1490 0, 0, 0, 0, 0, 0, 0, 0,
1491 0, 0, 0, 0, 0, 0, 0, 0,
1492 0, 0, 0, 0, 0, 0, 0, 0,
1493 0, 0, 0, 0, 0, 0, 0, 0,
1494 0, 0, 0, 0, 0, 0, 0, 0,
1495 0, 0, 0, 0, 0, 0, 0, 0,
1496 0, 0, 0, 0, 0, 0, 0, 0,
1500 const IVI3_DELTA_CBS: [&IviDeltaCB; 24] = [
1501 &DT_1_1, &DT_1_2, &DT_1_3, &DT_1_4, &DT_1_5, &DT_1_6, &DT_1_7, &DT_1_8,
1502 &DT_2_1, &DT_2_2, &DT_2_3, &DT_2_4, &DT_2_5, &DT_2_6, &DT_2_7, &DT_2_8,
1503 &DT_3_1, &DT_3_2, &DT_3_3, &DT_3_4, &DT_3_5, &DT_3_5, &DT_3_5, &DT_3_5