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