diff options
author | metamuffin <metamuffin@disroot.org> | 2023-03-09 09:07:34 +0100 |
---|---|---|
committer | metamuffin <metamuffin@disroot.org> | 2023-03-09 09:07:34 +0100 |
commit | ecb81ba6448d6e33a9e7ecd3cd5d41513713f814 (patch) | |
tree | 05e80cd4c995958815a2e4b1b4421e759b9a6e7f | |
parent | 2d61333ed37b2d9fd940291ee8b1f5dc68c65591 (diff) | |
download | video-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.rs | 118 | ||||
-rw-r--r-- | lvc/src/bin/test.rs | 17 | ||||
-rw-r--r-- | lvc/src/huff.rs | 39 |
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); |