aboutsummaryrefslogtreecommitdiff
path: root/lvc/src
diff options
context:
space:
mode:
Diffstat (limited to 'lvc/src')
-rw-r--r--lvc/src/debug.rs2
-rw-r--r--lvc/src/decode.rs2
-rw-r--r--lvc/src/encode.rs22
-rw-r--r--lvc/src/lib.rs2
-rw-r--r--lvc/src/main.rs101
5 files changed, 99 insertions, 30 deletions
diff --git a/lvc/src/debug.rs b/lvc/src/debug.rs
index 9959e9a..0e6fb7a 100644
--- a/lvc/src/debug.rs
+++ b/lvc/src/debug.rs
@@ -3,7 +3,7 @@ use crate::{split::split, Block, Frame, Pixel, View, P2};
pub fn draw_debug(frame: &mut Frame, view: View, block: &Block) {
match block {
Block::Lit(_) => rect(frame, view, Pixel::GREEN),
- Block::Split([a, b]) => {
+ Block::Split(a, b) => {
let [av, bv] = split(view);
draw_debug(frame, av, &a);
draw_debug(frame, bv, &b);
diff --git a/lvc/src/decode.rs b/lvc/src/decode.rs
index b4f2391..da69080 100644
--- a/lvc/src/decode.rs
+++ b/lvc/src/decode.rs
@@ -3,7 +3,7 @@ use crate::{split::split, Block, Frame, View, P2};
pub fn decode(last_frame: &Frame, frame: &mut Frame, view: View, block: &Block) {
match block {
Block::Lit(pxs) => frame.import(view, &pxs),
- Block::Split([a, b]) => {
+ Block::Split(a, b) => {
let [av, bv] = split(view);
decode(last_frame, frame, av, &a);
decode(last_frame, frame, bv, &b);
diff --git a/lvc/src/encode.rs b/lvc/src/encode.rs
index 5df803b..935aaba 100644
--- a/lvc/src/encode.rs
+++ b/lvc/src/encode.rs
@@ -1,18 +1,20 @@
use crate::diff::diff;
-use crate::impls::ToArray;
use crate::split::split;
use crate::{Block, Frame, Ref, View};
-pub fn encode(last_frame: &Frame, frame: &Frame, view: View) -> Block {
- if view.size().area() > 1024 {
+pub struct EncodeConfig {
+ pub threshold: u32,
+ pub max_block_size: usize,
+}
+
+pub fn encode(last_frame: &Frame, frame: &Frame, view: View, config: &EncodeConfig) -> Block {
+ if view.size().area() > config.max_block_size {
let [av, bv] = split(view);
- return Block::Split(
- rayon::join(
- || Box::new(encode(last_frame, frame, av)),
- || Box::new(encode(last_frame, frame, bv)),
- )
- .to_array(),
+ let (ab, bb) = rayon::join(
+ || Box::new(encode(last_frame, frame, av, config)),
+ || Box::new(encode(last_frame, frame, bv, config)),
);
+ return Block::Split(ab, bb);
}
let mut r = Ref::default();
@@ -30,7 +32,7 @@ pub fn encode(last_frame: &Frame, frame: &Frame, view: View) -> Block {
}
}
- if d < 10000 {
+ if d < config.threshold {
return Block::Ref(r);
} else {
Block::Lit(frame.export(view))
diff --git a/lvc/src/lib.rs b/lvc/src/lib.rs
index d9fdfa3..33a8cfb 100644
--- a/lvc/src/lib.rs
+++ b/lvc/src/lib.rs
@@ -40,7 +40,7 @@ pub struct View {
#[derive(Debug, Clone, Encode, Decode)]
pub enum Block {
Lit(Vec<Pixel>),
- Split([Box<Block>; 2]),
+ Split(Box<Block>,Box<Block>),
Ref(Ref),
}
diff --git a/lvc/src/main.rs b/lvc/src/main.rs
index 413e4a4..48df911 100644
--- a/lvc/src/main.rs
+++ b/lvc/src/main.rs
@@ -1,30 +1,97 @@
-use lvc::{debug::draw_debug, decode::decode, encode::encode, Frame, Pixel, PixelValue, View, P2};
+use bincode::config::standard;
+use clap::{Parser, Subcommand};
+use lvc::{
+ debug::draw_debug,
+ decode::decode,
+ encode::{encode, EncodeConfig},
+ Block, Frame, Pixel, PixelValue, View, P2,
+};
use std::io::{stdin, stdout, BufReader, BufWriter, Read, Write};
+#[derive(Parser)]
+#[clap(about, version)]
+struct Args {
+ // Width of the video signal
+ #[arg(short, long)]
+ width: u16,
+ // Height of the video signal
+ #[arg(short, long)]
+ height: u16,
+ #[clap(subcommand)]
+ action: Action,
+}
+#[derive(Clone, Subcommand)]
+enum Action {
+ // Compress video
+ Encode {
+ #[arg(short, long, default_value_t = 1024)]
+ block_size: usize,
+ #[arg(short, long, default_value_t = 10_000)]
+ threshold: u32,
+ },
+ // Decompress video
+ Decode {
+ #[arg(short, long)]
+ debug: bool,
+ },
+}
+
fn main() {
- let size = P2 { x: 1920, y: 1080 };
+ let args = Args::parse();
- let mut last_frame = Frame::new(size);
- let mut debug_frame = Some(Frame::new(size));
+ let size = P2 {
+ x: args.width as i32,
+ y: args.height as i32,
+ };
+ match args.action {
+ Action::Decode { debug } => {
+ let mut frame = Frame::new(size);
+ let mut last_frame = Frame::new(size);
+ let mut debug_frame = if debug { Some(Frame::new(size)) } else { None };
- let mut stdin = BufReader::new(stdin());
- let mut stdout = BufWriter::new(stdout());
+ let mut stdin = BufReader::new(stdin());
+ let mut stdout = BufWriter::new(stdout());
- loop {
- let mut frame = read_frame(&mut stdin, size);
+ loop {
+ let b: Block = bincode::decode_from_std_read(&mut stdin, standard()).unwrap();
+ decode(&last_frame, &mut frame, View::all(size), &b);
- let b = encode(&last_frame, &frame, View::all(size));
- decode(&last_frame, &mut frame, View::all(size), &b);
+ if let Some(debug_frame) = &mut debug_frame {
+ debug_frame.pixels.copy_from_slice(&frame.pixels);
+ draw_debug(debug_frame, View::all(size), &b);
+ write_frame(&mut stdout, &debug_frame);
+ } else {
+ write_frame(&mut stdout, &frame);
+ }
- if let Some(debug_frame) = &mut debug_frame {
- debug_frame.pixels.copy_from_slice(&frame.pixels);
- draw_debug(debug_frame, View::all(size), &b);
- write_frame(&mut stdout, &debug_frame);
- } else {
- write_frame(&mut stdout, &frame);
+ last_frame.pixels.copy_from_slice(&frame.pixels);
+ }
}
+ Action::Encode {
+ block_size,
+ threshold,
+ } => {
+ let config = EncodeConfig {
+ threshold,
+ max_block_size: block_size,
+ };
+
+ let mut last_frame = Frame::new(size);
- last_frame = frame;
+ let mut stdin = BufReader::new(stdin());
+ let mut stdout = BufWriter::new(stdout());
+
+ for frame_number in 0.. {
+ eprintln!("encode frame {frame_number}");
+ let mut frame = read_frame(&mut stdin, size);
+
+ let b: Block = encode(&last_frame, &frame, View::all(size), &config);
+ bincode::encode_into_std_write(&b, &mut stdout, standard()).unwrap();
+
+ decode(&last_frame, &mut frame, View::all(size), &b);
+ last_frame = frame;
+ }
+ }
}
}