aboutsummaryrefslogtreecommitdiff
path: root/evc
diff options
context:
space:
mode:
authormetamuffin <metamuffin@disroot.org>2022-12-06 07:47:51 +0100
committermetamuffin <metamuffin@disroot.org>2022-12-06 07:47:51 +0100
commitbafb1df8b7764a0a62f1c656eb52fbe7bfd8b8ac (patch)
tree0e824b9f85ba80ca0082fc8d8ec8bf96bf411823 /evc
parentcace782584d19674f70351f462e746d3d589ba90 (diff)
downloadvideo-codec-experiments-bafb1df8b7764a0a62f1c656eb52fbe7bfd8b8ac.tar
video-codec-experiments-bafb1df8b7764a0a62f1c656eb52fbe7bfd8b8ac.tar.bz2
video-codec-experiments-bafb1df8b7764a0a62f1c656eb52fbe7bfd8b8ac.tar.zst
decoder
Diffstat (limited to 'evc')
-rw-r--r--evc/.gitignore1
-rw-r--r--evc/src/bin/decode.rs60
-rw-r--r--evc/src/bin/encode.rs13
-rw-r--r--evc/src/frame.rs27
-rw-r--r--evc/src/header.rs5
-rw-r--r--evc/src/ser.rs20
-rw-r--r--evc/src/view.rs93
7 files changed, 192 insertions, 27 deletions
diff --git a/evc/.gitignore b/evc/.gitignore
index ea8c4bf..0f285c7 100644
--- a/evc/.gitignore
+++ b/evc/.gitignore
@@ -1 +1,2 @@
/target
+/samples
diff --git a/evc/src/bin/decode.rs b/evc/src/bin/decode.rs
new file mode 100644
index 0000000..293181a
--- /dev/null
+++ b/evc/src/bin/decode.rs
@@ -0,0 +1,60 @@
+#![feature(box_patterns)]
+use std::io::{self, BufReader, BufWriter};
+
+use clap::Parser;
+use evc::{
+ block::{Block, BlockInner},
+ frame::Frame,
+ header::Header,
+ ser::Source,
+ view::View,
+};
+
+#[derive(Parser)]
+#[clap(about, version)]
+pub struct DecodeArgs {}
+
+fn main() -> io::Result<()> {
+ let _args = DecodeArgs::parse();
+
+ let mut input = BufReader::new(std::io::stdin());
+ let mut output = BufWriter::new(std::io::stdout());
+
+ let header = input.get::<Header>()?;
+ eprintln!("{header:?}");
+ let size = header.resolution;
+
+ let mut prev = Frame::new(size);
+ loop {
+ let block = Block::read(&mut input, size)?;
+ let mut frame = Frame::new(size);
+
+ blit_block(
+ &block,
+ frame.view_mut((0, 0), size),
+ prev.view((0, 0), size),
+ );
+
+ frame.write(&mut output)?;
+ prev = frame;
+ }
+}
+
+fn blit_block(block: &Block, mut target: View<&mut Frame>, prev: View<&Frame>) {
+ match &block.inner {
+ BlockInner::Literal(pixels) => {
+ for x in 0..block.size.0 {
+ for y in 0..block.size.1 {
+ target[(x, y)] = pixels[x + y * block.size.0]
+ }
+ }
+ }
+ BlockInner::Split(box [a, b]) => {
+ let [at, bt] = target.split_mut_unsafe();
+ let [ap, bp] = prev.split();
+ blit_block(a, at, ap);
+ blit_block(b, bt, bp);
+ }
+ BlockInner::Reference { translation: _ } => target.copy_from(&prev),
+ }
+}
diff --git a/evc/src/bin/encode.rs b/evc/src/bin/encode.rs
index 04b7c42..c426aba 100644
--- a/evc/src/bin/encode.rs
+++ b/evc/src/bin/encode.rs
@@ -2,6 +2,7 @@ use clap::Parser;
use evc::{
block::{Block, BlockInner},
frame::Frame,
+ header::Header,
ser::Sink,
view::View,
};
@@ -23,6 +24,10 @@ fn main() -> io::Result<()> {
let mut output = BufWriter::new(std::io::stdout());
let size = (args.width, args.height);
+ output.put(Header {
+ resolution: size,
+ frame_count: 0,
+ })?;
let mut prev_frame = Frame::new(size);
for i in 0.. {
@@ -41,10 +46,10 @@ fn main() -> io::Result<()> {
Ok(())
}
-fn encode_block(view: View, prev: View) -> Block {
- let diff = View::diff(&view, &prev);
-
- let inner = if diff < 10_000.0 {
+fn encode_block(view: View<&Frame>, prev: View<&Frame>) -> Block {
+ let diff = View::diff(&view, &prev) / view.area() as f64;
+ eprintln!("{:?} {diff}", view.size);
+ let inner = if diff < 0.5 {
BlockInner::Reference {
translation: (0, 0),
}
diff --git a/evc/src/frame.rs b/evc/src/frame.rs
index 6e565b6..1269bf2 100644
--- a/evc/src/frame.rs
+++ b/evc/src/frame.rs
@@ -1,4 +1,8 @@
-use crate::{pixel::Pixel, ser::Source, view::View};
+use crate::{
+ pixel::Pixel,
+ ser::{Sink, Source},
+ view::View,
+};
use std::{
io,
ops::{Index, IndexMut},
@@ -20,15 +24,30 @@ impl Frame {
}
pub fn read(source: &mut impl Source, size: (usize, usize)) -> io::Result<Self> {
let mut frame = Frame::new(size);
- for x in 0..size.0 {
- for y in 0..size.1 {
+ for y in 0..size.1 {
+ for x in 0..size.0 {
let pixel = source.get::<Pixel>()?;
frame[(x, y)] = pixel;
}
}
Ok(frame)
}
- pub fn view<'a>(&'a self, offset: (usize, usize), size: (usize, usize)) -> View<'a> {
+ pub fn write(&self, sink: &mut impl Sink) -> io::Result<()> {
+ for y in 0..self.size.1 {
+ for x in 0..self.size.0 {
+ sink.put(self[(x, y)])?;
+ }
+ }
+ Ok(())
+ }
+ pub fn view<'a>(&'a self, offset: (usize, usize), size: (usize, usize)) -> View<&'a Frame> {
+ View::new(self, offset, size)
+ }
+ pub fn view_mut<'a>(
+ &'a mut self,
+ offset: (usize, usize),
+ size: (usize, usize),
+ ) -> View<&'a mut Frame> {
View::new(self, offset, size)
}
}
diff --git a/evc/src/header.rs b/evc/src/header.rs
index e5f008d..923e8ff 100644
--- a/evc/src/header.rs
+++ b/evc/src/header.rs
@@ -15,9 +15,10 @@ impl Ser for Header {
fn read(source: &mut impl std::io::Read) -> std::io::Result<Self> {
source.get::<[u8; 4]>()?;
+ let (resolution, frame_count) = source.get()?;
Ok(Self {
- resolution: source.get()?,
- frame_count: source.get()?,
+ resolution,
+ frame_count,
})
}
}
diff --git a/evc/src/ser.rs b/evc/src/ser.rs
index 05072b2..2d0bc82 100644
--- a/evc/src/ser.rs
+++ b/evc/src/ser.rs
@@ -152,3 +152,23 @@ impl Ser for f64 {
Ok(unsafe { std::mem::transmute_copy(&buf) })
}
}
+
+#[cfg(test)]
+mod test {
+ use super::Sink;
+ use crate::ser::Source;
+ use std::io::Cursor;
+
+ #[test]
+ fn simple() {
+ let mut buf = vec![];
+ Cursor::new(&mut buf).put(10usize).unwrap();
+ assert_eq!(10usize, Cursor::new(&mut buf).get().unwrap());
+ }
+ #[test]
+ fn tuple() {
+ let mut buf = vec![];
+ Cursor::new(&mut buf).put((10usize, 5u8, 3u16)).unwrap();
+ assert_eq!((10usize, 5u8, 3u16), Cursor::new(&mut buf).get().unwrap());
+ }
+}
diff --git a/evc/src/view.rs b/evc/src/view.rs
index ae7012f..983fe67 100644
--- a/evc/src/view.rs
+++ b/evc/src/view.rs
@@ -1,32 +1,55 @@
use crate::{frame::Frame, pixel::Pixel};
-use std::ops::Index;
+use std::ops::{Index, IndexMut};
-pub struct View<'a> {
- pub frame: &'a Frame,
+pub struct View<T> {
+ pub frame: T,
pub offset: (usize, usize),
pub size: (usize, usize),
}
-impl<'a> View<'a> {
- pub fn new(frame: &'a Frame, offset: (usize, usize), size: (usize, usize)) -> Self {
+impl<T> View<T> {
+ pub fn new(frame: T, offset: (usize, usize), size: (usize, usize)) -> Self {
Self {
frame,
offset,
size,
}
}
- 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 {
- let a = va[(x, y)];
- let b = vb[(x, y)];
- acc += Pixel::distance(a, b);
- }
- }
- acc
+ pub fn area(&self) -> usize {
+ self.size.0 * self.size.1
+ }
+}
+
+impl<T> View<&mut T> {
+ pub fn split_mut_unsafe(&mut self) -> [Self; 2] {
+ let vert = self.size.0 > self.size.1;
+ [
+ Self {
+ frame: unsafe { std::mem::transmute::<_, &mut T>(&mut self.frame) },
+ offset: self.offset,
+ size: if vert {
+ (self.size.0 / 2, self.size.1)
+ } else {
+ (self.size.0, self.size.1 / 2)
+ },
+ },
+ Self {
+ frame: unsafe { std::mem::transmute::<_, &mut T>(&mut self.frame) },
+ offset: if vert {
+ (self.offset.0 + self.size.0 / 2, self.offset.1)
+ } else {
+ (self.offset.0, self.offset.1 + self.size.1 / 2)
+ },
+ size: if vert {
+ (self.size.0 - self.size.0 / 2, self.size.1)
+ } else {
+ (self.size.0, self.size.1 - self.size.1 / 2)
+ },
+ },
+ ]
}
+}
+impl<T: Copy> View<T> {
pub fn split(&self) -> [Self; 2] {
let vert = self.size.0 > self.size.1;
[
@@ -54,6 +77,20 @@ impl<'a> View<'a> {
},
]
}
+}
+impl<T: Index<(usize, usize), 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 {
+ let a = va[(x, y)];
+ let b = vb[(x, y)];
+ acc += Pixel::distance(a, b);
+ }
+ }
+ acc
+ }
pub fn pixels(&self) -> Vec<Pixel> {
let mut v = vec![];
for x in 0..self.size.0 {
@@ -64,11 +101,33 @@ impl<'a> View<'a> {
v
}
}
+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 {
+ self[(x, y)] = other[(x, y)];
+ }
+ }
+ }
+}
-impl Index<(usize, usize)> for View<'_> {
+impl<T: Index<(usize, usize), Output = Pixel>> Index<(usize, usize)> 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)]
+ }
+}
+impl<T: Index<(usize, usize), Output = Pixel>> Index<(usize, usize)> 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)]
}
}
+impl<T: IndexMut<(usize, usize), Output = Pixel>> IndexMut<(usize, usize)> 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)]
+ }
+}