annotate the sources for test samples
[nihav.git] / nihav-indeo / src / codecs / indeo3.rs
1 use nihav_core::formats;
2 use nihav_core::codecs::*;
3 use nihav_core::io::byteio::*;
4 use std::io::SeekFrom;
5 use std::mem;
6
7 struct IviDeltaCB {
8 quad_radix: u8,
9 data: &'static [i8],
10 }
11
12 #[derive(Clone, Copy)]
13 struct MV {
14 x: i8,
15 y: i8
16 }
17
18 struct Buffers {
19 width: usize,
20 height: usize,
21 cw: usize,
22 ch: usize,
23 sbuf: Vec<u8>,
24 dbuf: Vec<u8>,
25 }
26
27 const DEFAULT_PIXEL: u8 = 0x40;
28
29 impl Buffers {
30 fn new() -> Self { Buffers { width: 0, height: 0, cw: 0, ch: 0, sbuf: Vec::new(), dbuf: Vec::new() } }
31 fn reset(&mut self) {
32 self.width = 0;
33 self.height = 0;
34 self.sbuf.clear();
35 self.dbuf.clear();
36 }
37 fn alloc(&mut self, w: usize, h: usize) {
38 self.width = w;
39 self.height = h;
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);
44 }
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 }
48 }
49 fn get_offset(&mut self, planeno: usize) -> usize {
50 match planeno {
51 1 => self.width * self.height,
52 2 => self.width * self.height + self.cw * self.ch,
53 _ => 0,
54 }
55 }
56 fn fill_framebuf(&mut self, fbuf: &mut NAVideoBuffer<u8>) {
57 for planeno in 0..3 {
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();
66 for _ in 0..height {
67 for x in 0..width {
68 dst[doff + x] = src[soff + x] * 2;
69 }
70 soff += sstride;
71 doff += dstride;
72 }
73 }
74 }
75 fn copy_block(&mut self, doff: usize, soff: usize, stride: usize, w: usize, h: usize) {
76 let mut sidx = soff;
77 let mut didx = doff;
78 for _ in 0..h {
79 self.dbuf[didx..][..w].copy_from_slice(&self.sbuf[sidx..][..w]);
80 sidx += stride;
81 didx += stride;
82 }
83 }
84 fn fill_block(&mut self, doff: usize, stride: usize, w: usize, h: usize, topline: bool) {
85 let mut didx = doff;
86 let mut buf: [u8; 8] = [0; 8];
87 if topline {
88 for _ in 0..h {
89 for i in 0..w { self.dbuf[didx + i] = DEFAULT_PIXEL; }
90 didx += stride;
91 }
92 } else {
93 for i in 0..w { buf[i] = self.dbuf[didx - stride + i]; }
94 for _ in 0..h {
95 self.dbuf[didx..][..w].copy_from_slice(&buf[..w]);
96 didx += stride;
97 }
98 }
99 }
100 }
101
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; }
107 }
108
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; }
114 if !topline {
115 for i in 0..4 { dst[i] = (dst[i + stride] + dst[i]) >> 1; }
116 } else {
117 for i in 0..4 { dst[i] = dst[i + stride]; }
118 }
119 }
120
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; }
127 }
128
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; }
135 }
136
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];
140 if !firstline {
141 for i in 0..8 { dst[i + stride] = dst[i ].wrapping_add(deltas[i >> 1]) & 0x7F; }
142 } else {
143 for i in 0..8 { dst[i + stride] = dst[i & !1].wrapping_add(deltas[i >> 1]) & 0x7F; }
144 }
145 if !topline {
146 for i in 0..8 { dst[i] = (dst[i + stride] + dst[i]) >> 1; }
147 } else {
148 for i in 0..8 { dst[i] = dst[i + stride]; }
149 }
150 }
151
152 fn copy_line_top(bufs: &mut Buffers, off: usize, stride: usize, bw: usize, topline: bool) {
153 let mut buf: [u8; 8] = [0; 8];
154 if !topline {
155 let src = &bufs.dbuf[(off - stride)..(off - stride + bw)];
156 buf[..bw].copy_from_slice(&src[..bw]);
157 } else {
158 for i in 0..bw { buf[i] = DEFAULT_PIXEL; }
159 }
160 let dst = &mut bufs.dbuf[off..][..bw];
161 dst.copy_from_slice(&buf[..bw]);
162 }
163
164 fn copy_line_top4x4(bufs: &mut Buffers, off: usize, stride: usize, topline: bool) {
165 copy_line_top(bufs, off, stride, 4, topline);
166 }
167
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);
171 }
172
173 fn copy_line_top8x8(bufs: &mut Buffers, off: usize, stride: usize, topline: bool) {
174 let mut buf: [u8; 8] = [0; 8];
175 if !topline {
176 let src = &bufs.dbuf[(off - stride)..(off - stride + 8)];
177 for i in 0..8 { buf[i] = src[i & !1]; }
178 } else {
179 for i in 0..8 { buf[i] = DEFAULT_PIXEL; }
180 }
181 let dst = &mut bufs.dbuf[off..][..8];
182 dst.copy_from_slice(&buf[..8]);
183 }
184
185 fn fill_block8x8(bufs: &mut Buffers, doff: usize, stride: usize, h: usize, topline: bool, firstline: bool) {
186 let mut didx = doff;
187 let mut buf: [u8; 8] = [0; 8];
188 if firstline {
189 for i in 0..8 { buf[i] = DEFAULT_PIXEL; }
190 } else {
191 for i in 0..8 { buf[i] = bufs.dbuf[doff - stride + i]; }
192 }
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; }
196 }
197
198 let start = if !topline { 0 } else { 1 };
199 if topline {
200 didx += stride;
201 }
202 for _ in start..h {
203 bufs.dbuf[didx..][..8].copy_from_slice(&buf[..8]);
204 didx += stride;
205 }
206 }
207
208 struct Indeo3Decoder {
209 info: NACodecInfoRef,
210 bpos: u8,
211 bbuf: u8,
212 width: u16,
213 height: u16,
214 mvs: Vec<MV>,
215 altquant: [u8; 16],
216 vq_offset: u8,
217 bufs: Buffers,
218 requant_tab: [[u8; 128]; 8],
219 }
220
221 #[derive(Clone,Copy)]
222 struct IV3Cell {
223 x: u16,
224 y: u16,
225 w: u16,
226 h: u16,
227 d: u8,
228 vqt: bool,
229 mv: Option<MV>,
230 }
231
232 impl IV3Cell {
233 fn new(w: u16, h: u16) -> Self {
234 IV3Cell { x: 0, y: 0, w, h, d: 20, vqt: false, mv: None }
235 }
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;
240 cell1.h = h1;
241 cell1.d -= 1;
242 let mut cell2 = *self;
243 cell2.y += h1;
244 cell2.h = h2;
245 cell2.d -= 1;
246 (cell1, cell2)
247 }
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 }
251 } else {
252 if self.w > 2 { ((self.w + 2) >> 2) << 1 } else { 1 }
253 };
254 let w2 = self.w - w1;
255 let mut cell1 = *self;
256 cell1.w = w1;
257 cell1.d -= 1;
258 let mut cell2 = *self;
259 cell2.x += w1;
260 cell2.w = w2;
261 cell2.d -= 1;
262 (cell1, cell2)
263 }
264 fn no_mv(&self) -> bool { self.mv.is_none() }
265 }
266
267 struct CellDecParams {
268 tab: [usize; 2],
269 bw: u16,
270 bh: u16,
271 swap_q: [bool; 2],
272 hq: bool,
273 apply_delta: fn (&mut Buffers, usize, usize, &[u8], bool, bool),
274 copy_line_top: fn (&mut Buffers, usize, usize, bool),
275 }
276
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);
279
280 const H_SPLIT: u8 = 0;
281 const V_SPLIT: u8 = 1;
282 const SKIP_OR_TREE: u8 = 2;
283
284 impl Indeo3Decoder {
285 fn new() -> Self {
286 const REQUANT_OFF: [i32; 8] = [ 0, 1, 0, 4, 4, 1, 0, 1 ];
287
288 let dummy_info = NACodecInfo::new_dummy();
289
290 let mut requant_tab = [[0u8; 128]; 8];
291 for i in 0..8 {
292 let step = (i as i32) + 2;
293 let start = if (i == 3) || (i == 4) { -3 } else { step / 2 };
294 let mut last = 0;
295 for j in 0..128 {
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];
299 } else {
300 requant_tab[i][j] = last;
301 }
302 }
303 }
304 requant_tab[1][7] = 10;
305 requant_tab[1][119] = 118;
306 requant_tab[1][120] = 118;
307 requant_tab[4][8] = 10;
308
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 }
312 }
313
314 fn br_reset(&mut self) {
315 self.bpos = 0;
316 self.bbuf = 0;
317 }
318
319 fn get_2bits(&mut self, br: &mut ByteReader) -> DecoderResult<u8> {
320 if self.bpos == 0 {
321 self.bbuf = br.read_byte()?;
322 self.bpos = 8;
323 }
324 self.bpos -= 2;
325 Ok((self.bbuf >> self.bpos) & 0x3)
326 }
327
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 };
334
335 validate!((((cell.w * 4) % params.bw) == 0) && (((cell.h * 4) % params.bh) == 0));
336
337 let mut run_blocks = 0;
338 let mut run_skip = false;
339
340 let mut didx: usize = ((cell.x*4) as usize) + ((cell.y * 4) as usize) * stride + off;
341 let mut sidx: usize;
342
343 if cell.no_mv() {
344 sidx = 0;
345 } else {
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;
353 validate!(l >= 0);
354 validate!(t >= 0);
355 validate!(r <= (self.width as i16));
356 validate!(b <= (self.height as i16));
357 sidx = (l as usize) + (t as usize) * stride + off;
358 }
359 if vq_idx >= 8 {
360 let requant_tab = &self.requant_tab[(vq_idx & 7) as usize];
361 if cell.no_mv() {
362 if cell.y > 0 {
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];
365 }
366 }
367 } else {
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];
370 }
371 }
372 }
373 for y in 0..blk_h {
374 let mut xoff: usize = 0;
375 for _ in 0..blk_w {
376 if run_blocks > 0 {
377 if !run_skip || !cell.no_mv() {
378 if !(params.bw == 8 && cell.no_mv()) {
379 if !cell.no_mv() {
380 self.bufs.copy_block(didx + xoff, sidx + xoff, stride,
381 params.bw as usize, params.bh as usize);
382 } else {
383 self.bufs.fill_block(didx + xoff, stride,
384 params.bw as usize, params.bh as usize,
385 (cell.y == 0) && (y == 0));
386 }
387 } else {
388 fill_block8x8(&mut self.bufs,
389 didx + xoff, stride, 8,
390 y == 0, (cell.y == 0) && (y == 0));
391 }
392 }
393 run_blocks -= 1;
394 } else {
395 let mut line: usize = 0;
396 while line < 4 {
397 let c = br.read_byte()?;
398 if c < 0xF8 {
399 let delta_tab = if params.hq {
400 IVI3_DELTA_CBS[params.tab[line & 1]]
401 } else {
402 IVI3_DELTA_CBS[params.tab[1]]
403 };
404 let mut idx1;
405 let mut idx2;
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);
409 idx2 = c as usize;
410 } else {
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);
416 }
417 }
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);
424 if cell.no_mv() {
425 (params.copy_line_top)(&mut self.bufs,
426 didx + xoff + line * scale * stride,
427 stride, topline);
428 } else {
429 self.bufs.copy_block(didx + xoff + line * scale * stride,
430 sidx + xoff + line * scale * stride,
431 stride, params.bw as usize, scale);
432 }
433 (params.apply_delta)(&mut self.bufs,
434 didx + xoff + line * scale * stride,
435 stride, &deltas, topline, first_line);
436 line += 1;
437 } else {
438 let mut tocopy: usize = 0;
439 let mut do_copy = true;
440 if c == 0xF8 { return Err(DecoderError::InvalidData); }
441 if c == 0xF9 {
442 run_blocks = 1;
443 run_skip = true;
444 validate!(line == 0);
445 tocopy = 4;
446 do_copy = !cell.no_mv();
447 }
448 if c == 0xFA {
449 validate!(line == 0);
450 tocopy = 4;
451 do_copy = !cell.no_mv();
452 }
453 if c == 0xFB {
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;
458 tocopy = 4 - line;
459 if params.bw == 4 && cell.no_mv() && run_skip {
460 do_copy = false;
461 }
462 }
463 if c == 0xFC {
464 run_skip = false;
465 run_blocks = 1;
466 tocopy = 4 - line;
467 }
468 if c >= 0xFD {
469 let nl = 257 - i16::from(c) - (line as i16);
470 validate!(nl > 0);
471 tocopy = nl as usize;
472 }
473 if do_copy {
474 if !(params.bh == 8 && cell.no_mv()) {
475 if !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,
479 tocopy * scale);
480 } else {
481 self.bufs.fill_block(didx + xoff + line * scale * stride,
482 stride, params.bw as usize,
483 tocopy * scale,
484 (cell.y == 0) && (y == 0) && (line == 0));
485 }
486 } else {
487 fill_block8x8(&mut self.bufs,
488 didx + xoff + line * 2 * stride,
489 stride, tocopy * 2,
490 (y == 0) && (line == 0),
491 (cell.y == 0) && (y == 0) && (line == 0));
492 }
493 }
494 line += tocopy;
495 }
496 }
497 }
498 xoff += params.bw as usize;
499 }
500 didx += stride * (params.bh as usize);
501 sidx += stride * (params.bh as usize);
502 }
503 Ok(())
504 }
505
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;
515 validate!(l >= 0);
516 validate!(t >= 0);
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);
522 Ok(())
523 }
524
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;
530
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;
537 } else {
538 idx1 += self.vq_offset as usize;
539 idx2 += self.vq_offset as usize;
540 }
541 validate!((idx1 < 24) && (idx2 < 24));
542
543 let mut cp = CellDecParams {
544 tab: [idx2, idx1],
545 bw: 0, bh: 0,
546 swap_q: [idx2 >= 16, idx1 >= 16],
547 hq: false,
548 apply_delta: apply_delta4x4,
549 copy_line_top: copy_line_top4x4,
550 };
551 if (mode == 0) || (mode == 1) {
552 cp.bw = 4;
553 cp.bh = 4;
554 cp.hq = true;
555 } else if (mode == 3) || (mode == 4) {
556 if !cell.no_mv() { return Err(DecoderError::InvalidData); }
557 cp.bw = 4;
558 cp.bh = 8;
559 cp.hq = true;
560 cp.apply_delta = apply_delta4x8;
561 cp.copy_line_top = copy_line_top4x8;
562 } else if mode == 10 {
563 if !cell.no_mv() {
564 validate!(!intra);
565 cp.apply_delta = apply_delta8x8p;
566 } else {
567 cp.apply_delta = apply_delta8x8i;
568 }
569 cp.bw = 8;
570 cp.bh = 8;
571 cp.copy_line_top = copy_line_top8x8;
572 } else if mode == 11 {
573 if cell.no_mv() { return Err(DecoderError::InvalidData); }
574 validate!(!intra);
575 cp.bw = 4;
576 cp.bh = 8;
577 cp.apply_delta = apply_delta4x8m11;
578 cp.copy_line_top = copy_line_top4x8;
579 } else {
580 return Err(DecoderError::InvalidData);
581 }
582 self.decode_cell_data(br, cell, off, stride, cp, vq_idx)
583 }
584
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)?;
588 if op == H_SPLIT {
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)?;
594 Ok(())
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)?;
601 Ok(())
602 } else if op == SKIP_OR_TREE {
603 if !cell.vqt {
604 let mut newcell = cell;
605 newcell.vqt = true;
606 newcell.d -= 1;
607 self.parse_tree(br, newcell, off, stride, stripw, intra)
608 } else {
609 validate!(!intra);
610 let code = self.get_2bits(br)?;
611 validate!(code < 2);
612 if code == 1 { return Err(DecoderError::NotImplemented); }
613 self.copy_cell(cell, off, stride)
614 }
615 } else {
616 if !cell.vqt {
617 let mut newcell = cell;
618 newcell.vqt = true;
619 newcell.d -= 1;
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)
624 } else {
625 self.decode_cell(br, cell, off, stride, intra)
626 }
627 }
628 }
629
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))?;
635
636 let nvec = br.read_u32le()?;
637 validate!(nvec == 0); // for intra there should be no mc_vecs
638 self.mvs.clear();
639 for _ in 0..nvec {
640 let x = br.read_byte()? as i8;
641 let y = br.read_byte()? as i8;
642 self.mvs.push(MV{ x, y });
643 }
644
645 let (cellwidth, cellheight) = if planeno == 0 {
646 (self.bufs.width >> 2, self.bufs.height >> 2)
647 } else {
648 (((self.bufs.width >> 2) + 3) >> 2, ((self.bufs.height >> 2) + 3) >> 2)
649 };
650 let cell = IV3Cell::new(cellwidth as u16, cellheight as u16);
651 self.br_reset();
652 self.parse_tree(br, cell, offs, stride, if planeno > 0 { 10 } else { 40 }, true)?;
653 validate!(br.tell() <= end);
654 Ok(())
655 }
656
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))?;
662
663 let nvec = br.read_u32le()?;
664 validate!(nvec <= 256); // for intra there should be no mc_vecs
665 self.mvs.clear();
666 for _ in 0..nvec {
667 let y = br.read_byte()? as i8;
668 let x = br.read_byte()? as i8;
669 self.mvs.push(MV{ x, y });
670 }
671
672 let (cellwidth, cellheight) = if planeno == 0 {
673 (self.bufs.width >> 2, self.bufs.height >> 2)
674 } else {
675 (((self.bufs.width >> 2) + 3) >> 2, ((self.bufs.height >> 2) + 3) >> 2)
676 };
677 let cell = IV3Cell::new(cellwidth as u16, cellheight as u16);
678 self.br_reset();
679 self.parse_tree(br, cell, offs, stride, if planeno > 0 { 10 } else { 40 }, false)?;
680 validate!(br.tell() <= end);
681 Ok(())
682 }
683 }
684
685 const FLAG_KEYFRAME: u16 = 1 << 2;
686 const FLAG_NONREF: u16 = 1 << 8;
687
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();
696 self.bufs.reset();
697 Ok(())
698 } else {
699 Err(DecoderError::InvalidData)
700 }
701 }
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()?;
710
711 let data_start = br.tell();
712
713 if (frameno ^ hdr_2 ^ size ^ FRMH_TAG) != check {
714 return Err(DecoderError::InvalidData);
715 }
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()?;
721 if size2 == 0x80 {
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());
726 }
727 validate!(((size2 + 7) >> 3) <= size);
728 let cb = br.read_byte()?;
729 self.vq_offset = cb;
730 br.read_skip(3)?;
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));
736 let vinfo;
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);
740 } else {
741 vinfo = self.info.get_properties().get_video_info().unwrap();
742 }
743 self.width = width;
744 self.height = height;
745
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); }
752
753 br.read_skip(4)?;
754 br.read_buf(&mut self.altquant)?;
755
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; }
759 let mut uend = size;
760 if (yoff < uend) && (yoff > uoff) { uend = yoff; }
761 if (voff < uend) && (voff > uoff) { uend = voff; }
762 let mut vend = size;
763 if (yoff < vend) && (yoff > voff) { vend = yoff; }
764 if (uoff < vend) && (uoff > voff) { vend = uoff; }
765
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);
775 if intraframe {
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)?;
779 } else {
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)?;
783 }
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 });
789 Ok(frm.into_ref())
790 }
791 fn flush(&mut self) {
792 self.bufs.reset();
793 }
794 }
795
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 }
800 }
801
802 pub fn get_decoder() -> Box<dyn NADecoder + Send> {
803 Box::new(Indeo3Decoder::new())
804 }
805
806 #[cfg(test)]
807 mod test {
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;
813 #[test]
814 fn test_indeo3() {
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);
819
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]]));
834 }
835 }
836
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,
887 ]};
888
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,
930 ]};
931
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,
966 -84, -84,
967 ]};
968
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,
999 ]};
1000
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,
1027 -69, -69,
1028 ]};
1029
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,
1054 -80, -80,
1055 ]};
1056
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,
1080 ]};
1081
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,
1102 -104, -104,
1103 ]};
1104
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,
1155 ]};
1156
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,
1198 ]};
1199
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,
1234 -84, -84,
1235 ]};
1236
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,
1267 ]};
1268
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,
1295 -66, -66,
1296 ]};
1297
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,
1322 -77, -77,
1323 ]};
1324
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,
1348 ]};
1349
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,
1370 -108, -108,
1371 ]};
1372
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,
1406 ]};
1407
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,
1429 ]};
1430
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,
1452 ]};
1453
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,
1475 ]};
1476
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,
1497 0, 0, 0, 0, 0, 0,
1498 ]};
1499
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
1504 ];