// prepare plane data structure
for &planeno in PLANE_ORDER.iter() {
let ref_plane = &self.pframe.plane[planeno];
- let tree = self.cframe.plane[planeno].find_cells(is_intra, ref_plane, &self.mv_est);
+ let mut tree = self.cframe.plane[planeno].find_cells(is_intra, ref_plane, &self.mv_est);
if self.debug_tree {
println!(" tree for plane {}:", planeno);
tree.print();
}
- trees.push(tree);
let mvs = &mut self.cframe.plane[planeno].mvs;
- compact_mvs(mvs);
+ if mvs.len() > 256 {
+ compact_mvs(mvs);
+ self.cframe.plane[planeno].prune_extra_mvs(&mut tree);
+ }
+ trees.push(tree);
}
self.encode_planes(&mut dbuf, &trees, is_intra)?;
let enc_options = &[
NAOption { name: super::TRY_AGAIN_OPTION, value: NAValue::Bool(true) },
];
- encode_test("indeo3.avi", enc_options, Some(4), &[0xd62f9996, 0x7fb4ba1b, 0x1f552801, 0xfd4e4726]);
+ encode_test("indeo3.avi", enc_options, Some(4), &[0xc23464a1, 0xd319a38f, 0x7421165e, 0x42786e50]);
}
/*#[test]
fn test_indeo3_roundtrip() {
calc_cell_diff(cur_ptr, ref_ptr, cur.width, cell.get_width(), cell.get_height())
}
-fn get_mv_diff(mv1: MV, mv2: MV) -> i8 {
- (mv1.x - mv2.x).abs() + (mv1.y - mv2.y).abs()
-}
-
pub fn compact_mvs(mvs: &mut Vec<(MV, u16)>) {
- mvs.sort_by(|a, b| a.1.cmp(&b.1));
- while mvs.len() > 256 {
- let (mv, _) = mvs.pop().unwrap();
- if let Some(idx) = find_mv(mv, mvs) {
- mvs[usize::from(idx)].1 += 1;
- }
- }
+ mvs.sort_by(|a, b| b.1.cmp(&a.1));
+ mvs.truncate(256);
}
pub fn find_mv(mv: MV, mvs: &[(MV, u16)]) -> Option<u8> {
- let mut best_idx = None;
- let mut best_cand_diff = 42;
- let mut best_cand_count = 0;
- for (i, &(cand_mv, count)) in mvs.iter().enumerate() {
+ for (i, &(cand_mv, _)) in mvs.iter().enumerate() {
if cand_mv == mv {
return Some(i as u8);
}
- let diff = get_mv_diff(mv, cand_mv);
- if diff <= 2 {
- if diff < best_cand_diff || (diff == best_cand_diff && count > best_cand_count) {
- best_idx = Some(i as u8);
- best_cand_diff = diff;
- best_cand_count = count;
- }
- }
}
- best_idx
+ None
}
use super::Indeo3Writer;
use super::mv::*;
use super::cell::{CellEncoder, MAX_CELL_SIZE};
+use std::ops::DerefMut;
pub enum Indeo3PrimaryTree {
VSplit(Box<Indeo3PrimaryTree>, Box<Indeo3PrimaryTree>),
} else {
if !cell.intra {
if let Some((mv, flat)) = mv_est.mv_search(self, pplane, cell) {
- return self.add_mv_tree(mv, flat);
+ return self.add_mv_tree(mv, flat, cell);
}
// try splitting once to see if it improves situation
let search2 = mv_est.mv_search(self, pplane, cell2);
if search1.is_some() || search2.is_some() {
let tree1 = if let Some((mv, flat)) = search1 {
- self.add_mv_tree(mv, flat)
+ self.add_mv_tree(mv, flat, cell1)
} else {
let sec = self.split_sec(cell1);
Box::new(Indeo3PrimaryTree::AbsFill(sec))
};
let tree2 = if let Some((mv, flat)) = search2 {
- self.add_mv_tree(mv, flat)
+ self.add_mv_tree(mv, flat, cell2)
} else {
let sec = self.split_sec(cell2);
Box::new(Indeo3PrimaryTree::AbsFill(sec))
Box::new(Indeo3PrimaryTree::AbsFill(sec))
}
}
- fn add_mv_tree(&mut self, mv: MV, flat: bool) -> Box<Indeo3PrimaryTree> {
+ fn add_mv_tree(&mut self, mv: MV, flat: bool, cell: Indeo3Cell) -> Box<Indeo3PrimaryTree> {
let sec = if flat {
Box::new(Indeo3SecondaryTree::VQNull(0))
} else {
let mut found = false;
for (ref cmv, ref mut count) in self.mvs.iter_mut() {
if cmv == &mv {
- *count += 1;
+ *count += u16::from(cell.w) * u16::from(cell.h);
found = true;
break;
}
let area = (w * h) as u32;
(hdiff * 16 / area, vdiff * 16 / area)
}
+ pub fn prune_extra_mvs(&mut self, tree: &mut Box<Indeo3PrimaryTree>) {
+ let cell = Indeo3Cell::new(self.width, self.height, true);
+ self.prune_pri(cell, tree)
+ }
+ fn prune_pri(&mut self, cell: Indeo3Cell, tree: &mut Box<Indeo3PrimaryTree>) {
+ match tree.deref_mut() {
+ Indeo3PrimaryTree::HSplit(ref mut tree1, ref mut tree2) => {
+ let (cell1, cell2) = cell.split_h();
+ self.prune_pri(cell1, tree1);
+ self.prune_pri(cell2, tree2);
+ },
+ Indeo3PrimaryTree::VSplit(ref mut tree1, ref mut tree2) => {
+ let (cell1, cell2) = cell.split_v(self.stripw);
+ self.prune_pri(cell1, tree1);
+ self.prune_pri(cell2, tree2);
+ },
+ Indeo3PrimaryTree::AbsFill(_) => {},
+ Indeo3PrimaryTree::RelFill(ref mv, ref _sec) => {
+ if find_mv(*mv, &self.mvs).is_none() {
+ let sec = self.split_sec(cell);
+ *tree = Box::new(Indeo3PrimaryTree::AbsFill(sec));
+ }
+ },
+ }
+ }
pub fn encode_tree(&mut self, iw: &mut Indeo3Writer, tree: &Indeo3PrimaryTree, cenc: &mut CellEncoder, is_intra: bool, refp: &Plane) {
let cell = Indeo3Cell::new(self.width, self.height, is_intra);
self.encode_pri(iw, cell, tree, cenc, refp);