aboutsummaryrefslogtreecommitdiff
path: root/evc/src/codec
diff options
context:
space:
mode:
Diffstat (limited to 'evc/src/codec')
-rw-r--r--evc/src/codec/decode.rs18
-rw-r--r--evc/src/codec/encode.rs34
-rw-r--r--evc/src/codec/mod.rs2
3 files changed, 54 insertions, 0 deletions
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;