aboutsummaryrefslogtreecommitdiff
path: root/lvc/src/encode.rs
diff options
context:
space:
mode:
Diffstat (limited to 'lvc/src/encode.rs')
-rw-r--r--lvc/src/encode.rs82
1 files changed, 51 insertions, 31 deletions
diff --git a/lvc/src/encode.rs b/lvc/src/encode.rs
index d85ac30..5df803b 100644
--- a/lvc/src/encode.rs
+++ b/lvc/src/encode.rs
@@ -1,51 +1,71 @@
use crate::diff::diff;
+use crate::impls::ToArray;
use crate::split::split;
use crate::{Block, Frame, Ref, View};
pub fn encode(last_frame: &Frame, frame: &Frame, view: View) -> Block {
if view.size().area() > 1024 {
let [av, bv] = split(view);
- return Block::Split([
- Box::new(encode(last_frame, frame, av)),
- Box::new(encode(last_frame, frame, bv)),
- ]);
+ return Block::Split(
+ rayon::join(
+ || Box::new(encode(last_frame, frame, av)),
+ || Box::new(encode(last_frame, frame, bv)),
+ )
+ .to_array(),
+ );
}
- let mut rp = Ref::default();
- let mut d = diff([last_frame, frame], view, rp);
+ let mut r = Ref::default();
+ let mut d = diff([last_frame, frame], view, r);
- for _ in 0..500 {
- let (nd, nrp) = optimize_ref(last_frame, frame, view, rp);
- if nd < d {
- rp = nrp;
- d = nd;
- } else {
- break;
+ for granularity in [4, 2, 1] {
+ for _ in 0..10 {
+ let (nd, nrp) = optimize_ref(last_frame, frame, view, d, r, granularity);
+ if nd < d {
+ r = nrp;
+ d = nd;
+ } else {
+ break;
+ }
}
}
if d < 10000 {
- return Block::Ref(rp);
+ return Block::Ref(r);
} else {
Block::Lit(frame.export(view))
}
}
-pub fn optimize_ref(last_frame: &Frame, frame: &Frame, view: View, rp: Ref) -> (u32, Ref) {
- [
- rp.apply(|r| r.pos_off.x += 1),
- rp.apply(|r| r.pos_off.x -= 1),
- rp.apply(|r| r.pos_off.y += 1),
- rp.apply(|r| r.pos_off.y -= 1),
- rp.apply(|r| r.color_off.r += 10),
- rp.apply(|r| r.color_off.r -= 10),
- rp.apply(|r| r.color_off.g += 10),
- rp.apply(|r| r.color_off.g -= 10),
- rp.apply(|r| r.color_off.b += 10),
- rp.apply(|r| r.color_off.b -= 10),
- ]
- .map(|p| (diff([last_frame, frame], view, p), p))
- .into_iter()
- .min_by_key(|x| x.0)
- .unwrap()
+pub fn optimize_ref(
+ last_frame: &Frame,
+ frame: &Frame,
+ view: View,
+ mut d: u32,
+ mut r: Ref,
+ granularity: i32,
+) -> (u32, Ref) {
+ let mut n = |f: fn(&mut Ref, i32)| {
+ let mut r2 = r;
+ f(&mut r2, granularity);
+
+ let d2 = diff([last_frame, frame], view, r2);
+ if d2 < d {
+ d = d2;
+ r = r2;
+ }
+ };
+
+ n(|r, g| r.pos_off.x += g);
+ n(|r, g| r.pos_off.x -= g);
+ n(|r, g| r.pos_off.y += g);
+ n(|r, g| r.pos_off.y -= g);
+ n(|r, g| r.color_off.r += (g as i16) << 2);
+ n(|r, g| r.color_off.r -= (g as i16) << 2);
+ n(|r, g| r.color_off.g += (g as i16) << 2);
+ n(|r, g| r.color_off.g -= (g as i16) << 2);
+ n(|r, g| r.color_off.b += (g as i16) << 2);
+ n(|r, g| r.color_off.b -= (g as i16) << 2);
+
+ (d, r)
}