diff options
author | metamuffin <metamuffin@disroot.org> | 2023-05-20 14:03:12 +0200 |
---|---|---|
committer | metamuffin <metamuffin@disroot.org> | 2023-05-20 14:03:12 +0200 |
commit | 9c211e161f0f9cfb97aeb5778591563def6239fc (patch) | |
tree | fe4e7bff6f28b0fa13aaf434db155be9572e1fbf /bv1 | |
parent | 1315e39714ab846ba7fed052598f70a453e0f964 (diff) | |
download | video-codec-experiments-9c211e161f0f9cfb97aeb5778591563def6239fc.tar video-codec-experiments-9c211e161f0f9cfb97aeb5778591563def6239fc.tar.bz2 video-codec-experiments-9c211e161f0f9cfb97aeb5778591563def6239fc.tar.zst |
idk
Diffstat (limited to 'bv1')
-rw-r--r-- | bv1/app/src/bin/bench.rs | 2 | ||||
-rw-r--r-- | bv1/app/src/bin/main.rs | 5 | ||||
-rw-r--r-- | bv1/codec/src/decode.rs | 1 | ||||
-rw-r--r-- | bv1/codec/src/diff.rs | 131 | ||||
-rw-r--r-- | bv1/codec/src/encode.rs | 44 | ||||
-rw-r--r-- | bv1/codec/src/lib.rs | 1 |
6 files changed, 37 insertions, 147 deletions
diff --git a/bv1/app/src/bin/bench.rs b/bv1/app/src/bin/bench.rs index b9c6464..86edcac 100644 --- a/bv1/app/src/bin/bench.rs +++ b/bv1/app/src/bin/bench.rs @@ -1,4 +1,4 @@ -use bv1::{diff::*, Frame, Ref, View, P2}; +use bv1::{encode::diff, Frame, Ref, View, P2}; use std::time::Instant; fn measure(f: impl FnOnce()) { diff --git a/bv1/app/src/bin/main.rs b/bv1/app/src/bin/main.rs index 0b3596e..1898bf1 100644 --- a/bv1/app/src/bin/main.rs +++ b/bv1/app/src/bin/main.rs @@ -1,6 +1,7 @@ use bv1::{ + decode, encode::{encode, EncodeConfig}, - P2, decode, + P2, }; use clap::{Parser, Subcommand}; use std::io::{stdin, stdout}; @@ -53,6 +54,8 @@ fn main() { keyframe_interval, } => { let config = EncodeConfig { + min_block_size: 16, + motion_split_f: 2., threshold, max_block_size, attention_split, diff --git a/bv1/codec/src/decode.rs b/bv1/codec/src/decode.rs index 616b7af..aaebc6a 100644 --- a/bv1/codec/src/decode.rs +++ b/bv1/codec/src/decode.rs @@ -36,7 +36,6 @@ impl Decoder { let b = if huff { let mut buf = vec![]; read_huff(&mut input, &mut buf)?; - eprintln!("{}", buf.len()); let mut buf = std::io::Cursor::new(&mut buf); Block::read(&mut buf, View::all(self.size))? } else { diff --git a/bv1/codec/src/diff.rs b/bv1/codec/src/diff.rs deleted file mode 100644 index 4d1a805..0000000 --- a/bv1/codec/src/diff.rs +++ /dev/null @@ -1,131 +0,0 @@ -use crate::{Frame, Pixel, Ref, View, P2}; - -// 4ms -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 -} - -// 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); - -// let mut diff_lanes = i32x16::from_array([0; 16]); -// let mut k1 = [0; 32]; -// let mut k2 = [0; 32]; - -// let next_line = frame1.size.x as usize - view.size().x as usize; -// let index_start = view.a.x as usize + view.a.y as usize * frame1.size.x as usize; -// let index_end = view.b.x as usize + (view.b.y as usize - 1) * frame1.size.x as usize; - -// let mut i = index_start; -// let mut x = view.a.x; - -// while i < index_end { - -// let f1: &[u8] = -// unsafe { std::slice::from_raw_parts(frame1.pixels[sl_start..].as_ptr() as *mut u8, sl_size) }; -// let f2: &[u8] = -// unsafe { std::slice::from_raw_parts(frame2.pixels[sl_start..].as_ptr() as *mut u8, sl_size) }; - -// for i in 0..15 { -// k1[i] = f1[i] as i32; -// k2[i] = f2[i] as i32; -// } - -// // for j in 0..5 { -// // let j3 = j * 3; -// // k1[j3] = frame1.pixels[i + j].r as i32; -// // k2[j3] = frame2.pixels[i + j].r as i32; -// // k1[j3 + 1] = frame1.pixels[i + j].g as i32; -// // k2[j3 + 1] = frame2.pixels[i + j].g as i32; -// // k1[j3 + 2] = frame1.pixels[i + j].b as i32; -// // k2[j3 + 2] = frame2.pixels[i + j].b as i32; -// // } -// let pl1 = i16x32::from_array(k1); -// let pl2 = i16x32::from_array(k2); -// diff_lanes += (pl1 - pl2).abs(); - -// i += 5; -// x += 5; -// if x > view.b.x { -// i += next_line; -// x = view.a.x -// } -// } - -// return diff_lanes.reduce_sum() as u32; -// } - -// pub fn fast_diff([frame1, frame2]: [&Frame; 2], view: View, rp: Ref) -> u32 { -// let mut diff_lanes = i32x16::from_array([0; 16]); -// let mut k1 = [0; 16]; -// let mut k2 = [0; 16]; - -// let next_line = frame1.size.x as usize - view.size().x as usize; -// let index_start = view.a.x as usize + view.a.y as usize * frame1.size.x as usize; -// let index_end = view.b.x as usize + (view.b.y as usize - 1) * frame1.size.x as usize; - -// let mut i = index_start; -// let mut x = view.a.x; -// let mut kfill = 0; - -// while i < index_end { -// k1[kfill] = frame1.pixels[i].r as i32; -// k2[kfill] = frame2.pixels[i].r as i32; -// kfill += 1; -// k1[kfill] = frame1.pixels[i].g as i32; -// k2[kfill] = frame2.pixels[i].g as i32; -// kfill += 1; -// k1[kfill] = frame1.pixels[i].b as i32; -// k2[kfill] = frame2.pixels[i].b as i32; -// kfill += 1; - -// i += 1; -// x += 1; -// if x > view.b.x { -// i += next_line; -// x = view.a.x -// } - -// if kfill == 15 { -// let pl1 = i32x16::from_array(k1); -// let pl2 = i32x16::from_array(k2); -// diff_lanes += (pl1 - pl2).abs(); -// kfill = 0; -// } -// } - -// return diff_lanes.reduce_sum() as u32; -// } 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 +} diff --git a/bv1/codec/src/lib.rs b/bv1/codec/src/lib.rs index c764211..a88d8c5 100644 --- a/bv1/codec/src/lib.rs +++ b/bv1/codec/src/lib.rs @@ -4,7 +4,6 @@ pub mod debug; pub mod decode; -pub mod diff; pub mod encode; pub mod frameio; pub mod huff; |