aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lvc/src/bench.rs16
-rw-r--r--lvc/src/diff.rs19
-rw-r--r--lvc/src/encode.rs98
-rw-r--r--lvc/src/impls.rs11
-rwxr-xr-xlvc/tools/d-disp2
-rwxr-xr-xlvc/tools/d-dispd2
6 files changed, 109 insertions, 39 deletions
diff --git a/lvc/src/bench.rs b/lvc/src/bench.rs
index 91b13b6..48d220c 100644
--- a/lvc/src/bench.rs
+++ b/lvc/src/bench.rs
@@ -1,4 +1,4 @@
-use crate::{diff::diff, Frame, Ref, View, P2};
+use crate::{diff::*, Frame, Ref, View, P2};
use std::time::Instant;
fn measure(f: impl FnOnce()) {
@@ -13,7 +13,17 @@ fn bench_diff() {
let size = P2 { x: 2000, y: 2000 };
let f1 = Frame::new(size);
let f2 = Frame::new(size);
- measure(move || {
+ measure(|| {
diff([&f1, &f2], View::all(size), Ref::default());
- })
+ });
}
+
+// #[test]
+// fn bench_fast_diff() {
+// let size = P2 { x: 2000, y: 2000 };
+// let f1 = Frame::new(size);
+// let f2 = Frame::new(size);
+// measure(|| {
+// diff_fast([&f1, &f2], View::all(size), Ref::default());
+// });
+// }
diff --git a/lvc/src/diff.rs b/lvc/src/diff.rs
index fbb6b0a..4d1a805 100644
--- a/lvc/src/diff.rs
+++ b/lvc/src/diff.rs
@@ -19,6 +19,25 @@ pub fn pixel_diff(p1: Pixel, p2: Pixel) -> u32 {
p1.r.abs_diff(p2.r) as u32 + p1.g.abs_diff(p2.g) as u32 + p1.b.abs_diff(p2.b) as u32
}
+// pub fn diff([frame1, frame2]: [&Frame; 2], view: View, rp: Ref) -> u32 {
+// let mut k = 0;
+// for y in view.a.y..view.b.y {
+// let s1_ystart = (y * frame1.size.x) as usize;
+// let s2_ystart = ((y + rp.pos_off.y) * frame1.size.x + rp.pos_off.x) as usize;
+// let s1 = &frame1.pixels[s1_ystart + view.a.x as usize..s1_ystart + view.b.x as usize];
+// let s2 = &frame2.pixels[s2_ystart + view.a.x as usize..s2_ystart + view.b.x as usize];
+// let s1 = unsafe { std::mem::transmute::<_, &[i16]>(s1) };
+// let s2 = unsafe { std::mem::transmute::<_, &[i16]>(s2) };
+
+// k += s1
+// .iter()
+// .zip(s2.iter())
+// .map(|(a, b)| a.abs_diff(*b) as u32)
+// .sum::<u32>()
+// }
+// k
+// }
+
// pub fn fast_diff([frame1, frame2]: [&Frame; 2], view: View, rp: Ref) -> u32 {
// assert!(view.size().x % 5 == 0);
diff --git a/lvc/src/encode.rs b/lvc/src/encode.rs
index 10f8c50..fde4f94 100644
--- a/lvc/src/encode.rs
+++ b/lvc/src/encode.rs
@@ -1,6 +1,6 @@
use crate::diff::{diff, pixel_diff};
use crate::split::split;
-use crate::{Block, Frame, Ref, View, P2};
+use crate::{Block, Frame, Pixel, Ref, View, P2};
pub struct EncodeConfig {
pub threshold: u32,
@@ -25,15 +25,15 @@ pub fn encode(last_frame: &Frame, frame: &Frame, view: View, config: &EncodeConf
let att = 1. - attention(frame, view) as f32 * 0.000001;
let thres = (config.threshold as f32 * att.clamp(0.2, 1.0)) as u32;
- for granularity in [4, 2, 1] {
- for _ in 0..config.iters {
- let (nd, nrp) = optimize_ref(last_frame, frame, view, d, r, granularity);
- if nd < d {
- r = nrp;
- d = nd;
- } else {
- break;
- }
+ let target_average = average_color(frame, view);
+
+ for granularity in [8, 8, 4, 2, 1, 1, 1] {
+ let (nd, nrp) = optimize_ref(last_frame, frame, view, r, granularity, target_average);
+ if nd < d {
+ r = nrp;
+ d = nd;
+ } else {
+ break;
}
}
@@ -48,33 +48,42 @@ pub fn optimize_ref(
last_frame: &Frame,
frame: &Frame,
view: View,
- mut d: u32,
- mut r: Ref,
+ r: Ref,
granularity: i32,
+ target_average: Pixel,
) -> (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);
+ [
+ Some(r.apply(|r| r.pos_off.x += granularity)),
+ Some(r.apply(|r| r.pos_off.x -= granularity)),
+ Some(r.apply(|r| r.pos_off.y += granularity)),
+ Some(r.apply(|r| r.pos_off.y -= granularity)),
+ {
+ let mut r = r;
+ let last_avr = average_color(last_frame, view);
+ let diff = target_average - last_avr;
+ r.color_off = diff;
+ if diff != Pixel::BLACK {
+ Some(r)
+ } else {
+ None
+ }
+ },
+ // 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);
+ ]
+ .into_iter()
+ .flatten()
+ .map(|r| {
+ let d = diff([last_frame, frame], view, r);
- (d, r)
+ (d, r)
+ })
+ .min_by_key(|e| e.0)
+ .unwrap()
}
pub fn attention(frame: &Frame, view: View) -> u32 {
@@ -88,3 +97,24 @@ pub fn attention(frame: &Frame, view: View) -> u32 {
}
k
}
+
+pub fn average_color(frame: &Frame, view: View) -> Pixel {
+ let mut r = 0u32;
+ let mut g = 0u32;
+ let mut b = 0u32;
+
+ for y in view.a.y..view.b.y {
+ for x in view.a.x..view.b.x {
+ let p = frame[P2 { x, y }];
+ r += p.r as u32;
+ g += p.g as u32;
+ b += p.b as u32;
+ }
+ }
+ let area = view.size().area() as u32;
+ Pixel {
+ r: (r / area) as i16,
+ g: (g / area) as i16,
+ b: (b / area) as i16,
+ }
+}
diff --git a/lvc/src/impls.rs b/lvc/src/impls.rs
index 2a5a497..04699c6 100644
--- a/lvc/src/impls.rs
+++ b/lvc/src/impls.rs
@@ -50,6 +50,17 @@ impl Add for Pixel {
}
}
}
+impl Sub for Pixel {
+ type Output = Pixel;
+ #[inline]
+ fn sub(self, rhs: Self) -> Self::Output {
+ Self {
+ r: self.r - rhs.r,
+ g: self.g - rhs.g,
+ b: self.b - rhs.b,
+ }
+ }
+}
impl P2 {
pub const ZERO: P2 = P2 { x: 0, y: 0 };
pub const X: P2 = P2 { x: 1, y: 0 };
diff --git a/lvc/tools/d-disp b/lvc/tools/d-disp
index 5879bf3..f62d229 100755
--- a/lvc/tools/d-disp
+++ b/lvc/tools/d-disp
@@ -1,2 +1,2 @@
#!/bin/fish
-cargo run --release -- -w 1920 -h 1080 decode | ffplay -video_size 1920x1080 -pixel_format rgb24 -f rawvideo pipe:0 \ No newline at end of file
+cargo run --release -- -w 1920 -h 1080 decode | ffplay -loglevel quiet -video_size 1920x1080 -pixel_format rgb24 -f rawvideo pipe:0 \ No newline at end of file
diff --git a/lvc/tools/d-dispd b/lvc/tools/d-dispd
index c4b435d..dac3faf 100755
--- a/lvc/tools/d-dispd
+++ b/lvc/tools/d-dispd
@@ -1,2 +1,2 @@
#!/bin/fish
-cargo run --release -- -w 1920 -h 1080 decode --debug | ffplay -video_size 1920x1080 -pixel_format rgb24 -f rawvideo pipe:0 \ No newline at end of file
+cargo run --release -- -w 1920 -h 1080 decode --debug | ffplay -loglevel quiet -video_size 1920x1080 -pixel_format rgb24 -f rawvideo pipe:0 \ No newline at end of file