From 9c211e161f0f9cfb97aeb5778591563def6239fc Mon Sep 17 00:00:00 2001 From: metamuffin Date: Sat, 20 May 2023 14:03:12 +0200 Subject: idk --- bv1/codec/src/encode.rs | 44 ++++++++++++++++++++++++++++++++------------ 1 file changed, 32 insertions(+), 12 deletions(-) (limited to 'bv1/codec/src/encode.rs') diff --git a/bv1/codec/src/encode.rs b/bv1/codec/src/encode.rs index 564b0b3..2f40c07 100644 --- a/bv1/codec/src/encode.rs +++ b/bv1/codec/src/encode.rs @@ -1,4 +1,3 @@ -use crate::diff::{diff, pixel_diff}; use crate::huff::write_huff; use crate::impls::join; use crate::split::split; @@ -10,7 +9,9 @@ use std::time::Instant; pub struct EncodeConfig { pub threshold: f32, pub max_block_size: usize, + pub min_block_size: usize, pub attention_split: u32, + pub motion_split_f: f32, pub keyframe_interval: usize, } @@ -74,27 +75,28 @@ pub fn encode( pub fn encode_block(last_frame: &Frame, frame: &Frame, view: View, config: &EncodeConfig) -> Block { let view_area = view.size().area(); + let thres = config.threshold * view_area as f32; + if view_area > config.max_block_size - || (view_area > 64 && attention(frame, view) > config.attention_split) + || (view_area > config.min_block_size + && (total_contrast(frame, view) > config.attention_split + || diff([last_frame, frame], view, Ref::default()) + > (thres * config.motion_split_f) as u32)) { let [av, bv] = split(view); let (ab, bb) = join( - || Box::new(encode_block(last_frame, frame, av, config)), - || Box::new(encode_block(last_frame, frame, bv, config)), + || encode_block(last_frame, frame, av, config), + || encode_block(last_frame, frame, bv, config), ); - return Block::Split(ab, bb); + return Block::Split(box ab, box bb); } let mut r = Ref::default(); let mut d = diff([last_frame, frame], view, r); - // let att = 1. - attention(frame, view) as f32 * 0.000001; - // let thres = (config.threshold as f32 * att.clamp(0.2, 1.0)) as u32; - let thres = (config.threshold * view_area as f32) as u32; - let target_average = average_color(frame, view); - for granularity in [2, 1, 2, 1, 2, 1, 2, 1] { + for granularity in [1, 2, 3, 5, 7, 5, 3, 2, 1] { let (nd, nrp) = optimize_ref(last_frame, frame, view, r, granularity, target_average); if nd < d { r = nrp; @@ -104,7 +106,7 @@ pub fn encode_block(last_frame: &Frame, frame: &Frame, view: View, config: &Enco } } - if d < thres { + if d < thres as u32 { return Block::Ref(r); } else { Block::Lit(frame.export(view)) @@ -156,7 +158,7 @@ pub fn optimize_ref( .unwrap() } -pub fn attention(frame: &Frame, view: View) -> u32 { +pub fn total_contrast(frame: &Frame, view: View) -> u32 { let mut k = 0; for y in view.a.y..view.b.y - 1 { for x in view.a.x..view.b.x - 1 { @@ -188,3 +190,21 @@ pub fn average_color(frame: &Frame, view: View) -> Pixel { b: (b / area) as i16, } } + +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 { + for x in view.a.x..view.b.x { + let pos = P2 { x, y }; + let p1 = frame1[pos + rp.pos_off] + rp.color_off; + let p2 = frame2[pos]; + k += pixel_diff(p1, p2) + } + } + k +} + +#[inline(always)] +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 +} -- cgit v1.2.3-70-g09d2