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