diff options
Diffstat (limited to 'lvc/src/encode.rs')
-rw-r--r-- | lvc/src/encode.rs | 82 |
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) } |