aboutsummaryrefslogtreecommitdiff
path: root/evc/src/codec/encode/advanced.rs
diff options
context:
space:
mode:
Diffstat (limited to 'evc/src/codec/encode/advanced.rs')
-rw-r--r--evc/src/codec/encode/advanced.rs109
1 files changed, 109 insertions, 0 deletions
diff --git a/evc/src/codec/encode/advanced.rs b/evc/src/codec/encode/advanced.rs
new file mode 100644
index 0000000..e86a1b8
--- /dev/null
+++ b/evc/src/codec/encode/advanced.rs
@@ -0,0 +1,109 @@
+use super::EncodeConfig;
+use crate::{
+ block::{AdvancedReference, Block},
+ frame::Frame,
+ refsampler::Sampler,
+ view::View,
+};
+
+pub fn default(
+ view: &View<&Frame>,
+ prev: &View<&Frame>,
+ config: &EncodeConfig,
+ max_diff: f64,
+) -> (f64, Block) {
+ let mut pm = AdvancedReference::default();
+ let sampler = Sampler::from_refblock(prev.clone(), &pm);
+ let mut diff = View::diff_sampler(&view, &sampler);
+ if diff < max_diff {
+ (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 += 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);
+ }
+
+ if d >= diff {
+ break (diff, Block::AdvancedReference(pm));
+ }
+
+ diff = d;
+ pm = p;
+ }
+ }
+}
+
+pub fn partial(
+ view: &View<&Frame>,
+ prev: &View<&Frame>,
+ _config: &EncodeConfig,
+ max_diff: f64,
+) -> (f64, Block) {
+ let mut pm = AdvancedReference::default();
+ let sampler = Sampler::from_refblock(prev.clone(), &pm);
+ let mut diff = View::diff_sampler(&view, &sampler);
+ if diff < max_diff {
+ (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;
+ }
+ }
+}
+
+#[inline]
+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;
+ }
+}