aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormetamuffin <metamuffin@disroot.org>2022-12-17 18:01:51 +0100
committermetamuffin <metamuffin@disroot.org>2022-12-17 18:01:51 +0100
commit0a346b8372140b56bf65a6df1c00e2cd6c6cdf86 (patch)
treee52234d5904939323e19586128d8ac2d345e450e
parent82eedf3594bf21c8b780580050a95f0bdb5fd667 (diff)
downloadvideo-codec-experiments-0a346b8372140b56bf65a6df1c00e2cd6c6cdf86.tar
video-codec-experiments-0a346b8372140b56bf65a6df1c00e2cd6c6cdf86.tar.bz2
video-codec-experiments-0a346b8372140b56bf65a6df1c00e2cd6c6cdf86.tar.zst
small optimizations and info binary
-rwxr-xr-xevc/scripts/bench_modes5
-rwxr-xr-xevc/scripts/bench_out10
-rw-r--r--evc/src/bin/encode.rs2
-rw-r--r--evc/src/bin/info.rs11
-rw-r--r--evc/src/block.rs28
-rw-r--r--evc/src/codec/decode.rs1
-rw-r--r--evc/src/codec/encode/mod.rs16
-rw-r--r--evc/src/codec/encode/simple.rs5
-rw-r--r--evc/src/debug.rs2
-rw-r--r--evc/src/frame.rs7
-rw-r--r--evc/src/helpers/matrix.rs2
-rw-r--r--evc/src/helpers/pixel.rs9
12 files changed, 63 insertions, 35 deletions
diff --git a/evc/scripts/bench_modes b/evc/scripts/bench_modes
index 7cc6abd..9fa17f6 100755
--- a/evc/scripts/bench_modes
+++ b/evc/scripts/bench_modes
@@ -4,14 +4,15 @@ set h $argv[2]
set t $argv[3]
ffmpeg -hide_banner -i $argv[4] -to {$t} -vf scale={$w}x{$h},fps=30,format=rgb24 -f rawvideo pipe:1 >samples/raw
-ffmpeg -hide_banner -y -i $argv[4] -to {$t} -vf scale={$w}x{$h},fps=30,format=rgb24 -c:v vp9 samples/reference.webm
+# ffmpeg -hide_banner -y -i $argv[4] -to {$t} -vf scale={$w}x{$h},fps=30,format=rgb24 -c:v vp9 samples/reference.webm
echo
echo "file: "$argv[4]
echo "resolution: "{$w}x{$h}
echo "frames: "(math $t \* 30)
echo "reference (raw): "(du -h samples/raw | cut -f 1)
-echo "reference (vp8): "(du -h samples/reference.webm | cut -f 1)
+echo "reference (input): "(du -h $argv[4] | cut -f 1)
+# echo "reference (vp8): "(du -h samples/reference.webm | cut -f 1)
for mode in trivial simple-exhaustive simple-fast advanced advanced-partial
echo -----------
echo "mode: $mode"
diff --git a/evc/scripts/bench_out b/evc/scripts/bench_out
new file mode 100755
index 0000000..5bb0639
--- /dev/null
+++ b/evc/scripts/bench_out
@@ -0,0 +1,10 @@
+#!/bin/fish
+set w $argv[1]
+set h $argv[2]
+
+for mode in trivial simple-exhaustive simple-fast advanced advanced-partial
+ cargo run --release --bin decode -- --debug < samples/encoded-$mode |
+ ffmpeg -y -hide_banner -framerate 25 -video_size {$w}x{$h} -pixel_format rgb24 -f rawvideo -i pipe:0 samples/decoded-$mode-debug.mp4
+ cargo run --release --bin decode -- < samples/encoded-$mode |
+ ffmpeg -y -hide_banner -framerate 25 -video_size {$w}x{$h} -pixel_format rgb24 -f rawvideo -i pipe:0 samples/decoded-$mode.mp4
+end
diff --git a/evc/src/bin/encode.rs b/evc/src/bin/encode.rs
index c9d8792..32af242 100644
--- a/evc/src/bin/encode.rs
+++ b/evc/src/bin/encode.rs
@@ -26,7 +26,7 @@ pub struct EncodeArgs {
#[arg(short, long, default_value = "8")]
jobs: usize,
- #[arg(short, long, default_value = "8")]
+ #[arg(short, long, default_value = "4")]
min_block_size: isize,
#[arg(short = 't', long, default_value = "200")]
diff --git a/evc/src/bin/info.rs b/evc/src/bin/info.rs
new file mode 100644
index 0000000..1e1472a
--- /dev/null
+++ b/evc/src/bin/info.rs
@@ -0,0 +1,11 @@
+use std::io::BufReader;
+
+use anyhow::Context;
+use evc::format::{header::Header, ser::Source};
+
+fn main() {
+ env_logger::init_from_env("LOG");
+ let mut input = BufReader::new(std::io::stdin());
+ let header = input.get::<Header>().context("reading header").unwrap();
+ eprintln!("{header:#?}")
+}
diff --git a/evc/src/block.rs b/evc/src/block.rs
index 8d7686f..cbf69bf 100644
--- a/evc/src/block.rs
+++ b/evc/src/block.rs
@@ -5,15 +5,16 @@ use crate::{
};
use anyhow::bail;
-#[derive(Clone, Debug)]
+#[derive(Clone, Debug, PartialEq)]
pub enum Block {
Literal(Vec<Pixel>),
+ CompressedLiteral(Vec<Pixel>),
Split(Box<[Block; 2]>),
Reference { translation: Vec2<isize> },
AdvancedReference(AdvancedReference),
}
-#[derive(Clone, Debug)]
+#[derive(Clone, Debug, PartialEq)]
pub struct AdvancedReference {
pub translation: Vec2<i8>,
pub transform: Mat2<i8>,
@@ -31,14 +32,15 @@ impl Block {
sink.put(0u8)?;
pixels.write_const_size(sink, size.area() as usize)?;
}
+ Block::CompressedLiteral(_) => bail!("compressed literal is not supported"),
Block::Split(box [a, b]) => {
- sink.put(1u8)?;
+ sink.put(2u8)?;
let [asize, bsize] = split_size(size);
a.write(sink, asize)?;
b.write(sink, bsize)?;
}
Block::Reference { translation } => {
- sink.put(2u8)?;
+ sink.put(3u8)?;
sink.put(Small(*translation))?;
}
Block::AdvancedReference(AdvancedReference {
@@ -46,7 +48,7 @@ impl Block {
transform,
value_scale,
}) => {
- sink.put(3u8)?;
+ sink.put(4u8)?;
sink.put((*translation, *transform, *value_scale))?;
}
}
@@ -56,16 +58,17 @@ impl Block {
pub fn read(source: &mut impl std::io::Read, size: Vec2<isize>) -> anyhow::Result<Self> {
Ok(match source.get::<u8>()? {
0 => Block::Literal(Vec::read_const_size(source, size.area() as usize)?),
- 1 => Block::Split(Box::new({
+ 1 => bail!("compressed literal is not supported"),
+ 2 => Block::Split(Box::new({
let [asize, bsize] = split_size(size);
let a = Block::read(source, asize)?;
let b = Block::read(source, bsize)?;
[a, b]
})),
- 2 => Block::Reference {
+ 3 => Block::Reference {
translation: source.get::<Small<Vec2<isize>>>()?.0,
},
- 3 => Block::AdvancedReference(AdvancedReference {
+ 4 => Block::AdvancedReference(AdvancedReference {
translation: source.get()?,
transform: source.get()?,
value_scale: source.get()?,
@@ -95,13 +98,8 @@ impl Block {
pub fn is_literal(&self) -> bool {
matches!(self, Block::Literal(..))
}
- pub fn is_ref_without_translation(&self) -> bool {
- matches!(
- self,
- Block::Reference {
- translation: Vec2::<isize>::ZERO
- }
- )
+ pub fn identical_ref(a: &Self, b: &Self) -> bool {
+ matches!(a, Block::Reference { .. }) && a == b
}
}
diff --git a/evc/src/codec/decode.rs b/evc/src/codec/decode.rs
index 197028c..61234da 100644
--- a/evc/src/codec/decode.rs
+++ b/evc/src/codec/decode.rs
@@ -29,6 +29,7 @@ pub fn decode_block(
config.max_threads,
);
}
+ Block::CompressedLiteral(_) => todo!(),
Block::Reference { translation } => target.copy_from(&prev.offset(*translation)),
Block::AdvancedReference(r) => target.copy_from_sampler(&Sampler::from_refblock(prev, r)),
}
diff --git a/evc/src/codec/encode/mod.rs b/evc/src/codec/encode/mod.rs
index 2ccac64..336f298 100644
--- a/evc/src/codec/encode/mod.rs
+++ b/evc/src/codec/encode/mod.rs
@@ -69,15 +69,19 @@ pub fn encode_block(view: View<&Frame>, prev: View<&Frame>, config: &EncodeConfi
let config = unsafe { std::mem::transmute::<_, &'static EncodeConfig>(config) };
// only bother to do multithreading, when the block is big.
- let (a, b) = both_par(
- || encode_block(av, ap, config),
- || encode_block(bv, bp, config),
- config.max_threads,
- );
+ let (a, b) = if view.area() > 100 {
+ both_par(
+ || encode_block(av, ap, config),
+ || encode_block(bv, bp, config),
+ config.max_threads,
+ )
+ } else {
+ (encode_block(av, ap, config), encode_block(bv, bp, config))
+ };
if a.is_literal() && b.is_literal() {
Block::Literal(view.pixels())
- } else if a.is_ref_without_translation() && b.is_ref_without_translation() {
+ } else if Block::identical_ref(&a, &b) {
Block::Reference {
translation: Vec2::<isize>::ZERO,
}
diff --git a/evc/src/codec/encode/simple.rs b/evc/src/codec/encode/simple.rs
index cabbc15..2a971af 100644
--- a/evc/src/codec/encode/simple.rs
+++ b/evc/src/codec/encode/simple.rs
@@ -45,6 +45,11 @@ pub fn fast(
}
};
+ probe(offset + Vec2 { x: 8, y: 0 });
+ probe(offset + Vec2 { x: -8, y: 0 });
+ probe(offset + Vec2 { x: 0, y: 8 });
+ probe(offset + Vec2 { x: 0, y: -8 });
+
probe(offset + Vec2 { x: 1, y: 0 });
probe(offset + Vec2 { x: -1, y: 0 });
probe(offset + Vec2 { x: 0, y: 1 });
diff --git a/evc/src/debug.rs b/evc/src/debug.rs
index 99723b8..c3ea7d0 100644
--- a/evc/src/debug.rs
+++ b/evc/src/debug.rs
@@ -64,7 +64,7 @@ impl Pixel {
pub fn draw_debug(block: &Block, mut target: View<&mut Frame>) {
match &block {
- Block::Literal(_) => {
+ Block::Literal(_) | Block::CompressedLiteral(_) => {
target.draw_box(Pixel::GREEN);
}
Block::Split(box [a, b]) => {
diff --git a/evc/src/frame.rs b/evc/src/frame.rs
index 81fdf3b..78d0e73 100644
--- a/evc/src/frame.rs
+++ b/evc/src/frame.rs
@@ -63,11 +63,8 @@ impl Index<Vec2<isize>> for Frame {
type Output = Pixel;
#[inline]
fn index(&self, Vec2 { x, y }: Vec2<isize>) -> &Self::Output {
- if x >= 0 && y >= 0 && x < self.size.x && y < self.size.y {
- &self.buffer[(x + y * self.size.x) as usize]
- } else {
- &Pixel::BLACK
- }
+ &self.buffer
+ [(x.clamp(0, self.size.x - 1) + y.clamp(0, self.size.y - 1) * self.size.x) as usize]
}
}
impl IndexMut<Vec2<isize>> for Frame {
diff --git a/evc/src/helpers/matrix.rs b/evc/src/helpers/matrix.rs
index 87c0e7d..c3c120b 100644
--- a/evc/src/helpers/matrix.rs
+++ b/evc/src/helpers/matrix.rs
@@ -1,6 +1,6 @@
use crate::helpers::vector::Vec2;
-#[derive(Debug, Clone, Copy)]
+#[derive(Debug, Clone, Copy, PartialEq)]
pub struct Mat2<T> {
pub a: T,
pub b: T,
diff --git a/evc/src/helpers/pixel.rs b/evc/src/helpers/pixel.rs
index 816d7dc..39fe98c 100644
--- a/evc/src/helpers/pixel.rs
+++ b/evc/src/helpers/pixel.rs
@@ -1,6 +1,6 @@
use crate::format::ser::{Ser, Sink, Source};
-#[derive(Copy, Clone, Debug, Default)]
+#[derive(Copy, Clone, Debug, Default, PartialEq)]
pub struct Pixel {
pub r: u8,
pub g: u8,
@@ -24,11 +24,12 @@ impl Pixel {
pub fn distance(a: Pixel, b: Pixel) -> usize {
let (rd, gd, bd) = (
a.r.abs_diff(b.r) as usize,
- a.r.abs_diff(b.r) as usize,
- a.r.abs_diff(b.r) as usize,
+ a.g.abs_diff(b.g) as usize,
+ a.b.abs_diff(b.b) as usize,
);
// fast_sqrt(rd * rd + gd * gd + bd * bd)
- SQRT[rd + gd + bd]
+ // SQRT[rd + gd + bd]
+ rd + gd + bd
}
#[inline]