use super::super::vp6dsp::*;
use super::super::vp6data::*;
use super::ResidueMB;
-
-use std::str::FromStr;
-
-#[derive(Debug,Clone,Copy,PartialEq)]
-pub enum MVSearchMode {
- Full,
- Diamond,
- Hexagon,
-}
-
-impl Default for MVSearchMode {
- fn default() -> Self { MVSearchMode::Hexagon }
-}
-
-pub struct ParseError{}
-
-impl FromStr for MVSearchMode {
- type Err = ParseError;
-
- #[allow(clippy::single_match)]
- fn from_str(s: &str) -> Result<Self, Self::Err> {
- match s {
- "full" => Ok(MVSearchMode::Full),
- "dia" => Ok(MVSearchMode::Diamond),
- "hex" => Ok(MVSearchMode::Hexagon),
- _ => Err(ParseError{}),
- }
- }
-}
-
-impl std::fmt::Display for MVSearchMode {
- fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
- match *self {
- MVSearchMode::Full => write!(f, "full"),
- MVSearchMode::Diamond => write!(f, "dia"),
- MVSearchMode::Hexagon => write!(f, "hex"),
- }
- }
-}
+use crate::codecs::vpenc::motion_est::*;
+pub use crate::codecs::vpenc::motion_est::MVSearchMode;
const C1S7: i32 = 64277;
}
}
+pub trait MVSearchModeCreate {
+ fn create_search(&self) -> Box<dyn MVSearch + Send>;
+}
+
+impl MVSearchModeCreate for MVSearchMode {
+ fn create_search(&self) -> Box<dyn MVSearch + Send> {
+ match *self {
+ MVSearchMode::Full => Box::new(FullMVSearch::new()),
+ MVSearchMode::Diamond => Box::new(DiaSearch::new()),
+ MVSearchMode::Hexagon => Box::new(HexSearch::new()),
+ _ => unreachable!(),
+ }
+ }
+}
+
const MAX_DIST: u32 = std::u32::MAX;
const DIST_THRESH: u32 = 256;
}
}
-const DIA_PATTERN: [MV; 9] = [
- ZERO_MV,
- MV {x: -2, y: 0},
- MV {x: -1, y: 1},
- MV {x: 0, y: 2},
- MV {x: 1, y: 1},
- MV {x: 2, y: 0},
- MV {x: 1, y: -1},
- MV {x: 0, y: -2},
- MV {x: -1, y: -1}
-];
-
-const HEX_PATTERN: [MV; 7] = [
- ZERO_MV,
- MV {x: -2, y: 0},
- MV {x: -1, y: 2},
- MV {x: 1, y: 2},
- MV {x: 2, y: 0},
- MV {x: 1, y: -2},
- MV {x: -1, y: -2}
-];
-
-const REFINEMENT: [MV; 4] = [
- MV {x: -1, y: 0},
- MV {x: 0, y: 1},
- MV {x: 1, y: 0},
- MV {x: 0, y: -1}
-];
-
-macro_rules! search_template {
- ($self: expr, $mv_est: expr, $cur_blk: expr, $mb_x: expr, $mb_y: expr, $sad_func: ident) => ({
- let mut best_dist = MAX_DIST;
- let mut best_mv;
-
- let mut min_dist;
- let mut min_idx;
-
- $self.reset();
- loop {
- let mut cur_best_dist = best_dist;
- for (dist, &point) in $self.dist.iter_mut().zip($self.point.iter()) {
- if *dist == MAX_DIST {
- *dist = $mv_est.$sad_func($cur_blk, $mb_x, $mb_y, point.from_pixels(), cur_best_dist);
- cur_best_dist = cur_best_dist.min(*dist);
- if *dist <= DIST_THRESH {
- break;
- }
- }
- }
- min_dist = $self.dist[0];
- min_idx = 0;
- for (i, &dist) in $self.dist.iter().enumerate().skip(1) {
- if dist < min_dist {
- min_dist = dist;
- min_idx = i;
- if dist <= DIST_THRESH {
- break;
- }
- }
- }
- if min_dist <= DIST_THRESH || min_idx == 0 || best_dist == min_dist || $self.point[min_idx].x.abs() >= $mv_est.mv_range || $self.point[min_idx].y.abs() >= $mv_est.mv_range {
- break;
- }
- best_dist = min_dist;
- $self.update($self.steps[min_idx]);
- }
- best_dist = min_dist;
- best_mv = $self.point[min_idx];
- if best_dist <= DIST_THRESH {
- return (best_mv.from_pixels(), best_dist);
- }
- for &step in REFINEMENT.iter() {
- let mv = best_mv + step;
- let dist = $mv_est.$sad_func($cur_blk, $mb_x, $mb_y, mv.from_pixels(), MAX_DIST);
- if best_dist > dist {
- best_dist = dist;
- best_mv = mv;
- }
- }
- best_mv = best_mv.from_pixels();
- if best_dist <= DIST_THRESH {
- return (best_mv, best_dist);
- }
-
- // subpel refinement
- $self.set_new_point(best_mv, best_dist);
- loop {
- let mut cur_best_dist = best_dist;
- for (dist, &point) in $self.dist.iter_mut().zip($self.point.iter()) {
- if *dist == MAX_DIST {
- *dist = $mv_est.$sad_func($cur_blk, $mb_x, $mb_y, point, cur_best_dist);
- cur_best_dist = cur_best_dist.min(*dist);
- if *dist <= DIST_THRESH {
- break;
- }
- }
- }
- min_dist = $self.dist[0];
- min_idx = 0;
- for (i, &dist) in $self.dist.iter().enumerate().skip(1) {
- if dist < min_dist {
- min_dist = dist;
- min_idx = i;
- if dist <= DIST_THRESH {
- break;
- }
- }
- }
- if min_dist <= DIST_THRESH || min_idx == 0 || best_dist == min_dist || $self.point[min_idx].x.abs() >= $mv_est.mv_range * 4 || $self.point[min_idx].y.abs() >= $mv_est.mv_range * 4 {
- break;
- }
- best_dist = min_dist;
- $self.update($self.steps[min_idx]);
- }
- best_dist = min_dist;
- best_mv = $self.point[min_idx];
- if best_dist <= DIST_THRESH {
- return (best_mv, best_dist);
- }
- for &step in REFINEMENT.iter() {
- let mv = best_mv + step;
- let dist = $mv_est.$sad_func($cur_blk, $mb_x, $mb_y, mv, MAX_DIST);
- if best_dist > dist {
- best_dist = dist;
- best_mv = mv;
- }
- }
- (best_mv, best_dist)
- })
-}
-
macro_rules! pattern_search {
($struct_name: ident, $patterns: expr) => {
pub struct $struct_name {
impl MVSearch for $struct_name {
fn search_mb(&mut self, mv_est: &mut MVEstimator, cur_blk: &[[u8; 64]; 6], mb_x: usize, mb_y: usize) -> (MV, u32) {
- search_template!(self, mv_est, cur_blk, mb_x, mb_y, sad_mb)
+ search_template!(self, mv_est, cur_blk, mb_x, mb_y, sad_mb, DIST_THRESH)
}
fn search_blk(&mut self, mv_est: &mut MVEstimator, cur_blk: &[u8; 64], xpos: usize, ypos: usize) -> (MV, u32) {
- search_template!(self, mv_est, cur_blk, xpos, ypos, sad_blk)
+ search_template!(self, mv_est, cur_blk, xpos, ypos, sad_blk, DIST_THRESH)
}
}
}
filter_alpha: usize,
loop_thr: i16,
mv_range: i16,
-pub count: usize,
-pub count2: usize,
}
impl MVEstimator {
filter_alpha: 0,
loop_thr,
mv_range,
-count: 0,
-count2: 0,
}
}
pub fn mc_block(&mut self, dst_idx: usize, plane: usize, x: usize, y: usize, mv: MV) {
for i in 0..4 {
self.mc_block(i, 0, mb_x * 16 + (i & 1) * 8, mb_y * 16 + (i >> 1) * 8, cur_mv);
dist += sad(&cur_blk[i], &self.ref_blk[i]);
-self.count2 += 1;
if dist > best_dist {
break;
}
for plane in 1..3 {
self.mc_block(plane + 3, plane, mb_x * 8, mb_y * 8, cur_mv);
dist += sad(&cur_blk[plane + 3], &self.ref_blk[plane + 3]);
-self.count2 += 1;
if dist > best_dist {
break;
}
}
}
-self.count += 1;
dist
}
fn sad_blk(&mut self, cur_blk: &[u8; 64], xpos: usize, ypos: usize, cur_mv: MV, _: u32) -> u32 {