1705a432605cdd0594eb125eb7e445c7840d25c2
[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.truncate(0);
35 self.dbuf.truncate(0);
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::cyclomatic_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.truncate(0);
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.truncate(0);
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_codecs;
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_codecs(&mut dec_reg);
819
820 test_decoding("avi", "indeo3", "assets/Indeo/iv32_example.avi", Some(10),
821 &dmx_reg, &dec_reg, ExpectedTestResult::MD5Frames(vec![
822 [0x90be698e, 0x326db071, 0x08e8c6a5, 0x39349acc],
823 [0x25d677fc, 0x63f96aaa, 0xd412ca98, 0x61416313],
824 [0xc4368250, 0x63e7b6bc, 0xffcff950, 0x11f13239],
825 [0x7e869758, 0x027abc2e, 0x25204bca, 0x93fbaa03],
826 [0x5a1e822c, 0x2b1a4cd5, 0x72059843, 0xe5689ad1],
827 [0x3a971cce, 0x5ec22135, 0x1a45f802, 0x0f5f9264],
828 [0x0a65f782, 0xd8767cf3, 0x878b4b8d, 0xfc94c88b],
829 [0x4ac70139, 0x3300eac1, 0xba84b068, 0x47f5ff29],
830 [0x3e8c8ec4, 0x9421b38c, 0x580abbbd, 0x92792d19],
831 [0x9096ee9b, 0x8dd9fb14, 0x981e31e3, 0x3ffd7d29],
832 [0x22dc71ec, 0x3d8f6f7e, 0x1a198982, 0x41d17ecc]]));
833 }
834 }
835
836 const DT_1_1: IviDeltaCB = IviDeltaCB{ quad_radix: 7, data: &[
837 0, 0, 2, 2, -2, -2, -1, 3,
838 1, -3, 3, -1, -3, 1, 4, 4,
839 -4, -4, 1, 5, -1, -5, 5, 1,
840 -5, -1, -4, 4, 4, -4, -2, 6,
841 2, -6, 6, -2, -6, 2, 4, 9,
842 -4, -9, 9, 4, -9, -4, 9, 9,
843 -9, -9, 1, 10, -1, -10, 10, 1,
844 -10, -1, -5, 8, 5, -8, 8, -5,
845 -8, 5, 9, 15, -9, -15, 15, 9,
846 -15, -9, -3, 12, 3, -12, 12, -3,
847 -12, 3, 4, 16, -4, -16, 16, 4,
848 -16, -4, 16, 16, -16, -16, 0, 18,
849 0, -18, 18, 0, -18, 0, -12, 12,
850 12, -12, -9, 16, 9, -16, 16, -9,
851 -16, 9, 11, 27, -11, -27, 27, 11,
852 -27, -11, 19, 28, -19, -28, 28, 19,
853 -28, -19, -6, 22, 6, -22, 22, -6,
854 -22, 6, 4, 29, -4, -29, 29, 4,
855 -29, -4, 30, 30, -30, -30, -2, 33,
856 2, -33, 33, -2, -33, 2, -18, 23,
857 18, -23, 23, -18, -23, 18, -15, 30,
858 15, -30, 30, -15, -30, 15, 22, 46,
859 -22, -46, 46, 22, -46, -22, 13, 47,
860 -13, -47, 47, 13, -47, -13, 35, 49,
861 -35, -49, 49, 35, -49, -35, -11, 41,
862 11, -41, 41, -11, -41, 11, 4, 51,
863 -4, -51, 51, 4, -51, -4, 54, 54,
864 -54, -54, -34, 34, 34, -34, -29, 42,
865 29, -42, 42, -29, -42, 29, -6, 60,
866 6, -60, 60, -6, -60, 6, 27, 76,
867 -27, -76, 76, 27, -76, -27, 43, 77,
868 -43, -77, 77, 43, -77, -43, -24, 55,
869 24, -55, 55, -24, -55, 24, 14, 79,
870 -14, -79, 79, 14, -79, -14, 63, 83,
871 -63, -83, 83, 63, -83, -63, -20, 74,
872 20, -74, 74, -20, -74, 20, 2, 88,
873 -2, -88, 88, 2, -88, -2, 93, 93,
874 -93, -93, -52, 61, 52, -61, 61, -52,
875 -61, 52, 52, 120, -52, -120, 120, 52,
876 -120, -52, -45, 75, 45, -75, 75, -45,
877 -75, 45, 75, 125, -75, -125, 125, 75,
878 -125, -75, 33, 122, -33, -122, 122, 33,
879 -122, -33, -13, 103, 13, -103, 103, -13,
880 -103, 13, -40, 96, 40, -96, 96, -40,
881 -96, 40, -34, 127, 34, -127, 127, -34,
882 -127, 34, -89, 89, 89, -89, -78, 105,
883 78, -105, 105, -78, -105, 78, 12, 12,
884 -12, -12, 23, 23, -23, -23, 42, 42,
885 -42, -42, 73, 73, -73, -73,
886 ]};
887
888 const DT_1_2: IviDeltaCB = IviDeltaCB{ quad_radix: 9, data: &[
889 0, 0, 3, 3, -3, -3, -1, 4,
890 1, -4, 4, -1, -4, 1, 7, 7,
891 -7, -7, 2, 8, -2, -8, 8, 2,
892 -8, -2, -2, 9, 2, -9, 9, -2,
893 -9, 2, -6, 6, 6, -6, 6, 13,
894 -6, -13, 13, 6, -13, -6, 13, 13,
895 -13, -13, 1, 14, -1, -14, 14, 1,
896 -14, -1, -8, 12, 8, -12, 12, -8,
897 -12, 8, 14, 23, -14, -23, 23, 14,
898 -23, -14, -5, 18, 5, -18, 18, -5,
899 -18, 5, 6, 24, -6, -24, 24, 6,
900 -24, -6, 24, 24, -24, -24, -1, 27,
901 1, -27, 27, -1, -27, 1, -17, 17,
902 17, -17, -13, 23, 13, -23, 23, -13,
903 -23, 13, 16, 40, -16, -40, 40, 16,
904 -40, -16, 28, 41, -28, -41, 41, 28,
905 -41, -28, -9, 33, 9, -33, 33, -9,
906 -33, 9, 6, 43, -6, -43, 43, 6,
907 -43, -6, 46, 46, -46, -46, -4, 50,
908 4, -50, 50, -4, -50, 4, -27, 34,
909 27, -34, 34, -27, -34, 27, -22, 45,
910 22, -45, 45, -22, -45, 22, 34, 69,
911 -34, -69, 69, 34, -69, -34, 19, 70,
912 -19, -70, 70, 19, -70, -19, 53, 73,
913 -53, -73, 73, 53, -73, -53, -17, 62,
914 17, -62, 62, -17, -62, 17, 5, 77,
915 -5, -77, 77, 5, -77, -5, 82, 82,
916 -82, -82, -51, 51, 51, -51, -43, 64,
917 43, -64, 64, -43, -64, 43, -10, 90,
918 10, -90, 90, -10, -90, 10, 41, 114,
919 -41, -114, 114, 41, -114, -41, 64, 116,
920 -64, -116, 116, 64, -116, -64, -37, 82,
921 37, -82, 82, -37, -82, 37, 22, 119,
922 -22, -119, 119, 22, -119, -22, 95, 124,
923 -95, -124, 124, 95, -124, -95, -30, 111,
924 30, -111, 111, -30, -111, 30, -78, 92,
925 78, -92, 92, -78, -92, 78, -68, 113,
926 68, -113, 113, -68, -113, 68, 18, 18,
927 -18, -18, 34, 34, -34, -34, 63, 63,
928 -63, -63, 109, 109, -109, -109,
929 ]};
930
931 const DT_1_3: IviDeltaCB = IviDeltaCB{ quad_radix: 10, data: &[
932 0, 0, 4, 4, -4, -4, -1, 5,
933 1, -5, 5, -1, -5, 1, 3, 10,
934 -3, -10, 10, 3, -10, -3, 9, 9,
935 -9, -9, -7, 7, 7, -7, -3, 12,
936 3, -12, 12, -3, -12, 3, 8, 17,
937 -8, -17, 17, 8, -17, -8, 17, 17,
938 -17, -17, 1, 19, -1, -19, 19, 1,
939 -19, -1, -11, 16, 11, -16, 16, -11,
940 -16, 11, -6, 23, 6, -23, 23, -6,
941 -23, 6, 18, 31, -18, -31, 31, 18,
942 -31, -18, 8, 32, -8, -32, 32, 8,
943 -32, -8, 33, 33, -33, -33, -1, 36,
944 1, -36, 36, -1, -36, 1, -23, 23,
945 23, -23, -17, 31, 17, -31, 31, -17,
946 -31, 17, 21, 54, -21, -54, 54, 21,
947 -54, -21, 37, 55, -37, -55, 55, 37,
948 -55, -37, -12, 44, 12, -44, 44, -12,
949 -44, 12, 8, 57, -8, -57, 57, 8,
950 -57, -8, 61, 61, -61, -61, -5, 66,
951 5, -66, 66, -5, -66, 5, -36, 45,
952 36, -45, 45, -36, -45, 36, -29, 60,
953 29, -60, 60, -29, -60, 29, 45, 92,
954 -45, -92, 92, 45, -92, -45, 25, 93,
955 -25, -93, 93, 25, -93, -25, 71, 97,
956 -71, -97, 97, 71, -97, -71, -22, 83,
957 22, -83, 83, -22, -83, 22, 7, 102,
958 -7, -102, 102, 7, -102, -7, 109, 109,
959 -109, -109, -68, 68, 68, -68, -57, 85,
960 57, -85, 85, -57, -85, 57, -13, 120,
961 13, -120, 120, -13, -120, 13, -49, 110,
962 49, -110, 110, -49, -110, 49, -104, 123,
963 104, -123, 123, -104, -123, 104, 24, 24,
964 -24, -24, 46, 46, -46, -46, 84, 84,
965 -84, -84,
966 ]};
967
968 const DT_1_4: IviDeltaCB = IviDeltaCB{ quad_radix: 11, data: &[
969 0, 0, 5, 5, -5, -5, -2, 7,
970 2, -7, 7, -2, -7, 2, 11, 11,
971 -11, -11, 3, 13, -3, -13, 13, 3,
972 -13, -3, -9, 9, 9, -9, -4, 15,
973 4, -15, 15, -4, -15, 4, 11, 22,
974 -11, -22, 22, 11, -22, -11, 21, 21,
975 -21, -21, 2, 24, -2, -24, 24, 2,
976 -24, -2, -14, 20, 14, -20, 20, -14,
977 -20, 14, 23, 38, -23, -38, 38, 23,
978 -38, -23, -8, 29, 8, -29, 29, -8,
979 -29, 8, 11, 39, -11, -39, 39, 11,
980 -39, -11, 41, 41, -41, -41, -1, 45,
981 1, -45, 45, -1, -45, 1, -29, 29,
982 29, -29, -22, 39, 22, -39, 39, -22,
983 -39, 22, 27, 67, -27, -67, 67, 27,
984 -67, -27, 47, 69, -47, -69, 69, 47,
985 -69, -47, -15, 56, 15, -56, 56, -15,
986 -56, 15, 11, 71, -11, -71, 71, 11,
987 -71, -11, 76, 76, -76, -76, -6, 83,
988 6, -83, 83, -6, -83, 6, -45, 57,
989 45, -57, 57, -45, -57, 45, -36, 75,
990 36, -75, 75, -36, -75, 36, 56, 115,
991 -56, -115, 115, 56, -115, -56, 31, 117,
992 -31, -117, 117, 31, -117, -31, 88, 122,
993 -88, -122, 122, 88, -122, -88, -28, 104,
994 28, -104, 104, -28, -104, 28, -85, 85,
995 85, -85, -72, 106, 72, -106, 106, -72,
996 -106, 72, 30, 30, -30, -30, 58, 58,
997 -58, -58, 105, 105, -105, -105,
998 ]};
999
1000 const DT_1_5: IviDeltaCB = IviDeltaCB{ quad_radix: 12, data: &[
1001 0, 0, 6, 6, -6, -6, -2, 8,
1002 2, -8, 8, -2, -8, 2, 13, 13,
1003 -13, -13, 4, 15, -4, -15, 15, 4,
1004 -15, -4, -11, 11, 11, -11, -5, 18,
1005 5, -18, 18, -5, -18, 5, 13, 26,
1006 -13, -26, 26, 13, -26, -13, 26, 26,
1007 -26, -26, 2, 29, -2, -29, 29, 2,
1008 -29, -2, -16, 24, 16, -24, 24, -16,
1009 -24, 16, 28, 46, -28, -46, 46, 28,
1010 -46, -28, -9, 35, 9, -35, 35, -9,
1011 -35, 9, 13, 47, -13, -47, 47, 13,
1012 -47, -13, 49, 49, -49, -49, -1, 54,
1013 1, -54, 54, -1, -54, 1, -35, 35,
1014 35, -35, -26, 47, 26, -47, 47, -26,
1015 -47, 26, 32, 81, -32, -81, 81, 32,
1016 -81, -32, 56, 83, -56, -83, 83, 56,
1017 -83, -56, -18, 67, 18, -67, 67, -18,
1018 -67, 18, 13, 86, -13, -86, 86, 13,
1019 -86, -13, 91, 91, -91, -91, -7, 99,
1020 7, -99, 99, -7, -99, 7, -54, 68,
1021 54, -68, 68, -54, -68, 54, -44, 90,
1022 44, -90, 90, -44, -90, 44, -33, 124,
1023 33, -124, 124, -33, -124, 33, -103, 103,
1024 103, -103, -86, 127, 86, -127, 127, -86,
1025 -127, 86, 37, 37, -37, -37, 69, 69,
1026 -69, -69,
1027 ]};
1028
1029 const DT_1_6: IviDeltaCB = IviDeltaCB{ quad_radix: 12, data: &[
1030 0, 0, 7, 7, -7, -7, -3, 10,
1031 3, -10, 10, -3, -10, 3, 16, 16,
1032 -16, -16, 5, 18, -5, -18, 18, 5,
1033 -18, -5, -13, 13, 13, -13, -6, 21,
1034 6, -21, 21, -6, -21, 6, 15, 30,
1035 -15, -30, 30, 15, -30, -15, 30, 30,
1036 -30, -30, 2, 34, -2, -34, 34, 2,
1037 -34, -2, -19, 28, 19, -28, 28, -19,
1038 -28, 19, 32, 54, -32, -54, 54, 32,
1039 -54, -32, -11, 41, 11, -41, 41, -11,
1040 -41, 11, 15, 55, -15, -55, 55, 15,
1041 -55, -15, 57, 57, -57, -57, -1, 63,
1042 1, -63, 63, -1, -63, 1, -40, 40,
1043 40, -40, -30, 55, 30, -55, 55, -30,
1044 -55, 30, 37, 94, -37, -94, 94, 37,
1045 -94, -37, 65, 96, -65, -96, 96, 65,
1046 -96, -65, -21, 78, 21, -78, 78, -21,
1047 -78, 21, 15, 100, -15, -100, 100, 15,
1048 -100, -15, 106, 106, -106, -106, -8, 116,
1049 8, -116, 116, -8, -116, 8, -63, 79,
1050 63, -79, 79, -63, -79, 63, -51, 105,
1051 51, -105, 105, -51, -105, 51, -120, 120,
1052 120, -120, 43, 43, -43, -43, 80, 80,
1053 -80, -80,
1054 ]};
1055
1056 const DT_1_7: IviDeltaCB = IviDeltaCB{ quad_radix: 12, data: &[
1057 0, 0, 8, 8, -8, -8, -3, 11,
1058 3, -11, 11, -3, -11, 3, 18, 18,
1059 -18, -18, 5, 20, -5, -20, 20, 5,
1060 -20, -5, -15, 15, 15, -15, -7, 24,
1061 7, -24, 24, -7, -24, 7, 17, 35,
1062 -17, -35, 35, 17, -35, -17, 34, 34,
1063 -34, -34, 3, 38, -3, -38, 38, 3,
1064 -38, -3, -22, 32, 22, -32, 32, -22,
1065 -32, 22, 37, 61, -37, -61, 61, 37,
1066 -61, -37, -13, 47, 13, -47, 47, -13,
1067 -47, 13, 17, 63, -17, -63, 63, 17,
1068 -63, -17, 65, 65, -65, -65, -1, 72,
1069 1, -72, 72, -1, -72, 1, -46, 46,
1070 46, -46, -35, 63, 35, -63, 63, -35,
1071 -63, 35, 43, 107, -43, -107, 107, 43,
1072 -107, -43, 75, 110, -75, -110, 110, 75,
1073 -110, -75, -24, 89, 24, -89, 89, -24,
1074 -89, 24, 17, 114, -17, -114, 114, 17,
1075 -114, -17, 121, 121, -121, -121, -72, 91,
1076 72, -91, 91, -72, -91, 72, -58, 120,
1077 58, -120, 120, -58, -120, 58, 49, 49,
1078 -49, -49, 92, 92, -92, -92,
1079 ]};
1080
1081 const DT_1_8: IviDeltaCB = IviDeltaCB{ quad_radix: 13, data: &[
1082 0, 0, 9, 9, -9, -9, -3, 12,
1083 3, -12, 12, -3, -12, 3, 20, 20,
1084 -20, -20, 6, 23, -6, -23, 23, 6,
1085 -23, -6, -17, 17, 17, -17, -7, 27,
1086 7, -27, 27, -7, -27, 7, 19, 39,
1087 -19, -39, 39, 19, -39, -19, 39, 39,
1088 -39, -39, 3, 43, -3, -43, 43, 3,
1089 -43, -3, -24, 36, 24, -36, 36, -24,
1090 -36, 24, 42, 69, -42, -69, 69, 42,
1091 -69, -42, -14, 53, 14, -53, 53, -14,
1092 -53, 14, 19, 71, -19, -71, 71, 19,
1093 -71, -19, 73, 73, -73, -73, -2, 80,
1094 2, -80, 80, -2, -80, 2, -52, 52,
1095 52, -52, -39, 70, 39, -70, 70, -39,
1096 -70, 39, 48, 121, -48, -121, 121, 48,
1097 -121, -48, 84, 124, -84, -124, 124, 84,
1098 -124, -84, -27, 100, 27, -100, 100, -27,
1099 -100, 27, -81, 102, 81, -102, 102, -81,
1100 -102, 81, 55, 55, -55, -55, 104, 104,
1101 -104, -104,
1102 ]};
1103
1104 const DT_2_1: IviDeltaCB = IviDeltaCB{ quad_radix: 7, data: &[
1105 0, 0, 2, 2, -2, -2, 0, 2,
1106 0, -2, 2, 0, -2, 0, 4, 4,
1107 -4, -4, 0, 4, 0, -4, 4, 0,
1108 -4, 0, -4, 4, 4, -4, -2, 6,
1109 2, -6, 6, -2, -6, 2, 4, 8,
1110 -4, -8, 8, 4, -8, -4, 8, 8,
1111 -8, -8, 0, 10, 0, -10, 10, 0,
1112 -10, 0, -4, 8, 4, -8, 8, -4,
1113 -8, 4, 8, 14, -8, -14, 14, 8,
1114 -14, -8, -2, 12, 2, -12, 12, -2,
1115 -12, 2, 4, 16, -4, -16, 16, 4,
1116 -16, -4, 16, 16, -16, -16, 0, 18,
1117 0, -18, 18, 0, -18, 0, -12, 12,
1118 12, -12, -8, 16, 8, -16, 16, -8,
1119 -16, 8, 10, 26, -10, -26, 26, 10,
1120 -26, -10, 18, 28, -18, -28, 28, 18,
1121 -28, -18, -6, 22, 6, -22, 22, -6,
1122 -22, 6, 4, 28, -4, -28, 28, 4,
1123 -28, -4, 30, 30, -30, -30, -2, 32,
1124 2, -32, 32, -2, -32, 2, -18, 22,
1125 18, -22, 22, -18, -22, 18, -14, 30,
1126 14, -30, 30, -14, -30, 14, 22, 46,
1127 -22, -46, 46, 22, -46, -22, 12, 46,
1128 -12, -46, 46, 12, -46, -12, 34, 48,
1129 -34, -48, 48, 34, -48, -34, -10, 40,
1130 10, -40, 40, -10, -40, 10, 4, 50,
1131 -4, -50, 50, 4, -50, -4, 54, 54,
1132 -54, -54, -34, 34, 34, -34, -28, 42,
1133 28, -42, 42, -28, -42, 28, -6, 60,
1134 6, -60, 60, -6, -60, 6, 26, 76,
1135 -26, -76, 76, 26, -76, -26, 42, 76,
1136 -42, -76, 76, 42, -76, -42, -24, 54,
1137 24, -54, 54, -24, -54, 24, 14, 78,
1138 -14, -78, 78, 14, -78, -14, 62, 82,
1139 -62, -82, 82, 62, -82, -62, -20, 74,
1140 20, -74, 74, -20, -74, 20, 2, 88,
1141 -2, -88, 88, 2, -88, -2, 92, 92,
1142 -92, -92, -52, 60, 52, -60, 60, -52,
1143 -60, 52, 52, 118, -52, -118, 118, 52,
1144 -118, -52, -44, 74, 44, -74, 74, -44,
1145 -74, 44, 74, 118, -74, -118, 118, 74,
1146 -118, -74, 32, 118, -32, -118, 118, 32,
1147 -118, -32, -12, 102, 12, -102, 102, -12,
1148 -102, 12, -40, 96, 40, -96, 96, -40,
1149 -96, 40, -34, 118, 34, -118, 118, -34,
1150 -118, 34, -88, 88, 88, -88, -78, 104,
1151 78, -104, 104, -78, -104, 78, 12, 12,
1152 -12, -12, 22, 22, -22, -22, 42, 42,
1153 -42, -42, 72, 72, -72, -72,
1154 ]};
1155
1156 const DT_2_2: IviDeltaCB = IviDeltaCB{ quad_radix: 9, data: &[
1157 0, 0, 3, 3, -3, -3, 0, 3,
1158 0, -3, 3, 0, -3, 0, 6, 6,
1159 -6, -6, 3, 9, -3, -9, 9, 3,
1160 -9, -3, -3, 9, 3, -9, 9, -3,
1161 -9, 3, -6, 6, 6, -6, 6, 12,
1162 -6, -12, 12, 6, -12, -6, 12, 12,
1163 -12, -12, 0, 15, 0, -15, 15, 0,
1164 -15, 0, -9, 12, 9, -12, 12, -9,
1165 -12, 9, 15, 24, -15, -24, 24, 15,
1166 -24, -15, -6, 18, 6, -18, 18, -6,
1167 -18, 6, 6, 24, -6, -24, 24, 6,
1168 -24, -6, 24, 24, -24, -24, 0, 27,
1169 0, -27, 27, 0, -27, 0, -18, 18,
1170 18, -18, -12, 24, 12, -24, 24, -12,
1171 -24, 12, 15, 39, -15, -39, 39, 15,
1172 -39, -15, 27, 42, -27, -42, 42, 27,
1173 -42, -27, -9, 33, 9, -33, 33, -9,
1174 -33, 9, 6, 42, -6, -42, 42, 6,
1175 -42, -6, 45, 45, -45, -45, -3, 51,
1176 3, -51, 51, -3, -51, 3, -27, 33,
1177 27, -33, 33, -27, -33, 27, -21, 45,
1178 21, -45, 45, -21, -45, 21, 33, 69,
1179 -33, -69, 69, 33, -69, -33, 18, 69,
1180 -18, -69, 69, 18, -69, -18, 54, 72,
1181 -54, -72, 72, 54, -72, -54, -18, 63,
1182 18, -63, 63, -18, -63, 18, 6, 78,
1183 -6, -78, 78, 6, -78, -6, 81, 81,
1184 -81, -81, -51, 51, 51, -51, -42, 63,
1185 42, -63, 63, -42, -63, 42, -9, 90,
1186 9, -90, 90, -9, -90, 9, 42, 114,
1187 -42, -114, 114, 42, -114, -42, 63, 117,
1188 -63, -117, 117, 63, -117, -63, -36, 81,
1189 36, -81, 81, -36, -81, 36, 21, 120,
1190 -21, -120, 120, 21, -120, -21, 96, 123,
1191 -96, -123, 123, 96, -123, -96, -30, 111,
1192 30, -111, 111, -30, -111, 30, -78, 93,
1193 78, -93, 93, -78, -93, 78, -69, 114,
1194 69, -114, 114, -69, -114, 69, 18, 18,
1195 -18, -18, 33, 33, -33, -33, 63, 63,
1196 -63, -63, 108, 108, -108, -108,
1197 ]};
1198
1199 const DT_2_3: IviDeltaCB = IviDeltaCB{ quad_radix: 10, data: &[
1200 0, 0, 4, 4, -4, -4, 0, 4,
1201 0, -4, 4, 0, -4, 0, 4, 8,
1202 -4, -8, 8, 4, -8, -4, 8, 8,
1203 -8, -8, -8, 8, 8, -8, -4, 12,
1204 4, -12, 12, -4, -12, 4, 8, 16,
1205 -8, -16, 16, 8, -16, -8, 16, 16,
1206 -16, -16, 0, 20, 0, -20, 20, 0,
1207 -20, 0, -12, 16, 12, -16, 16, -12,
1208 -16, 12, -4, 24, 4, -24, 24, -4,
1209 -24, 4, 16, 32, -16, -32, 32, 16,
1210 -32, -16, 8, 32, -8, -32, 32, 8,
1211 -32, -8, 32, 32, -32, -32, 0, 36,
1212 0, -36, 36, 0, -36, 0, -24, 24,
1213 24, -24, -16, 32, 16, -32, 32, -16,
1214 -32, 16, 20, 52, -20, -52, 52, 20,
1215 -52, -20, 36, 56, -36, -56, 56, 36,
1216 -56, -36, -12, 44, 12, -44, 44, -12,
1217 -44, 12, 8, 56, -8, -56, 56, 8,
1218 -56, -8, 60, 60, -60, -60, -4, 64,
1219 4, -64, 64, -4, -64, 4, -36, 44,
1220 36, -44, 44, -36, -44, 36, -28, 60,
1221 28, -60, 60, -28, -60, 28, 44, 92,
1222 -44, -92, 92, 44, -92, -44, 24, 92,
1223 -24, -92, 92, 24, -92, -24, 72, 96,
1224 -72, -96, 96, 72, -96, -72, -20, 84,
1225 20, -84, 84, -20, -84, 20, 8, 100,
1226 -8, -100, 100, 8, -100, -8, 108, 108,
1227 -108, -108, -68, 68, 68, -68, -56, 84,
1228 56, -84, 84, -56, -84, 56, -12, 120,
1229 12, -120, 120, -12, -120, 12, -48, 108,
1230 48, -108, 108, -48, -108, 48, -104, 124,
1231 104, -124, 124, -104, -124, 104, 24, 24,
1232 -24, -24, 44, 44, -44, -44, 84, 84,
1233 -84, -84,
1234 ]};
1235
1236 const DT_2_4: IviDeltaCB = IviDeltaCB{ quad_radix: 11, data: &[
1237 0, 0, 5, 5, -5, -5, 0, 5,
1238 0, -5, 5, 0, -5, 0, 10, 10,
1239 -10, -10, 5, 15, -5, -15, 15, 5,
1240 -15, -5, -10, 10, 10, -10, -5, 15,
1241 5, -15, 15, -5, -15, 5, 10, 20,
1242 -10, -20, 20, 10, -20, -10, 20, 20,
1243 -20, -20, 0, 25, 0, -25, 25, 0,
1244 -25, 0, -15, 20, 15, -20, 20, -15,
1245 -20, 15, 25, 40, -25, -40, 40, 25,
1246 -40, -25, -10, 30, 10, -30, 30, -10,
1247 -30, 10, 10, 40, -10, -40, 40, 10,
1248 -40, -10, 40, 40, -40, -40, 0, 45,
1249 0, -45, 45, 0, -45, 0, -30, 30,
1250 30, -30, -20, 40, 20, -40, 40, -20,
1251 -40, 20, 25, 65, -25, -65, 65, 25,
1252 -65, -25, 45, 70, -45, -70, 70, 45,
1253 -70, -45, -15, 55, 15, -55, 55, -15,
1254 -55, 15, 10, 70, -10, -70, 70, 10,
1255 -70, -10, 75, 75, -75, -75, -5, 85,
1256 5, -85, 85, -5, -85, 5, -45, 55,
1257 45, -55, 55, -45, -55, 45, -35, 75,
1258 35, -75, 75, -35, -75, 35, 55, 115,
1259 -55, -115, 115, 55, -115, -55, 30, 115,
1260 -30, -115, 115, 30, -115, -30, 90, 120,
1261 -90, -120, 120, 90, -120, -90, -30, 105,
1262 30, -105, 105, -30, -105, 30, -85, 85,
1263 85, -85, -70, 105, 70, -105, 105, -70,
1264 -105, 70, 30, 30, -30, -30, 60, 60,
1265 -60, -60, 105, 105, -105, -105,
1266 ]};
1267
1268 const DT_2_5: IviDeltaCB = IviDeltaCB{ quad_radix: 12, data: &[
1269 0, 0, 6, 6, -6, -6, 0, 6,
1270 0, -6, 6, 0, -6, 0, 12, 12,
1271 -12, -12, 6, 12, -6, -12, 12, 6,
1272 -12, -6, -12, 12, 12, -12, -6, 18,
1273 6, -18, 18, -6, -18, 6, 12, 24,
1274 -12, -24, 24, 12, -24, -12, 24, 24,
1275 -24, -24, 0, 30, 0, -30, 30, 0,
1276 -30, 0, -18, 24, 18, -24, 24, -18,
1277 -24, 18, 30, 48, -30, -48, 48, 30,
1278 -48, -30, -6, 36, 6, -36, 36, -6,
1279 -36, 6, 12, 48, -12, -48, 48, 12,
1280 -48, -12, 48, 48, -48, -48, 0, 54,
1281 0, -54, 54, 0, -54, 0, -36, 36,
1282 36, -36, -24, 48, 24, -48, 48, -24,
1283 -48, 24, 30, 78, -30, -78, 78, 30,
1284 -78, -30, 54, 84, -54, -84, 84, 54,
1285 -84, -54, -18, 66, 18, -66, 66, -18,
1286 -66, 18, 12, 84, -12, -84, 84, 12,
1287 -84, -12, 90, 90, -90, -90, -6, 96,
1288 6, -96, 96, -6, -96, 6, -54, 66,
1289 54, -66, 66, -54, -66, 54, -42, 90,
1290 42, -90, 90, -42, -90, 42, -30, 126,
1291 30, -126, 126, -30, -126, 30, -102, 102,
1292 102, -102, -84, 126, 84, -126, 126, -84,
1293 -126, 84, 36, 36, -36, -36, 66, 66,
1294 -66, -66,
1295 ]};
1296
1297 const DT_2_6: IviDeltaCB = IviDeltaCB{ quad_radix: 12, data: &[
1298 0, 0, 7, 7, -7, -7, 0, 7,
1299 0, -7, 7, 0, -7, 0, 14, 14,
1300 -14, -14, 7, 21, -7, -21, 21, 7,
1301 -21, -7, -14, 14, 14, -14, -7, 21,
1302 7, -21, 21, -7, -21, 7, 14, 28,
1303 -14, -28, 28, 14, -28, -14, 28, 28,
1304 -28, -28, 0, 35, 0, -35, 35, 0,
1305 -35, 0, -21, 28, 21, -28, 28, -21,
1306 -28, 21, 35, 56, -35, -56, 56, 35,
1307 -56, -35, -14, 42, 14, -42, 42, -14,
1308 -42, 14, 14, 56, -14, -56, 56, 14,
1309 -56, -14, 56, 56, -56, -56, 0, 63,
1310 0, -63, 63, 0, -63, 0, -42, 42,
1311 42, -42, -28, 56, 28, -56, 56, -28,
1312 -56, 28, 35, 91, -35, -91, 91, 35,
1313 -91, -35, 63, 98, -63, -98, 98, 63,
1314 -98, -63, -21, 77, 21, -77, 77, -21,
1315 -77, 21, 14, 98, -14, -98, 98, 14,
1316 -98, -14, 105, 105, -105, -105, -7, 119,
1317 7, -119, 119, -7, -119, 7, -63, 77,
1318 63, -77, 77, -63, -77, 63, -49, 105,
1319 49, -105, 105, -49, -105, 49, -119, 119,
1320 119, -119, 42, 42, -42, -42, 77, 77,
1321 -77, -77,
1322 ]};
1323
1324 const DT_2_7: IviDeltaCB = IviDeltaCB{ quad_radix: 12, data: &[
1325 0, 0, 8, 8, -8, -8, 0, 8,
1326 0, -8, 8, 0, -8, 0, 16, 16,
1327 -16, -16, 8, 16, -8, -16, 16, 8,
1328 -16, -8, -16, 16, 16, -16, -8, 24,
1329 8, -24, 24, -8, -24, 8, 16, 32,
1330 -16, -32, 32, 16, -32, -16, 32, 32,
1331 -32, -32, 0, 40, 0, -40, 40, 0,
1332 -40, 0, -24, 32, 24, -32, 32, -24,
1333 -32, 24, 40, 64, -40, -64, 64, 40,
1334 -64, -40, -16, 48, 16, -48, 48, -16,
1335 -48, 16, 16, 64, -16, -64, 64, 16,
1336 -64, -16, 64, 64, -64, -64, 0, 72,
1337 0, -72, 72, 0, -72, 0, -48, 48,
1338 48, -48, -32, 64, 32, -64, 64, -32,
1339 -64, 32, 40, 104, -40, -104, 104, 40,
1340 -104, -40, 72, 112, -72, -112, 112, 72,
1341 -112, -72, -24, 88, 24, -88, 88, -24,
1342 -88, 24, 16, 112, -16, -112, 112, 16,
1343 -112, -16, 120, 120, -120, -120, -72, 88,
1344 72, -88, 88, -72, -88, 72, -56, 120,
1345 56, -120, 120, -56, -120, 56, 48, 48,
1346 -48, -48, 88, 88, -88, -88,
1347 ]};
1348
1349 const DT_2_8: IviDeltaCB = IviDeltaCB{ quad_radix: 13, data: &[
1350 0, 0, 9, 9, -9, -9, 0, 9,
1351 0, -9, 9, 0, -9, 0, 18, 18,
1352 -18, -18, 9, 27, -9, -27, 27, 9,
1353 -27, -9, -18, 18, 18, -18, -9, 27,
1354 9, -27, 27, -9, -27, 9, 18, 36,
1355 -18, -36, 36, 18, -36, -18, 36, 36,
1356 -36, -36, 0, 45, 0, -45, 45, 0,
1357 -45, 0, -27, 36, 27, -36, 36, -27,
1358 -36, 27, 45, 72, -45, -72, 72, 45,
1359 -72, -45, -18, 54, 18, -54, 54, -18,
1360 -54, 18, 18, 72, -18, -72, 72, 18,
1361 -72, -18, 72, 72, -72, -72, 0, 81,
1362 0, -81, 81, 0, -81, 0, -54, 54,
1363 54, -54, -36, 72, 36, -72, 72, -36,
1364 -72, 36, 45, 117, -45, -117, 117, 45,
1365 -117, -45, 81, 126, -81, -126, 126, 81,
1366 -126, -81, -27, 99, 27, -99, 99, -27,
1367 -99, 27, -81, 99, 81, -99, 99, -81,
1368 -99, 81, 54, 54, -54, -54, 108, 108,
1369 -108, -108,
1370 ]};
1371
1372 const DT_3_1: IviDeltaCB = IviDeltaCB{ quad_radix: 11, data: &[
1373 0, 0, 2, 2, -2, -2, 0, 3,
1374 0, -3, 3, 0, -3, 0, 6, 6,
1375 -6, -6, 0, 7, 0, -7, 7, 0,
1376 -7, 0, -5, 5, 5, -5, 5, -5,
1377 -5, 5, 6, 11, -6, -11, 11, 6,
1378 -11, -6, 0, 8, 0, -8, 8, 0,
1379 -8, 0, 11, 11, -11, -11, 0, 12,
1380 0, -12, 12, 0, -12, 0, 12, 17,
1381 -12, -17, 17, 12, -17, -12, 17, 17,
1382 -17, -17, 6, 18, -6, -18, 18, 6,
1383 -18, -6, -8, 11, 8, -11, 11, -8,
1384 -11, 8, 0, 15, 0, -15, 15, 0,
1385 -15, 0, 0, 20, 0, -20, 20, 0,
1386 -20, 0, 18, 25, -18, -25, 25, 18,
1387 -25, -18, 11, 25, -11, -25, 25, 11,
1388 -25, -11, 25, 25, -25, -25, -14, 14,
1389 14, -14, 14, -14, -14, 14, 0, 26,
1390 0, -26, 26, 0, -26, 0, -11, 18,
1391 11, -18, 18, -11, -18, 11, -7, 22,
1392 7, -22, 22, -7, -22, 7, 26, 34,
1393 -26, -34, 34, 26, -34, -26, 18, 34,
1394 -18, -34, 34, 18, -34, -18, 34, 34,
1395 -34, -34, 11, 35, -11, -35, 35, 11,
1396 -35, -11, 0, 29, 0, -29, 29, 0,
1397 -29, 0, -19, 22, 19, -22, 22, -19,
1398 -22, 19, -15, 26, 15, -26, 26, -15,
1399 -26, 15, 0, 37, 0, -37, 37, 0,
1400 -37, 0, 27, 44, -27, -44, 44, 27,
1401 -44, -27, 36, 44, -36, -44, 44, 36,
1402 -44, -36, 18, 44, -18, -44, 44, 18,
1403 -44, -18, -10, 33, 10, -33, 33, -10,
1404 -33, 10, 45, 45, -45, -45, 0, 0,
1405 ]};
1406
1407 const DT_3_2: IviDeltaCB = IviDeltaCB{ quad_radix: 13, data: &[
1408 0, 0, 0, 2, 0, -2, 2, 0,
1409 -2, 0, 2, 2, -2, -2, 6, 6,
1410 -6, -6, 0, 6, 0, -6, 6, 0,
1411 -6, 0, -4, 4, 4, -4, 10, -6,
1412 -10, 6, 0, -12, 0, 12, -6, -12,
1413 6, -12, -6, 12, 6, 12, -14, 0,
1414 14, 0, 12, 12, -12, -12, 0, -18,
1415 0, 18, 14, -12, -14, 12, -18, -6,
1416 18, -6, -18, 6, 18, 6, -10, -18,
1417 10, -18, -10, 18, 10, 18, -22, 0,
1418 22, 0, 0, -24, 0, 24, -22, -12,
1419 22, -12, -22, 12, 22, 12, -8, -24,
1420 8, -24, -8, 24, 8, 24, -26, -6,
1421 26, -6, -26, 6, 26, 6, -28, 0,
1422 28, 0, 20, 20, -20, -20, -14, -26,
1423 14, 26, -30, -12, 30, 12, -10, -32,
1424 10, 32, -18, -32, 18, 32, -26, -26,
1425 26, 26, -34, -20, 34, 20, -38, -12,
1426 38, 12, -32, -32, 32, 32, 32, 32,
1427 -22, -40, -34, -34, 34, 34,
1428 ]};
1429
1430 const DT_3_3: IviDeltaCB = IviDeltaCB{ quad_radix: 13, data: &[
1431 0, 0, 0, 2, 0, -2, 2, 0,
1432 -2, 0, 4, 4, -4, -4, 10, 10,
1433 -10, -10, 0, 10, 0, -10, 10, 0,
1434 -10, 0, -6, 6, 6, -6, 14, -8,
1435 -14, 8, -18, 0, 18, 0, 10, -16,
1436 -10, 16, 0, -24, 0, 24, -24, -8,
1437 24, -8, -24, 8, 24, 8, 18, 18,
1438 -18, -18, 20, -16, -20, 16, -14, -26,
1439 14, -26, -14, 26, 14, 26, -30, 0,
1440 30, 0, 0, -34, 0, 34, -34, -8,
1441 34, -8, -34, 8, 34, 8, -30, -18,
1442 30, -18, -30, 18, 30, 18, -10, -34,
1443 10, -34, -10, 34, 10, 34, -20, -34,
1444 20, 34, -40, 0, 40, 0, 30, 30,
1445 -30, -30, -40, -18, 40, 18, 0, -44,
1446 0, 44, -16, -44, 16, 44, -36, -36,
1447 -36, -36, 36, 36, -26, -44, 26, 44,
1448 -46, -26, 46, 26, -52, -18, 52, 18,
1449 -20, -54, -44, -44, 44, 44, -32, -54,
1450 -46, -46, -46, -46, 46, 46,
1451 ]};
1452
1453 const DT_3_4: IviDeltaCB = IviDeltaCB{ quad_radix: 13, data: &[
1454 0, 0, 0, 4, 0, -4, 4, 0,
1455 -4, 0, 4, 4, -4, -4, 12, 12,
1456 -12, -12, 0, 12, 0, -12, 12, 0,
1457 -12, 0, -8, 8, 8, -8, 8, -16,
1458 -8, 16, 0, -24, 0, 24, -24, -8,
1459 24, -8, -24, 8, 24, 8, 20, -16,
1460 -20, 16, -28, 0, 28, 0, -16, -24,
1461 16, -24, -16, 24, 16, 24, 0, -32,
1462 0, 32, -28, -16, 28, -16, -28, 16,
1463 28, 16, -8, -32, 8, -32, -32, -8,
1464 32, -8, -32, 8, 32, 8, -8, 32,
1465 8, 32, 24, 24, -24, -24, 24, -24,
1466 -24, 24, -20, -32, 20, 32, -40, 0,
1467 40, 0, -40, -16, 40, 16, 0, -44,
1468 0, -44, -44, 0, 44, 0, 0, 44,
1469 0, 44, -32, -32, 32, 32, -16, -44,
1470 16, 44, -24, -44, -44, -24, 44, 24,
1471 24, 44, -48, -16, 48, 16, -36, -36,
1472 -36, -36, 36, 36, 36, 36, -20, -52,
1473 40, 40, -40, -40, -32, -52,
1474 ]};
1475
1476 const DT_3_5: IviDeltaCB = IviDeltaCB{ quad_radix: 13, data: &[
1477 0, 0, 2, 2, -2, -2, 6, 6,
1478 -6, -6, 12, 12, -12, -12, 20, 20,
1479 -20, -20, 32, 32, -32, -32, 46, 46,
1480 -46, -46, 0, 0, 0, 0, 0, 0,
1481 0, 0, 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,
1497 ]};
1498
1499 const IVI3_DELTA_CBS: [&IviDeltaCB; 24] = [
1500 &DT_1_1, &DT_1_2, &DT_1_3, &DT_1_4, &DT_1_5, &DT_1_6, &DT_1_7, &DT_1_8,
1501 &DT_2_1, &DT_2_2, &DT_2_3, &DT_2_4, &DT_2_5, &DT_2_6, &DT_2_7, &DT_2_8,
1502 &DT_3_1, &DT_3_2, &DT_3_3, &DT_3_4, &DT_3_5, &DT_3_5, &DT_3_5, &DT_3_5
1503 ];