diff options
author | metamuffin <metamuffin@disroot.org> | 2022-12-06 07:47:51 +0100 |
---|---|---|
committer | metamuffin <metamuffin@disroot.org> | 2022-12-06 07:47:51 +0100 |
commit | bafb1df8b7764a0a62f1c656eb52fbe7bfd8b8ac (patch) | |
tree | 0e824b9f85ba80ca0082fc8d8ec8bf96bf411823 /evc/src | |
parent | cace782584d19674f70351f462e746d3d589ba90 (diff) | |
download | video-codec-experiments-bafb1df8b7764a0a62f1c656eb52fbe7bfd8b8ac.tar video-codec-experiments-bafb1df8b7764a0a62f1c656eb52fbe7bfd8b8ac.tar.bz2 video-codec-experiments-bafb1df8b7764a0a62f1c656eb52fbe7bfd8b8ac.tar.zst |
decoder
Diffstat (limited to 'evc/src')
-rw-r--r-- | evc/src/bin/decode.rs | 60 | ||||
-rw-r--r-- | evc/src/bin/encode.rs | 13 | ||||
-rw-r--r-- | evc/src/frame.rs | 27 | ||||
-rw-r--r-- | evc/src/header.rs | 5 | ||||
-rw-r--r-- | evc/src/ser.rs | 20 | ||||
-rw-r--r-- | evc/src/view.rs | 93 |
6 files changed, 191 insertions, 27 deletions
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)] + } +} |