diff options
author | metamuffin <metamuffin@disroot.org> | 2023-03-09 18:09:07 +0100 |
---|---|---|
committer | metamuffin <metamuffin@disroot.org> | 2023-03-09 18:09:07 +0100 |
commit | 4fbf4bb4310da4bede43c9428809ac9a8804982a (patch) | |
tree | daa7b2b34bb0aad4c188550b413ccd725eb1c5c4 | |
parent | ecb81ba6448d6e33a9e7ecd3cd5d41513713f814 (diff) | |
download | video-codec-experiments-4fbf4bb4310da4bede43c9428809ac9a8804982a.tar video-codec-experiments-4fbf4bb4310da4bede43c9428809ac9a8804982a.tar.bz2 video-codec-experiments-4fbf4bb4310da4bede43c9428809ac9a8804982a.tar.zst |
works very well
-rw-r--r-- | lvc/src/bin/main.rs | 29 | ||||
-rw-r--r-- | lvc/src/decode.rs | 9 | ||||
-rw-r--r-- | lvc/src/encode.rs | 37 | ||||
-rw-r--r-- | lvc/src/huff.rs | 6 |
4 files changed, 46 insertions, 35 deletions
diff --git a/lvc/src/bin/main.rs b/lvc/src/bin/main.rs index 7c0d965..6037855 100644 --- a/lvc/src/bin/main.rs +++ b/lvc/src/bin/main.rs @@ -28,12 +28,14 @@ struct Args { enum Action { // Compress video Encode { - #[arg(short, long, default_value_t = 400)] + #[arg(short, long, default_value_t = 800)] max_block_size: usize, + #[arg(short, long, default_value_t = 10_000)] + attention_split: u32, + #[arg(short, long, default_value_t = 10.)] + threshold: f32, #[arg(short, long, default_value_t = 10)] - iters: usize, - #[arg(short, long, default_value_t = 5_000)] - threshold: u32, + keyframe_interval: usize, }, // Decompress video Decode { @@ -53,12 +55,13 @@ fn main() { Action::Encode { max_block_size, threshold, - iters, + attention_split, + keyframe_interval, } => { let config = EncodeConfig { threshold, max_block_size, - iters, + attention_split, }; let mut last_frame = Frame::new(size); @@ -70,6 +73,11 @@ fn main() { for frame_number in 0.. { let mut frame = read_frame(&mut stdin, size); + let mut config = config.clone(); + if frame_number % keyframe_interval != 0 { + config.threshold = std::f32::INFINITY; + } + let t = Instant::now(); let b: Block = encode(&last_frame, &frame, View::all(size), &config); let time_encode = t.elapsed(); @@ -95,12 +103,12 @@ fn main() { time_decode + time_huff + time_encode ); eprintln!( - "\tencode {time_encode:?} ({}%)", - ((bits_raw as f32 / (size.area() * 24) as f32) * 100.0).round() + "\tencode {time_encode:?} ({:.2}%)", + (bits_raw as f32 / (size.area() * 24) as f32) * 100.0 ); eprintln!( - "\thuff {time_huff:?} ({}%)", - ((bits_huff as f32 / bits_raw as f32) * 100.0).round() + "\thuff {time_huff:?} ({:.2}%)", + (bits_huff as f32 / bits_raw as f32) * 100.0 ); eprintln!("\tdecode {time_decode:?}"); } else { @@ -119,7 +127,6 @@ fn main() { let huff = true; loop { - let b = if huff { let mut buf = vec![]; read_huff(&mut stdin, &mut buf).unwrap(); diff --git a/lvc/src/decode.rs b/lvc/src/decode.rs index da69080..771cba9 100644 --- a/lvc/src/decode.rs +++ b/lvc/src/decode.rs @@ -1,12 +1,17 @@ use crate::{split::split, Block, Frame, View, P2}; +use rayon::join; pub fn decode(last_frame: &Frame, frame: &mut Frame, view: View, block: &Block) { match block { Block::Lit(pxs) => frame.import(view, &pxs), Block::Split(a, b) => { let [av, bv] = split(view); - decode(last_frame, frame, av, &a); - decode(last_frame, frame, bv, &b); + let (frame1, frame2) = + unsafe { (&mut *(frame as *mut Frame), &mut *(frame as *mut Frame)) }; + join( + || decode(last_frame, frame1, av, &a), + || decode(last_frame, frame2, bv, &b), + ); } Block::Ref(r) => { for y in view.a.y..view.b.y { diff --git a/lvc/src/encode.rs b/lvc/src/encode.rs index 4ec72cf..030e882 100644 --- a/lvc/src/encode.rs +++ b/lvc/src/encode.rs @@ -2,15 +2,18 @@ use crate::diff::{diff, pixel_diff}; use crate::split::split; use crate::{Block, Frame, Pixel, Ref, View, P2}; +#[derive(Debug, Clone)] pub struct EncodeConfig { - pub threshold: u32, + pub threshold: f32, pub max_block_size: usize, - pub iters: usize, + pub attention_split: u32, } pub fn encode(last_frame: &Frame, frame: &Frame, view: View, config: &EncodeConfig) -> Block { let view_area = view.size().area(); - if view_area > config.max_block_size { + if view_area > config.max_block_size + || (view_area > 64 && attention(frame, view) > config.attention_split) + { let [av, bv] = split(view); let (ab, bb) = rayon::join( || Box::new(encode(last_frame, frame, av, config)), @@ -22,12 +25,13 @@ pub fn encode(last_frame: &Frame, frame: &Frame, view: View, config: &EncodeConf 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 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 [8, 8, 4, 2, 1, 1, 1] { + for granularity in [2, 1, 2, 1, 2, 1, 2, 1] { let (nd, nrp) = optimize_ref(last_frame, frame, view, r, granularity, target_average); if nd < d { r = nrp; @@ -52,6 +56,7 @@ pub fn optimize_ref( g: i32, target_average: Pixel, ) -> (u32, Ref) { + let g2 = g * 2; [ Some(r.apply(|r| r.pos_off += P2 { x: g, y: 0 })), Some(r.apply(|r| r.pos_off += P2 { x: g, y: g })), @@ -61,6 +66,14 @@ pub fn optimize_ref( Some(r.apply(|r| r.pos_off += P2 { x: -g, y: -g })), Some(r.apply(|r| r.pos_off += P2 { x: 0, y: -g })), Some(r.apply(|r| r.pos_off += P2 { x: g, y: -g })), + Some(r.apply(|r| r.pos_off += P2 { x: g2, y: 0 })), + Some(r.apply(|r| r.pos_off += P2 { x: g2, y: g2 })), + Some(r.apply(|r| r.pos_off += P2 { x: 0, y: g2 })), + Some(r.apply(|r| r.pos_off += P2 { x: -g2, y: g2 })), + Some(r.apply(|r| r.pos_off += P2 { x: -g2, y: 0 })), + Some(r.apply(|r| r.pos_off += P2 { x: -g2, y: -g2 })), + Some(r.apply(|r| r.pos_off += P2 { x: 0, y: -g2 })), + Some(r.apply(|r| r.pos_off += P2 { x: g2, y: -g2 })), { let mut r = r; let last_avr = average_color(last_frame, view); @@ -72,20 +85,10 @@ pub fn optimize_ref( None } }, - // Some(r.apply(|r| r.color_off.r += (g as i16) << 2)), - // Some(r.apply(|r| r.color_off.r -= (g as i16) << 2)), - // Some(r.apply(|r| r.color_off.g += (g as i16) << 2)), - // Some(r.apply(|r| r.color_off.g -= (g as i16) << 2)), - // Some(r.apply(|r| r.color_off.b += (g as i16) << 2)), - // Some(r.apply(|r| r.color_off.b -= (g as i16) << 2)), ] .into_iter() .flatten() - .map(|r| { - let d = diff([last_frame, frame], view, r); - - (d, r) - }) + .map(|r| (diff([last_frame, frame], view, r), r)) .min_by_key(|e| e.0) .unwrap() } diff --git a/lvc/src/huff.rs b/lvc/src/huff.rs index b00aaa0..6d74c42 100644 --- a/lvc/src/huff.rs +++ b/lvc/src/huff.rs @@ -22,6 +22,7 @@ pub fn write_huff(buf: &[u8], w: &mut impl Write) -> Result<usize> { tree.create_lut(&mut table, 1); tree.write(&mut w)?; + for b in buf { let mut k = table[*b as usize]; while k != 1 { @@ -31,7 +32,6 @@ pub fn write_huff(buf: &[u8], w: &mut impl Write) -> Result<usize> { } w.flush()?; - eprintln!("{}", w.position); Ok(w.position) } @@ -43,9 +43,7 @@ pub fn read_huff(r: &mut impl Read, buf: &mut Vec<u8>) -> Result<usize> { len |= (r.rbyte()? as usize) << 8; len |= (r.rbyte()? as usize) << 16; - eprintln!("len={len:?}"); let root = HT::read(&mut r)?; - // eprintln!("{root:?}"); let root = match &root { HT::Branch(a, b) => [a, b], _ => panic!("no!"), @@ -64,8 +62,6 @@ pub fn read_huff(r: &mut impl Read, buf: &mut Vec<u8>) -> Result<usize> { } } } - eprintln!("len(buf)={}", buf.len()); - eprintln!("{}", r.position); Ok(r.position) } |