diff options
author | metamuffin <metamuffin@disroot.org> | 2022-12-06 15:52:08 +0100 |
---|---|---|
committer | metamuffin <metamuffin@disroot.org> | 2022-12-06 15:52:08 +0100 |
commit | 6a3aaca8727d3f0292d62dbcd54e3bf87df74c0c (patch) | |
tree | d9bc5fe941c49de0885795288e2ef45f88d0a40c | |
parent | a5b09a2fc7a2e1ddc5776993373052cd3eda9b51 (diff) | |
download | video-codec-experiments-6a3aaca8727d3f0292d62dbcd54e3bf87df74c0c.tar video-codec-experiments-6a3aaca8727d3f0292d62dbcd54e3bf87df74c0c.tar.bz2 video-codec-experiments-6a3aaca8727d3f0292d62dbcd54e3bf87df74c0c.tar.zst |
split files
-rwxr-xr-x | evc/scripts/stream | 2 | ||||
-rwxr-xr-x | evc/scripts/stream-lq | 5 | ||||
-rw-r--r-- | evc/src/bin/decode.rs | 22 | ||||
-rw-r--r-- | evc/src/bin/encode.rs | 40 | ||||
-rw-r--r-- | evc/src/codec/decode.rs | 18 | ||||
-rw-r--r-- | evc/src/codec/encode.rs | 34 | ||||
-rw-r--r-- | evc/src/codec/mod.rs | 2 | ||||
-rw-r--r-- | evc/src/frame.rs | 14 | ||||
-rw-r--r-- | evc/src/lib.rs | 7 |
9 files changed, 85 insertions, 59 deletions
diff --git a/evc/scripts/stream b/evc/scripts/stream index 9fd9395..2072e21 100755 --- a/evc/scripts/stream +++ b/evc/scripts/stream @@ -1,5 +1,5 @@ #!/bin/fish -ffmpeg -i ~/videos/eddie-woo.mp4 -to 10 -vf scale=1920x1080,fps=30,format=rgb24 -f rawvideo pipe:1 2>/dev/null | +ffmpeg -i $argv[1] -vf scale=1920x1080,fps=30,format=rgb24 -f rawvideo pipe:1 2>/dev/null | cargo run --release --bin encode -- -W 1920 -H 1080 | cargo run --release --bin decode -- --debug | ffplay -framerate 30 -video_size 1920x1080 -pixel_format rgb24 -f rawvideo pipe:0 2>/dev/null diff --git a/evc/scripts/stream-lq b/evc/scripts/stream-lq new file mode 100755 index 0000000..486dbaf --- /dev/null +++ b/evc/scripts/stream-lq @@ -0,0 +1,5 @@ +#!/bin/fish +ffmpeg -i $argv[1] -vf scale=1280x720,fps=30,format=rgb24 -f rawvideo pipe:1 2>/dev/null | + cargo run --release --bin encode -- -W 1280 -H 720 | + cargo run --release --bin decode -- --debug | + ffplay -framerate 30 -video_size 1280x720 -pixel_format rgb24 -f rawvideo pipe:0 2>/dev/null diff --git a/evc/src/bin/decode.rs b/evc/src/bin/decode.rs index 44fcbe4..1500633 100644 --- a/evc/src/bin/decode.rs +++ b/evc/src/bin/decode.rs @@ -3,6 +3,7 @@ use anyhow::Context; use clap::Parser; use evc::{ block::{Block, BlockInner}, + codec::decode::decode_block, frame::Frame, header::Header, pixel::Pixel, @@ -34,15 +35,11 @@ fn main() -> anyhow::Result<()> { let block = Block::read(&mut input, size).context("reading encoded frame")?; let mut frame = Frame::new(size); - blit_block( - &block, - frame.view_mut((0, 0), size), - prev.view((0, 0), size), - ); + decode_block(&block, frame.view_mut(), prev.view()); if args.debug { let mut f2 = frame.clone(); - draw_debug(&block, f2.view_mut((0, 0), size)); + draw_debug(&block, f2.view_mut()); f2.write(&mut output).context("writing raw frame")?; } else { frame.write(&mut output).context("writing raw frame")?; @@ -54,19 +51,6 @@ fn main() -> anyhow::Result<()> { Ok(()) } -fn blit_block(block: &Block, mut target: View<&mut Frame>, prev: View<&Frame>) { - match &block.inner { - BlockInner::Literal(pixels) => target.set_pixels(pixels), - 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), - } -} - fn draw_debug(block: &Block, mut target: View<&mut Frame>) { match &block.inner { BlockInner::Literal(_) => { diff --git a/evc/src/bin/encode.rs b/evc/src/bin/encode.rs index 3e34a3c..50435e5 100644 --- a/evc/src/bin/encode.rs +++ b/evc/src/bin/encode.rs @@ -1,11 +1,10 @@ use anyhow::Context; use clap::Parser; use evc::{ - block::{Block, BlockInner}, + codec::{decode::decode_block, encode::encode_block}, frame::Frame, header::Header, ser::Sink, - view::View, }; use std::io::{BufReader, BufWriter}; @@ -35,47 +34,20 @@ fn main() -> anyhow::Result<()> { let mut prev_frame = Frame::new(size); for i in 0.. { eprintln!("encode frame {i}"); - let frame = Frame::read(&mut input, size) + let mut frame = Frame::read(&mut input, size) .context("reading raw frame") .unwrap(); - let v1 = frame.view((0, 0), size); - let v2 = prev_frame.view((0, 0), size); + let v1 = frame.view(); + let v2 = prev_frame.view(); let root = encode_block(v1, v2); root.write(&mut output).context("writing encoded frame")?; + decode_block(&root, frame.view_mut(), prev_frame.view()); + prev_frame = frame; } Ok(()) } - -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.9 { - BlockInner::Reference { - translation: (0, 0), - } - } else { - if view.size.0 < 32 { - BlockInner::Literal(view.pixels()) - } else { - let [av, bv] = view.split(); - let [ap, bp] = prev.split(); - let a = encode_block(av, ap); - let b = encode_block(bv, bp); - if a.is_literal() && b.is_literal() { - BlockInner::Literal(view.pixels()) - } else { - BlockInner::Split(Box::new([a, b])) - } - } - }; - - Block { - size: view.size, - inner, - } -} diff --git a/evc/src/codec/decode.rs b/evc/src/codec/decode.rs new file mode 100644 index 0000000..9dc6a69 --- /dev/null +++ b/evc/src/codec/decode.rs @@ -0,0 +1,18 @@ +use crate::{ + block::{Block, BlockInner}, + frame::Frame, + view::View, +}; + +pub fn decode_block(block: &Block, mut target: View<&mut Frame>, prev: View<&Frame>) { + match &block.inner { + BlockInner::Literal(pixels) => target.set_pixels(pixels), + BlockInner::Split(box [a, b]) => { + let [at, bt] = target.split_mut_unsafe(); + let [ap, bp] = prev.split(); + decode_block(a, at, ap); + decode_block(b, bt, bp); + } + BlockInner::Reference { translation: _ } => target.copy_from(&prev), + } +} diff --git a/evc/src/codec/encode.rs b/evc/src/codec/encode.rs new file mode 100644 index 0000000..cf407fa --- /dev/null +++ b/evc/src/codec/encode.rs @@ -0,0 +1,34 @@ +use crate::{ + block::{Block, BlockInner}, + frame::Frame, + view::View, +}; + +pub 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.9 { + BlockInner::Reference { + translation: (0, 0), + } + } else { + if view.size.0 < 32 { + BlockInner::Literal(view.pixels()) + } else { + let [av, bv] = view.split(); + let [ap, bp] = prev.split(); + let a = encode_block(av, ap); + let b = encode_block(bv, bp); + if a.is_literal() && b.is_literal() { + BlockInner::Literal(view.pixels()) + } else { + BlockInner::Split(Box::new([a, b])) + } + } + }; + + Block { + size: view.size, + inner, + } +} diff --git a/evc/src/codec/mod.rs b/evc/src/codec/mod.rs new file mode 100644 index 0000000..1c80d24 --- /dev/null +++ b/evc/src/codec/mod.rs @@ -0,0 +1,2 @@ +pub mod decode; +pub mod encode; diff --git a/evc/src/frame.rs b/evc/src/frame.rs index 5c2adfb..666dc00 100644 --- a/evc/src/frame.rs +++ b/evc/src/frame.rs @@ -38,10 +38,20 @@ impl Frame { } Ok(()) } - pub fn view<'a>(&'a self, offset: (usize, usize), size: (usize, usize)) -> View<&'a Frame> { + pub fn view<'a>(&'a self) -> View<&'a Frame> { + View::new(self, (0, 0), self.size) + } + pub fn view_mut<'a>(&'a mut self) -> View<&'a mut Frame> { + View::new(self, (0, 0), self.size) + } + pub fn view_area<'a>( + &'a self, + offset: (usize, usize), + size: (usize, usize), + ) -> View<&'a Frame> { View::new(self, offset, size) } - pub fn view_mut<'a>( + pub fn view_area_mut<'a>( &'a mut self, offset: (usize, usize), size: (usize, usize), diff --git a/evc/src/lib.rs b/evc/src/lib.rs index 65e8e2b..a513116 100644 --- a/evc/src/lib.rs +++ b/evc/src/lib.rs @@ -1,9 +1,10 @@ #![feature(box_patterns)] -pub mod ser; pub mod block; -pub mod header; +pub mod codec; +pub mod debug; pub mod frame; +pub mod header; pub mod pixel; +pub mod ser; pub mod view; -pub mod debug; |