aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormetamuffin <metamuffin@disroot.org>2022-12-07 18:40:24 +0100
committermetamuffin <metamuffin@disroot.org>2022-12-07 18:40:24 +0100
commit7be0d5039db7e8660bced13698178bf1d6758109 (patch)
treea8723d67b6bab98656b182478b6418f2361260fa
parent8ca219c6b0d5448fd4529713ccd093e89de4e252 (diff)
downloadvideo-codec-experiments-7be0d5039db7e8660bced13698178bf1d6758109.tar
video-codec-experiments-7be0d5039db7e8660bced13698178bf1d6758109.tar.bz2
video-codec-experiments-7be0d5039db7e8660bced13698178bf1d6758109.tar.zst
refactor
-rw-r--r--evc/Cargo.toml2
-rw-r--r--evc/src/bin/decode.rs5
-rw-r--r--evc/src/bin/encode.rs14
-rw-r--r--evc/src/block.rs26
-rw-r--r--evc/src/codec/decode.rs5
-rw-r--r--evc/src/codec/encode.rs80
-rw-r--r--evc/src/format/ser.rs34
-rw-r--r--evc/src/helpers/matrix.rs9
-rw-r--r--evc/src/refsampler.rs1
9 files changed, 131 insertions, 45 deletions
diff --git a/evc/Cargo.toml b/evc/Cargo.toml
index b5e9ee9..f88e947 100644
--- a/evc/Cargo.toml
+++ b/evc/Cargo.toml
@@ -2,7 +2,7 @@
name = "evc"
version = "0.1.0"
edition = "2021"
-
+
[dependencies]
clap = { version = "*", features = ["derive"] }
anyhow = "1.0.66"
diff --git a/evc/src/bin/decode.rs b/evc/src/bin/decode.rs
index b7dd4e1..36b1f80 100644
--- a/evc/src/bin/decode.rs
+++ b/evc/src/bin/decode.rs
@@ -68,5 +68,10 @@ fn draw_debug(block: &Block, mut target: View<&mut Frame>) {
.frame
.draw_line(target.center(), target.center() + *translation, Pixel::RED)
}
+ Block::AdvancedReference {
+ translation: _,
+ transform: _,
+ value_scale: _,
+ } => (), // TODO
}
}
diff --git a/evc/src/bin/encode.rs b/evc/src/bin/encode.rs
index f81bb5e..e5ffa41 100644
--- a/evc/src/bin/encode.rs
+++ b/evc/src/bin/encode.rs
@@ -3,7 +3,7 @@ use clap::Parser;
use evc::{
codec::{
decode::decode_block,
- encode::{encode_block, EncodeConfig},
+ encode::{encode_block, EncodeConfig, EncodeMode},
},
format::{header::Header, ser::Sink},
frame::Frame,
@@ -20,6 +20,12 @@ pub struct EncodeArgs {
#[arg(short = 'H', long)]
height: usize,
+ #[arg(short, long)]
+ mode: EncodeMode,
+
+ #[arg(short, long, default_value = "8")]
+ jobs: usize,
+
#[arg(short = 't', long, default_value = "1.5")]
ref_thres: f64,
#[arg(short = 'T', long)]
@@ -34,11 +40,11 @@ fn main() -> anyhow::Result<()> {
let mut output = BufWriter::new(std::io::stdout());
let config = EncodeConfig {
- translate: !args.no_translation,
+ mode: evc::codec::encode::EncodeMode::Advanced,
ref_thres: 50.0,
- max_diff_size: 10_000,
+ max_diff_area: 10_000,
min_block_size: 8,
- max_threads: 12,
+ max_threads: args.jobs,
};
let size = Vec2 {
diff --git a/evc/src/block.rs b/evc/src/block.rs
index 3a37820..0a7ace3 100644
--- a/evc/src/block.rs
+++ b/evc/src/block.rs
@@ -1,16 +1,23 @@
use anyhow::bail;
use crate::{
- format::ser::{Ser, Sink, Source, Small},
- helpers::pixel::Pixel,
+ format::ser::{Ser, Sink, Small, Source},
helpers::vector::Vec2,
+ helpers::{matrix::Mat2, pixel::Pixel},
};
#[derive(Clone, Debug)]
pub enum Block {
Literal(Vec<Pixel>),
Split(Box<[Block; 2]>),
- Reference { translation: Vec2<isize> },
+ Reference {
+ translation: Vec2<isize>,
+ },
+ AdvancedReference {
+ translation: Vec2<i8>,
+ transform: Mat2<i8>,
+ value_scale: i8,
+ },
}
impl Block {
@@ -29,6 +36,14 @@ impl Block {
sink.put(2u8)?;
sink.put(Small(*translation))?;
}
+ Block::AdvancedReference {
+ translation,
+ transform,
+ value_scale,
+ } => {
+ sink.put(3u8)?;
+ sink.put((*translation, *transform, *value_scale))?;
+ }
}
Ok(())
}
@@ -56,6 +71,11 @@ impl Block {
2 => Block::Reference {
translation: source.get::<Small<Vec2<isize>>>()?.0,
},
+ 3 => Block::AdvancedReference {
+ translation: source.get()?,
+ transform: source.get()?,
+ value_scale: source.get()?,
+ },
x => bail!("corrupt block type ({})", x),
})
}
diff --git a/evc/src/codec/decode.rs b/evc/src/codec/decode.rs
index e6fa918..2da320f 100644
--- a/evc/src/codec/decode.rs
+++ b/evc/src/codec/decode.rs
@@ -10,5 +10,10 @@ pub fn decode_block(block: &Block, mut target: View<&mut Frame>, prev: View<&Fra
decode_block(b, bt, bp);
}
Block::Reference { translation } => target.copy_from(&prev.offset(*translation)),
+ Block::AdvancedReference {
+ translation: _,
+ transform: _,
+ value_scale: _,
+ } => todo!(),
}
}
diff --git a/evc/src/codec/encode.rs b/evc/src/codec/encode.rs
index b11bbc0..5ce0b16 100644
--- a/evc/src/codec/encode.rs
+++ b/evc/src/codec/encode.rs
@@ -4,48 +4,70 @@ use crate::{
helpers::{pixel::Pixel, threading::both_par, vector::Vec2},
view::View,
};
+use clap::ValueEnum;
#[derive(Debug, Clone)]
pub struct EncodeConfig {
- pub translate: bool,
+ pub mode: EncodeMode,
pub ref_thres: f64,
- pub max_diff_size: isize,
+ pub max_diff_area: isize,
pub min_block_size: isize,
pub max_threads: usize,
- // pub importance_k: f64,
- // pub importance_scale: f64,
}
-pub fn encode_block(view: View<&Frame>, prev: View<&Frame>, config: &EncodeConfig) -> Block {
- // let importance = importance(&view);
+#[derive(Debug, Clone, ValueEnum)]
+pub enum EncodeMode {
+ Trivial,
+ Default,
+ Advanced,
+}
+
- let (diff, translation) = if view.area() > config.max_diff_size {
- (f64::INFINITY, Vec2::<isize>::ZERO)
- } else if config.translate {
- let mut best_diff = f64::INFINITY;
- let mut best_translation = Vec2::<isize>::ZERO;
- const OFFSETS: &[isize] = &[-64, -32, -16, -8, -4, -2, -1, 0, 1, 2, 4, 8, 16, 32, 64];
- for x in OFFSETS {
- for y in OFFSETS {
- let translation = Vec2 { x: *x, y: *y };
- let diff = View::diff(&view, &prev.offset(translation)); // / view.area() as f64;
- if diff < best_diff {
- best_translation = translation;
- best_diff = diff;
+pub fn encode_block(view: View<&Frame>, prev: View<&Frame>, config: &EncodeConfig) -> Block {
+ let (diff, refblock) = if view.area() > config.max_diff_area {
+ (
+ f64::INFINITY,
+ Block::Reference {
+ translation: Vec2::<isize>::ZERO,
+ },
+ )
+ } else {
+ match config.mode {
+ EncodeMode::Trivial => (
+ View::diff(&view, &prev) / view.area() as f64,
+ Block::Reference {
+ translation: Vec2::<isize>::ZERO,
+ },
+ ),
+ EncodeMode::Default => {
+ let mut best_diff = f64::INFINITY;
+ let mut best_translation = Vec2::<isize>::ZERO;
+ const OFFSETS: &[isize] =
+ &[-64, -32, -16, -8, -4, -2, -1, 0, 1, 2, 4, 8, 16, 32, 64];
+ for x in OFFSETS {
+ for y in OFFSETS {
+ let translation = Vec2 { x: *x, y: *y };
+ let diff = View::diff(&view, &prev.offset(translation)); // / view.area() as f64;
+ if diff < best_diff {
+ best_translation = translation;
+ best_diff = diff;
+ }
+ }
}
+ (
+ best_diff,
+ Block::Reference {
+ translation: best_translation,
+ },
+ )
+ }
+ EncodeMode::Advanced => {
+ todo!()
}
}
- (best_diff, best_translation)
- } else {
- (
- View::diff(&view, &prev) / view.area() as f64,
- Vec2::<isize>::ZERO,
- )
};
- // config.importance_k)
- // / (config.importance_k + importance * config.importance_scale)
- if diff < (config.ref_thres) {
- Block::Reference { translation }
+ if diff < config.ref_thres {
+ refblock
} else {
if view.size.x < config.min_block_size || view.size.y < config.min_block_size {
Block::Literal(view.pixels())
diff --git a/evc/src/format/ser.rs b/evc/src/format/ser.rs
index 65d5e26..731a7a3 100644
--- a/evc/src/format/ser.rs
+++ b/evc/src/format/ser.rs
@@ -1,7 +1,7 @@
use anyhow::Context;
use std::io::{Read, Write};
-use crate::helpers::vector::Vec2;
+use crate::helpers::{matrix::Mat2, vector::Vec2};
pub trait Sink {
fn put<V: Ser>(&mut self, value: V) -> anyhow::Result<()>;
@@ -49,6 +49,24 @@ impl<A: Ser, B: Ser, C: Ser> Ser for (A, B, C) {
Ok((A::read(source)?, B::read(source)?, C::read(source)?))
}
}
+impl<A: Ser, B: Ser, C: Ser, D: Ser> Ser for (A, B, C, D) {
+ fn write(&self, sink: &mut impl Write) -> anyhow::Result<()> {
+ self.0.write(sink).context("first tuple field")?;
+ self.1.write(sink).context("second tuple field")?;
+ self.2.write(sink).context("third tuple field")?;
+ self.3.write(sink).context("fourth tuple field")?;
+ Ok(())
+ }
+
+ fn read(source: &mut impl Read) -> anyhow::Result<Self> {
+ Ok((
+ A::read(source)?,
+ B::read(source)?,
+ C::read(source)?,
+ D::read(source)?,
+ ))
+ }
+}
impl<A: Ser, const N: usize> Ser for [A; N] {
fn write(&self, sink: &mut impl Write) -> anyhow::Result<()> {
@@ -192,8 +210,7 @@ impl Ser for f64 {
}
}
-
-impl Ser for Vec2<isize> {
+impl<T: Ser + Copy> Ser for Vec2<T> {
fn write(&self, sink: &mut impl std::io::Write) -> anyhow::Result<()> {
sink.put((self.x, self.y))
}
@@ -203,6 +220,16 @@ impl Ser for Vec2<isize> {
Ok(Vec2 { x, y })
}
}
+impl<T: Ser + Copy> Ser for Mat2<T> {
+ fn write(&self, sink: &mut impl std::io::Write) -> anyhow::Result<()> {
+ sink.put((self.a, self.b, self.c, self.d))
+ }
+
+ fn read(source: &mut impl std::io::Read) -> anyhow::Result<Self> {
+ let (a, b, c, d) = source.get()?;
+ Ok(Mat2 { a, b, c, d })
+ }
+}
pub struct Small<T>(pub T);
impl Ser for Small<Vec2<isize>> {
@@ -219,7 +246,6 @@ impl Ser for Small<Vec2<isize>> {
}
}
-
#[cfg(test)]
mod test {
use super::{Ser, Sink};
diff --git a/evc/src/helpers/matrix.rs b/evc/src/helpers/matrix.rs
index 74d2ae4..92f46b2 100644
--- a/evc/src/helpers/matrix.rs
+++ b/evc/src/helpers/matrix.rs
@@ -1,10 +1,11 @@
use crate::helpers::vector::Vec2;
+#[derive(Debug, Clone, Copy)]
pub struct Mat2<T> {
- a: T,
- b: T,
- c: T,
- d: T,
+ pub a: T,
+ pub b: T,
+ pub c: T,
+ pub d: T,
}
impl<T: std::ops::Mul<Output = T> + std::ops::Add<Output = T> + Copy> Mat2<T> {
diff --git a/evc/src/refsampler.rs b/evc/src/refsampler.rs
index db0ab6f..b27ceae 100644
--- a/evc/src/refsampler.rs
+++ b/evc/src/refsampler.rs
@@ -13,6 +13,7 @@ pub struct Sampler<'a> {
}
impl Sampler<'_> {
+ #[inline]
pub fn sample(&self, p: Vec2<f32>) -> Pixel {
self.frame
.sample(self.translation + self.transform.transform(p))