+ fn encode_inter_pal(bw: &mut ByteWriter, cur_frm: &mut NAVideoBuffer<u8>, in_frm: &NAVideoBuffer<u8>, prev_frm: &NAVideoBuffer<u8>, quality: u8, pal: &[UnpackedPixel; 256], ls: &LocalSearch) -> EncoderResult<bool> {
+ let (skip_threshold, fill_threshold) = map_quality_pal(quality);
+ let mut is_intra = true;
+ let src = in_frm.get_data();
+ let sstride = in_frm.get_stride(0);
+ let soff = in_frm.get_offset(0);
+ let (w, h) = in_frm.get_dimensions(0);
+ let rsrc = prev_frm.get_data();
+ let rstride = prev_frm.get_stride(0);
+ let roff = prev_frm.get_offset(0);
+ let dstride = cur_frm.get_stride(0);
+ let doff = cur_frm.get_offset(0);
+ let dst = cur_frm.get_data_mut().unwrap();
+ let mut skip_run = 0;
+ let bpainter = BlockPainterPal::new(ls);
+ for ((sstrip, rstrip), dstrip) in src[soff..].chunks(sstride * 4).take(h / 4).zip(rsrc[roff..].chunks(rstride * 4)).zip(dst[doff..].chunks_mut(dstride * 4)) {
+ for x in (0..w).step_by(4) {
+ let mut buf = [UnpackedPixel::default(); 16];
+ let mut refbuf = [UnpackedPixel::default(); 16];
+ Self::get_block8(&sstrip[x..], sstride, &mut buf, pal);
+ Self::get_block8(&rstrip[x..], rstride, &mut refbuf, pal);
+
+ let mut skip_dist = 0;
+ for (pix, rpix) in buf.iter().zip(refbuf.iter()) {
+ skip_dist += dist_core(*rpix, pix);
+ }
+ if skip_dist <= skip_threshold {
+ skip_run += 1;
+ is_intra = false;
+ for (dst, src) in dstrip[x..].chunks_mut(dstride).zip(rstrip[x..].chunks(rstride)).take(4) {
+ dst[..4].copy_from_slice(&src[..4]);
+ }
+ if skip_run == 1023 {
+ Self::write_skips(bw, skip_run)?;
+ skip_run = 0;
+ }
+ continue;
+ }
+
+ let mut bstate = BlockState::new_pal();
+ bstate.calc_stats(&buf);
+
+ let dst = &mut dstrip[x..];
+ if skip_dist <= bstate.fill_dist && skip_dist * 2 <= bstate.clr2_dist {
+ skip_run += 1;
+ is_intra = false;
+ for (dst, src) in dst.chunks_mut(dstride).zip(rstrip[x..].chunks(rstride)).take(4) {
+ dst[..4].copy_from_slice(&src[..4]);
+ }
+ if skip_run == 1023 {
+ Self::write_skips(bw, skip_run)?;
+ skip_run = 0;
+ }
+ } else if bstate.fill_dist <= fill_threshold ||
+ bstate.fill_dist <= bstate.clr2_dist {
+ let fill_val = bpainter.put_fill(&bstate, dst, dstride);
+ if skip_run != 0 {
+ Self::write_skips(bw, skip_run)?;
+ skip_run = 0;
+ }
+ BlockWriterPal::write_fill(bw, fill_val)?;
+ } else if bstate.clr8_dist < bstate.clr2_dist {
+ let clr8 = bpainter.put_clr8(&bstate, dst, dstride);
+ if skip_run != 0 {
+ Self::write_skips(bw, skip_run)?;
+ skip_run = 0;
+ }
+ BlockWriterPal::write_clr8(bw, bstate.clr8_flags, clr8)?;
+ } else {
+ let clr2 = bpainter.put_clr2(&bstate, dst, dstride);
+ if skip_run != 0 {
+ Self::write_skips(bw, skip_run)?;
+ skip_run = 0;
+ }
+ BlockWriterPal::write_clr2(bw, bstate.clr2_flags, clr2)?;
+ }
+ }
+ }
+ if skip_run != 0 {
+ Self::write_skips(bw, skip_run)?;
+ }
+ if is_intra {
+ bw.write_u16le(0)?;
+ } //xxx: something for inter?
+ Ok(is_intra)
+ }
+ fn encode_intra_pal(bw: &mut ByteWriter, cur_frm: &mut NAVideoBuffer<u8>, in_frm: &NAVideoBuffer<u8>, quality: u8, pal: &[UnpackedPixel; 256], ls: &LocalSearch) -> EncoderResult<bool> {
+ let (_, fill_threshold) = map_quality_pal(quality);
+ let src = in_frm.get_data();
+ let sstride = in_frm.get_stride(0);
+ let soff = in_frm.get_offset(0);
+ let (w, h) = in_frm.get_dimensions(0);
+ let dstride = cur_frm.get_stride(0);
+ let doff = cur_frm.get_offset(0);
+ let dst = cur_frm.get_data_mut().unwrap();
+ let bpainter = BlockPainterPal::new(ls);
+ for (sstrip, dstrip) in src[soff..].chunks(sstride * 4).take(h / 4).zip(dst[doff..].chunks_mut(dstride * 4)) {
+ for x in (0..w).step_by(4) {
+ let mut buf = [UnpackedPixel::default(); 16];
+ Self::get_block8(&sstrip[x..], sstride, &mut buf, pal);
+ let mut bstate = BlockState::new_pal();
+ bstate.calc_stats(&buf);
+
+ let dst = &mut dstrip[x..];
+ if bstate.fill_dist <= fill_threshold ||
+ bstate.fill_dist <= bstate.clr2_dist {
+ let fill_val = bpainter.put_fill(&bstate, dst, dstride);
+ BlockWriterPal::write_fill(bw, fill_val)?;
+ } else if bstate.clr8_dist < bstate.clr2_dist {
+ let clr8 = bpainter.put_clr8(&bstate, dst, dstride);
+ BlockWriterPal::write_clr8(bw, bstate.clr8_flags, clr8)?;
+ } else {
+ let clr2 = bpainter.put_clr2(&bstate, dst, dstride);
+ BlockWriterPal::write_clr2(bw, bstate.clr2_flags, clr2)?;
+ }
+ }
+ }
+ bw.write_u16le(0)?;
+ Ok(true)
+ }