diff options
author | metamuffin <metamuffin@disroot.org> | 2022-12-08 09:13:17 +0100 |
---|---|---|
committer | metamuffin <metamuffin@disroot.org> | 2022-12-08 09:13:17 +0100 |
commit | 6001cdeff335e12583a398acbb5a8a42c01bc077 (patch) | |
tree | 4c1c515cbf33e727f5db317880aadd425a1e0b96 /evc/src/codec/encode.rs | |
parent | 8b7792d6aa27578221fee7cc8be1ceb202602a5a (diff) | |
download | video-codec-experiments-6001cdeff335e12583a398acbb5a8a42c01bc077.tar video-codec-experiments-6001cdeff335e12583a398acbb5a8a42c01bc077.tar.bz2 video-codec-experiments-6001cdeff335e12583a398acbb5a8a42c01bc077.tar.zst |
fast mode
Diffstat (limited to 'evc/src/codec/encode.rs')
-rw-r--r-- | evc/src/codec/encode.rs | 177 |
1 files changed, 107 insertions, 70 deletions
diff --git a/evc/src/codec/encode.rs b/evc/src/codec/encode.rs index 4eb86b5..6b6f8a3 100644 --- a/evc/src/codec/encode.rs +++ b/evc/src/codec/encode.rs @@ -6,7 +6,6 @@ use crate::{ view::View, }; use clap::ValueEnum; -use log::debug; #[derive(Debug, Clone)] pub struct EncodeConfig { @@ -15,15 +14,38 @@ pub struct EncodeConfig { pub max_diff_area: isize, pub min_block_size: isize, pub max_threads: usize, + pub weight_factor: f64, + pub do_value_scale: bool, + pub do_matrix_transform: bool, } #[derive(Debug, Clone, ValueEnum)] pub enum EncodeMode { Trivial, + Fast, Default, Advanced, } +#[inline] +pub fn pk<F: FnMut(&mut AdvancedReference) -> ()>( + view: &View<&Frame>, + prev: &View<&Frame>, + diff: &mut f64, + params: &mut AdvancedReference, + initial_params: &AdvancedReference, + mut f: F, +) { + let mut p = initial_params.clone(); + f(&mut p); + let sampler = Sampler::from_refblock(prev.clone(), &p); + let d = View::diff_sampler(view, &sampler); + if d < *diff { + *diff = d; + *params = p; + } +} + pub fn encode_block(view: View<&Frame>, prev: View<&Frame>, config: &EncodeConfig) -> Block { let (diff, refblock) = if view.area() > config.max_diff_area { ( @@ -33,7 +55,9 @@ pub fn encode_block(view: View<&Frame>, prev: View<&Frame>, config: &EncodeConfi }, ) } else { - match config.mode { + let weight = importance(&view).max(0.5); + let irrelevance = config.weight_factor / weight; + let (diff, refblock) = match config.mode { EncodeMode::Trivial => ( View::diff(&view, &prev) / view.area() as f64, Block::Reference { @@ -41,87 +65,95 @@ pub fn encode_block(view: View<&Frame>, prev: View<&Frame>, config: &EncodeConfi }, ), EncodeMode::Default => { - let mut best_diff = f64::INFINITY; - let mut best_translation = Vec2::<isize>::ZERO; + let mut diff = f64::INFINITY; + let mut translation = Vec2::<isize>::ZERO; const OFFSETS: &[isize] = &[-64, -32, -16, -8, -4, -2, -1, 0, 1, 2, 4, 8, 16, 32, 64]; for x in OFFSETS { for y in OFFSETS { - let translation = Vec2 { x: *x, y: *y }; - let diff = View::diff(&view, &prev.offset(translation)); - if diff < best_diff { - best_translation = translation; - best_diff = diff; + let t = Vec2 { x: *x, y: *y }; + let d = View::diff(&view, &prev.offset(t)); + if d < diff { + translation = t; + diff = d; } } } - ( - best_diff, - Block::Reference { - translation: best_translation, - }, - ) + (diff, Block::Reference { translation }) } - EncodeMode::Advanced => { - let mut params = AdvancedReference::default(); - let sampler = Sampler::from_refblock(prev.clone(), ¶ms); + EncodeMode::Fast => { + let mut pm = AdvancedReference::default(); + let sampler = Sampler::from_refblock(prev.clone(), &pm); let mut diff = View::diff_sampler(&view, &sampler); - - loop { - pub fn pk<F: FnMut(&mut AdvancedReference) -> ()>( - view: &View<&Frame>, - prev: &View<&Frame>, - diff: &mut f64, - params: &mut AdvancedReference, - mut f: F, - ) { - let mut p = params.clone(); - f(&mut p); - let d = View::diff_sampler(view, &Sampler::from_refblock(prev.clone(), &p)); - if d < *diff { - *diff = d; - *params = p; + if diff - irrelevance < config.ref_thres { + (diff, Block::REFZERO) + } else { + loop { + let (mut d, mut p) = (diff, pm.clone()); + pk(&view, &prev, &mut d, &mut p, &pm, |p| p.translation.x += 2); + pk(&view, &prev, &mut d, &mut p, &pm, |p| p.translation.x -= 2); + pk(&view, &prev, &mut d, &mut p, &pm, |p| p.translation.y += 2); + pk(&view, &prev, &mut d, &mut p, &pm, |p| p.translation.y -= 2); + pk(&view, &prev, &mut d, &mut p, &pm, |p| p.translation.x += 1); + pk(&view, &prev, &mut d, &mut p, &pm, |p| p.translation.x -= 1); + pk(&view, &prev, &mut d, &mut p, &pm, |p| p.translation.y += 1); + pk(&view, &prev, &mut d, &mut p, &pm, |p| p.translation.y -= 1); + if d >= diff { + break (diff, Block::AdvancedReference(pm)); } + diff = d; + pm = p; } + } + } + EncodeMode::Advanced => { + let mut pm = AdvancedReference::default(); + let sampler = Sampler::from_refblock(prev.clone(), &pm); + let mut diff = View::diff_sampler(&view, &sampler); + if diff - irrelevance < config.ref_thres { + (diff, Block::REFZERO) + } else { + loop { + let (mut d, mut p) = (diff, pm.clone()); - let (mut d, mut p) = (diff, params.clone()); - - pk(&view, &prev, &mut d, &mut p, |p| p.translation.x += 4); - pk(&view, &prev, &mut d, &mut p, |p| p.translation.x -= 4); - pk(&view, &prev, &mut d, &mut p, |p| p.translation.y += 4); - pk(&view, &prev, &mut d, &mut p, |p| p.translation.y -= 4); - pk(&view, &prev, &mut d, &mut p, |p| p.translation.x += 2); - pk(&view, &prev, &mut d, &mut p, |p| p.translation.x -= 2); - pk(&view, &prev, &mut d, &mut p, |p| p.translation.y += 2); - pk(&view, &prev, &mut d, &mut p, |p| p.translation.y -= 2); - pk(&view, &prev, &mut d, &mut p, |p| p.translation.x += 1); - pk(&view, &prev, &mut d, &mut p, |p| p.translation.x -= 1); - pk(&view, &prev, &mut d, &mut p, |p| p.translation.y += 1); - pk(&view, &prev, &mut d, &mut p, |p| p.translation.y -= 1); - - pk(&view, &prev, &mut d, &mut p, |p| p.value_scale += 1); - pk(&view, &prev, &mut d, &mut p, |p| p.value_scale -= 1); - - pk(&view, &prev, &mut d, &mut p, |p| p.transform.a -= 1); - pk(&view, &prev, &mut d, &mut p, |p| p.transform.a += 1); - pk(&view, &prev, &mut d, &mut p, |p| p.transform.b -= 1); - pk(&view, &prev, &mut d, &mut p, |p| p.transform.b += 1); - pk(&view, &prev, &mut d, &mut p, |p| p.transform.c -= 1); - pk(&view, &prev, &mut d, &mut p, |p| p.transform.c += 1); - pk(&view, &prev, &mut d, &mut p, |p| p.transform.d -= 1); - pk(&view, &prev, &mut d, &mut p, |p| p.transform.d += 1); + pk(&view, &prev, &mut d, &mut p, &pm, |p| p.translation.x += 4); + pk(&view, &prev, &mut d, &mut p, &pm, |p| p.translation.x -= 4); + pk(&view, &prev, &mut d, &mut p, &pm, |p| p.translation.y += 4); + pk(&view, &prev, &mut d, &mut p, &pm, |p| p.translation.y -= 4); + pk(&view, &prev, &mut d, &mut p, &pm, |p| p.translation.x += 2); + pk(&view, &prev, &mut d, &mut p, &pm, |p| p.translation.x -= 2); + pk(&view, &prev, &mut d, &mut p, &pm, |p| p.translation.y += 2); + pk(&view, &prev, &mut d, &mut p, &pm, |p| p.translation.y -= 2); + pk(&view, &prev, &mut d, &mut p, &pm, |p| p.translation.x += 1); + pk(&view, &prev, &mut d, &mut p, &pm, |p| p.translation.x -= 1); + pk(&view, &prev, &mut d, &mut p, &pm, |p| p.translation.y += 1); + pk(&view, &prev, &mut d, &mut p, &pm, |p| p.translation.y -= 1); + if config.do_value_scale { + // pk(&view, &prev, &mut d, &mut p, &pm, |p| p.value_scale += 1); + // pk(&view, &prev, &mut d, &mut p, &pm, |p| p.value_scale -= 1); + } + if config.do_matrix_transform { + pk(&view, &prev, &mut d, &mut p, &pm, |p| p.transform.a -= 1); + pk(&view, &prev, &mut d, &mut p, &pm, |p| p.transform.a += 1); + pk(&view, &prev, &mut d, &mut p, &pm, |p| p.transform.b -= 1); + pk(&view, &prev, &mut d, &mut p, &pm, |p| p.transform.b += 1); + pk(&view, &prev, &mut d, &mut p, &pm, |p| p.transform.c -= 1); + pk(&view, &prev, &mut d, &mut p, &pm, |p| p.transform.c += 1); + pk(&view, &prev, &mut d, &mut p, &pm, |p| p.transform.d -= 1); + pk(&view, &prev, &mut d, &mut p, &pm, |p| p.transform.d += 1); + } - debug!("{diff} -> {d}"); + if d >= diff { + break (diff, Block::AdvancedReference(pm)); + } - if d >= diff { - break (diff, Block::AdvancedReference(params)); + diff = d; + pm = p; } - - diff = d; - params = p; } } - } + }; + (diff - irrelevance, refblock) }; if diff < config.ref_thres { refblock @@ -136,18 +168,23 @@ pub fn encode_block(view: View<&Frame>, prev: View<&Frame>, config: &EncodeConfi let config = unsafe { std::mem::transmute::<_, &'static EncodeConfig>(config) }; // only bother to do multithreading, when the block is big. - let (a, b) = if view.size.x > 64 { + let (a, b) = // if view.size.x > 64 { both_par( || encode_block(av, ap, config), || encode_block(bv, bp, config), config.max_threads, ) - } else { - (encode_block(av, ap, config), encode_block(bv, bp, config)) - }; + // } else { + // (encode_block(av, ap, config), encode_block(bv, bp, config)) + // } + ; if a.is_literal() && b.is_literal() { Block::Literal(view.pixels()) + } else if a.is_ref_without_translation() && b.is_ref_without_translation() { + Block::Reference { + translation: Vec2::<isize>::ZERO, + } } else { Block::Split(Box::new([a, b])) } |