1 use super::CB_SELECTORS;
3 use super::super::indeo3data::*;
4 use super::{Indeo3Cell, Plane};
6 pub const MAX_CELL_SIZE: usize = 2400;
7 const DEFAULT_PIXEL: u8 = 0x40;
8 const INTRA_FLAT_THRESHOLD: u32 = 8;
9 const INTER_FLAT_THRESHOLD: u32 = 8;
11 struct IndexWriter<'a> {
17 const SKIP_CELL: u8 = 0xFD;
18 const ZERO_CELL: u8 = 0xFD;
20 impl<'a> IndexWriter<'a> {
21 fn new(dst: &'a mut [u8], do_rle: bool) -> Self {
28 fn write_pair(&mut self, idx0: u8, idx1: u8, quad_radix: u8, esc: u8) {
29 //xxx: in theory one in theory the other index just has to make output fit byte range
30 if idx0 < quad_radix && idx1 < quad_radix {
31 let quad = idx1 * quad_radix + idx0 + esc;
32 self.dst[self.pos] = quad;
35 self.dst[self.pos] = idx0;
37 self.dst[self.pos] = idx1;
41 fn write_byte(&mut self, val: u8) {
42 self.dst[self.pos] = val;
45 fn compact_cell(&mut self, esc_vals: [u8; 4]) {
49 let tail = &self.dst[self.pos - 4..][..4];
51 for (&a, &b) in tail.iter().zip(esc_vals.iter()).rev() {
59 self.dst[self.pos] = ZERO_CELL;
63 fn compact_all_cells(&mut self) {
69 while i + 2 < self.pos {
70 if self.dst[i] == ZERO_CELL && self.dst[i + 1] == ZERO_CELL {
72 for j in (i + 1)..self.pos {
73 if self.dst[j] != ZERO_CELL {
78 let len = (last_idx - i + 1).min(31);
81 move_tail(&mut self.dst[i + 1..self.pos], 1);
85 self.dst[i + 1] = len as u8;
86 move_tail(&mut self.dst[i + 2..self.pos], len - 2);
94 fn end(self) -> usize {
99 fn move_tail(buf: &mut [u8], off: usize) {
102 buf[i - off] = buf[i];
107 struct CodebookSuggester {
111 const BINNING_FACTORS: [u8; 16] = [3, 7, 9, 12, 14, 16, 18, 40, 2, 3, 4, 5, 6, 7, 8, 9];
113 impl CodebookSuggester {
114 fn new() -> Self { Self::default() }
115 fn merge(cs1: &Self, cs2: &Self) -> Self {
116 let mut count = [0; 16];
117 for (dst, (&src1, &src2)) in count.iter_mut().zip(cs1.count.iter().zip(cs2.count.iter())) {
122 fn add_delta(&mut self, delta: u8) {
123 for (i, &fac) in BINNING_FACTORS.iter().enumerate() {
124 let val = if i < 8 { delta + fac - 1 } else { delta };
125 if (val % fac) == 0 {
130 fn add_line(&mut self, src: &[i8]) {
131 for &delta in src.iter() {
135 let delta = delta.abs() as u8;
136 self.add_delta(delta);
139 fn add_line_half(&mut self, src: &[i8]) {
140 for &delta in src.iter().step_by(2) {
144 let delta = delta.abs() as u8;
145 self.add_delta(delta);
148 fn get_best(&self) -> u8 {
150 for (i, &cnt) in self.count.iter().enumerate().skip(1) {
151 if cnt > self.count[idx] {
159 pub struct CellEncoder {
160 buf: [u8; MAX_CELL_SIZE + 160],
161 rbuf: [u8; MAX_CELL_SIZE + 160],
162 deltas: [i8; MAX_CELL_SIZE],
164 pub out: [u8; MAX_CELL_SIZE / 2 + 1],
170 pub quant: Option<u8>,
174 pub fn new() -> Self {
176 buf: [0; MAX_CELL_SIZE + 160],
177 rbuf: [0; MAX_CELL_SIZE + 160],
178 deltas: [0; MAX_CELL_SIZE],
179 cell: Indeo3Cell::new(0, 0),
180 out: [0; MAX_CELL_SIZE / 2 + 1],
183 flat_thr_i: INTRA_FLAT_THRESHOLD,
184 flat_thr_p: INTER_FLAT_THRESHOLD,
189 pub fn read_buffer(&mut self, plane: &Plane, cell: Indeo3Cell) {
192 let src = &plane.data[cell.get_x() + cell.get_y() * plane.width..];
193 let dst_w = cell.get_width();
194 for (dline, sline) in self.buf.chunks_mut(dst_w).skip(1).zip(src.chunks(plane.width)).take(cell.get_height()) {
195 dline.copy_from_slice(&sline[..dst_w]);
197 if cell.get_y() > 0 {
198 self.buf[..dst_w].copy_from_slice(&plane.data[cell.get_x() + (cell.get_y() - 1) * plane.width..][..dst_w]);
200 for el in self.buf[..dst_w].iter_mut() {
205 pub fn read_mv_buffer(&mut self, plane: &Plane, cell: Indeo3Cell, mv: MV) {
208 let xoff = (cell.get_x() as isize + isize::from(mv.x)) as usize;
209 let yoff = (cell.get_y() as isize + isize::from(mv.y)) as usize;
210 let src = &plane.data[xoff + yoff * plane.width..];
211 let dst_w = cell.get_width();
212 for (dline, sline) in self.rbuf.chunks_mut(dst_w).skip(1).zip(src.chunks(plane.width)).take(cell.get_height()) {
213 dline.copy_from_slice(&sline[..dst_w]);
216 pub fn null_mv(&mut self) {
217 let stride = self.cell.get_width();
218 self.buf[stride..].copy_from_slice(&self.rbuf[stride..]);
220 pub fn gen_diffs_intra(&mut self) {
221 let stride = self.cell.get_width();
222 let mut start = stride;
223 for dline in self.deltas.chunks_mut(stride).take(self.cell.get_height()) {
224 let (pprev, cur) = self.buf.split_at(start);
225 let prev = &pprev[pprev.len() - stride..];
227 for (dst, (&cur, &top)) in dline.iter_mut().zip(cur.iter().zip(prev.iter())) {
228 *dst = (cur as i8) - (top as i8);
234 pub fn gen_diffs_inter(&mut self) {
235 let stride = self.cell.get_width();
236 let prev_iter = self.rbuf.chunks(stride).skip(1);
237 let cur_iter = self.buf.chunks(stride).skip(1);
238 for (dline, (cur, prev)) in self.deltas.chunks_mut(stride).take(self.cell.get_height()).zip(cur_iter.zip(prev_iter)) {
239 for (dst, (&cur, &prev)) in dline.iter_mut().zip(cur.iter().zip(prev.iter())) {
240 *dst = (cur as i8) - (prev as i8);
244 pub fn put_buffer(&self, plane: &mut Plane) {
245 let to_skip = if !self.cell.is_intra() || self.cell.get_y() == 0 { 1 } else { 0 };
247 let dst = &mut plane.data[self.cell.get_x() + (self.cell.get_y() + to_skip - 1) * plane.width..];
248 let src_w = self.cell.get_width();
249 for (sline, dline) in self.buf.chunks(src_w).skip(to_skip).zip(dst.chunks_mut(plane.width)).take(self.cell.get_height() + 1 - to_skip) {
250 dline[..src_w].copy_from_slice(sline);
253 fn determine_mode(&self, intra: bool, mut mode_hint: u8) -> (u8, [u8; 2]) {
254 if let Some(qmode) = self.quant {
256 return (mode_hint, [qmode as u8, qmode as u8]);
258 let qmode = (qmode & 7) as u8;
259 return (mode_hint, [qmode, qmode]);
263 let stride = self.cell.get_width();
265 let mut cb_p = CodebookSuggester::new();
266 let mut cb_s = CodebookSuggester::new();
267 if !intra && (self.cell.get_height() & 7 == 0) {
270 for line_pair in self.deltas.chunks(stride * 2).take(self.cell.get_height() / 2) {
271 let (line1, line2) = line_pair.split_at(stride);
272 for (&el1, &el2) in line1.iter().zip(line2.iter()) {
273 let diff = i32::from(el1) - i32::from(el2);
274 vdiff += (diff * diff) as u32;
277 for line in self.deltas.chunks(stride).take(self.cell.get_height()) {
278 for pair in line.chunks(2) {
279 let diff = i32::from(pair[1]) - i32::from(pair[0]);
280 hdiff += (diff * diff) as u32;
283 vdiff /= (self.cell.get_width() * self.cell.get_height() / 2) as u32;
284 hdiff /= (self.cell.get_width() * self.cell.get_height() / 2) as u32;
286 mode_hint = match ((vdiff > self.flat_thr_p), (hdiff > self.flat_thr_p)) {
287 (false, false) if (self.cell.get_width() & 7) == 0 => 10,
294 for line_pair in self.deltas.chunks(stride * 2).take(self.cell.get_height() / 2) {
295 let (line1, line2) = line_pair.split_at(stride);
296 cb_p.add_line(line1);
297 cb_s.add_line(line2);
301 for line_quad in self.deltas.chunks(stride * 4).take(self.cell.get_height() / 4) {
302 let (line01, line23) = line_quad.split_at(stride * 2);
303 let (_line0, line1) = line01.split_at(stride);
304 let (_line2, line3) = line23.split_at(stride);
305 cb_p.add_line(line1);
306 cb_s.add_line(line3);
310 for line_quad in self.deltas.chunks(stride * 4).take(self.cell.get_height() / 4) {
311 let (line01, line23) = line_quad.split_at(stride * 2);
312 let (_line0, line1) = line01.split_at(stride);
313 let (_line2, line3) = line23.split_at(stride);
314 cb_p.add_line_half(line1);
315 cb_s.add_line_half(line3);
319 for line_quad in self.deltas.chunks(stride * 4).take(self.cell.get_height() / 4) {
320 let (line01, line23) = line_quad.split_at(stride * 2);
321 let (_line0, line1) = line01.split_at(stride);
322 let (_line2, line3) = line23.split_at(stride);
323 cb_p.add_line(line1);
324 cb_s.add_line(line3);
329 let cb_f = CodebookSuggester::merge(&cb_p, &cb_s).get_best();
330 let cb_p = cb_p.get_best();
331 let mut cb_s = cb_s.get_best();
333 let mut use_single = !intra || mode_hint == 10 || cb_p == cb_s;
335 if cb_s == 0 { // we can adjust to the CB_SELECTORS here
336 cb_s = (((cb_p & 7) + 1) * 2).min(15);
338 let ncb = (cb_p << 4) + cb_s;
339 use_single = !CB_SELECTORS.contains(&ncb);
343 if intra || cb_f < 8 { // we don't want requant happening in inter mode
344 (mode_hint, [cb_f, cb_f])
349 (mode_hint + 1, [cb_p, cb_s])
352 pub fn compress_intra(&mut self, mode_hint: u8) {
353 let (mode, vq_idx) = self.determine_mode(true, mode_hint);
355 let cb_no1 = usize::from(vq_idx[1]);
356 let cb_no2 = usize::from(vq_idx[0]);
357 let cb1 = IVI3_DELTA_CBS[cb_no1];
358 let cb2 = IVI3_DELTA_CBS[cb_no2];
360 let mut requant_idx = None;
361 if (mode == 1) || (mode == 4) {
362 let aq_idx = (vq_idx[0] << 4) | vq_idx[1];
364 for (i, &el) in CB_SELECTORS.iter().enumerate() {
370 self.out[0] = (mode << 4) | (idx as u8);
372 self.out[0] = (mode << 4) | (cb_no1 as u8);
374 if (8..=15).contains(&cb_no1) {
375 requant_idx = Some(cb_no1 - 8);
378 if self.cell.get_y() == 0 || !matches!(mode, 0 | 3 | 10) {
383 let mut iwriter = IndexWriter::new(&mut self.out[start..], self.do_rle);
385 let esc_val1 = (cb1.data.len() / 2) as u8;
386 let esc_val2 = (cb2.data.len() / 2) as u8;
388 let cbs = [cb1, cb2, cb1, cb2];
389 let esc_vals = [esc_val1, esc_val2, esc_val1, esc_val2];
391 let mut first_line = self.cell.get_y() == 0;
392 let stride = self.cell.get_width();
394 if let Some(ridx) = requant_idx {// && !first_line {
395 requant(&mut self.buf[..stride], ridx);
398 let mut cell4 = [0; 20];
401 for y in (0..self.cell.get_height()).step_by(4) {
402 for x in (0..self.cell.get_width()).step_by(4) {
403 Self::get_cell4(&self.buf, x, y, stride, &mut cell4);
404 // first check if the cell can be coded with zero predictor
408 let (top, cur) = cell4.split_at(pivot);
409 let top = &top[top.len() - 4..];
410 for (&tval, &cval) in top.iter().zip(cur.iter()) {
411 let cdiff = i32::from(tval) - i32::from(cval);
412 diff += cdiff * cdiff;
416 if (diff as u32) < self.flat_thr_i {
417 iwriter.write_byte(ZERO_CELL);
418 let (top, tail) = cell4.split_at_mut(4);
419 for dline in tail.chunks_mut(4) {
420 dline.copy_from_slice(top);
422 Self::put_cell4(&mut self.buf, x, y, stride, &cell4);
426 compress_intra_cell(&mut iwriter, &mut cell4, &cbs, esc_vals);
427 Self::put_cell4(&mut self.buf, x, y, stride, &cell4);
432 for y in (0..self.cell.get_height()).step_by(8) {
433 for x in (0..self.cell.get_width()).step_by(4) {
434 Self::get_cell_mode3(&self.buf, x, y, stride, &mut cell4);
435 compress_intra_cell(&mut iwriter, &mut cell4, &cbs, esc_vals);
436 Self::put_cell_mode3(&mut self.buf, x, y, stride, &cell4, first_line);
442 for y in (0..self.cell.get_height()).step_by(8) {
443 for x in (0..self.cell.get_width()).step_by(8) {
444 Self::get_cell_mode10i(&self.buf, x, y, stride, &mut cell4);
445 compress_intra_cell(&mut iwriter, &mut cell4, &cbs, esc_vals);
446 Self::put_cell_mode10i(&mut self.buf, x, y, stride, &cell4, first_line);
453 iwriter.compact_all_cells();
455 self.osize = iwriter.end() + start;
457 pub fn compress_inter(&mut self) {
458 let (mode, vq_idx) = self.determine_mode(false, 0);
460 let cb_no1 = usize::from(vq_idx[1]);
461 let cb_no2 = usize::from(vq_idx[0]);
462 let cb1 = IVI3_DELTA_CBS[cb_no1];
463 let cb2 = IVI3_DELTA_CBS[cb_no2];
465 if (mode == 1) || (mode == 4) {
466 let aq_idx = (vq_idx[0] << 4) | vq_idx[1];
468 for (i, &el) in CB_SELECTORS.iter().enumerate() {
474 self.out[0] = (mode << 4) | (idx as u8);
476 self.out[0] = (mode << 4) | (cb_no1 as u8);
479 let mut iwriter = IndexWriter::new(&mut self.out[start..], self.do_rle);
481 let esc_val1 = (cb1.data.len() / 2) as u8;
482 let esc_val2 = (cb2.data.len() / 2) as u8;
484 let cbs = [cb1, cb2, cb1, cb2];
485 let esc_vals = [esc_val1, esc_val2, esc_val1, esc_val2];
488 let stride = self.cell.get_width();
489 let mut ccell4 = [0; 20];
490 let mut pcell4 = [0; 20];
493 for y in (0..self.cell.get_height()).step_by(4) {
494 for x in (0..self.cell.get_width()).step_by(4) {
495 Self::get_cell4(&self.buf, x, y, stride, &mut ccell4);
496 Self::get_cell4(&self.rbuf, x, y, stride, &mut pcell4);
497 // first check if the cell can be coded with zero predictor
499 for (&pval, &cval) in pcell4[4..].iter().zip(ccell4[4..].iter()) {
500 let cdiff = i32::from(pval) - i32::from(cval);
501 diff += cdiff * cdiff;
504 iwriter.write_byte(SKIP_CELL);
505 Self::put_cell4(&mut self.buf, x, y, stride, &pcell4);
509 compress_inter_cell(&mut iwriter, &mut ccell4, &pcell4, &cbs, esc_vals);
510 Self::put_cell4(&mut self.buf, x, y, stride, &ccell4);
516 let mut ref_cell = [0; 64];
517 let mut avg_diff: [i16; 16];
518 for _y in (0..self.cell.get_height()).step_by(8) {
519 for x in (0..self.cell.get_width()).step_by(8) {
520 for (dline, sline) in ref_cell.chunks_mut(8).zip(self.rbuf[offset + stride + x..].chunks(stride)) {
521 dline.copy_from_slice(&sline[..8]);
526 avg_diff[i / 2 + (j / 2) * 4] += i16::from(self.deltas[offset + x + i + j * stride]);
529 for el in avg_diff.iter_mut() {
530 *el = (*el + 2) >> 2;
532 compress_inter_cell_mode10(&mut iwriter, &mut ref_cell, &avg_diff, &cbs, esc_vals);
533 for (sline, dline) in ref_cell.chunks(8).zip(self.buf[offset + stride + x..].chunks_mut(stride)) {
534 dline[..8].copy_from_slice(sline);
537 offset += stride * 8;
542 let mut ref_cell = [0; 32];
543 let mut avg_diff: [i16; 16];
544 for _y in (0..self.cell.get_height()).step_by(8) {
545 for x in (0..self.cell.get_width()).step_by(4) {
546 for (dline, sline) in ref_cell.chunks_mut(4).zip(self.rbuf[offset + stride + x..].chunks(stride)) {
547 dline.copy_from_slice(&sline[..4]);
552 avg_diff[i + (j / 2) * 4] += i16::from(self.deltas[offset + x + i + j * stride]);
555 for el in avg_diff.iter_mut() {
556 *el = (*el + 1) >> 1;
559 compress_inter_cell_mode11(&mut iwriter, &mut ref_cell, &avg_diff, &cbs, esc_vals);
560 for (sline, dline) in ref_cell.chunks(4).zip(self.buf[offset + stride + x..].chunks_mut(stride)) {
561 dline[..4].copy_from_slice(sline);
564 offset += stride * 8;
569 iwriter.compact_all_cells();
571 self.osize = iwriter.end() + start;
574 fn get_cell4(data: &[u8], x: usize, y: usize, stride: usize, cell: &mut [u8; 20]) {
575 for (dst, src) in cell.chunks_mut(4).zip(data[x + y * stride..].chunks(stride)) {
576 dst.copy_from_slice(&src[..4]);
579 fn put_cell4(data: &mut [u8], x: usize, y: usize, stride: usize, cell: &[u8; 20]) {
580 for (src, dst) in cell.chunks(4).zip(data[x + y * stride..].chunks_mut(stride)).skip(1) {
581 dst[..4].copy_from_slice(src);
584 fn get_cell_mode3(data: &[u8], x: usize, y: usize, stride: usize, cell: &mut [u8; 20]) {
585 let src = &data[x + y * stride..];
586 for (dline, slines) in cell.chunks_mut(4).zip(src.chunks(stride * 2)) {
587 dline.copy_from_slice(&slines[..4]);
590 fn put_cell_mode3(data: &mut [u8], x: usize, y: usize, stride: usize, cell: &[u8; 20], first_line: bool) {
591 let dst = &mut data[x + y * stride..];
592 let mut dst_idx = stride;
595 let top = cell[line * 4 + x];
596 let cur = cell[(line + 1) * 4 + x];
597 dst[dst_idx + x] = (top + cur) >> 1;
598 dst[dst_idx + stride + x] = cur;
600 dst_idx += stride * 2;
603 dst[stride..][..4].copy_from_slice(&cell[4..8]);
606 fn get_cell_mode10i(data: &[u8], x: usize, y: usize, stride: usize, cell: &mut [u8; 20]) {
607 let src = &data[x + y * stride..];
608 for (dline, src_pair) in cell.chunks_mut(4).zip(src.chunks(stride * 2)) {
609 for (dst, src) in dline.iter_mut().zip(src_pair.chunks(2)) {
614 fn put_cell_mode10i(data: &mut [u8], x: usize, y: usize, stride: usize, cell: &[u8; 20], first_line: bool) {
615 let dst = &mut data[x + y * stride..];
616 let mut dst_idx = stride;
619 let top = dst[dst_idx - stride + x];
620 let cur = cell[(line + 1) * 4 + x / 2];
621 dst[dst_idx + x] = (top + cur) >> 1;
622 dst[dst_idx + stride + x] = cur;
624 dst_idx += stride * 2;
627 let (top, tail) = dst[stride..].split_at_mut(stride);
628 top[..8].copy_from_slice(&tail[..8]);
633 fn requant(line: &mut [u8], rq_index: usize) {
634 let tab = &REQUANT_TAB[rq_index];
635 for el in line.iter_mut() {
636 *el = tab[usize::from(*el)];
640 fn compress_intra_cell(iwriter: &mut IndexWriter, cell4: &mut [u8; 20], cbs: &[&IviDeltaCB; 4], esc_vals: [u8; 4]) {
644 let esc_val = esc_vals[y];
646 let (prev, cur) = cell4.split_at_mut(pivot);
647 let prev = &prev[prev.len() - 4..];
648 let cur = &mut cur[..4];
649 let (idx0, idx1) = find_quad(&cb.data, prev, cur);
651 cur[0] = ((prev[0] as i8) + cb.data[usize::from(idx1) * 2]) as u8;
652 cur[1] = ((prev[1] as i8) + cb.data[usize::from(idx1) * 2 + 1]) as u8;
653 cur[2] = ((prev[2] as i8) + cb.data[usize::from(idx0) * 2]) as u8;
654 cur[3] = ((prev[3] as i8) + cb.data[usize::from(idx0) * 2 + 1]) as u8;
656 iwriter.write_pair(idx0, idx1, cb.quad_radix, esc_val);
660 iwriter.compact_cell(esc_vals);
663 fn compress_inter_cell(iwriter: &mut IndexWriter, ccell4: &mut [u8; 20], pcell: &[u8; 20], cbs: &[&IviDeltaCB; 4], esc_vals: [u8; 4]) {
664 for (y, (prev, cur)) in pcell[4..].chunks(4).zip(ccell4[4..].chunks_mut(4)).enumerate() {
666 let esc_val = esc_vals[y];
668 let (idx0, idx1) = find_quad(&cb.data, prev, cur);
670 cur[0] = ((prev[0] as i8) + cb.data[usize::from(idx1) * 2]) as u8;
671 cur[1] = ((prev[1] as i8) + cb.data[usize::from(idx1) * 2 + 1]) as u8;
672 cur[2] = ((prev[2] as i8) + cb.data[usize::from(idx0) * 2]) as u8;
673 cur[3] = ((prev[3] as i8) + cb.data[usize::from(idx0) * 2 + 1]) as u8;
675 iwriter.write_pair(idx0, idx1, cb.quad_radix, esc_val);
677 iwriter.compact_cell(esc_vals);
680 fn compress_inter_cell_mode10(iwriter: &mut IndexWriter, cell: &mut [u8; 64], diffs: &[i16; 16], cbs: &[&IviDeltaCB; 4], esc_vals: [u8; 4]) {
683 let esc_val = esc_vals[y];
684 let mut indices = [0, 0];
685 for pair_no in (0..4).step_by(2) {
686 let src_idx = y * 8 * 2 + pair_no * 2;
687 let src0 = [cell[src_idx], cell[src_idx + 1], cell[src_idx + 8], cell[src_idx + 9]];
688 let src1 = [cell[src_idx + 2], cell[src_idx + 3], cell[src_idx + 10], cell[src_idx + 11]];
690 let cur_diff = [diffs[y * 4 + pair_no] as i8, diffs[y * 4 + pair_no + 1] as i8];
692 let mut best_idx = 0;
693 let mut best_dist = pair_dist(&cur_diff, &[0, 0]);
694 for (idx, cbpair) in cb.data.chunks(2).enumerate().skip(1) {
695 let dist = pair_dist(&cur_diff, cbpair);
696 if dist < best_dist {
698 for &el in src0.iter() {
699 if !in_range(el as i8, cbpair[0]) {
704 for &el in src1.iter() {
705 if !in_range(el as i8, cbpair[1]) {
717 indices[pair_no / 2] = best_idx as u8;
719 let cb_pair = &cb.data[best_idx * 2..];
720 for row in cell[src_idx..].chunks_mut(8).take(2) {
721 row[0] = ((row[0] as i8) + cb_pair[0]) as u8;
722 row[1] = ((row[1] as i8) + cb_pair[0]) as u8;
723 row[2] = ((row[2] as i8) + cb_pair[1]) as u8;
724 row[3] = ((row[3] as i8) + cb_pair[1]) as u8;
727 iwriter.write_pair(indices[1], indices[0], cb.quad_radix, esc_val);
729 iwriter.compact_cell(esc_vals);
732 fn compress_inter_cell_mode11(iwriter: &mut IndexWriter, cell: &mut [u8; 32], diffs: &[i16; 16], cbs: &[&IviDeltaCB; 4], esc_vals: [u8; 4]) {
735 let esc_val = esc_vals[y];
736 let mut indices = [0, 0];
737 for pair_no in (0..4).step_by(2) {
738 let src_idx = y * 4 * 2 + pair_no;
739 let src0 = [cell[src_idx], cell[src_idx + 4]];
740 let src1 = [cell[src_idx + 1], cell[src_idx + 5]];
742 let cur_diff = [diffs[y * 4 + pair_no] as i8, diffs[y * 4 + pair_no + 1] as i8];
744 let mut best_idx = 0;
745 let mut best_dist = pair_dist(&cur_diff, &[0, 0]);
746 for (idx, cbpair) in cb.data.chunks(2).enumerate().skip(1) {
747 let dist = pair_dist(&cur_diff, cbpair);
748 if dist < best_dist {
750 for &el in src0.iter() {
751 if !in_range(el as i8, cbpair[0]) {
756 for &el in src1.iter() {
757 if !in_range(el as i8, cbpair[1]) {
769 indices[pair_no / 2] = best_idx as u8;
771 let cb_pair = &cb.data[best_idx * 2..];
772 cell[src_idx] = ((cell[src_idx] as i8) + cb_pair[0]) as u8;
773 cell[src_idx + 4] = ((cell[src_idx + 4] as i8) + cb_pair[0]) as u8;
774 cell[src_idx + 1] = ((cell[src_idx + 1] as i8) + cb_pair[1]) as u8;
775 cell[src_idx + 5] = ((cell[src_idx + 5] as i8) + cb_pair[1]) as u8;
777 iwriter.write_pair(indices[1], indices[0], cb.quad_radix, esc_val);
779 iwriter.compact_cell(esc_vals);
782 fn pair_dist(src: &[i8], pair: &[i8]) -> u32 {
783 let d0 = (i32::from(src[0]) - i32::from(pair[0])).abs() as u32;
784 let d1 = (i32::from(src[1]) - i32::from(pair[1])).abs() as u32;
788 fn in_range(base: i8, delta: i8) -> bool {
789 if let Some(val) = base.checked_add(delta) {
796 fn find_pair(cb_data: &[i8], ppair: &[u8], cpair: &[u8]) -> u8 {
797 let ppair = [ppair[0] as i8, ppair[1] as i8];
798 let diff = [(cpair[0] as i8) - ppair[0], (cpair[1] as i8) - ppair[1]];
799 // pair 0 is always zero;
803 let mut best_idx = 0;
804 let mut best_dist = pair_dist(&diff, &[0, 0]);
805 for (idx, cbpair) in cb_data.chunks(2).enumerate().skip(1) {
806 let dist = pair_dist(&diff, cbpair);
807 if dist < best_dist && in_range(ppair[0], cbpair[0]) && in_range(ppair[1], cbpair[1]) {
815 fn find_quad(cb_data: &[i8], prev: &[u8], cur: &[u8]) -> (u8, u8) {
816 let (ppair1, ppair0) = prev.split_at(2);
817 let (cpair1, cpair0) = cur.split_at(2);
818 let idx1 = find_pair(cb_data, ppair1, cpair1);
819 let idx0 = find_pair(cb_data, ppair0, cpair0);
823 const REQUANT_TAB: [[u8; 128]; 8] = [
825 0x00, 0x02, 0x02, 0x04, 0x04, 0x06, 0x06, 0x08,
826 0x08, 0x0a, 0x0a, 0x0c, 0x0c, 0x0e, 0x0e, 0x10,
827 0x10, 0x12, 0x12, 0x14, 0x14, 0x16, 0x16, 0x18,
828 0x18, 0x1a, 0x1a, 0x1c, 0x1c, 0x1e, 0x1e, 0x20,
829 0x20, 0x22, 0x22, 0x24, 0x24, 0x26, 0x26, 0x28,
830 0x28, 0x2a, 0x2a, 0x2c, 0x2c, 0x2e, 0x2e, 0x30,
831 0x30, 0x32, 0x32, 0x34, 0x34, 0x36, 0x36, 0x38,
832 0x38, 0x3a, 0x3a, 0x3c, 0x3c, 0x3e, 0x3e, 0x40,
833 0x40, 0x42, 0x42, 0x44, 0x44, 0x46, 0x46, 0x48,
834 0x48, 0x4a, 0x4a, 0x4c, 0x4c, 0x4e, 0x4e, 0x50,
835 0x50, 0x52, 0x52, 0x54, 0x54, 0x56, 0x56, 0x58,
836 0x58, 0x5a, 0x5a, 0x5c, 0x5c, 0x5e, 0x5e, 0x60,
837 0x60, 0x62, 0x62, 0x64, 0x64, 0x66, 0x66, 0x68,
838 0x68, 0x6a, 0x6a, 0x6c, 0x6c, 0x6e, 0x6e, 0x70,
839 0x70, 0x72, 0x72, 0x74, 0x74, 0x76, 0x76, 0x78,
840 0x78, 0x7a, 0x7a, 0x7c, 0x7c, 0x7e, 0x7e, 0x7e
842 0x01, 0x01, 0x04, 0x04, 0x04, 0x07, 0x07, 0x0a,
843 0x0a, 0x0a, 0x0a, 0x0d, 0x0d, 0x0d, 0x10, 0x10,
844 0x10, 0x13, 0x13, 0x13, 0x16, 0x16, 0x16, 0x19,
845 0x19, 0x19, 0x1c, 0x1c, 0x1c, 0x1f, 0x1f, 0x1f,
846 0x22, 0x22, 0x22, 0x25, 0x25, 0x25, 0x28, 0x28,
847 0x28, 0x2b, 0x2b, 0x2b, 0x2e, 0x2e, 0x2e, 0x31,
848 0x31, 0x31, 0x34, 0x34, 0x34, 0x37, 0x37, 0x37,
849 0x3a, 0x3a, 0x3a, 0x3d, 0x3d, 0x3d, 0x40, 0x40,
850 0x40, 0x43, 0x43, 0x43, 0x46, 0x46, 0x46, 0x49,
851 0x49, 0x49, 0x4c, 0x4c, 0x4c, 0x4f, 0x4f, 0x4f,
852 0x52, 0x52, 0x52, 0x55, 0x55, 0x55, 0x58, 0x58,
853 0x58, 0x5b, 0x5b, 0x5b, 0x5e, 0x5e, 0x5e, 0x61,
854 0x61, 0x61, 0x64, 0x64, 0x64, 0x67, 0x67, 0x67,
855 0x6a, 0x6a, 0x6a, 0x6d, 0x6d, 0x6d, 0x70, 0x70,
856 0x70, 0x73, 0x73, 0x73, 0x76, 0x76, 0x76, 0x76,
857 0x76, 0x79, 0x7c, 0x7c, 0x7c, 0x7f, 0x7f, 0x7f
859 0x00, 0x00, 0x04, 0x04, 0x04, 0x04, 0x08, 0x08,
860 0x08, 0x08, 0x0c, 0x0c, 0x0c, 0x0c, 0x10, 0x10,
861 0x10, 0x10, 0x14, 0x14, 0x14, 0x14, 0x18, 0x18,
862 0x18, 0x18, 0x1c, 0x1c, 0x1c, 0x1c, 0x20, 0x20,
863 0x20, 0x20, 0x24, 0x24, 0x24, 0x24, 0x28, 0x28,
864 0x28, 0x28, 0x2c, 0x2c, 0x2c, 0x2c, 0x30, 0x30,
865 0x30, 0x30, 0x34, 0x34, 0x34, 0x34, 0x38, 0x38,
866 0x38, 0x38, 0x3c, 0x3c, 0x3c, 0x3c, 0x40, 0x40,
867 0x40, 0x40, 0x44, 0x44, 0x44, 0x44, 0x48, 0x48,
868 0x48, 0x48, 0x4c, 0x4c, 0x4c, 0x4c, 0x50, 0x50,
869 0x50, 0x50, 0x54, 0x54, 0x54, 0x54, 0x58, 0x58,
870 0x58, 0x58, 0x5c, 0x5c, 0x5c, 0x5c, 0x60, 0x60,
871 0x60, 0x60, 0x64, 0x64, 0x64, 0x64, 0x68, 0x68,
872 0x68, 0x68, 0x6c, 0x6c, 0x6c, 0x6c, 0x70, 0x70,
873 0x70, 0x70, 0x74, 0x74, 0x74, 0x74, 0x78, 0x78,
874 0x78, 0x78, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c
876 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
877 0x09, 0x09, 0x09, 0x09, 0x09, 0x0e, 0x0e, 0x0e,
878 0x0e, 0x0e, 0x13, 0x13, 0x13, 0x13, 0x13, 0x18,
879 0x18, 0x18, 0x18, 0x18, 0x1d, 0x1d, 0x1d, 0x1d,
880 0x1d, 0x22, 0x22, 0x22, 0x22, 0x22, 0x27, 0x27,
881 0x27, 0x27, 0x27, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c,
882 0x31, 0x31, 0x31, 0x31, 0x31, 0x36, 0x36, 0x36,
883 0x36, 0x36, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x40,
884 0x40, 0x40, 0x40, 0x40, 0x45, 0x45, 0x45, 0x45,
885 0x45, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4f, 0x4f,
886 0x4f, 0x4f, 0x4f, 0x54, 0x54, 0x54, 0x54, 0x54,
887 0x59, 0x59, 0x59, 0x59, 0x59, 0x5e, 0x5e, 0x5e,
888 0x5e, 0x5e, 0x63, 0x63, 0x63, 0x63, 0x63, 0x68,
889 0x68, 0x68, 0x68, 0x68, 0x6d, 0x6d, 0x6d, 0x6d,
890 0x6d, 0x72, 0x72, 0x72, 0x72, 0x72, 0x77, 0x77,
891 0x77, 0x77, 0x77, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c
893 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
894 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x10,
895 0x10, 0x10, 0x10, 0x10, 0x10, 0x16, 0x16, 0x16,
896 0x16, 0x16, 0x16, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c,
897 0x1c, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x28,
898 0x28, 0x28, 0x28, 0x28, 0x28, 0x2e, 0x2e, 0x2e,
899 0x2e, 0x2e, 0x2e, 0x34, 0x34, 0x34, 0x34, 0x34,
900 0x34, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x40,
901 0x40, 0x40, 0x40, 0x40, 0x40, 0x46, 0x46, 0x46,
902 0x46, 0x46, 0x46, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c,
903 0x4c, 0x52, 0x52, 0x52, 0x52, 0x52, 0x52, 0x58,
904 0x58, 0x58, 0x58, 0x58, 0x58, 0x5e, 0x5e, 0x5e,
905 0x5e, 0x5e, 0x5e, 0x64, 0x64, 0x64, 0x64, 0x64,
906 0x64, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x70,
907 0x70, 0x70, 0x70, 0x70, 0x70, 0x76, 0x76, 0x76,
908 0x76, 0x76, 0x76, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c
910 0x01, 0x01, 0x01, 0x01, 0x08, 0x08, 0x08, 0x08,
911 0x08, 0x08, 0x08, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
912 0x0f, 0x0f, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16,
913 0x16, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d,
914 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x2b,
915 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x32, 0x32,
916 0x32, 0x32, 0x32, 0x32, 0x32, 0x39, 0x39, 0x39,
917 0x39, 0x39, 0x39, 0x39, 0x40, 0x40, 0x40, 0x40,
918 0x40, 0x40, 0x40, 0x47, 0x47, 0x47, 0x47, 0x47,
919 0x47, 0x47, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e,
920 0x4e, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
921 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x63,
922 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x6a, 0x6a,
923 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x71, 0x71, 0x71,
924 0x71, 0x71, 0x71, 0x71, 0x78, 0x78, 0x78, 0x78,
925 0x78, 0x78, 0x78, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f
927 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08,
928 0x08, 0x08, 0x08, 0x08, 0x10, 0x10, 0x10, 0x10,
929 0x10, 0x10, 0x10, 0x10, 0x18, 0x18, 0x18, 0x18,
930 0x18, 0x18, 0x18, 0x18, 0x20, 0x20, 0x20, 0x20,
931 0x20, 0x20, 0x20, 0x20, 0x28, 0x28, 0x28, 0x28,
932 0x28, 0x28, 0x28, 0x28, 0x30, 0x30, 0x30, 0x30,
933 0x30, 0x30, 0x30, 0x30, 0x38, 0x38, 0x38, 0x38,
934 0x38, 0x38, 0x38, 0x38, 0x40, 0x40, 0x40, 0x40,
935 0x40, 0x40, 0x40, 0x40, 0x48, 0x48, 0x48, 0x48,
936 0x48, 0x48, 0x48, 0x48, 0x50, 0x50, 0x50, 0x50,
937 0x50, 0x50, 0x50, 0x50, 0x58, 0x58, 0x58, 0x58,
938 0x58, 0x58, 0x58, 0x58, 0x60, 0x60, 0x60, 0x60,
939 0x60, 0x60, 0x60, 0x60, 0x68, 0x68, 0x68, 0x68,
940 0x68, 0x68, 0x68, 0x68, 0x70, 0x70, 0x70, 0x70,
941 0x70, 0x70, 0x70, 0x70, 0x78, 0x78, 0x78, 0x78,
942 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78
944 0x01, 0x01, 0x01, 0x01, 0x01, 0x0a, 0x0a, 0x0a,
945 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x13, 0x13,
946 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x1c,
947 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c,
948 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25,
949 0x25, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e,
950 0x2e, 0x2e, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37,
951 0x37, 0x37, 0x37, 0x40, 0x40, 0x40, 0x40, 0x40,
952 0x40, 0x40, 0x40, 0x40, 0x49, 0x49, 0x49, 0x49,
953 0x49, 0x49, 0x49, 0x49, 0x49, 0x52, 0x52, 0x52,
954 0x52, 0x52, 0x52, 0x52, 0x52, 0x52, 0x5b, 0x5b,
955 0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x64,
956 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64,
957 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d,
958 0x6d, 0x76, 0x76, 0x76, 0x76, 0x76, 0x76, 0x76,
959 0x76, 0x76, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f