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);
373 requant_idx = Some(idx - 8);
376 self.out[0] = (mode << 4) | (cb_no1 as u8);
378 if (8..=15).contains(&cb_no1) {
379 requant_idx = Some(cb_no1 - 8);
382 if self.cell.get_y() == 0 {
387 let mut iwriter = IndexWriter::new(&mut self.out[start..], self.do_rle);
389 let esc_val1 = (cb1.data.len() / 2) as u8;
390 let esc_val2 = (cb2.data.len() / 2) as u8;
392 let cbs = [cb1, cb2, cb1, cb2];
393 let esc_vals = [esc_val1, esc_val2, esc_val1, esc_val2];
395 let mut first_line = self.cell.get_y() == 0;
396 let stride = self.cell.get_width();
398 if let Some(ridx) = requant_idx {// && !first_line {
399 requant(&mut self.buf[..stride], ridx);
402 let mut cell4 = [0; 20];
405 for y in (0..self.cell.get_height()).step_by(4) {
406 for x in (0..self.cell.get_width()).step_by(4) {
407 Self::get_cell4(&self.buf, x, y, stride, &mut cell4);
408 // first check if the cell can be coded with zero predictor
412 let (top, cur) = cell4.split_at(pivot);
413 let top = &top[top.len() - 4..];
414 for (&tval, &cval) in top.iter().zip(cur.iter()) {
415 let cdiff = i32::from(tval) - i32::from(cval);
416 diff += cdiff * cdiff;
420 if (diff as u32) < self.flat_thr_i {
421 iwriter.write_byte(ZERO_CELL);
422 let (top, tail) = cell4.split_at_mut(4);
423 for dline in tail.chunks_mut(4) {
424 dline.copy_from_slice(top);
426 Self::put_cell4(&mut self.buf, x, y, stride, &cell4);
430 compress_intra_cell(&mut iwriter, &mut cell4, &cbs, esc_vals);
431 Self::put_cell4(&mut self.buf, x, y, stride, &cell4);
436 for y in (0..self.cell.get_height()).step_by(8) {
437 for x in (0..self.cell.get_width()).step_by(4) {
438 Self::get_cell_mode3(&self.buf, x, y, stride, &mut cell4);
439 compress_intra_cell(&mut iwriter, &mut cell4, &cbs, esc_vals);
440 Self::put_cell_mode3(&mut self.buf, x, y, stride, &cell4, first_line);
446 for y in (0..self.cell.get_height()).step_by(8) {
447 for x in (0..self.cell.get_width()).step_by(8) {
448 Self::get_cell_mode10i(&self.buf, x, y, stride, &mut cell4);
449 compress_intra_cell(&mut iwriter, &mut cell4, &cbs, esc_vals);
450 Self::put_cell_mode10i(&mut self.buf, x, y, stride, &cell4, first_line);
457 iwriter.compact_all_cells();
459 self.osize = iwriter.end() + start;
461 pub fn compress_inter(&mut self) {
462 let (mode, vq_idx) = self.determine_mode(false, 0);
464 let cb_no1 = usize::from(vq_idx[1]);
465 let cb_no2 = usize::from(vq_idx[0]);
466 let cb1 = IVI3_DELTA_CBS[cb_no1];
467 let cb2 = IVI3_DELTA_CBS[cb_no2];
469 if (mode == 1) || (mode == 4) {
470 let aq_idx = (vq_idx[0] << 4) | vq_idx[1];
472 for (i, &el) in CB_SELECTORS.iter().enumerate() {
478 self.out[0] = (mode << 4) | (idx as u8);
480 self.out[0] = (mode << 4) | (cb_no1 as u8);
483 let mut iwriter = IndexWriter::new(&mut self.out[start..], self.do_rle);
485 let esc_val1 = (cb1.data.len() / 2) as u8;
486 let esc_val2 = (cb2.data.len() / 2) as u8;
488 let cbs = [cb1, cb2, cb1, cb2];
489 let esc_vals = [esc_val1, esc_val2, esc_val1, esc_val2];
492 let stride = self.cell.get_width();
493 let mut ccell4 = [0; 20];
494 let mut pcell4 = [0; 20];
497 for y in (0..self.cell.get_height()).step_by(4) {
498 for x in (0..self.cell.get_width()).step_by(4) {
499 Self::get_cell4(&self.buf, x, y, stride, &mut ccell4);
500 Self::get_cell4(&self.rbuf, x, y, stride, &mut pcell4);
501 // first check if the cell can be coded with zero predictor
503 for (&pval, &cval) in pcell4[4..].iter().zip(ccell4[4..].iter()) {
504 let cdiff = i32::from(pval) - i32::from(cval);
505 diff += cdiff * cdiff;
508 iwriter.write_byte(SKIP_CELL);
509 Self::put_cell4(&mut self.buf, x, y, stride, &pcell4);
513 compress_inter_cell(&mut iwriter, &mut ccell4, &pcell4, &cbs, esc_vals);
514 Self::put_cell4(&mut self.buf, x, y, stride, &ccell4);
520 let mut ref_cell = [0; 64];
521 let mut avg_diff: [i16; 16];
522 for _y in (0..self.cell.get_height()).step_by(8) {
523 for x in (0..self.cell.get_width()).step_by(8) {
524 for (dline, sline) in ref_cell.chunks_mut(8).zip(self.rbuf[offset + stride + x..].chunks(stride)) {
525 dline.copy_from_slice(&sline[..8]);
530 avg_diff[i / 2 + (j / 2) * 4] += i16::from(self.deltas[offset + x + i + j * stride]);
533 for el in avg_diff.iter_mut() {
534 *el = (*el + 2) >> 2;
536 compress_inter_cell_mode10(&mut iwriter, &mut ref_cell, &avg_diff, &cbs, esc_vals);
537 for (sline, dline) in ref_cell.chunks(8).zip(self.buf[offset + stride + x..].chunks_mut(stride)) {
538 dline[..8].copy_from_slice(sline);
541 offset += stride * 8;
546 let mut ref_cell = [0; 32];
547 let mut avg_diff: [i16; 16];
548 for _y in (0..self.cell.get_height()).step_by(8) {
549 for x in (0..self.cell.get_width()).step_by(4) {
550 for (dline, sline) in ref_cell.chunks_mut(4).zip(self.rbuf[offset + stride + x..].chunks(stride)) {
551 dline.copy_from_slice(&sline[..4]);
556 avg_diff[i + (j / 2) * 4] += i16::from(self.deltas[offset + x + i + j * stride]);
559 for el in avg_diff.iter_mut() {
560 *el = (*el + 1) >> 1;
563 compress_inter_cell_mode11(&mut iwriter, &mut ref_cell, &avg_diff, &cbs, esc_vals);
564 for (sline, dline) in ref_cell.chunks(4).zip(self.buf[offset + stride + x..].chunks_mut(stride)) {
565 dline[..4].copy_from_slice(sline);
568 offset += stride * 8;
573 iwriter.compact_all_cells();
575 self.osize = iwriter.end() + start;
578 fn get_cell4(data: &[u8], x: usize, y: usize, stride: usize, cell: &mut [u8; 20]) {
579 for (dst, src) in cell.chunks_mut(4).zip(data[x + y * stride..].chunks(stride)) {
580 dst.copy_from_slice(&src[..4]);
583 fn put_cell4(data: &mut [u8], x: usize, y: usize, stride: usize, cell: &[u8; 20]) {
584 for (src, dst) in cell.chunks(4).zip(data[x + y * stride..].chunks_mut(stride)).skip(1) {
585 dst[..4].copy_from_slice(src);
588 fn get_cell_mode3(data: &[u8], x: usize, y: usize, stride: usize, cell: &mut [u8; 20]) {
589 let src = &data[x + y * stride..];
590 for (dline, slines) in cell.chunks_mut(4).zip(src.chunks(stride * 2)) {
591 dline.copy_from_slice(&slines[..4]);
594 fn put_cell_mode3(data: &mut [u8], x: usize, y: usize, stride: usize, cell: &[u8; 20], first_line: bool) {
595 let dst = &mut data[x + y * stride..];
596 let mut dst_idx = stride;
599 let top = cell[line * 4 + x];
600 let cur = cell[(line + 1) * 4 + x];
601 dst[dst_idx + x] = (top + cur) >> 1;
602 dst[dst_idx + stride + x] = cur;
604 dst_idx += stride * 2;
607 dst[stride..][..4].copy_from_slice(&cell[4..8]);
610 fn get_cell_mode10i(data: &[u8], x: usize, y: usize, stride: usize, cell: &mut [u8; 20]) {
611 let src = &data[x + y * stride..];
612 for (dline, src_pair) in cell.chunks_mut(4).zip(src.chunks(stride * 2)) {
613 for (dst, src) in dline.iter_mut().zip(src_pair.chunks(2)) {
618 fn put_cell_mode10i(data: &mut [u8], x: usize, y: usize, stride: usize, cell: &[u8; 20], first_line: bool) {
619 let dst = &mut data[x + y * stride..];
620 let mut dst_idx = stride;
623 let top = dst[dst_idx - stride + x];
624 let cur = cell[(line + 1) * 4 + x / 2];
625 dst[dst_idx + x] = (top + cur) >> 1;
626 dst[dst_idx + stride + x] = cur;
628 dst_idx += stride * 2;
631 let (top, tail) = dst[stride..].split_at_mut(stride);
632 top[..8].copy_from_slice(&tail[..8]);
637 fn requant(line: &mut [u8], rq_index: usize) {
638 let tab = &REQUANT_TAB[rq_index];
639 for el in line.iter_mut() {
640 *el = tab[usize::from(*el)];
644 fn compress_intra_cell(iwriter: &mut IndexWriter, cell4: &mut [u8; 20], cbs: &[&IviDeltaCB; 4], esc_vals: [u8; 4]) {
648 let esc_val = esc_vals[y];
650 let (prev, cur) = cell4.split_at_mut(pivot);
651 let prev = &prev[prev.len() - 4..];
652 let cur = &mut cur[..4];
653 let (idx0, idx1) = find_quad(&cb.data, prev, cur);
655 cur[0] = ((prev[0] as i8) + cb.data[usize::from(idx1) * 2]) as u8;
656 cur[1] = ((prev[1] as i8) + cb.data[usize::from(idx1) * 2 + 1]) as u8;
657 cur[2] = ((prev[2] as i8) + cb.data[usize::from(idx0) * 2]) as u8;
658 cur[3] = ((prev[3] as i8) + cb.data[usize::from(idx0) * 2 + 1]) as u8;
660 iwriter.write_pair(idx0, idx1, cb.quad_radix, esc_val);
664 iwriter.compact_cell(esc_vals);
667 fn compress_inter_cell(iwriter: &mut IndexWriter, ccell4: &mut [u8; 20], pcell: &[u8; 20], cbs: &[&IviDeltaCB; 4], esc_vals: [u8; 4]) {
668 for (y, (prev, cur)) in pcell[4..].chunks(4).zip(ccell4[4..].chunks_mut(4)).enumerate() {
670 let esc_val = esc_vals[y];
672 let (idx0, idx1) = find_quad(&cb.data, prev, cur);
674 cur[0] = ((prev[0] as i8) + cb.data[usize::from(idx1) * 2]) as u8;
675 cur[1] = ((prev[1] as i8) + cb.data[usize::from(idx1) * 2 + 1]) as u8;
676 cur[2] = ((prev[2] as i8) + cb.data[usize::from(idx0) * 2]) as u8;
677 cur[3] = ((prev[3] as i8) + cb.data[usize::from(idx0) * 2 + 1]) as u8;
679 iwriter.write_pair(idx0, idx1, cb.quad_radix, esc_val);
681 iwriter.compact_cell(esc_vals);
684 fn compress_inter_cell_mode10(iwriter: &mut IndexWriter, cell: &mut [u8; 64], diffs: &[i16; 16], cbs: &[&IviDeltaCB; 4], esc_vals: [u8; 4]) {
687 let esc_val = esc_vals[y];
688 let mut indices = [0, 0];
689 for pair_no in (0..4).step_by(2) {
690 let src_idx = y * 8 * 2 + pair_no * 2;
691 let src0 = [cell[src_idx], cell[src_idx + 1], cell[src_idx + 8], cell[src_idx + 9]];
692 let src1 = [cell[src_idx + 2], cell[src_idx + 3], cell[src_idx + 10], cell[src_idx + 11]];
694 let cur_diff = [diffs[y * 4 + pair_no] as i8, diffs[y * 4 + pair_no + 1] as i8];
696 let mut best_idx = 0;
697 let mut best_dist = pair_dist(&cur_diff, &[0, 0]);
698 for (idx, cbpair) in cb.data.chunks(2).enumerate().skip(1) {
699 let dist = pair_dist(&cur_diff, cbpair);
700 if dist < best_dist {
702 for &el in src0.iter() {
703 if !in_range(el as i8, cbpair[0]) {
708 for &el in src1.iter() {
709 if !in_range(el as i8, cbpair[1]) {
721 indices[pair_no / 2] = best_idx as u8;
723 let cb_pair = &cb.data[best_idx * 2..];
724 for row in cell[src_idx..].chunks_mut(8).take(2) {
725 row[0] = ((row[0] as i8) + cb_pair[0]) as u8;
726 row[1] = ((row[1] as i8) + cb_pair[0]) as u8;
727 row[2] = ((row[2] as i8) + cb_pair[1]) as u8;
728 row[3] = ((row[3] as i8) + cb_pair[1]) as u8;
731 iwriter.write_pair(indices[1], indices[0], cb.quad_radix, esc_val);
733 iwriter.compact_cell(esc_vals);
736 fn compress_inter_cell_mode11(iwriter: &mut IndexWriter, cell: &mut [u8; 32], diffs: &[i16; 16], cbs: &[&IviDeltaCB; 4], esc_vals: [u8; 4]) {
739 let esc_val = esc_vals[y];
740 let mut indices = [0, 0];
741 for pair_no in (0..4).step_by(2) {
742 let src_idx = y * 4 * 2 + pair_no;
743 let src0 = [cell[src_idx], cell[src_idx + 4]];
744 let src1 = [cell[src_idx + 1], cell[src_idx + 5]];
746 let cur_diff = [diffs[y * 4 + pair_no] as i8, diffs[y * 4 + pair_no + 1] as i8];
748 let mut best_idx = 0;
749 let mut best_dist = pair_dist(&cur_diff, &[0, 0]);
750 for (idx, cbpair) in cb.data.chunks(2).enumerate().skip(1) {
751 let dist = pair_dist(&cur_diff, cbpair);
752 if dist < best_dist {
754 for &el in src0.iter() {
755 if !in_range(el as i8, cbpair[0]) {
760 for &el in src1.iter() {
761 if !in_range(el as i8, cbpair[1]) {
773 indices[pair_no / 2] = best_idx as u8;
775 let cb_pair = &cb.data[best_idx * 2..];
776 cell[src_idx] = ((cell[src_idx] as i8) + cb_pair[0]) as u8;
777 cell[src_idx + 4] = ((cell[src_idx + 4] as i8) + cb_pair[0]) as u8;
778 cell[src_idx + 1] = ((cell[src_idx + 1] as i8) + cb_pair[1]) as u8;
779 cell[src_idx + 5] = ((cell[src_idx + 5] as i8) + cb_pair[1]) as u8;
781 iwriter.write_pair(indices[1], indices[0], cb.quad_radix, esc_val);
783 iwriter.compact_cell(esc_vals);
786 fn pair_dist(src: &[i8], pair: &[i8]) -> u32 {
787 let d0 = (i32::from(src[0]) - i32::from(pair[0])).abs() as u32;
788 let d1 = (i32::from(src[1]) - i32::from(pair[1])).abs() as u32;
792 fn in_range(base: i8, delta: i8) -> bool {
793 if let Some(val) = base.checked_add(delta) {
800 fn find_pair(cb_data: &[i8], ppair: &[u8], cpair: &[u8]) -> u8 {
801 let ppair = [ppair[0] as i8, ppair[1] as i8];
802 let diff = [(cpair[0] as i8) - ppair[0], (cpair[1] as i8) - ppair[1]];
803 // pair 0 is always zero;
807 let mut best_idx = 0;
808 let mut best_dist = pair_dist(&diff, &[0, 0]);
809 for (idx, cbpair) in cb_data.chunks(2).enumerate().skip(1) {
810 let dist = pair_dist(&diff, cbpair);
811 if dist < best_dist && in_range(ppair[0], cbpair[0]) && in_range(ppair[1], cbpair[1]) {
819 fn find_quad(cb_data: &[i8], prev: &[u8], cur: &[u8]) -> (u8, u8) {
820 let (ppair1, ppair0) = prev.split_at(2);
821 let (cpair1, cpair0) = cur.split_at(2);
822 let idx1 = find_pair(cb_data, ppair1, cpair1);
823 let idx0 = find_pair(cb_data, ppair0, cpair0);
827 const REQUANT_TAB: [[u8; 128]; 8] = [
829 0x00, 0x02, 0x02, 0x04, 0x04, 0x06, 0x06, 0x08,
830 0x08, 0x0a, 0x0a, 0x0c, 0x0c, 0x0e, 0x0e, 0x10,
831 0x10, 0x12, 0x12, 0x14, 0x14, 0x16, 0x16, 0x18,
832 0x18, 0x1a, 0x1a, 0x1c, 0x1c, 0x1e, 0x1e, 0x20,
833 0x20, 0x22, 0x22, 0x24, 0x24, 0x26, 0x26, 0x28,
834 0x28, 0x2a, 0x2a, 0x2c, 0x2c, 0x2e, 0x2e, 0x30,
835 0x30, 0x32, 0x32, 0x34, 0x34, 0x36, 0x36, 0x38,
836 0x38, 0x3a, 0x3a, 0x3c, 0x3c, 0x3e, 0x3e, 0x40,
837 0x40, 0x42, 0x42, 0x44, 0x44, 0x46, 0x46, 0x48,
838 0x48, 0x4a, 0x4a, 0x4c, 0x4c, 0x4e, 0x4e, 0x50,
839 0x50, 0x52, 0x52, 0x54, 0x54, 0x56, 0x56, 0x58,
840 0x58, 0x5a, 0x5a, 0x5c, 0x5c, 0x5e, 0x5e, 0x60,
841 0x60, 0x62, 0x62, 0x64, 0x64, 0x66, 0x66, 0x68,
842 0x68, 0x6a, 0x6a, 0x6c, 0x6c, 0x6e, 0x6e, 0x70,
843 0x70, 0x72, 0x72, 0x74, 0x74, 0x76, 0x76, 0x78,
844 0x78, 0x7a, 0x7a, 0x7c, 0x7c, 0x7e, 0x7e, 0x7e
846 0x01, 0x01, 0x04, 0x04, 0x04, 0x07, 0x07, 0x0a,
847 0x0a, 0x0a, 0x0a, 0x0d, 0x0d, 0x0d, 0x10, 0x10,
848 0x10, 0x13, 0x13, 0x13, 0x16, 0x16, 0x16, 0x19,
849 0x19, 0x19, 0x1c, 0x1c, 0x1c, 0x1f, 0x1f, 0x1f,
850 0x22, 0x22, 0x22, 0x25, 0x25, 0x25, 0x28, 0x28,
851 0x28, 0x2b, 0x2b, 0x2b, 0x2e, 0x2e, 0x2e, 0x31,
852 0x31, 0x31, 0x34, 0x34, 0x34, 0x37, 0x37, 0x37,
853 0x3a, 0x3a, 0x3a, 0x3d, 0x3d, 0x3d, 0x40, 0x40,
854 0x40, 0x43, 0x43, 0x43, 0x46, 0x46, 0x46, 0x49,
855 0x49, 0x49, 0x4c, 0x4c, 0x4c, 0x4f, 0x4f, 0x4f,
856 0x52, 0x52, 0x52, 0x55, 0x55, 0x55, 0x58, 0x58,
857 0x58, 0x5b, 0x5b, 0x5b, 0x5e, 0x5e, 0x5e, 0x61,
858 0x61, 0x61, 0x64, 0x64, 0x64, 0x67, 0x67, 0x67,
859 0x6a, 0x6a, 0x6a, 0x6d, 0x6d, 0x6d, 0x70, 0x70,
860 0x70, 0x73, 0x73, 0x73, 0x76, 0x76, 0x76, 0x76,
861 0x76, 0x79, 0x7c, 0x7c, 0x7c, 0x7f, 0x7f, 0x7f
863 0x00, 0x00, 0x04, 0x04, 0x04, 0x04, 0x08, 0x08,
864 0x08, 0x08, 0x0c, 0x0c, 0x0c, 0x0c, 0x10, 0x10,
865 0x10, 0x10, 0x14, 0x14, 0x14, 0x14, 0x18, 0x18,
866 0x18, 0x18, 0x1c, 0x1c, 0x1c, 0x1c, 0x20, 0x20,
867 0x20, 0x20, 0x24, 0x24, 0x24, 0x24, 0x28, 0x28,
868 0x28, 0x28, 0x2c, 0x2c, 0x2c, 0x2c, 0x30, 0x30,
869 0x30, 0x30, 0x34, 0x34, 0x34, 0x34, 0x38, 0x38,
870 0x38, 0x38, 0x3c, 0x3c, 0x3c, 0x3c, 0x40, 0x40,
871 0x40, 0x40, 0x44, 0x44, 0x44, 0x44, 0x48, 0x48,
872 0x48, 0x48, 0x4c, 0x4c, 0x4c, 0x4c, 0x50, 0x50,
873 0x50, 0x50, 0x54, 0x54, 0x54, 0x54, 0x58, 0x58,
874 0x58, 0x58, 0x5c, 0x5c, 0x5c, 0x5c, 0x60, 0x60,
875 0x60, 0x60, 0x64, 0x64, 0x64, 0x64, 0x68, 0x68,
876 0x68, 0x68, 0x6c, 0x6c, 0x6c, 0x6c, 0x70, 0x70,
877 0x70, 0x70, 0x74, 0x74, 0x74, 0x74, 0x78, 0x78,
878 0x78, 0x78, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c
880 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
881 0x09, 0x09, 0x09, 0x09, 0x09, 0x0e, 0x0e, 0x0e,
882 0x0e, 0x0e, 0x13, 0x13, 0x13, 0x13, 0x13, 0x18,
883 0x18, 0x18, 0x18, 0x18, 0x1d, 0x1d, 0x1d, 0x1d,
884 0x1d, 0x22, 0x22, 0x22, 0x22, 0x22, 0x27, 0x27,
885 0x27, 0x27, 0x27, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c,
886 0x31, 0x31, 0x31, 0x31, 0x31, 0x36, 0x36, 0x36,
887 0x36, 0x36, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x40,
888 0x40, 0x40, 0x40, 0x40, 0x45, 0x45, 0x45, 0x45,
889 0x45, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4f, 0x4f,
890 0x4f, 0x4f, 0x4f, 0x54, 0x54, 0x54, 0x54, 0x54,
891 0x59, 0x59, 0x59, 0x59, 0x59, 0x5e, 0x5e, 0x5e,
892 0x5e, 0x5e, 0x63, 0x63, 0x63, 0x63, 0x63, 0x68,
893 0x68, 0x68, 0x68, 0x68, 0x6d, 0x6d, 0x6d, 0x6d,
894 0x6d, 0x72, 0x72, 0x72, 0x72, 0x72, 0x77, 0x77,
895 0x77, 0x77, 0x77, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c
897 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
898 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x10,
899 0x10, 0x10, 0x10, 0x10, 0x10, 0x16, 0x16, 0x16,
900 0x16, 0x16, 0x16, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c,
901 0x1c, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x28,
902 0x28, 0x28, 0x28, 0x28, 0x28, 0x2e, 0x2e, 0x2e,
903 0x2e, 0x2e, 0x2e, 0x34, 0x34, 0x34, 0x34, 0x34,
904 0x34, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x40,
905 0x40, 0x40, 0x40, 0x40, 0x40, 0x46, 0x46, 0x46,
906 0x46, 0x46, 0x46, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c,
907 0x4c, 0x52, 0x52, 0x52, 0x52, 0x52, 0x52, 0x58,
908 0x58, 0x58, 0x58, 0x58, 0x58, 0x5e, 0x5e, 0x5e,
909 0x5e, 0x5e, 0x5e, 0x64, 0x64, 0x64, 0x64, 0x64,
910 0x64, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x70,
911 0x70, 0x70, 0x70, 0x70, 0x70, 0x76, 0x76, 0x76,
912 0x76, 0x76, 0x76, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c
914 0x01, 0x01, 0x01, 0x01, 0x08, 0x08, 0x08, 0x08,
915 0x08, 0x08, 0x08, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
916 0x0f, 0x0f, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16,
917 0x16, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d,
918 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x2b,
919 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x32, 0x32,
920 0x32, 0x32, 0x32, 0x32, 0x32, 0x39, 0x39, 0x39,
921 0x39, 0x39, 0x39, 0x39, 0x40, 0x40, 0x40, 0x40,
922 0x40, 0x40, 0x40, 0x47, 0x47, 0x47, 0x47, 0x47,
923 0x47, 0x47, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e,
924 0x4e, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
925 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x63,
926 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x6a, 0x6a,
927 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x71, 0x71, 0x71,
928 0x71, 0x71, 0x71, 0x71, 0x78, 0x78, 0x78, 0x78,
929 0x78, 0x78, 0x78, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f
931 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08,
932 0x08, 0x08, 0x08, 0x08, 0x10, 0x10, 0x10, 0x10,
933 0x10, 0x10, 0x10, 0x10, 0x18, 0x18, 0x18, 0x18,
934 0x18, 0x18, 0x18, 0x18, 0x20, 0x20, 0x20, 0x20,
935 0x20, 0x20, 0x20, 0x20, 0x28, 0x28, 0x28, 0x28,
936 0x28, 0x28, 0x28, 0x28, 0x30, 0x30, 0x30, 0x30,
937 0x30, 0x30, 0x30, 0x30, 0x38, 0x38, 0x38, 0x38,
938 0x38, 0x38, 0x38, 0x38, 0x40, 0x40, 0x40, 0x40,
939 0x40, 0x40, 0x40, 0x40, 0x48, 0x48, 0x48, 0x48,
940 0x48, 0x48, 0x48, 0x48, 0x50, 0x50, 0x50, 0x50,
941 0x50, 0x50, 0x50, 0x50, 0x58, 0x58, 0x58, 0x58,
942 0x58, 0x58, 0x58, 0x58, 0x60, 0x60, 0x60, 0x60,
943 0x60, 0x60, 0x60, 0x60, 0x68, 0x68, 0x68, 0x68,
944 0x68, 0x68, 0x68, 0x68, 0x70, 0x70, 0x70, 0x70,
945 0x70, 0x70, 0x70, 0x70, 0x78, 0x78, 0x78, 0x78,
946 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78
948 0x01, 0x01, 0x01, 0x01, 0x01, 0x0a, 0x0a, 0x0a,
949 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x13, 0x13,
950 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x1c,
951 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c,
952 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25,
953 0x25, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e,
954 0x2e, 0x2e, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37,
955 0x37, 0x37, 0x37, 0x40, 0x40, 0x40, 0x40, 0x40,
956 0x40, 0x40, 0x40, 0x40, 0x49, 0x49, 0x49, 0x49,
957 0x49, 0x49, 0x49, 0x49, 0x49, 0x52, 0x52, 0x52,
958 0x52, 0x52, 0x52, 0x52, 0x52, 0x52, 0x5b, 0x5b,
959 0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x64,
960 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64,
961 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d,
962 0x6d, 0x76, 0x76, 0x76, 0x76, 0x76, 0x76, 0x76,
963 0x76, 0x76, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f