aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormetamuffin <metamuffin@disroot.org>2022-12-06 17:45:26 +0100
committermetamuffin <metamuffin@disroot.org>2022-12-06 17:45:26 +0100
commite3c742ff04a665c70c029f266aa0fe72e12ac72c (patch)
treee6a262a223d151afd804359e243cc5d0301e732f
parent849c3769fbd38940c9bfa73bcea160848a38d9b6 (diff)
downloadvideo-codec-experiments-e3c742ff04a665c70c029f266aa0fe72e12ac72c.tar
video-codec-experiments-e3c742ff04a665c70c029f266aa0fe72e12ac72c.tar.bz2
video-codec-experiments-e3c742ff04a665c70c029f266aa0fe72e12ac72c.tar.zst
vec2 everywhere
-rw-r--r--evc/src/bin/encode.rs6
-rw-r--r--evc/src/block.rs17
-rw-r--r--evc/src/codec/encode.rs16
-rw-r--r--evc/src/debug.rs4
-rw-r--r--evc/src/frame.rs67
-rw-r--r--evc/src/header.rs7
-rw-r--r--evc/src/lib.rs1
-rw-r--r--evc/src/pixel.rs1
-rw-r--r--evc/src/ser.rs15
-rw-r--r--evc/src/vec2.rs59
-rw-r--r--evc/src/view.rs142
11 files changed, 249 insertions, 86 deletions
diff --git a/evc/src/bin/encode.rs b/evc/src/bin/encode.rs
index acd6e92..05ebd24 100644
--- a/evc/src/bin/encode.rs
+++ b/evc/src/bin/encode.rs
@@ -5,6 +5,7 @@ use evc::{
frame::Frame,
header::Header,
ser::Sink,
+ vec2::Vec2,
};
use log::info;
use std::io::{BufReader, BufWriter};
@@ -25,7 +26,10 @@ fn main() -> anyhow::Result<()> {
let mut input = BufReader::new(std::io::stdin());
let mut output = BufWriter::new(std::io::stdout());
- let size = (args.width, args.height);
+ let size = Vec2 {
+ x: args.width as isize,
+ y: args.height as isize,
+ };
output
.put(Header {
resolution: size,
diff --git a/evc/src/block.rs b/evc/src/block.rs
index 8daba5c..d0dd4d5 100644
--- a/evc/src/block.rs
+++ b/evc/src/block.rs
@@ -3,13 +3,14 @@ use anyhow::bail;
use crate::{
pixel::Pixel,
ser::{Ser, Sink, Source},
+ vec2::Vec2,
};
#[derive(Clone, Debug)]
pub enum Block {
Literal(Vec<Pixel>),
Split(Box<[Block; 2]>),
- Reference { translation: (usize, usize) },
+ Reference { translation: Vec2 },
}
impl Block {
@@ -32,20 +33,20 @@ impl Block {
Ok(())
}
- pub fn read(source: &mut impl std::io::Read, size: (usize, usize)) -> anyhow::Result<Self> {
+ pub fn read(source: &mut impl std::io::Read, size: Vec2) -> anyhow::Result<Self> {
Ok(match source.get::<u8>()? {
0 => Block::Literal(source.get()?),
1 => Block::Split(Box::new({
- let vert = size.0 > size.1;
+ let vert = size.x > size.y;
let asize = if vert {
- (size.0 / 2, size.1)
+ (size.x / 2, size.y).into()
} else {
- (size.0, size.1 / 2)
+ (size.x, size.y / 2).into()
};
let bsize = if vert {
- (size.0 - size.0 / 2, size.1)
+ (size.x - size.x / 2, size.y).into()
} else {
- (size.0, size.1 - size.1 / 2)
+ (size.x, size.y - size.y / 2).into()
};
let a = Block::read(source, asize)?;
@@ -53,7 +54,7 @@ impl Block {
[a, b]
})),
2 => Block::Reference {
- translation: (0, 0), //source.get()?,
+ translation: Vec2::ZERO, //source.get()?,
},
x => bail!("corrupt block type ({})", x),
})
diff --git a/evc/src/codec/encode.rs b/evc/src/codec/encode.rs
index 43a2783..7256265 100644
--- a/evc/src/codec/encode.rs
+++ b/evc/src/codec/encode.rs
@@ -1,14 +1,22 @@
-use crate::{block::Block, frame::Frame, view::View};
+use crate::{block::Block, frame::Frame, view::View, vec2::Vec2};
pub fn encode_block(view: View<&Frame>, prev: View<&Frame>) -> Block {
+ // let mut best_diff = f64::INFINITY;
+ // for x in [-32, -16, -8, -4, -2, -1, 0, 1, 2, 4, 8, 16, 32] {
+ // for y in [-32, -16, -8, -4, -2, -1, 0, 1, 2, 4, 8, 16, 32] {
+ // let diff = View::diff(&view, &prev) / view.area() as f64;
+ // if diff < best_diff {
+ // }
+ // }
+ // }
let diff = View::diff(&view, &prev) / view.area() as f64;
- // eprintln!("{:?} {diff}", view.size);
+ // if best_diff < 0.9 {
if diff < 0.9 {
Block::Reference {
- translation: (0, 0),
+ translation: Vec2::ZERO,
}
} else {
- if view.size.0 < 16 {
+ if view.size.x < 16 {
Block::Literal(view.pixels())
} else {
let [av, bv] = view.split();
diff --git a/evc/src/debug.rs b/evc/src/debug.rs
index 44b51cf..7b27b83 100644
--- a/evc/src/debug.rs
+++ b/evc/src/debug.rs
@@ -2,8 +2,8 @@ use crate::{frame::Frame, pixel::Pixel, view::View};
impl View<&mut Frame> {
pub fn draw_box(&mut self, color: Pixel) {
- let w = self.size.0;
- let h = self.size.1;
+ let w = self.size.x;
+ let h = self.size.y;
for x in 0..w {
self[(x, 0)] = color;
self[(x, h - 1)] = color;
diff --git a/evc/src/frame.rs b/evc/src/frame.rs
index 666dc00..81390a2 100644
--- a/evc/src/frame.rs
+++ b/evc/src/frame.rs
@@ -1,29 +1,28 @@
use crate::{
pixel::Pixel,
ser::{Sink, Source},
+ vec2::Vec2,
view::View,
};
use std::ops::{Index, IndexMut};
#[derive(Debug, Clone)]
pub struct Frame {
- pub size: (usize, usize),
- buffer: Vec<Vec<Pixel>>,
+ pub size: Vec2,
+ buffer: Vec<Pixel>,
}
impl Frame {
- pub fn new(size: (usize, usize)) -> Self {
+ pub fn new(size: Vec2) -> Self {
Self {
size,
- buffer: (0..size.0)
- .map(|_| (0..size.1).map(|_| Pixel::default()).collect())
- .collect(),
+ buffer: (0..size.x * size.y).map(|_| Pixel::default()).collect(),
}
}
- pub fn read(source: &mut impl Source, size: (usize, usize)) -> anyhow::Result<Self> {
+ pub fn read(source: &mut impl Source, size: Vec2) -> anyhow::Result<Self> {
let mut frame = Frame::new(size);
- for y in 0..size.1 {
- for x in 0..size.0 {
+ for y in 0..size.y {
+ for x in 0..size.x {
let pixel = source.get::<Pixel>()?;
frame[(x, y)] = pixel;
}
@@ -31,45 +30,55 @@ impl Frame {
Ok(frame)
}
pub fn write(&self, sink: &mut impl Sink) -> anyhow::Result<()> {
- for y in 0..self.size.1 {
- for x in 0..self.size.0 {
+ for y in 0..self.size.y {
+ for x in 0..self.size.x {
sink.put(self[(x, y)])?;
}
}
Ok(())
}
pub fn view<'a>(&'a self) -> View<&'a Frame> {
- View::new(self, (0, 0), self.size)
+ View::new(self, Vec2::ZERO, self.size)
}
pub fn view_mut<'a>(&'a mut self) -> View<&'a mut Frame> {
- View::new(self, (0, 0), self.size)
+ View::new(self, Vec2::ZERO, self.size)
}
- pub fn view_area<'a>(
- &'a self,
- offset: (usize, usize),
- size: (usize, usize),
- ) -> View<&'a Frame> {
+ pub fn view_area<'a>(&'a self, offset: Vec2, size: Vec2) -> View<&'a Frame> {
View::new(self, offset, size)
}
- pub fn view_area_mut<'a>(
- &'a mut self,
- offset: (usize, usize),
- size: (usize, usize),
- ) -> View<&'a mut Frame> {
+ pub fn view_area_mut<'a>(&'a mut self, offset: Vec2, size: Vec2) -> View<&'a mut Frame> {
View::new(self, offset, size)
}
}
-impl Index<(usize, usize)> for Frame {
+impl Index<Vec2> for Frame {
type Output = Pixel;
#[inline]
- fn index(&self, (x, y): (usize, usize)) -> &Self::Output {
- &self.buffer[x][y]
+ fn index(&self, Vec2 { x, y }: Vec2) -> &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
+ }
+ }
+}
+impl IndexMut<Vec2> for Frame {
+ #[inline]
+ fn index_mut(&mut self, Vec2 { x, y }: Vec2) -> &mut Self::Output {
+ &mut self.buffer[(x + y * self.size.x) as usize]
+ }
+}
+
+impl Index<(isize, isize)> for Frame {
+ type Output = Pixel;
+ #[inline]
+ fn index(&self, (x, y): (isize, isize)) -> &Self::Output {
+ &self[Vec2 { x, y }]
}
}
-impl IndexMut<(usize, usize)> for Frame {
+impl IndexMut<(isize, isize)> for Frame {
#[inline]
- fn index_mut(&mut self, (x, y): (usize, usize)) -> &mut Self::Output {
- &mut self.buffer[x][y]
+ fn index_mut(&mut self, (x, y): (isize, isize)) -> &mut Self::Output {
+ &mut self[Vec2 { x, y }]
}
}
diff --git a/evc/src/header.rs b/evc/src/header.rs
index 5244ce5..a613627 100644
--- a/evc/src/header.rs
+++ b/evc/src/header.rs
@@ -1,8 +1,11 @@
-use crate::ser::{Ser, Sink, Source};
+use crate::{
+ ser::{Ser, Sink, Source},
+ vec2::Vec2,
+};
#[derive(Debug, Clone, PartialEq, Copy)]
pub struct Header {
- pub resolution: (usize, usize),
+ pub resolution: Vec2,
pub frame_count: usize,
}
diff --git a/evc/src/lib.rs b/evc/src/lib.rs
index a513116..ee242e6 100644
--- a/evc/src/lib.rs
+++ b/evc/src/lib.rs
@@ -8,3 +8,4 @@ pub mod header;
pub mod pixel;
pub mod ser;
pub mod view;
+pub mod vec2;
diff --git a/evc/src/pixel.rs b/evc/src/pixel.rs
index aaf8d83..b3ef841 100644
--- a/evc/src/pixel.rs
+++ b/evc/src/pixel.rs
@@ -19,6 +19,7 @@ impl Ser for Pixel {
}
impl Pixel {
+ pub const BLACK: Pixel = Pixel { r: 0, g: 0, b: 0 };
#[inline]
pub fn distance(a: Pixel, b: Pixel) -> f64 {
let (rd, gd, bd) = (
diff --git a/evc/src/ser.rs b/evc/src/ser.rs
index 3b7814f..61ca684 100644
--- a/evc/src/ser.rs
+++ b/evc/src/ser.rs
@@ -141,6 +141,18 @@ impl Ser for usize {
Ok(unsafe { std::mem::transmute_copy(&buf) })
}
}
+impl Ser for isize {
+ fn write(&self, sink: &mut impl Write) -> anyhow::Result<()> {
+ Ok(sink
+ .write_all(&unsafe { std::mem::transmute_copy::<_, [u8; 8]>(self) })
+ .context("write isize")?)
+ }
+ fn read(source: &mut impl Read) -> anyhow::Result<Self> {
+ let mut buf = [0u8; 8];
+ source.read_exact(&mut buf)?;
+ Ok(unsafe { std::mem::transmute_copy(&buf) })
+ }
+}
impl Ser for f32 {
fn write(&self, sink: &mut impl Write) -> anyhow::Result<()> {
Ok(sink
@@ -171,6 +183,7 @@ mod test {
use super::{Ser, Sink};
use crate::header::Header;
use crate::ser::Source;
+ use crate::vec2::Vec2;
use std::fmt::Debug;
use std::io::Cursor;
@@ -196,7 +209,7 @@ mod test {
fn header() {
test_ser(Header {
frame_count: 123,
- resolution: (13, 37),
+ resolution: Vec2 { x: 13, y: 37 },
});
}
#[test]
diff --git a/evc/src/vec2.rs b/evc/src/vec2.rs
new file mode 100644
index 0000000..ffee124
--- /dev/null
+++ b/evc/src/vec2.rs
@@ -0,0 +1,59 @@
+use crate::ser::{Ser, Sink, Source};
+
+#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
+pub struct Vec2 {
+ pub x: isize,
+ pub y: isize,
+}
+impl Vec2 {
+ pub const ZERO: Vec2 = Vec2 { x: 0, y: 0 };
+}
+
+impl Ser for Vec2 {
+ fn write(&self, sink: &mut impl std::io::Write) -> anyhow::Result<()> {
+ sink.put((self.x, self.y))
+ }
+
+ fn read(source: &mut impl std::io::Read) -> anyhow::Result<Self> {
+ let (x, y) = source.get()?;
+ Ok(Vec2 { x, y })
+ }
+}
+
+impl std::ops::Add for Vec2 {
+ type Output = Vec2;
+ #[inline]
+ fn add(self, rhs: Self) -> Self::Output {
+ Vec2 {
+ x: self.x + rhs.x,
+ y: self.y + rhs.y,
+ }
+ }
+}
+impl std::ops::Sub for Vec2 {
+ type Output = Vec2;
+ #[inline]
+ fn sub(self, rhs: Self) -> Self::Output {
+ Vec2 {
+ x: self.x - rhs.x,
+ y: self.y - rhs.y,
+ }
+ }
+}
+impl std::ops::Mul for Vec2 {
+ type Output = Vec2;
+ #[inline]
+ fn mul(self, rhs: Self) -> Self::Output {
+ Vec2 {
+ x: self.x * rhs.x,
+ y: self.y * rhs.y,
+ }
+ }
+}
+
+impl From<(isize, isize)> for Vec2 {
+ #[inline]
+ fn from((x, y): (isize, isize)) -> Self {
+ Vec2 { x, y }
+ }
+}
diff --git a/evc/src/view.rs b/evc/src/view.rs
index 9c4778b..4cd4a45 100644
--- a/evc/src/view.rs
+++ b/evc/src/view.rs
@@ -1,89 +1,132 @@
-use crate::{frame::Frame, pixel::Pixel};
+use crate::{frame::Frame, pixel::Pixel, vec2::Vec2};
use std::ops::{Index, IndexMut};
pub struct View<T> {
pub frame: T,
- pub offset: (usize, usize),
- pub size: (usize, usize),
+ pub offset: Vec2,
+ pub size: Vec2,
}
impl<T> View<T> {
- pub fn new(frame: T, offset: (usize, usize), size: (usize, usize)) -> Self {
+ pub fn new(frame: T, offset: Vec2, size: Vec2) -> Self {
Self {
frame,
offset,
size,
}
}
- pub fn area(&self) -> usize {
- self.size.0 * self.size.1
+ pub fn area(&self) -> isize {
+ self.size.x * self.size.y
}
}
impl<T> View<&mut T> {
pub fn split_mut_unsafe(&mut self) -> [Self; 2] {
- let vert = self.size.0 > self.size.1;
+ let vert = self.size.x > self.size.y;
[
Self {
frame: unsafe { std::mem::transmute::<&mut T, &mut T>(&mut self.frame) },
offset: self.offset,
size: if vert {
- (self.size.0 / 2, self.size.1)
+ Vec2 {
+ x: self.size.x / 2,
+ y: self.size.y,
+ }
} else {
- (self.size.0, self.size.1 / 2)
+ Vec2 {
+ x: self.size.x,
+ y: self.size.y / 2,
+ }
},
},
Self {
frame: unsafe { std::mem::transmute::<&mut T, &mut T>(&mut self.frame) },
offset: if vert {
- (self.offset.0 + self.size.0 / 2, self.offset.1)
+ Vec2 {
+ x: self.offset.x + self.size.x / 2,
+ y: self.offset.y,
+ }
} else {
- (self.offset.0, self.offset.1 + self.size.1 / 2)
+ Vec2 {
+ x: self.offset.x,
+ y: self.offset.y + self.size.y / 2,
+ }
},
size: if vert {
- (self.size.0 - self.size.0 / 2, self.size.1)
+ Vec2 {
+ x: self.size.x - self.size.x / 2,
+ y: self.size.y,
+ }
} else {
- (self.size.0, self.size.1 - self.size.1 / 2)
+ Vec2 {
+ x: self.size.x,
+ y: self.size.y - self.size.y / 2,
+ }
},
},
]
}
}
impl<T: Copy> View<T> {
+ pub fn offset(&self, offset: Vec2) -> Self {
+ Self {
+ frame: self.frame,
+ offset: self.offset + offset,
+ size: self.size,
+ }
+ }
pub fn split(&self) -> [Self; 2] {
- let vert = self.size.0 > self.size.1;
+ let vert = self.size.x > self.size.y;
[
Self {
frame: self.frame,
offset: self.offset,
size: if vert {
- (self.size.0 / 2, self.size.1)
+ Vec2 {
+ x: self.size.x / 2,
+ y: self.size.y,
+ }
} else {
- (self.size.0, self.size.1 / 2)
+ Vec2 {
+ x: self.size.x,
+ y: self.size.y / 2,
+ }
},
},
Self {
frame: self.frame,
offset: if vert {
- (self.offset.0 + self.size.0 / 2, self.offset.1)
+ Vec2 {
+ x: self.offset.x + self.size.x / 2,
+ y: self.offset.y,
+ }
} else {
- (self.offset.0, self.offset.1 + self.size.1 / 2)
+ Vec2 {
+ x: self.offset.x,
+ y: self.offset.y + self.size.y / 2,
+ }
},
size: if vert {
- (self.size.0 - self.size.0 / 2, self.size.1)
+ Vec2 {
+ x: self.size.x - self.size.x / 2,
+ y: self.size.y,
+ }
} else {
- (self.size.0, self.size.1 - self.size.1 / 2)
+ Vec2 {
+ x: self.size.x,
+ y: self.size.y - self.size.y / 2,
+ }
},
},
]
}
}
-impl<T: Index<(usize, usize), Output = Pixel>> View<&T> {
+impl<T: Index<Vec2, Output = Pixel>> View<&T> {
pub fn diff(va: &Self, vb: &Self) -> f64 {
assert_eq!(va.size, vb.size);
let mut acc = 0.0;
- for x in 0..va.size.0 {
- for y in 0..va.size.1 {
+ for x in 0..va.size.x {
+ for y in 0..va.size.y {
let a = va[(x, y)];
let b = vb[(x, y)];
acc += Pixel::distance(a, b);
@@ -93,8 +136,8 @@ impl<T: Index<(usize, usize), Output = Pixel>> View<&T> {
}
pub fn pixels(&self) -> Vec<Pixel> {
let mut v = vec![];
- for x in 0..self.size.0 {
- for y in 0..self.size.1 {
+ for x in 0..self.size.x {
+ for y in 0..self.size.y {
v.push(self[(x, y)]);
}
}
@@ -103,38 +146,59 @@ impl<T: Index<(usize, usize), Output = Pixel>> View<&T> {
}
impl View<&mut Frame> {
pub fn copy_from(&mut self, other: &View<&Frame>) {
- for x in 0..self.size.0 {
- for y in 0..self.size.1 {
+ for x in 0..self.size.x {
+ for y in 0..self.size.y {
self[(x, y)] = other[(x, y)];
}
}
}
pub fn set_pixels(&mut self, pixels: &Vec<Pixel>) {
- for x in 0..self.size.0 {
- for y in 0..self.size.1 {
- self[(x, y)] = pixels[x * self.size.1 + y]
+ for x in 0..self.size.x {
+ for y in 0..self.size.y {
+ self[(x, y)] = pixels[(x * self.size.y + y) as usize]
}
}
}
}
-impl<T: Index<(usize, usize), Output = Pixel>> Index<(usize, usize)> for View<&T> {
+impl<T: Index<Vec2, Output = Pixel>> Index<Vec2> for View<&T> {
+ type Output = Pixel;
+ #[inline]
+ fn index(&self, p: Vec2) -> &Self::Output {
+ &self.frame[self.offset + p]
+ }
+}
+impl<T: Index<Vec2, Output = Pixel>> Index<Vec2> for View<&mut T> {
+ type Output = Pixel;
+ #[inline]
+ fn index(&self, p: Vec2) -> &Self::Output {
+ &self.frame[self.offset + p]
+ }
+}
+impl<T: IndexMut<Vec2, Output = Pixel>> IndexMut<Vec2> for View<&mut T> {
+ #[inline]
+ fn index_mut(&mut self, p: Vec2) -> &mut Self::Output {
+ &mut self.frame[self.offset + p]
+ }
+}
+
+impl<T: Index<Vec2, Output = Pixel>> Index<(isize, isize)> for View<&T> {
type Output = Pixel;
#[inline]
- fn index(&self, (x, y): (usize, usize)) -> &Self::Output {
- &self.frame[(x + self.offset.0, y + self.offset.1)]
+ fn index(&self, (x, y): (isize, isize)) -> &Self::Output {
+ &self[Vec2 { x, y }]
}
}
-impl<T: Index<(usize, usize), Output = Pixel>> Index<(usize, usize)> for View<&mut T> {
+impl<T: Index<Vec2, Output = Pixel>> Index<(isize, isize)> for View<&mut T> {
type Output = Pixel;
#[inline]
- fn index(&self, (x, y): (usize, usize)) -> &Self::Output {
- &self.frame[(x + self.offset.0, y + self.offset.1)]
+ fn index(&self, (x, y): (isize, isize)) -> &Self::Output {
+ &self[Vec2 { x, y }]
}
}
-impl<T: IndexMut<(usize, usize), Output = Pixel>> IndexMut<(usize, usize)> for View<&mut T> {
+impl<T: IndexMut<Vec2, Output = Pixel>> IndexMut<(isize, isize)> for View<&mut T> {
#[inline]
- fn index_mut(&mut self, (x, y): (usize, usize)) -> &mut Self::Output {
- &mut self.frame[(x + self.offset.0, y + self.offset.1)]
+ fn index_mut(&mut self, (x, y): (isize, isize)) -> &mut Self::Output {
+ &mut self[Vec2 { x, y }]
}
}