indeo3: various small fixes
[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 for i in 0..w { self.dbuf[didx + i] = self.sbuf[sidx + i]; }
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 for i in 0..w { self.dbuf[didx + i] = buf[i]; }
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 for i in 0..bw { buf[i] = src[i]; }
157 } else {
158 for i in 0..bw { buf[i] = DEFAULT_PIXEL; }
159 }
160 let dst = &mut bufs.dbuf[off..][..bw];
161 for i in 0..bw { dst[i] = buf[i]; }
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 for i in 0..8 {dst[i] = buf[i]; }
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 for i in 0..8 { bufs.dbuf[didx + i] = buf[i]; }
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 }
219
220 #[derive(Clone,Copy)]
221 struct IV3Cell {
222 x: u16,
223 y: u16,
224 w: u16,
225 h: u16,
226 d: u8,
227 vqt: bool,
228 mv: Option<MV>,
229 }
230
231 impl IV3Cell {
232 fn new(w: u16, h: u16) -> Self {
233 IV3Cell { x: 0, y: 0, w, h, d: 20, vqt: false, mv: None }
234 }
235 fn split_h(&self) -> (Self, Self) {
236 let h1 = if self.h > 2 { ((self.h + 2) >> 2) << 1 } else { 1 };
237 let h2 = self.h - h1;
238 let mut cell1 = *self;
239 cell1.h = h1;
240 cell1.d -= 1;
241 let mut cell2 = *self;
242 cell2.y += h1;
243 cell2.h = h2;
244 cell2.d -= 1;
245 (cell1, cell2)
246 }
247 fn split_w(&self, stripw: u16) -> (Self, Self) {
248 let w1 = if self.w > stripw {
249 if self.w > stripw * 2 { stripw * 2 } else { stripw }
250 } else {
251 if self.w > 2 { ((self.w + 2) >> 2) << 1 } else { 1 }
252 };
253 let w2 = self.w - w1;
254 let mut cell1 = *self;
255 cell1.w = w1;
256 cell1.d -= 1;
257 let mut cell2 = *self;
258 cell2.x += w1;
259 cell2.w = w2;
260 cell2.d -= 1;
261 (cell1, cell2)
262 }
263 fn no_mv(&self) -> bool { self.mv.is_none() }
264 }
265
266 struct CellDecParams {
267 tab: [usize; 2],
268 bw: u16,
269 bh: u16,
270 swap_q: [bool; 2],
271 hq: bool,
272 apply_delta: fn (&mut Buffers, usize, usize, &[u8], bool, bool),
273 copy_line_top: fn (&mut Buffers, usize, usize, bool),
274 }
275
276 const FRMH_TAG: u32 = ((b'F' as u32) << 24) | ((b'R' as u32) << 16)
277 | ((b'M' as u32) << 8) | (b'H' as u32);
278
279 const H_SPLIT: u8 = 0;
280 const V_SPLIT: u8 = 1;
281 const SKIP_OR_TREE: u8 = 2;
282
283 impl Indeo3Decoder {
284 fn new() -> Self {
285 let dummy_info = NACodecInfo::new_dummy();
286 Indeo3Decoder { info: dummy_info, bpos: 0, bbuf: 0, width: 0, height: 0,
287 mvs: Vec::new(), altquant: [0; 16],
288 vq_offset: 0, bufs: Buffers::new() }
289 }
290
291 fn br_reset(&mut self) {
292 self.bpos = 0;
293 self.bbuf = 0;
294 }
295
296 fn get_2bits(&mut self, br: &mut ByteReader) -> DecoderResult<u8> {
297 if self.bpos == 0 {
298 self.bbuf = br.read_byte()?;
299 self.bpos = 8;
300 }
301 self.bpos -= 2;
302 Ok((self.bbuf >> self.bpos) & 0x3)
303 }
304
305 fn decode_cell_data(&mut self, br: &mut ByteReader, cell: IV3Cell,
306 off: usize, stride: usize, params: CellDecParams) -> DecoderResult<()> {
307 let blk_w = cell.w * 4 / params.bw;
308 let blk_h = cell.h * 4 / params.bh;
309 let scale: usize = if params.bh == 4 { 1 } else { 2 };
310
311 validate!((((cell.w * 4) % params.bw) == 0) && (((cell.h * 4) % params.bh) == 0));
312
313 let mut run_blocks = 0;
314 let mut run_skip = false;
315
316 let mut didx: usize = ((cell.x*4) as usize) + ((cell.y * 4) as usize) * stride + off;
317 let mut sidx: usize;
318
319 if cell.no_mv() {
320 sidx = 0;
321 } else {
322 let mv = cell.mv.unwrap();
323 let mx = i16::from(mv.x);
324 let my = i16::from(mv.y);
325 let l = (cell.x as i16) * 4 + mx;
326 let t = (cell.y as i16) * 4 + my;
327 let r = ((cell.x + cell.w) as i16) * 4 + mx;
328 let b = ((cell.y + cell.h) as i16) * 4 + my;
329 validate!(l >= 0);
330 validate!(t >= 0);
331 validate!(r <= (self.width as i16));
332 validate!(b <= (self.height as i16));
333 sidx = (l as usize) + (t as usize) * stride + off;
334 }
335 for y in 0..blk_h {
336 let mut xoff: usize = 0;
337 for _ in 0..blk_w {
338 if run_blocks > 0 {
339 if !run_skip || !cell.no_mv() {
340 if !(params.bw == 8 && cell.no_mv()) {
341 if !cell.no_mv() {
342 self.bufs.copy_block(didx + xoff, sidx + xoff, stride,
343 params.bw as usize, params.bh as usize);
344 } else {
345 self.bufs.fill_block(didx + xoff, stride,
346 params.bw as usize, params.bh as usize,
347 (cell.y == 0) && (y == 0));
348 }
349 } else {
350 fill_block8x8(&mut self.bufs,
351 didx + xoff, stride, 8,
352 y == 0, (cell.y == 0) && (y == 0));
353 }
354 }
355 run_blocks -= 1;
356 } else {
357 let mut line: usize = 0;
358 while line < 4 {
359 let c = br.read_byte()?;
360 if c < 0xF8 {
361 let delta_tab = if params.hq {
362 IVI3_DELTA_CBS[params.tab[line & 1]]
363 } else {
364 IVI3_DELTA_CBS[params.tab[1]]
365 };
366 let mut idx1;
367 let mut idx2;
368 if (c as usize) < delta_tab.data.len()/2 {
369 idx1 = br.read_byte()? as usize;
370 validate!(idx1 < delta_tab.data.len() / 2);
371 idx2 = c as usize;
372 } else {
373 let tmp = (c as usize) - delta_tab.data.len()/2;
374 idx1 = tmp / (delta_tab.quad_radix as usize);
375 idx2 = tmp % (delta_tab.quad_radix as usize);
376 if params.swap_q[line & 1] {
377 mem::swap(&mut idx1, &mut idx2);
378 }
379 }
380 let deltas: [u8; 4] = [delta_tab.data[idx1 * 2] as u8,
381 delta_tab.data[idx1 * 2 + 1] as u8,
382 delta_tab.data[idx2 * 2 + 0] as u8,
383 delta_tab.data[idx2 * 2 + 1] as u8];
384 let topline = (cell.y == 0) && (y == 0) && (line == 0);
385 let first_line = (y == 0) && (line == 0);
386 if cell.no_mv() {
387 (params.copy_line_top)(&mut self.bufs,
388 didx + xoff + line * scale * stride,
389 stride, topline);
390 } else {
391 self.bufs.copy_block(didx + xoff + line * scale * stride,
392 sidx + xoff + line * scale * stride,
393 stride, params.bw as usize, scale);
394 }
395 (params.apply_delta)(&mut self.bufs,
396 didx + xoff + line * scale * stride,
397 stride, &deltas, topline, first_line);
398 line += 1;
399 } else {
400 let mut tocopy: usize = 0;
401 let mut do_copy = true;
402 if c == 0xF8 { return Err(DecoderError::InvalidData); }
403 if c == 0xF9 {
404 run_blocks = 1;
405 run_skip = true;
406 validate!(line == 0);
407 tocopy = 4;
408 do_copy = !cell.no_mv();
409 }
410 if c == 0xFA {
411 validate!(line == 0);
412 tocopy = 4;
413 do_copy = !cell.no_mv();
414 }
415 if c == 0xFB {
416 let c = br.read_byte()?;
417 validate!((c < 64) && ((c & 0x1F) != 0));
418 run_blocks = (c & 0x1F) - 1;
419 run_skip = (c & 0x20) != 0;
420 tocopy = 4 - line;
421 if params.bw == 4 && cell.no_mv() && run_skip {
422 do_copy = false;
423 }
424 }
425 if c == 0xFC {
426 run_skip = false;
427 run_blocks = 1;
428 tocopy = 4 - line;
429 }
430 if c >= 0xFD {
431 let nl = 257 - i16::from(c) - (line as i16);
432 validate!(nl > 0);
433 tocopy = nl as usize;
434 }
435 if do_copy {
436 if !(params.bh == 8 && cell.no_mv()) {
437 if !cell.no_mv() {
438 self.bufs.copy_block(didx + xoff + line * scale * stride,
439 sidx + xoff + line * scale * stride,
440 stride, params.bw as usize,
441 tocopy * scale);
442 } else {
443 self.bufs.fill_block(didx + xoff + line * scale * stride,
444 stride, params.bw as usize,
445 tocopy * scale,
446 (cell.y == 0) && (y == 0) && (line == 0));
447 }
448 } else {
449 fill_block8x8(&mut self.bufs,
450 didx + xoff + line * 2 * stride,
451 stride, tocopy * 2,
452 (y == 0) && (line == 0),
453 (cell.y == 0) && (y == 0) && (line == 0));
454 }
455 }
456 line += tocopy;
457 }
458 }
459 }
460 xoff += params.bw as usize;
461 }
462 didx += stride * (params.bh as usize);
463 sidx += stride * (params.bh as usize);
464 }
465 Ok(())
466 }
467
468 fn copy_cell(&mut self, cell: IV3Cell, off: usize, stride: usize) -> DecoderResult<()> {
469 if cell.no_mv() { return Err(DecoderError::InvalidData); }
470 let mv = cell.mv.unwrap();
471 let mx = i16::from(mv.x);
472 let my = i16::from(mv.y);
473 let l = (cell.x as i16) * 4 + mx;
474 let t = (cell.y as i16) * 4 + my;
475 let r = ((cell.x + cell.w) as i16) * 4 + mx;
476 let b = ((cell.y + cell.h) as i16) * 4 + my;
477 validate!(l >= 0);
478 validate!(t >= 0);
479 validate!(r <= (self.width as i16));
480 validate!(b <= (self.height as i16));
481 let sidx: usize = off + (l as usize) + (t as usize) * stride;
482 let didx: usize = off + ((cell.x * 4) as usize) + ((cell.y * 4) as usize) * stride;
483 self.bufs.copy_block(didx, sidx, stride, (cell.w * 4) as usize, (cell.h * 4) as usize);
484 Ok(())
485 }
486
487 fn decode_cell(&mut self, br: &mut ByteReader, cell: IV3Cell, off: usize,
488 stride: usize, intra: bool) -> DecoderResult<()> {
489 let code = br.read_byte()?;
490 let mode = code >> 4;
491 let vq_idx = code & 0xF;
492
493 let mut idx1: usize = vq_idx as usize;
494 let mut idx2: usize = vq_idx as usize;
495 if (mode == 1) || (mode == 4) {
496 let c = self.altquant[vq_idx as usize];
497 idx1 = (c >> 4) as usize;
498 idx2 = (c & 0xF) as usize;
499 } else {
500 idx1 += self.vq_offset as usize;
501 idx2 += self.vq_offset as usize;
502 }
503 validate!((idx1 < 24) && (idx2 < 24));
504
505 let mut cp = CellDecParams {
506 tab: [idx2, idx1],
507 bw: 0, bh: 0,
508 swap_q: [idx2 >= 16, idx1 >= 16],
509 hq: false,
510 apply_delta: apply_delta4x4,
511 copy_line_top: copy_line_top4x4,
512 };
513 if (mode == 0) || (mode == 1) {
514 cp.bw = 4;
515 cp.bh = 4;
516 cp.hq = true;
517 } else if (mode == 3) || (mode == 4) {
518 if !cell.no_mv() { return Err(DecoderError::InvalidData); }
519 cp.bw = 4;
520 cp.bh = 8;
521 cp.hq = true;
522 cp.apply_delta = apply_delta4x8;
523 cp.copy_line_top = copy_line_top4x8;
524 } else if mode == 10 {
525 if !cell.no_mv() {
526 validate!(!intra);
527 cp.apply_delta = apply_delta8x8p;
528 } else {
529 cp.apply_delta = apply_delta8x8i;
530 }
531 cp.bw = 8;
532 cp.bh = 8;
533 cp.copy_line_top = copy_line_top8x8;
534 } else if mode == 11 {
535 if cell.no_mv() { return Err(DecoderError::InvalidData); }
536 validate!(!intra);
537 cp.bw = 4;
538 cp.bh = 8;
539 cp.apply_delta = apply_delta4x8m11;
540 cp.copy_line_top = copy_line_top4x8;
541 } else {
542 return Err(DecoderError::InvalidData);
543 }
544 self.decode_cell_data(br, cell, off, stride, cp)
545 }
546
547 fn parse_tree(&mut self, br: &mut ByteReader, cell: IV3Cell, off: usize,
548 stride: usize, stripw: u16, intra: bool) -> DecoderResult<()> {
549 let op = self.get_2bits(br)?;
550 if op == H_SPLIT {
551 validate!(cell.h > 1);
552 validate!(cell.d > 0);
553 let (cell1, cell2) = cell.split_h();
554 self.parse_tree(br, cell1, off, stride, stripw, intra)?;
555 self.parse_tree(br, cell2, off, stride, stripw, intra)?;
556 Ok(())
557 } else if op == V_SPLIT {
558 validate!(cell.w > 1);
559 validate!(cell.d > 0);
560 let (cell1, cell2) = cell.split_w(stripw);
561 self.parse_tree(br, cell1, off, stride, stripw, intra)?;
562 self.parse_tree(br, cell2, off, stride, stripw, intra)?;
563 Ok(())
564 } else if op == SKIP_OR_TREE {
565 if !cell.vqt {
566 let mut newcell = cell;
567 newcell.vqt = true;
568 newcell.d -= 1;
569 self.parse_tree(br, newcell, off, stride, stripw, intra)
570 } else {
571 validate!(!intra);
572 let code = self.get_2bits(br)?;
573 validate!(code < 2);
574 if code == 1 { return Err(DecoderError::NotImplemented); }
575 self.copy_cell(cell, off, stride)
576 }
577 } else {
578 if !cell.vqt {
579 let mut newcell = cell;
580 newcell.vqt = true;
581 newcell.d -= 1;
582 let mv_idx = br.read_byte()? as usize;
583 validate!(mv_idx < self.mvs.len());
584 newcell.mv = Some(self.mvs[mv_idx]);
585 self.parse_tree(br, newcell, off, stride, stripw, intra)
586 } else {
587 self.decode_cell(br, cell, off, stride, intra)
588 }
589 }
590 }
591
592 fn decode_plane_intra(&mut self, br: &mut ByteReader, planeno: usize,
593 start: u64, end: u64) -> DecoderResult<()> {
594 let offs = self.bufs.get_offset(planeno);
595 let stride = self.bufs.get_stride(planeno);
596 br.seek(SeekFrom::Start(start))?;
597
598 let nvec = br.read_u32le()?;
599 validate!(nvec == 0); // for intra there should be no mc_vecs
600 self.mvs.truncate(0);
601 for _ in 0..nvec {
602 let x = br.read_byte()? as i8;
603 let y = br.read_byte()? as i8;
604 self.mvs.push(MV{ x, y });
605 }
606
607 let (cellwidth, cellheight) = if planeno == 0 {
608 (self.bufs.width >> 2, self.bufs.height >> 2)
609 } else {
610 (((self.bufs.width >> 2) + 3) >> 2, ((self.bufs.height >> 2) + 3) >> 2)
611 };
612 let cell = IV3Cell::new(cellwidth as u16, cellheight as u16);
613 self.br_reset();
614 self.parse_tree(br, cell, offs, stride, if planeno > 0 { 10 } else { 40 }, true)?;
615 validate!(br.tell() <= end);
616 Ok(())
617 }
618
619 fn decode_plane_inter(&mut self, br: &mut ByteReader, planeno: usize,
620 start: u64, end: u64) -> DecoderResult<()> {
621 let offs = self.bufs.get_offset(planeno);
622 let stride = self.bufs.get_stride(planeno);
623 br.seek(SeekFrom::Start(start))?;
624
625 let nvec = br.read_u32le()?;
626 validate!(nvec <= 256); // for intra there should be no mc_vecs
627 self.mvs.truncate(0);
628 for _ in 0..nvec {
629 let y = br.read_byte()? as i8;
630 let x = br.read_byte()? as i8;
631 self.mvs.push(MV{ x, y });
632 }
633
634 let (cellwidth, cellheight) = if planeno == 0 {
635 (self.bufs.width >> 2, self.bufs.height >> 2)
636 } else {
637 (((self.bufs.width >> 2) + 3) >> 2, ((self.bufs.height >> 2) + 3) >> 2)
638 };
639 let cell = IV3Cell::new(cellwidth as u16, cellheight as u16);
640 self.br_reset();
641 self.parse_tree(br, cell, offs, stride, if planeno > 0 { 10 } else { 40 }, false)?;
642 validate!(br.tell() <= end);
643 Ok(())
644 }
645 }
646
647 const FLAG_KEYFRAME: u16 = 1 << 2;
648 const FLAG_NONREF: u16 = 1 << 8;
649
650 impl NADecoder for Indeo3Decoder {
651 fn init(&mut self, _supp: &mut NADecoderSupport, info: NACodecInfoRef) -> DecoderResult<()> {
652 if let NACodecTypeInfo::Video(vinfo) = info.get_properties() {
653 let w = vinfo.get_width();
654 let h = vinfo.get_height();
655 let fmt = formats::YUV410_FORMAT;
656 let myinfo = NACodecTypeInfo::Video(NAVideoInfo::new(w, h, false, fmt));
657 self.info = NACodecInfo::new_ref(info.get_name(), myinfo, info.get_extradata()).into_ref();
658 self.bufs.reset();
659 Ok(())
660 } else {
661 Err(DecoderError::InvalidData)
662 }
663 }
664 fn decode(&mut self, _supp: &mut NADecoderSupport, pkt: &NAPacket) -> DecoderResult<NAFrameRef> {
665 let src = pkt.get_buffer();
666 let mut mr = MemoryReader::new_read(&src);
667 let mut br = ByteReader::new(&mut mr);
668 let frameno = br.read_u32le()?;
669 let hdr_2 = br.read_u32le()?;
670 let check = br.read_u32le()?;
671 let size = br.read_u32le()?;
672
673 let data_start = br.tell();
674
675 if (frameno ^ hdr_2 ^ size ^ FRMH_TAG) != check {
676 return Err(DecoderError::InvalidData);
677 }
678 if i64::from(size) > br.left() { return Err(DecoderError::InvalidData); }
679 let ver = br.read_u16le()?;
680 if ver != 32 { return Err(DecoderError::NotImplemented); }
681 let flags = br.read_u16le()?;
682 let size2 = br.read_u32le()?;
683 validate!(((size2 + 7) >> 3) <= size);
684 let cb = br.read_byte()?;
685 self.vq_offset = cb;
686 br.read_skip(3)?;
687 let height = br.read_u16le()?;
688 let width = br.read_u16le()?;
689 validate!((width >= 16) && (width <= 640));
690 validate!((height >= 16) && (height <= 640));
691 validate!(((width & 3) == 0) && ((height & 3) == 0));
692 if (self.bufs.width != (width as usize)) || (self.bufs.height != (height as usize)) {
693 self.bufs.alloc(width as usize, height as usize);
694 }
695 self.width = width;
696 self.height = height;
697
698 let yoff = br.read_u32le()?;
699 let uoff = br.read_u32le()?;
700 let voff = br.read_u32le()?;
701 if yoff > size { return Err(DecoderError::InvalidData); }
702 if uoff > size { return Err(DecoderError::InvalidData); }
703 if voff > size { return Err(DecoderError::InvalidData); }
704
705 br.read_skip(4)?;
706 br.read_buf(&mut self.altquant)?;
707
708 let mut yend = src.len() as u32;//size;
709 if (uoff < yend) && (uoff > yoff) { yend = uoff; }
710 if (voff < yend) && (voff > yoff) { yend = voff; }
711 let mut uend = size;
712 if (yoff < uend) && (yoff > uoff) { uend = yoff; }
713 if (voff < uend) && (voff > uoff) { uend = voff; }
714 let mut vend = size;
715 if (yoff < vend) && (yoff > voff) { vend = yoff; }
716 if (uoff < vend) && (uoff > voff) { vend = uoff; }
717
718 let intraframe = (flags & FLAG_KEYFRAME) != 0;
719 let vinfo = self.info.get_properties().get_video_info().unwrap();
720 validate!((vinfo.get_width() & !3) == (self.width & !3).into());
721 validate!((vinfo.get_height() & !3) == (self.height & !3).into());
722 let bufinfo = alloc_video_buffer(vinfo, 4)?;
723 let mut buf = bufinfo.get_vbuf().unwrap();
724 let ystart = data_start + u64::from(yoff);
725 let ustart = data_start + u64::from(uoff);
726 let vstart = data_start + u64::from(voff);
727 let yendpos = data_start + u64::from(yend);
728 let uendpos = data_start + u64::from(uend);
729 let vendpos = data_start + u64::from(vend);
730 if intraframe {
731 self.decode_plane_intra(&mut br, 0, ystart, yendpos)?;
732 self.decode_plane_intra(&mut br, 1, vstart, vendpos)?;
733 self.decode_plane_intra(&mut br, 2, ustart, uendpos)?;
734 } else {
735 self.decode_plane_inter(&mut br, 0, ystart, yendpos)?;
736 self.decode_plane_inter(&mut br, 1, vstart, vendpos)?;
737 self.decode_plane_inter(&mut br, 2, ustart, uendpos)?;
738 }
739 self.bufs.fill_framebuf(&mut buf);
740 if (flags & FLAG_NONREF) == 0 { self.bufs.flip(); }
741 let mut frm = NAFrame::new_from_pkt(pkt, self.info.clone(), bufinfo);
742 frm.set_keyframe(intraframe);
743 frm.set_frame_type(if intraframe { FrameType::I } else { FrameType::P });
744 Ok(frm.into_ref())
745 }
746 fn flush(&mut self) {
747 self.bufs.reset();
748 }
749 }
750
751 pub fn get_decoder() -> Box<dyn NADecoder + Send> {
752 Box::new(Indeo3Decoder::new())
753 }
754
755 #[cfg(test)]
756 mod test {
757 use nihav_core::codecs::RegisteredDecoders;
758 use nihav_core::demuxers::RegisteredDemuxers;
759 use nihav_core::test::dec_video::*;
760 use crate::codecs::indeo_register_all_codecs;
761 use nihav_commonfmt::demuxers::generic_register_all_demuxers;
762 #[test]
763 fn test_indeo3() {
764 let mut dmx_reg = RegisteredDemuxers::new();
765 generic_register_all_demuxers(&mut dmx_reg);
766 let mut dec_reg = RegisteredDecoders::new();
767 indeo_register_all_codecs(&mut dec_reg);
768
769 test_file_decoding("avi", "assets/Indeo/iv32_example.avi", Some(10), true, false, None, &dmx_reg, &dec_reg);
770 }
771 }
772
773 const DT_1_1: IviDeltaCB = IviDeltaCB{ quad_radix: 7, data: &[
774 0, 0, 2, 2, -2, -2, -1, 3,
775 1, -3, 3, -1, -3, 1, 4, 4,
776 -4, -4, 1, 5, -1, -5, 5, 1,
777 -5, -1, -4, 4, 4, -4, -2, 6,
778 2, -6, 6, -2, -6, 2, 4, 9,
779 -4, -9, 9, 4, -9, -4, 9, 9,
780 -9, -9, 1, 10, -1, -10, 10, 1,
781 -10, -1, -5, 8, 5, -8, 8, -5,
782 -8, 5, 9, 15, -9, -15, 15, 9,
783 -15, -9, -3, 12, 3, -12, 12, -3,
784 -12, 3, 4, 16, -4, -16, 16, 4,
785 -16, -4, 16, 16, -16, -16, 0, 18,
786 0, -18, 18, 0, -18, 0, -12, 12,
787 12, -12, -9, 16, 9, -16, 16, -9,
788 -16, 9, 11, 27, -11, -27, 27, 11,
789 -27, -11, 19, 28, -19, -28, 28, 19,
790 -28, -19, -6, 22, 6, -22, 22, -6,
791 -22, 6, 4, 29, -4, -29, 29, 4,
792 -29, -4, 30, 30, -30, -30, -2, 33,
793 2, -33, 33, -2, -33, 2, -18, 23,
794 18, -23, 23, -18, -23, 18, -15, 30,
795 15, -30, 30, -15, -30, 15, 22, 46,
796 -22, -46, 46, 22, -46, -22, 13, 47,
797 -13, -47, 47, 13, -47, -13, 35, 49,
798 -35, -49, 49, 35, -49, -35, -11, 41,
799 11, -41, 41, -11, -41, 11, 4, 51,
800 -4, -51, 51, 4, -51, -4, 54, 54,
801 -54, -54, -34, 34, 34, -34, -29, 42,
802 29, -42, 42, -29, -42, 29, -6, 60,
803 6, -60, 60, -6, -60, 6, 27, 76,
804 -27, -76, 76, 27, -76, -27, 43, 77,
805 -43, -77, 77, 43, -77, -43, -24, 55,
806 24, -55, 55, -24, -55, 24, 14, 79,
807 -14, -79, 79, 14, -79, -14, 63, 83,
808 -63, -83, 83, 63, -83, -63, -20, 74,
809 20, -74, 74, -20, -74, 20, 2, 88,
810 -2, -88, 88, 2, -88, -2, 93, 93,
811 -93, -93, -52, 61, 52, -61, 61, -52,
812 -61, 52, 52, 120, -52, -120, 120, 52,
813 -120, -52, -45, 75, 45, -75, 75, -45,
814 -75, 45, 75, 125, -75, -125, 125, 75,
815 -125, -75, 33, 122, -33, -122, 122, 33,
816 -122, -33, -13, 103, 13, -103, 103, -13,
817 -103, 13, -40, 96, 40, -96, 96, -40,
818 -96, 40, -34, 127, 34, -127, 127, -34,
819 -127, 34, -89, 89, 89, -89, -78, 105,
820 78, -105, 105, -78, -105, 78, 12, 12,
821 -12, -12, 23, 23, -23, -23, 42, 42,
822 -42, -42, 73, 73, -73, -73,
823 ]};
824
825 const DT_1_2: IviDeltaCB = IviDeltaCB{ quad_radix: 9, data: &[
826 0, 0, 3, 3, -3, -3, -1, 4,
827 1, -4, 4, -1, -4, 1, 7, 7,
828 -7, -7, 2, 8, -2, -8, 8, 2,
829 -8, -2, -2, 9, 2, -9, 9, -2,
830 -9, 2, -6, 6, 6, -6, 6, 13,
831 -6, -13, 13, 6, -13, -6, 13, 13,
832 -13, -13, 1, 14, -1, -14, 14, 1,
833 -14, -1, -8, 12, 8, -12, 12, -8,
834 -12, 8, 14, 23, -14, -23, 23, 14,
835 -23, -14, -5, 18, 5, -18, 18, -5,
836 -18, 5, 6, 24, -6, -24, 24, 6,
837 -24, -6, 24, 24, -24, -24, -1, 27,
838 1, -27, 27, -1, -27, 1, -17, 17,
839 17, -17, -13, 23, 13, -23, 23, -13,
840 -23, 13, 16, 40, -16, -40, 40, 16,
841 -40, -16, 28, 41, -28, -41, 41, 28,
842 -41, -28, -9, 33, 9, -33, 33, -9,
843 -33, 9, 6, 43, -6, -43, 43, 6,
844 -43, -6, 46, 46, -46, -46, -4, 50,
845 4, -50, 50, -4, -50, 4, -27, 34,
846 27, -34, 34, -27, -34, 27, -22, 45,
847 22, -45, 45, -22, -45, 22, 34, 69,
848 -34, -69, 69, 34, -69, -34, 19, 70,
849 -19, -70, 70, 19, -70, -19, 53, 73,
850 -53, -73, 73, 53, -73, -53, -17, 62,
851 17, -62, 62, -17, -62, 17, 5, 77,
852 -5, -77, 77, 5, -77, -5, 82, 82,
853 -82, -82, -51, 51, 51, -51, -43, 64,
854 43, -64, 64, -43, -64, 43, -10, 90,
855 10, -90, 90, -10, -90, 10, 41, 114,
856 -41, -114, 114, 41, -114, -41, 64, 116,
857 -64, -116, 116, 64, -116, -64, -37, 82,
858 37, -82, 82, -37, -82, 37, 22, 119,
859 -22, -119, 119, 22, -119, -22, 95, 124,
860 -95, -124, 124, 95, -124, -95, -30, 111,
861 30, -111, 111, -30, -111, 30, -78, 92,
862 78, -92, 92, -78, -92, 78, -68, 113,
863 68, -113, 113, -68, -113, 68, 18, 18,
864 -18, -18, 34, 34, -34, -34, 63, 63,
865 -63, -63, 109, 109, -109, -109,
866 ]};
867
868 const DT_1_3: IviDeltaCB = IviDeltaCB{ quad_radix: 10, data: &[
869 0, 0, 4, 4, -4, -4, -1, 5,
870 1, -5, 5, -1, -5, 1, 3, 10,
871 -3, -10, 10, 3, -10, -3, 9, 9,
872 -9, -9, -7, 7, 7, -7, -3, 12,
873 3, -12, 12, -3, -12, 3, 8, 17,
874 -8, -17, 17, 8, -17, -8, 17, 17,
875 -17, -17, 1, 19, -1, -19, 19, 1,
876 -19, -1, -11, 16, 11, -16, 16, -11,
877 -16, 11, -6, 23, 6, -23, 23, -6,
878 -23, 6, 18, 31, -18, -31, 31, 18,
879 -31, -18, 8, 32, -8, -32, 32, 8,
880 -32, -8, 33, 33, -33, -33, -1, 36,
881 1, -36, 36, -1, -36, 1, -23, 23,
882 23, -23, -17, 31, 17, -31, 31, -17,
883 -31, 17, 21, 54, -21, -54, 54, 21,
884 -54, -21, 37, 55, -37, -55, 55, 37,
885 -55, -37, -12, 44, 12, -44, 44, -12,
886 -44, 12, 8, 57, -8, -57, 57, 8,
887 -57, -8, 61, 61, -61, -61, -5, 66,
888 5, -66, 66, -5, -66, 5, -36, 45,
889 36, -45, 45, -36, -45, 36, -29, 60,
890 29, -60, 60, -29, -60, 29, 45, 92,
891 -45, -92, 92, 45, -92, -45, 25, 93,
892 -25, -93, 93, 25, -93, -25, 71, 97,
893 -71, -97, 97, 71, -97, -71, -22, 83,
894 22, -83, 83, -22, -83, 22, 7, 102,
895 -7, -102, 102, 7, -102, -7, 109, 109,
896 -109, -109, -68, 68, 68, -68, -57, 85,
897 57, -85, 85, -57, -85, 57, -13, 120,
898 13, -120, 120, -13, -120, 13, -49, 110,
899 49, -110, 110, -49, -110, 49, -104, 123,
900 104, -123, 123, -104, -123, 104, 24, 24,
901 -24, -24, 46, 46, -46, -46, 84, 84,
902 -84, -84,
903 ]};
904
905 const DT_1_4: IviDeltaCB = IviDeltaCB{ quad_radix: 11, data: &[
906 0, 0, 5, 5, -5, -5, -2, 7,
907 2, -7, 7, -2, -7, 2, 11, 11,
908 -11, -11, 3, 13, -3, -13, 13, 3,
909 -13, -3, -9, 9, 9, -9, -4, 15,
910 4, -15, 15, -4, -15, 4, 11, 22,
911 -11, -22, 22, 11, -22, -11, 21, 21,
912 -21, -21, 2, 24, -2, -24, 24, 2,
913 -24, -2, -14, 20, 14, -20, 20, -14,
914 -20, 14, 23, 38, -23, -38, 38, 23,
915 -38, -23, -8, 29, 8, -29, 29, -8,
916 -29, 8, 11, 39, -11, -39, 39, 11,
917 -39, -11, 41, 41, -41, -41, -1, 45,
918 1, -45, 45, -1, -45, 1, -29, 29,
919 29, -29, -22, 39, 22, -39, 39, -22,
920 -39, 22, 27, 67, -27, -67, 67, 27,
921 -67, -27, 47, 69, -47, -69, 69, 47,
922 -69, -47, -15, 56, 15, -56, 56, -15,
923 -56, 15, 11, 71, -11, -71, 71, 11,
924 -71, -11, 76, 76, -76, -76, -6, 83,
925 6, -83, 83, -6, -83, 6, -45, 57,
926 45, -57, 57, -45, -57, 45, -36, 75,
927 36, -75, 75, -36, -75, 36, 56, 115,
928 -56, -115, 115, 56, -115, -56, 31, 117,
929 -31, -117, 117, 31, -117, -31, 88, 122,
930 -88, -122, 122, 88, -122, -88, -28, 104,
931 28, -104, 104, -28, -104, 28, -85, 85,
932 85, -85, -72, 106, 72, -106, 106, -72,
933 -106, 72, 30, 30, -30, -30, 58, 58,
934 -58, -58, 105, 105, -105, -105,
935 ]};
936
937 const DT_1_5: IviDeltaCB = IviDeltaCB{ quad_radix: 12, data: &[
938 0, 0, 6, 6, -6, -6, -2, 8,
939 2, -8, 8, -2, -8, 2, 13, 13,
940 -13, -13, 4, 15, -4, -15, 15, 4,
941 -15, -4, -11, 11, 11, -11, -5, 18,
942 5, -18, 18, -5, -18, 5, 13, 26,
943 -13, -26, 26, 13, -26, -13, 26, 26,
944 -26, -26, 2, 29, -2, -29, 29, 2,
945 -29, -2, -16, 24, 16, -24, 24, -16,
946 -24, 16, 28, 46, -28, -46, 46, 28,
947 -46, -28, -9, 35, 9, -35, 35, -9,
948 -35, 9, 13, 47, -13, -47, 47, 13,
949 -47, -13, 49, 49, -49, -49, -1, 54,
950 1, -54, 54, -1, -54, 1, -35, 35,
951 35, -35, -26, 47, 26, -47, 47, -26,
952 -47, 26, 32, 81, -32, -81, 81, 32,
953 -81, -32, 56, 83, -56, -83, 83, 56,
954 -83, -56, -18, 67, 18, -67, 67, -18,
955 -67, 18, 13, 86, -13, -86, 86, 13,
956 -86, -13, 91, 91, -91, -91, -7, 99,
957 7, -99, 99, -7, -99, 7, -54, 68,
958 54, -68, 68, -54, -68, 54, -44, 90,
959 44, -90, 90, -44, -90, 44, -33, 124,
960 33, -124, 124, -33, -124, 33, -103, 103,
961 103, -103, -86, 127, 86, -127, 127, -86,
962 -127, 86, 37, 37, -37, -37, 69, 69,
963 -69, -69,
964 ]};
965
966 const DT_1_6: IviDeltaCB = IviDeltaCB{ quad_radix: 12, data: &[
967 0, 0, 7, 7, -7, -7, -3, 10,
968 3, -10, 10, -3, -10, 3, 16, 16,
969 -16, -16, 5, 18, -5, -18, 18, 5,
970 -18, -5, -13, 13, 13, -13, -6, 21,
971 6, -21, 21, -6, -21, 6, 15, 30,
972 -15, -30, 30, 15, -30, -15, 30, 30,
973 -30, -30, 2, 34, -2, -34, 34, 2,
974 -34, -2, -19, 28, 19, -28, 28, -19,
975 -28, 19, 32, 54, -32, -54, 54, 32,
976 -54, -32, -11, 41, 11, -41, 41, -11,
977 -41, 11, 15, 55, -15, -55, 55, 15,
978 -55, -15, 57, 57, -57, -57, -1, 63,
979 1, -63, 63, -1, -63, 1, -40, 40,
980 40, -40, -30, 55, 30, -55, 55, -30,
981 -55, 30, 37, 94, -37, -94, 94, 37,
982 -94, -37, 65, 96, -65, -96, 96, 65,
983 -96, -65, -21, 78, 21, -78, 78, -21,
984 -78, 21, 15, 100, -15, -100, 100, 15,
985 -100, -15, 106, 106, -106, -106, -8, 116,
986 8, -116, 116, -8, -116, 8, -63, 79,
987 63, -79, 79, -63, -79, 63, -51, 105,
988 51, -105, 105, -51, -105, 51, -120, 120,
989 120, -120, 43, 43, -43, -43, 80, 80,
990 -80, -80,
991 ]};
992
993 const DT_1_7: IviDeltaCB = IviDeltaCB{ quad_radix: 12, data: &[
994 0, 0, 8, 8, -8, -8, -3, 11,
995 3, -11, 11, -3, -11, 3, 18, 18,
996 -18, -18, 5, 20, -5, -20, 20, 5,
997 -20, -5, -15, 15, 15, -15, -7, 24,
998 7, -24, 24, -7, -24, 7, 17, 35,
999 -17, -35, 35, 17, -35, -17, 34, 34,
1000 -34, -34, 3, 38, -3, -38, 38, 3,
1001 -38, -3, -22, 32, 22, -32, 32, -22,
1002 -32, 22, 37, 61, -37, -61, 61, 37,
1003 -61, -37, -13, 47, 13, -47, 47, -13,
1004 -47, 13, 17, 63, -17, -63, 63, 17,
1005 -63, -17, 65, 65, -65, -65, -1, 72,
1006 1, -72, 72, -1, -72, 1, -46, 46,
1007 46, -46, -35, 63, 35, -63, 63, -35,
1008 -63, 35, 43, 107, -43, -107, 107, 43,
1009 -107, -43, 75, 110, -75, -110, 110, 75,
1010 -110, -75, -24, 89, 24, -89, 89, -24,
1011 -89, 24, 17, 114, -17, -114, 114, 17,
1012 -114, -17, 121, 121, -121, -121, -72, 91,
1013 72, -91, 91, -72, -91, 72, -58, 120,
1014 58, -120, 120, -58, -120, 58, 49, 49,
1015 -49, -49, 92, 92, -92, -92,
1016 ]};
1017
1018 const DT_1_8: IviDeltaCB = IviDeltaCB{ quad_radix: 13, data: &[
1019 0, 0, 9, 9, -9, -9, -3, 12,
1020 3, -12, 12, -3, -12, 3, 20, 20,
1021 -20, -20, 6, 23, -6, -23, 23, 6,
1022 -23, -6, -17, 17, 17, -17, -7, 27,
1023 7, -27, 27, -7, -27, 7, 19, 39,
1024 -19, -39, 39, 19, -39, -19, 39, 39,
1025 -39, -39, 3, 43, -3, -43, 43, 3,
1026 -43, -3, -24, 36, 24, -36, 36, -24,
1027 -36, 24, 42, 69, -42, -69, 69, 42,
1028 -69, -42, -14, 53, 14, -53, 53, -14,
1029 -53, 14, 19, 71, -19, -71, 71, 19,
1030 -71, -19, 73, 73, -73, -73, -2, 80,
1031 2, -80, 80, -2, -80, 2, -52, 52,
1032 52, -52, -39, 70, 39, -70, 70, -39,
1033 -70, 39, 48, 121, -48, -121, 121, 48,
1034 -121, -48, 84, 124, -84, -124, 124, 84,
1035 -124, -84, -27, 100, 27, -100, 100, -27,
1036 -100, 27, -81, 102, 81, -102, 102, -81,
1037 -102, 81, 55, 55, -55, -55, 104, 104,
1038 -104, -104,
1039 ]};
1040
1041 const DT_2_1: IviDeltaCB = IviDeltaCB{ quad_radix: 7, data: &[
1042 0, 0, 2, 2, -2, -2, 0, 2,
1043 0, -2, 2, 0, -2, 0, 4, 4,
1044 -4, -4, 0, 4, 0, -4, 4, 0,
1045 -4, 0, -4, 4, 4, -4, -2, 6,
1046 2, -6, 6, -2, -6, 2, 4, 8,
1047 -4, -8, 8, 4, -8, -4, 8, 8,
1048 -8, -8, 0, 10, 0, -10, 10, 0,
1049 -10, 0, -4, 8, 4, -8, 8, -4,
1050 -8, 4, 8, 14, -8, -14, 14, 8,
1051 -14, -8, -2, 12, 2, -12, 12, -2,
1052 -12, 2, 4, 16, -4, -16, 16, 4,
1053 -16, -4, 16, 16, -16, -16, 0, 18,
1054 0, -18, 18, 0, -18, 0, -12, 12,
1055 12, -12, -8, 16, 8, -16, 16, -8,
1056 -16, 8, 10, 26, -10, -26, 26, 10,
1057 -26, -10, 18, 28, -18, -28, 28, 18,
1058 -28, -18, -6, 22, 6, -22, 22, -6,
1059 -22, 6, 4, 28, -4, -28, 28, 4,
1060 -28, -4, 30, 30, -30, -30, -2, 32,
1061 2, -32, 32, -2, -32, 2, -18, 22,
1062 18, -22, 22, -18, -22, 18, -14, 30,
1063 14, -30, 30, -14, -30, 14, 22, 46,
1064 -22, -46, 46, 22, -46, -22, 12, 46,
1065 -12, -46, 46, 12, -46, -12, 34, 48,
1066 -34, -48, 48, 34, -48, -34, -10, 40,
1067 10, -40, 40, -10, -40, 10, 4, 50,
1068 -4, -50, 50, 4, -50, -4, 54, 54,
1069 -54, -54, -34, 34, 34, -34, -28, 42,
1070 28, -42, 42, -28, -42, 28, -6, 60,
1071 6, -60, 60, -6, -60, 6, 26, 76,
1072 -26, -76, 76, 26, -76, -26, 42, 76,
1073 -42, -76, 76, 42, -76, -42, -24, 54,
1074 24, -54, 54, -24, -54, 24, 14, 78,
1075 -14, -78, 78, 14, -78, -14, 62, 82,
1076 -62, -82, 82, 62, -82, -62, -20, 74,
1077 20, -74, 74, -20, -74, 20, 2, 88,
1078 -2, -88, 88, 2, -88, -2, 92, 92,
1079 -92, -92, -52, 60, 52, -60, 60, -52,
1080 -60, 52, 52, 118, -52, -118, 118, 52,
1081 -118, -52, -44, 74, 44, -74, 74, -44,
1082 -74, 44, 74, 118, -74, -118, 118, 74,
1083 -118, -74, 32, 118, -32, -118, 118, 32,
1084 -118, -32, -12, 102, 12, -102, 102, -12,
1085 -102, 12, -40, 96, 40, -96, 96, -40,
1086 -96, 40, -34, 118, 34, -118, 118, -34,
1087 -118, 34, -88, 88, 88, -88, -78, 104,
1088 78, -104, 104, -78, -104, 78, 12, 12,
1089 -12, -12, 22, 22, -22, -22, 42, 42,
1090 -42, -42, 72, 72, -72, -72,
1091 ]};
1092
1093 const DT_2_2: IviDeltaCB = IviDeltaCB{ quad_radix: 9, data: &[
1094 0, 0, 3, 3, -3, -3, 0, 3,
1095 0, -3, 3, 0, -3, 0, 6, 6,
1096 -6, -6, 3, 9, -3, -9, 9, 3,
1097 -9, -3, -3, 9, 3, -9, 9, -3,
1098 -9, 3, -6, 6, 6, -6, 6, 12,
1099 -6, -12, 12, 6, -12, -6, 12, 12,
1100 -12, -12, 0, 15, 0, -15, 15, 0,
1101 -15, 0, -9, 12, 9, -12, 12, -9,
1102 -12, 9, 15, 24, -15, -24, 24, 15,
1103 -24, -15, -6, 18, 6, -18, 18, -6,
1104 -18, 6, 6, 24, -6, -24, 24, 6,
1105 -24, -6, 24, 24, -24, -24, 0, 27,
1106 0, -27, 27, 0, -27, 0, -18, 18,
1107 18, -18, -12, 24, 12, -24, 24, -12,
1108 -24, 12, 15, 39, -15, -39, 39, 15,
1109 -39, -15, 27, 42, -27, -42, 42, 27,
1110 -42, -27, -9, 33, 9, -33, 33, -9,
1111 -33, 9, 6, 42, -6, -42, 42, 6,
1112 -42, -6, 45, 45, -45, -45, -3, 51,
1113 3, -51, 51, -3, -51, 3, -27, 33,
1114 27, -33, 33, -27, -33, 27, -21, 45,
1115 21, -45, 45, -21, -45, 21, 33, 69,
1116 -33, -69, 69, 33, -69, -33, 18, 69,
1117 -18, -69, 69, 18, -69, -18, 54, 72,
1118 -54, -72, 72, 54, -72, -54, -18, 63,
1119 18, -63, 63, -18, -63, 18, 6, 78,
1120 -6, -78, 78, 6, -78, -6, 81, 81,
1121 -81, -81, -51, 51, 51, -51, -42, 63,
1122 42, -63, 63, -42, -63, 42, -9, 90,
1123 9, -90, 90, -9, -90, 9, 42, 114,
1124 -42, -114, 114, 42, -114, -42, 63, 117,
1125 -63, -117, 117, 63, -117, -63, -36, 81,
1126 36, -81, 81, -36, -81, 36, 21, 120,
1127 -21, -120, 120, 21, -120, -21, 96, 123,
1128 -96, -123, 123, 96, -123, -96, -30, 111,
1129 30, -111, 111, -30, -111, 30, -78, 93,
1130 78, -93, 93, -78, -93, 78, -69, 114,
1131 69, -114, 114, -69, -114, 69, 18, 18,
1132 -18, -18, 33, 33, -33, -33, 63, 63,
1133 -63, -63, 108, 108, -108, -108,
1134 ]};
1135
1136 const DT_2_3: IviDeltaCB = IviDeltaCB{ quad_radix: 10, data: &[
1137 0, 0, 4, 4, -4, -4, 0, 4,
1138 0, -4, 4, 0, -4, 0, 4, 8,
1139 -4, -8, 8, 4, -8, -4, 8, 8,
1140 -8, -8, -8, 8, 8, -8, -4, 12,
1141 4, -12, 12, -4, -12, 4, 8, 16,
1142 -8, -16, 16, 8, -16, -8, 16, 16,
1143 -16, -16, 0, 20, 0, -20, 20, 0,
1144 -20, 0, -12, 16, 12, -16, 16, -12,
1145 -16, 12, -4, 24, 4, -24, 24, -4,
1146 -24, 4, 16, 32, -16, -32, 32, 16,
1147 -32, -16, 8, 32, -8, -32, 32, 8,
1148 -32, -8, 32, 32, -32, -32, 0, 36,
1149 0, -36, 36, 0, -36, 0, -24, 24,
1150 24, -24, -16, 32, 16, -32, 32, -16,
1151 -32, 16, 20, 52, -20, -52, 52, 20,
1152 -52, -20, 36, 56, -36, -56, 56, 36,
1153 -56, -36, -12, 44, 12, -44, 44, -12,
1154 -44, 12, 8, 56, -8, -56, 56, 8,
1155 -56, -8, 60, 60, -60, -60, -4, 64,
1156 4, -64, 64, -4, -64, 4, -36, 44,
1157 36, -44, 44, -36, -44, 36, -28, 60,
1158 28, -60, 60, -28, -60, 28, 44, 92,
1159 -44, -92, 92, 44, -92, -44, 24, 92,
1160 -24, -92, 92, 24, -92, -24, 72, 96,
1161 -72, -96, 96, 72, -96, -72, -20, 84,
1162 20, -84, 84, -20, -84, 20, 8, 100,
1163 -8, -100, 100, 8, -100, -8, 108, 108,
1164 -108, -108, -68, 68, 68, -68, -56, 84,
1165 56, -84, 84, -56, -84, 56, -12, 120,
1166 12, -120, 120, -12, -120, 12, -48, 108,
1167 48, -108, 108, -48, -108, 48, -104, 124,
1168 104, -124, 124, -104, -124, 104, 24, 24,
1169 -24, -24, 44, 44, -44, -44, 84, 84,
1170 -84, -84,
1171 ]};
1172
1173 const DT_2_4: IviDeltaCB = IviDeltaCB{ quad_radix: 11, data: &[
1174 0, 0, 5, 5, -5, -5, 0, 5,
1175 0, -5, 5, 0, -5, 0, 10, 10,
1176 -10, -10, 5, 15, -5, -15, 15, 5,
1177 -15, -5, -10, 10, 10, -10, -5, 15,
1178 5, -15, 15, -5, -15, 5, 10, 20,
1179 -10, -20, 20, 10, -20, -10, 20, 20,
1180 -20, -20, 0, 25, 0, -25, 25, 0,
1181 -25, 0, -15, 20, 15, -20, 20, -15,
1182 -20, 15, 25, 40, -25, -40, 40, 25,
1183 -40, -25, -10, 30, 10, -30, 30, -10,
1184 -30, 10, 10, 40, -10, -40, 40, 10,
1185 -40, -10, 40, 40, -40, -40, 0, 45,
1186 0, -45, 45, 0, -45, 0, -30, 30,
1187 30, -30, -20, 40, 20, -40, 40, -20,
1188 -40, 20, 25, 65, -25, -65, 65, 25,
1189 -65, -25, 45, 70, -45, -70, 70, 45,
1190 -70, -45, -15, 55, 15, -55, 55, -15,
1191 -55, 15, 10, 70, -10, -70, 70, 10,
1192 -70, -10, 75, 75, -75, -75, -5, 85,
1193 5, -85, 85, -5, -85, 5, -45, 55,
1194 45, -55, 55, -45, -55, 45, -35, 75,
1195 35, -75, 75, -35, -75, 35, 55, 115,
1196 -55, -115, 115, 55, -115, -55, 30, 115,
1197 -30, -115, 115, 30, -115, -30, 90, 120,
1198 -90, -120, 120, 90, -120, -90, -30, 105,
1199 30, -105, 105, -30, -105, 30, -85, 85,
1200 85, -85, -70, 105, 70, -105, 105, -70,
1201 -105, 70, 30, 30, -30, -30, 60, 60,
1202 -60, -60, 105, 105, -105, -105,
1203 ]};
1204
1205 const DT_2_5: IviDeltaCB = IviDeltaCB{ quad_radix: 12, data: &[
1206 0, 0, 6, 6, -6, -6, 0, 6,
1207 0, -6, 6, 0, -6, 0, 12, 12,
1208 -12, -12, 6, 12, -6, -12, 12, 6,
1209 -12, -6, -12, 12, 12, -12, -6, 18,
1210 6, -18, 18, -6, -18, 6, 12, 24,
1211 -12, -24, 24, 12, -24, -12, 24, 24,
1212 -24, -24, 0, 30, 0, -30, 30, 0,
1213 -30, 0, -18, 24, 18, -24, 24, -18,
1214 -24, 18, 30, 48, -30, -48, 48, 30,
1215 -48, -30, -6, 36, 6, -36, 36, -6,
1216 -36, 6, 12, 48, -12, -48, 48, 12,
1217 -48, -12, 48, 48, -48, -48, 0, 54,
1218 0, -54, 54, 0, -54, 0, -36, 36,
1219 36, -36, -24, 48, 24, -48, 48, -24,
1220 -48, 24, 30, 78, -30, -78, 78, 30,
1221 -78, -30, 54, 84, -54, -84, 84, 54,
1222 -84, -54, -18, 66, 18, -66, 66, -18,
1223 -66, 18, 12, 84, -12, -84, 84, 12,
1224 -84, -12, 90, 90, -90, -90, -6, 96,
1225 6, -96, 96, -6, -96, 6, -54, 66,
1226 54, -66, 66, -54, -66, 54, -42, 90,
1227 42, -90, 90, -42, -90, 42, -30, 126,
1228 30, -126, 126, -30, -126, 30, -102, 102,
1229 102, -102, -84, 126, 84, -126, 126, -84,
1230 -126, 84, 36, 36, -36, -36, 66, 66,
1231 -66, -66,
1232 ]};
1233
1234 const DT_2_6: IviDeltaCB = IviDeltaCB{ quad_radix: 12, data: &[
1235 0, 0, 7, 7, -7, -7, 0, 7,
1236 0, -7, 7, 0, -7, 0, 14, 14,
1237 -14, -14, 7, 21, -7, -21, 21, 7,
1238 -21, -7, -14, 14, 14, -14, -7, 21,
1239 7, -21, 21, -7, -21, 7, 14, 28,
1240 -14, -28, 28, 14, -28, -14, 28, 28,
1241 -28, -28, 0, 35, 0, -35, 35, 0,
1242 -35, 0, -21, 28, 21, -28, 28, -21,
1243 -28, 21, 35, 56, -35, -56, 56, 35,
1244 -56, -35, -14, 42, 14, -42, 42, -14,
1245 -42, 14, 14, 56, -14, -56, 56, 14,
1246 -56, -14, 56, 56, -56, -56, 0, 63,
1247 0, -63, 63, 0, -63, 0, -42, 42,
1248 42, -42, -28, 56, 28, -56, 56, -28,
1249 -56, 28, 35, 91, -35, -91, 91, 35,
1250 -91, -35, 63, 98, -63, -98, 98, 63,
1251 -98, -63, -21, 77, 21, -77, 77, -21,
1252 -77, 21, 14, 98, -14, -98, 98, 14,
1253 -98, -14, 105, 105, -105, -105, -7, 119,
1254 7, -119, 119, -7, -119, 7, -63, 77,
1255 63, -77, 77, -63, -77, 63, -49, 105,
1256 49, -105, 105, -49, -105, 49, -119, 119,
1257 119, -119, 42, 42, -42, -42, 77, 77,
1258 -77, -77,
1259 ]};
1260
1261 const DT_2_7: IviDeltaCB = IviDeltaCB{ quad_radix: 12, data: &[
1262 0, 0, 8, 8, -8, -8, 0, 8,
1263 0, -8, 8, 0, -8, 0, 16, 16,
1264 -16, -16, 8, 16, -8, -16, 16, 8,
1265 -16, -8, -16, 16, 16, -16, -8, 24,
1266 8, -24, 24, -8, -24, 8, 16, 32,
1267 -16, -32, 32, 16, -32, -16, 32, 32,
1268 -32, -32, 0, 40, 0, -40, 40, 0,
1269 -40, 0, -24, 32, 24, -32, 32, -24,
1270 -32, 24, 40, 64, -40, -64, 64, 40,
1271 -64, -40, -16, 48, 16, -48, 48, -16,
1272 -48, 16, 16, 64, -16, -64, 64, 16,
1273 -64, -16, 64, 64, -64, -64, 0, 72,
1274 0, -72, 72, 0, -72, 0, -48, 48,
1275 48, -48, -32, 64, 32, -64, 64, -32,
1276 -64, 32, 40, 104, -40, -104, 104, 40,
1277 -104, -40, 72, 112, -72, -112, 112, 72,
1278 -112, -72, -24, 88, 24, -88, 88, -24,
1279 -88, 24, 16, 112, -16, -112, 112, 16,
1280 -112, -16, 120, 120, -120, -120, -72, 88,
1281 72, -88, 88, -72, -88, 72, -56, 120,
1282 56, -120, 120, -56, -120, 56, 48, 48,
1283 -48, -48, 88, 88, -88, -88,
1284 ]};
1285
1286 const DT_2_8: IviDeltaCB = IviDeltaCB{ quad_radix: 13, data: &[
1287 0, 0, 9, 9, -9, -9, 0, 9,
1288 0, -9, 9, 0, -9, 0, 18, 18,
1289 -18, -18, 9, 27, -9, -27, 27, 9,
1290 -27, -9, -18, 18, 18, -18, -9, 27,
1291 9, -27, 27, -9, -27, 9, 18, 36,
1292 -18, -36, 36, 18, -36, -18, 36, 36,
1293 -36, -36, 0, 45, 0, -45, 45, 0,
1294 -45, 0, -27, 36, 27, -36, 36, -27,
1295 -36, 27, 45, 72, -45, -72, 72, 45,
1296 -72, -45, -18, 54, 18, -54, 54, -18,
1297 -54, 18, 18, 72, -18, -72, 72, 18,
1298 -72, -18, 72, 72, -72, -72, 0, 81,
1299 0, -81, 81, 0, -81, 0, -54, 54,
1300 54, -54, -36, 72, 36, -72, 72, -36,
1301 -72, 36, 45, 117, -45, -117, 117, 45,
1302 -117, -45, 81, 126, -81, -126, 126, 81,
1303 -126, -81, -27, 99, 27, -99, 99, -27,
1304 -99, 27, -81, 99, 81, -99, 99, -81,
1305 -99, 81, 54, 54, -54, -54, 108, 108,
1306 -108, -108,
1307 ]};
1308
1309 const DT_3_1: IviDeltaCB = IviDeltaCB{ quad_radix: 11, data: &[
1310 0, 0, 2, 2, -2, -2, 0, 3,
1311 0, -3, 3, 0, -3, 0, 6, 6,
1312 -6, -6, 0, 7, 0, -7, 7, 0,
1313 -7, 0, -5, 5, 5, -5, 5, -5,
1314 -5, 5, 6, 11, -6, -11, 11, 6,
1315 -11, -6, 0, 8, 0, -8, 8, 0,
1316 -8, 0, 11, 11, -11, -11, 0, 12,
1317 0, -12, 12, 0, -12, 0, 12, 17,
1318 -12, -17, 17, 12, -17, -12, 17, 17,
1319 -17, -17, 6, 18, -6, -18, 18, 6,
1320 -18, -6, -8, 11, 8, -11, 11, -8,
1321 -11, 8, 0, 15, 0, -15, 15, 0,
1322 -15, 0, 0, 20, 0, -20, 20, 0,
1323 -20, 0, 18, 25, -18, -25, 25, 18,
1324 -25, -18, 11, 25, -11, -25, 25, 11,
1325 -25, -11, 25, 25, -25, -25, -14, 14,
1326 14, -14, 14, -14, -14, 14, 0, 26,
1327 0, -26, 26, 0, -26, 0, -11, 18,
1328 11, -18, 18, -11, -18, 11, -7, 22,
1329 7, -22, 22, -7, -22, 7, 26, 34,
1330 -26, -34, 34, 26, -34, -26, 18, 34,
1331 -18, -34, 34, 18, -34, -18, 34, 34,
1332 -34, -34, 11, 35, -11, -35, 35, 11,
1333 -35, -11, 0, 29, 0, -29, 29, 0,
1334 -29, 0, -19, 22, 19, -22, 22, -19,
1335 -22, 19, -15, 26, 15, -26, 26, -15,
1336 -26, 15, 0, 37, 0, -37, 37, 0,
1337 -37, 0, 27, 44, -27, -44, 44, 27,
1338 -44, -27, 36, 44, -36, -44, 44, 36,
1339 -44, -36, 18, 44, -18, -44, 44, 18,
1340 -44, -18, -10, 33, 10, -33, 33, -10,
1341 -33, 10, 45, 45, -45, -45, 0, 0,
1342 ]};
1343
1344 const DT_3_2: IviDeltaCB = IviDeltaCB{ quad_radix: 13, data: &[
1345 0, 0, 0, 2, 0, -2, 2, 0,
1346 -2, 0, 2, 2, -2, -2, 6, 6,
1347 -6, -6, 0, 6, 0, -6, 6, 0,
1348 -6, 0, -4, 4, 4, -4, 10, -6,
1349 -10, 6, 0, -12, 0, 12, -6, -12,
1350 6, -12, -6, 12, 6, 12, -14, 0,
1351 14, 0, 12, 12, -12, -12, 0, -18,
1352 0, 18, 14, -12, -14, 12, -18, -6,
1353 18, -6, -18, 6, 18, 6, -10, -18,
1354 10, -18, -10, 18, 10, 18, -22, 0,
1355 22, 0, 0, -24, 0, 24, -22, -12,
1356 22, -12, -22, 12, 22, 12, -8, -24,
1357 8, -24, -8, 24, 8, 24, -26, -6,
1358 26, -6, -26, 6, 26, 6, -28, 0,
1359 28, 0, 20, 20, -20, -20, -14, -26,
1360 14, 26, -30, -12, 30, 12, -10, -32,
1361 10, 32, -18, -32, 18, 32, -26, -26,
1362 26, 26, -34, -20, 34, 20, -38, -12,
1363 38, 12, -32, -32, 32, 32, 32, 32,
1364 -22, -40, -34, -34, 34, 34,
1365 ]};
1366
1367 const DT_3_3: IviDeltaCB = IviDeltaCB{ quad_radix: 13, data: &[
1368 0, 0, 0, 2, 0, -2, 2, 0,
1369 -2, 0, 4, 4, -4, -4, 10, 10,
1370 -10, -10, 0, 10, 0, -10, 10, 0,
1371 -10, 0, -6, 6, 6, -6, 14, -8,
1372 -14, 8, -18, 0, 18, 0, 10, -16,
1373 -10, 16, 0, -24, 0, 24, -24, -8,
1374 24, -8, -24, 8, 24, 8, 18, 18,
1375 -18, -18, 20, -16, -20, 16, -14, -26,
1376 14, -26, -14, 26, 14, 26, -30, 0,
1377 30, 0, 0, -34, 0, 34, -34, -8,
1378 34, -8, -34, 8, 34, 8, -30, -18,
1379 30, -18, -30, 18, 30, 18, -10, -34,
1380 10, -34, -10, 34, 10, 34, -20, -34,
1381 20, 34, -40, 0, 40, 0, 30, 30,
1382 -30, -30, -40, -18, 40, 18, 0, -44,
1383 0, 44, -16, -44, 16, 44, -36, -36,
1384 -36, -36, 36, 36, -26, -44, 26, 44,
1385 -46, -26, 46, 26, -52, -18, 52, 18,
1386 -20, -54, -44, -44, 44, 44, -32, -54,
1387 -46, -46, -46, -46, 46, 46,
1388 ]};
1389
1390 const DT_3_4: IviDeltaCB = IviDeltaCB{ quad_radix: 13, data: &[
1391 0, 0, 0, 4, 0, -4, 4, 0,
1392 -4, 0, 4, 4, -4, -4, 12, 12,
1393 -12, -12, 0, 12, 0, -12, 12, 0,
1394 -12, 0, -8, 8, 8, -8, 8, -16,
1395 -8, 16, 0, -24, 0, 24, -24, -8,
1396 24, -8, -24, 8, 24, 8, 20, -16,
1397 -20, 16, -28, 0, 28, 0, -16, -24,
1398 16, -24, -16, 24, 16, 24, 0, -32,
1399 0, 32, -28, -16, 28, -16, -28, 16,
1400 28, 16, -8, -32, 8, -32, -32, -8,
1401 32, -8, -32, 8, 32, 8, -8, 32,
1402 8, 32, 24, 24, -24, -24, 24, -24,
1403 -24, 24, -20, -32, 20, 32, -40, 0,
1404 40, 0, -40, -16, 40, 16, 0, -44,
1405 0, -44, -44, 0, 44, 0, 0, 44,
1406 0, 44, -32, -32, 32, 32, -16, -44,
1407 16, 44, -24, -44, -44, -24, 44, 24,
1408 24, 44, -48, -16, 48, 16, -36, -36,
1409 -36, -36, 36, 36, 36, 36, -20, -52,
1410 40, 40, -40, -40, -32, -52,
1411 ]};
1412
1413 const DT_3_5: IviDeltaCB = IviDeltaCB{ quad_radix: 13, data: &[
1414 0, 0, 2, 2, -2, -2, 6, 6,
1415 -6, -6, 12, 12, -12, -12, 20, 20,
1416 -20, -20, 32, 32, -32, -32, 46, 46,
1417 -46, -46, 0, 0, 0, 0, 0, 0,
1418 0, 0, 0, 0, 0, 0, 0, 0,
1419 0, 0, 0, 0, 0, 0, 0, 0,
1420 0, 0, 0, 0, 0, 0, 0, 0,
1421 0, 0, 0, 0, 0, 0, 0, 0,
1422 0, 0, 0, 0, 0, 0, 0, 0,
1423 0, 0, 0, 0, 0, 0, 0, 0,
1424 0, 0, 0, 0, 0, 0, 0, 0,
1425 0, 0, 0, 0, 0, 0, 0, 0,
1426 0, 0, 0, 0, 0, 0, 0, 0,
1427 0, 0, 0, 0, 0, 0, 0, 0,
1428 0, 0, 0, 0, 0, 0, 0, 0,
1429 0, 0, 0, 0, 0, 0, 0, 0,
1430 0, 0, 0, 0, 0, 0, 0, 0,
1431 0, 0, 0, 0, 0, 0, 0, 0,
1432 0, 0, 0, 0, 0, 0, 0, 0,
1433 0, 0, 0, 0, 0, 0,
1434 ]};
1435
1436 const IVI3_DELTA_CBS: [&IviDeltaCB; 24] = [
1437 &DT_1_1, &DT_1_2, &DT_1_3, &DT_1_4, &DT_1_5, &DT_1_6, &DT_1_7, &DT_1_8,
1438 &DT_2_1, &DT_2_2, &DT_2_3, &DT_2_4, &DT_2_5, &DT_2_6, &DT_2_7, &DT_2_8,
1439 &DT_3_1, &DT_3_2, &DT_3_3, &DT_3_4, &DT_3_5, &DT_3_5, &DT_3_5, &DT_3_5
1440 ];