aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormetamuffin <metamuffin@disroot.org>2023-03-09 09:07:34 +0100
committermetamuffin <metamuffin@disroot.org>2023-03-09 09:07:34 +0100
commitecb81ba6448d6e33a9e7ecd3cd5d41513713f814 (patch)
tree05e80cd4c995958815a2e4b1b4421e759b9a6e7f
parent2d61333ed37b2d9fd940291ee8b1f5dc68c65591 (diff)
downloadvideo-codec-experiments-ecb81ba6448d6e33a9e7ecd3cd5d41513713f814.tar
video-codec-experiments-ecb81ba6448d6e33a9e7ecd3cd5d41513713f814.tar.bz2
video-codec-experiments-ecb81ba6448d6e33a9e7ecd3cd5d41513713f814.tar.zst
fixing huff 1/2
-rw-r--r--lvc/src/bin/main.rs118
-rw-r--r--lvc/src/bin/test.rs17
-rw-r--r--lvc/src/huff.rs39
3 files changed, 95 insertions, 79 deletions
diff --git a/lvc/src/bin/main.rs b/lvc/src/bin/main.rs
index e579f72..7c0d965 100644
--- a/lvc/src/bin/main.rs
+++ b/lvc/src/bin/main.rs
@@ -3,7 +3,7 @@ use lvc::{
debug::draw_debug,
decode::decode,
encode::{encode, EncodeConfig},
- huff::{read_huffman, write_huffman},
+ huff::{read_huff, write_huff},
Block, Frame, Pixel, PixelValue, View, P2,
};
use std::{
@@ -50,38 +50,6 @@ fn main() {
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());
-
- loop {
- let mut buf = vec![];
- read_huffman(&mut stdin, &mut buf).unwrap();
-
- eprintln!("{:?}", &buf[..20]);
- let b = {
- let mut buf = std::io::Cursor::new(&mut buf);
- Block::read(&mut buf, View::all(size)).unwrap()
- };
-
- 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);
- }
-
- last_frame.pixels.copy_from_slice(&frame.pixels); // TODO use mem::swap
- frame.pixels.iter_mut().for_each(|e| *e = Pixel::BLACK);
- }
- }
Action::Encode {
max_block_size,
threshold,
@@ -92,12 +60,13 @@ fn main() {
max_block_size,
iters,
};
-
let mut last_frame = Frame::new(size);
let mut stdin = BufReader::new(stdin());
let mut stdout = BufWriter::new(stdout());
+ let huff = true;
+
for frame_number in 0.. {
let mut frame = read_frame(&mut stdin, size);
@@ -110,27 +79,68 @@ fn main() {
last_frame = frame;
let time_decode = t.elapsed();
- let mut buf = vec![];
- let mut bufw = std::io::Cursor::new(&mut buf);
- b.write(&mut bufw).unwrap();
- drop(bufw);
- let t = Instant::now();
- let bits_raw = buf.len() * 8;
- // eprintln!("{:?}", &buf[..20]);
- let bits_huff = write_huffman(&buf, &mut stdout).unwrap();
- let time_huff = t.elapsed();
- drop(buf);
+ if huff {
+ let mut buf = vec![];
+ let mut bufw = std::io::Cursor::new(&mut buf);
+ b.write(&mut bufw).unwrap();
+ drop(bufw);
+ let t = Instant::now();
+ let bits_raw = buf.len() * 8;
+ let bits_huff = write_huff(&buf, &mut stdout).unwrap();
+ let time_huff = t.elapsed();
+ drop(buf);
- eprintln!(
- "frame {frame_number}: {:?}",
- time_decode + time_huff + time_encode
- );
- eprintln!("\tencode {time_encode:?}");
- eprintln!("\tdecode {time_decode:?}");
- eprintln!(
- "\thuff {time_huff:?} ({}%)",
- ((bits_huff as f32 / bits_raw as f32) * 100.0).round()
- );
+ eprintln!(
+ "frame {frame_number}: {:?}",
+ time_decode + time_huff + time_encode
+ );
+ eprintln!(
+ "\tencode {time_encode:?} ({}%)",
+ ((bits_raw as f32 / (size.area() * 24) as f32) * 100.0).round()
+ );
+ eprintln!(
+ "\thuff {time_huff:?} ({}%)",
+ ((bits_huff as f32 / bits_raw as f32) * 100.0).round()
+ );
+ eprintln!("\tdecode {time_decode:?}");
+ } else {
+ b.write(&mut stdout).unwrap();
+ }
+ }
+ }
+ 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 huff = true;
+
+ loop {
+
+ let b = if huff {
+ let mut buf = vec![];
+ read_huff(&mut stdin, &mut buf).unwrap();
+ let mut buf = std::io::Cursor::new(&mut buf);
+ Block::read(&mut buf, View::all(size)).unwrap()
+ } else {
+ Block::read(&mut stdin, View::all(size)).unwrap()
+ };
+
+ 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);
+ }
+
+ last_frame.pixels.copy_from_slice(&frame.pixels); // TODO use mem::swap
+ frame.pixels.iter_mut().for_each(|e| *e = Pixel::BLACK);
}
}
}
diff --git a/lvc/src/bin/test.rs b/lvc/src/bin/test.rs
index 0f630d3..f4e0ed4 100644
--- a/lvc/src/bin/test.rs
+++ b/lvc/src/bin/test.rs
@@ -1,7 +1,7 @@
#[cfg(test)]
mod test {
- use lvc::huff::{read_huffman, write_huffman, BitIO};
+ use lvc::huff::{read_huff, write_huff, BitIO};
use std::io::Cursor;
#[test]
@@ -19,26 +19,27 @@ mod test {
b.wbit(true).unwrap();
b.wbit(true).unwrap();
b.wbit(true).unwrap();
+ b.wbyte(0xff).unwrap();
b.flush().unwrap();
}
{
let mut b = BitIO::new(Cursor::new(&mut buf));
- for _ in 0..9 {
- eprintln!("{:?}", b.rbit().unwrap())
+ for _ in 0..17 {
+ let _v = b.rbit().unwrap();
+ // eprintln!("{:?}", _v)
}
}
}
#[test]
fn test_huff() {
- let a = vec![1; 10000];
+ let a = vec![1, 2, 3, 4, 5, 1, 3, 6, 3, 2, 4, 6, 7, 4, 3, 2, 1, 3, 4];
let mut b = vec![];
let mut buf = Vec::<u8>::new();
- write_huffman(&a, &mut Cursor::new(&mut buf)).unwrap();
- eprintln!("out {buf:x?}");
- read_huffman(&mut Cursor::new(&mut buf), &mut b).unwrap();
-
+ write_huff(&a, &mut Cursor::new(&mut buf)).unwrap();
+ read_huff(&mut Cursor::new(&mut buf), &mut b).unwrap();
+
assert_eq!(a, b)
}
}
diff --git a/lvc/src/huff.rs b/lvc/src/huff.rs
index b21d38d..b00aaa0 100644
--- a/lvc/src/huff.rs
+++ b/lvc/src/huff.rs
@@ -6,9 +6,8 @@ enum HT {
Terminal(u8),
}
-pub fn write_huffman(buf: &[u8], w: &mut impl Write) -> Result<usize> {
+pub fn write_huff(buf: &[u8], w: &mut impl Write) -> Result<usize> {
let mut w = BitIO::new(w);
-
assert!(buf.len() <= 0xffffff, "huff frame too big");
w.wbyte((buf.len() & 0xff) as u8)?;
w.wbyte(((buf.len() >> 8) & 0xff) as u8)?;
@@ -26,16 +25,17 @@ pub fn write_huffman(buf: &[u8], w: &mut impl Write) -> Result<usize> {
for b in buf {
let mut k = table[*b as usize];
while k != 1 {
- w.wbit((k & 1) != 0)?;
+ w.wbit((k & 1) == 1)?;
k >>= 1;
}
}
-
+
w.flush()?;
+ eprintln!("{}", w.position);
Ok(w.position)
}
-pub fn read_huffman(r: &mut impl Read, buf: &mut Vec<u8>) -> Result<usize> {
+pub fn read_huff(r: &mut impl Read, buf: &mut Vec<u8>) -> Result<usize> {
let mut r = BitIO::new(r);
let mut len = 0usize;
@@ -43,29 +43,30 @@ pub fn read_huffman(r: &mut impl Read, buf: &mut Vec<u8>) -> Result<usize> {
len |= (r.rbyte()? as usize) << 8;
len |= (r.rbyte()? as usize) << 16;
- eprintln!("{len:?}");
+ eprintln!("len={len:?}");
let root = HT::read(&mut r)?;
- eprintln!("{root:?}");
+ // eprintln!("{root:?}");
let root = match &root {
HT::Branch(a, b) => [a, b],
_ => panic!("no!"),
};
- let mut cn = root;
- for _ in 0..len * 8 {
+ let mut cursor = root;
+ while buf.len() != len {
let v = r.rbit()?;
- match cn[v as usize].as_ref() {
+ match cursor[v as usize].as_ref() {
HT::Branch(a, b) => {
- cn = [a, b];
+ cursor = [a, b];
}
HT::Terminal(n) => {
buf.push(*n);
- cn = root;
+ cursor = root;
}
}
}
-
- Ok(len)
+ eprintln!("len(buf)={}", buf.len());
+ eprintln!("{}", r.position);
+ Ok(r.position)
}
impl HT {
@@ -83,12 +84,16 @@ impl HT {
}
parts[0].1.clone()
}
- pub fn create_lut(&self, table: &mut [u32; 256], prefix: u32) {
+ pub fn create_lut(&self, table: &mut [u32; 256], mut prefix: u32) {
assert!(self.depth() < 30, "too deep! doesnt fit {}", self.depth());
match self {
HT::Branch(a, b) => {
- a.create_lut(table, (prefix << 1) | 0);
- b.create_lut(table, (prefix << 1) | 1);
+ let pz = 32 - prefix.leading_zeros();
+ prefix ^= 1 << pz;
+ prefix ^= 1 << (pz - 1);
+ a.create_lut(table, prefix);
+ prefix ^= 1 << (pz - 1);
+ b.create_lut(table, prefix);
}
HT::Terminal(n) => {
assert_eq!(table[*n as usize], 0);