aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormetamuffin <metamuffin@disroot.org>2022-12-06 15:52:08 +0100
committermetamuffin <metamuffin@disroot.org>2022-12-06 15:52:08 +0100
commit6a3aaca8727d3f0292d62dbcd54e3bf87df74c0c (patch)
treed9bc5fe941c49de0885795288e2ef45f88d0a40c
parenta5b09a2fc7a2e1ddc5776993373052cd3eda9b51 (diff)
downloadvideo-codec-experiments-6a3aaca8727d3f0292d62dbcd54e3bf87df74c0c.tar
video-codec-experiments-6a3aaca8727d3f0292d62dbcd54e3bf87df74c0c.tar.bz2
video-codec-experiments-6a3aaca8727d3f0292d62dbcd54e3bf87df74c0c.tar.zst
split files
-rwxr-xr-xevc/scripts/stream2
-rwxr-xr-xevc/scripts/stream-lq5
-rw-r--r--evc/src/bin/decode.rs22
-rw-r--r--evc/src/bin/encode.rs40
-rw-r--r--evc/src/codec/decode.rs18
-rw-r--r--evc/src/codec/encode.rs34
-rw-r--r--evc/src/codec/mod.rs2
-rw-r--r--evc/src/frame.rs14
-rw-r--r--evc/src/lib.rs7
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;