X-Git-Url: https://git.nihav.org/?p=nihav.git;a=blobdiff_plain;f=nihav-duck%2Fsrc%2Fcodecs%2Fvp6enc%2Fdsp.rs;h=b83cd11e09d5c96f4fb357efdbff07a52627d798;hp=41b72cf849c0c3081bd878a8d2cf5f73284388e8;hb=19cfcd2f207b472c03de4c14db85d0cac1d93fa9;hpb=fafa7da322906def9ed7d924a51d50e39998fe61 diff --git a/nihav-duck/src/codecs/vp6enc/dsp.rs b/nihav-duck/src/codecs/vp6enc/dsp.rs index 41b72cf..b83cd11 100644 --- a/nihav-duck/src/codecs/vp6enc/dsp.rs +++ b/nihav-duck/src/codecs/vp6enc/dsp.rs @@ -4,45 +4,8 @@ use super::super::vpcommon::*; 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 { - 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; @@ -177,137 +140,6 @@ impl MVSearch for FullMVSearch { } } -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 {