diff options
author | metamuffin <metamuffin@disroot.org> | 2023-03-09 22:01:20 +0100 |
---|---|---|
committer | metamuffin <metamuffin@disroot.org> | 2023-03-09 22:01:20 +0100 |
commit | 7494981595712cf42681823e8fd79977b9b5f9dc (patch) | |
tree | 7f85af24f4c1e56b6cf1c7baf6fe8a6cd798c7b3 | |
parent | 11b78570656bd0ca67594472765fc629aa25fd25 (diff) | |
download | video-codec-experiments-7494981595712cf42681823e8fd79977b9b5f9dc.tar video-codec-experiments-7494981595712cf42681823e8fd79977b9b5f9dc.tar.bz2 video-codec-experiments-7494981595712cf42681823e8fd79977b9b5f9dc.tar.zst |
web!
-rw-r--r-- | lvc/Cargo.lock | 98 | ||||
-rw-r--r-- | lvc/Cargo.toml | 4 | ||||
-rw-r--r-- | lvc/app/src/bin/main.rs | 3 | ||||
-rw-r--r-- | lvc/codec-web/Cargo.toml | 13 | ||||
-rw-r--r-- | lvc/codec-web/src/lib.rs | 64 | ||||
-rw-r--r-- | lvc/codec-web/web/.gitignore | 2 | ||||
-rw-r--r-- | lvc/codec-web/web/index.html | 11 | ||||
-rw-r--r-- | lvc/codec-web/web/main.ts | 18 | ||||
-rw-r--r-- | lvc/codec/Cargo.toml | 7 | ||||
-rw-r--r-- | lvc/codec/src/decode.rs | 56 | ||||
-rw-r--r-- | lvc/codec/src/encode.rs | 3 | ||||
-rw-r--r-- | lvc/codec/src/impls.rs | 13 | ||||
-rw-r--r-- | lvc/codec/src/lib.rs | 5 |
13 files changed, 270 insertions, 27 deletions
diff --git a/lvc/Cargo.lock b/lvc/Cargo.lock index aa2f8b5..cd51668 100644 --- a/lvc/Cargo.lock +++ b/lvc/Cargo.lock @@ -23,6 +23,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] +name = "bumpalo" +version = "3.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d261e256854913907f67ed06efbc3338dfe6179796deefc1ff763fc1aee5535" + +[[package]] name = "bv1" version = "0.1.0" dependencies = [ @@ -79,6 +85,26 @@ dependencies = [ ] [[package]] +name = "codec-web" +version = "0.1.0" +dependencies = [ + "bv1", + "console_error_panic_hook", + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "console_error_panic_hook" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a06aeb73f470f66dcdbf7223caeebb85984942f22f1adb2a088cf9668146bbbc" +dependencies = [ + "cfg-if", + "wasm-bindgen", +] + +[[package]] name = "crossbeam-channel" version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -192,6 +218,15 @@ dependencies = [ ] [[package]] +name = "js-sys" +version = "0.3.61" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "445dde2150c55e483f3d8416706b97ec8e8237c307e5b7b4b8dd15e6af2a0730" +dependencies = [ + "wasm-bindgen", +] + +[[package]] name = "libc" version = "0.2.139" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -204,6 +239,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f051f77a7c8e6957c0696eac88f26b0117e54f52d3fc682ab19397a8812846a4" [[package]] +name = "log" +version = "0.4.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" +dependencies = [ + "cfg-if", +] + +[[package]] name = "memoffset" version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -357,6 +401,60 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" [[package]] +name = "wasm-bindgen" +version = "0.2.84" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31f8dcbc21f30d9b8f2ea926ecb58f6b91192c17e9d33594b3df58b2007ca53b" +dependencies = [ + "cfg-if", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.84" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95ce90fd5bcc06af55a641a86428ee4229e44e07033963a2290a8e241607ccb9" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.84" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c21f77c0bedc37fd5dc21f897894a5ca01e7bb159884559461862ae90c0b4c5" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.84" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2aff81306fcac3c7515ad4e177f521b5c9a15f2b08f4e32d823066102f35a5f6" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.84" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0046fef7e28c3804e5e38bfa31ea2a0f73905319b677e57ebe37e49358989b5d" + +[[package]] name = "winapi" version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" diff --git a/lvc/Cargo.toml b/lvc/Cargo.toml index b45cf70..489eec7 100644 --- a/lvc/Cargo.toml +++ b/lvc/Cargo.toml @@ -1,3 +1,3 @@ [workspace] -members = ["codec", "app"] -default-members = ["app"] +members = ["codec", "app", "codec-web"] +default-members = ["app", "codec-web"] diff --git a/lvc/app/src/bin/main.rs b/lvc/app/src/bin/main.rs index 8cac292..0b3596e 100644 --- a/lvc/app/src/bin/main.rs +++ b/lvc/app/src/bin/main.rs @@ -1,7 +1,6 @@ use bv1::{ - decode::decode, encode::{encode, EncodeConfig}, - P2, + P2, decode, }; use clap::{Parser, Subcommand}; use std::io::{stdin, stdout}; diff --git a/lvc/codec-web/Cargo.toml b/lvc/codec-web/Cargo.toml new file mode 100644 index 0000000..f1a3f6a --- /dev/null +++ b/lvc/codec-web/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "codec-web" +version = "0.1.0" +edition = "2021" + +[lib] +crate-type = ["cdylib"] + +[dependencies] +bv1 = { path = "../codec" } +wasm-bindgen = "0.2.84" +js-sys = "0.3.61" +console_error_panic_hook = "0.1.7" diff --git a/lvc/codec-web/src/lib.rs b/lvc/codec-web/src/lib.rs new file mode 100644 index 0000000..c26da29 --- /dev/null +++ b/lvc/codec-web/src/lib.rs @@ -0,0 +1,64 @@ +use bv1::{Decoder, Frame, P2}; +use std::{collections::VecDeque, sync::RwLock}; +use wasm_bindgen::prelude::*; + +static DECODER: RwLock<Option<State>> = RwLock::new(None); + +struct State { + buffer: VecDeque<u8>, + frame: Frame, + decoder: Decoder, +} + +#[wasm_bindgen] +extern "C" { + #[wasm_bindgen(js_namespace = console)] + fn log(s: &str); + #[wasm_bindgen(js_namespace = console, js_name = "log")] + fn logs(s: String); +} + +#[wasm_bindgen(start)] +fn panic_init() { + std::panic::set_hook(Box::new(console_error_panic_hook::hook)); +} + +#[wasm_bindgen] +pub fn decode_init(width: i32, height: i32) { + let size = P2 { + x: width, + y: height, + }; + *DECODER.write().unwrap() = Some(State { + frame: Frame::new(size), + decoder: Decoder::new(size), + buffer: VecDeque::new(), + }); +} + +#[wasm_bindgen] +pub fn decode_frame(buf: &[u8], debug: bool) -> Vec<u8> { + let mut arr = Vec::new(); + let mut g = DECODER.write().unwrap(); + let state = g.as_mut().unwrap(); + state.buffer.extend(buf.iter()); + log("d"); + logs(format!("{}", state.buffer.len())); + + log("a"); + state + .decoder + .decode_frame(&mut state.buffer, &mut state.frame, debug) + .unwrap(); + log("b"); + + for y in 0..state.frame.size.y { + for x in 0..state.frame.size.x { + arr.push(state.frame[P2 { x, y }].r.clamp(0, 255) as u8); + arr.push(state.frame[P2 { x, y }].g.clamp(0, 255) as u8); + arr.push(state.frame[P2 { x, y }].b.clamp(0, 255) as u8); + } + } + + arr +} diff --git a/lvc/codec-web/web/.gitignore b/lvc/codec-web/web/.gitignore new file mode 100644 index 0000000..93d7118 --- /dev/null +++ b/lvc/codec-web/web/.gitignore @@ -0,0 +1,2 @@ +/codec_web* +/bundle* diff --git a/lvc/codec-web/web/index.html b/lvc/codec-web/web/index.html new file mode 100644 index 0000000..2580ed9 --- /dev/null +++ b/lvc/codec-web/web/index.html @@ -0,0 +1,11 @@ +<!DOCTYPE html> +<html lang="en"> + <head> + <meta charset="UTF-8" /> + <meta http-equiv="X-UA-Compatible" content="IE=edge" /> + <meta name="viewport" content="width=device-width, initial-scale=1.0" /> + <title>bv1 web player</title> + <script defer async src="./bundle.js" type="module"></script> + </head> + <body></body> +</html> diff --git a/lvc/codec-web/web/main.ts b/lvc/codec-web/web/main.ts new file mode 100644 index 0000000..150e1c3 --- /dev/null +++ b/lvc/codec-web/web/main.ts @@ -0,0 +1,18 @@ +/// <reference lib="dom" /> + +import init, { decode_frame, decode_init } from "./codec_web.js" +console.log("init wasm"); +await init() +console.log("done"); + +decode_init(1920, 1080) + +const res = await fetch("/data/encoded") +if (!res.ok) throw new Error("not ok"); + +const buf = new Uint8Array(await res.arrayBuffer()) + +console.log("decode"); +const frame = decode_frame(buf.slice(0, 500000), true); +console.log("done"); +console.log(frame); diff --git a/lvc/codec/Cargo.toml b/lvc/codec/Cargo.toml index 67189bb..0c52ad2 100644 --- a/lvc/codec/Cargo.toml +++ b/lvc/codec/Cargo.toml @@ -4,4 +4,9 @@ version = "0.1.0" edition = "2021" [dependencies] -rayon = "1.7.0" +rayon = {version="1.7.0",optional = true} + +[features] +default = ["parallel"] +parallel = ["dep:rayon"] + diff --git a/lvc/codec/src/decode.rs b/lvc/codec/src/decode.rs index 4830156..616b7af 100644 --- a/lvc/codec/src/decode.rs +++ b/lvc/codec/src/decode.rs @@ -1,38 +1,54 @@ -use crate::{debug::draw_debug, huff::read_huff, split::split, Block, Frame, Pixel, View, P2}; -use rayon::join; +use crate::{ + debug::draw_debug, huff::read_huff, impls::join, split::split, Block, Frame, View, P2, +}; use std::io::{BufReader, BufWriter, Read, Result, Write}; pub fn decode(size: P2, debug: bool, input: impl Read, output: impl Write) -> Result<()> { let mut input = BufReader::new(input); let mut output = BufWriter::new(output); + let mut d = Decoder::new(size); + let mut f = Frame::new(size); + loop { + d.decode_frame(&mut input, &mut f, debug)?; + Frame::write(&mut output, &f)?; + } +} - 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 }; +pub struct Decoder { + last_frame: Frame, + size: P2, +} - let huff = true; - loop { +impl Decoder { + pub fn new(size: P2) -> Self { + Self { + size, + last_frame: Frame::new(size), + } + } + pub fn decode_frame( + &mut self, + mut input: impl Read, + output: &mut Frame, + debug: bool, + ) -> Result<()> { + let huff = true; let b = if huff { let mut buf = vec![]; read_huff(&mut input, &mut buf)?; + eprintln!("{}", buf.len()); let mut buf = std::io::Cursor::new(&mut buf); - Block::read(&mut buf, View::all(size))? + Block::read(&mut buf, View::all(self.size))? } else { - Block::read(&mut input, View::all(size))? + Block::read(&mut input, View::all(self.size))? }; - decode_block(&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); - Frame::write(&mut output, &debug_frame)?; - } else { - Frame::write(&mut output, &frame)?; + decode_block(&self.last_frame, output, View::all(self.size), &b); + self.last_frame.pixels.copy_from_slice(&output.pixels); // TODO use mem::swap + if debug { + draw_debug(output, View::all(self.size), &b); } - - last_frame.pixels.copy_from_slice(&frame.pixels); // TODO use mem::swap - frame.pixels.iter_mut().for_each(|e| *e = Pixel::BLACK); + Ok(()) } } diff --git a/lvc/codec/src/encode.rs b/lvc/codec/src/encode.rs index d612daf..564b0b3 100644 --- a/lvc/codec/src/encode.rs +++ b/lvc/codec/src/encode.rs @@ -1,5 +1,6 @@ use crate::diff::{diff, pixel_diff}; use crate::huff::write_huff; +use crate::impls::join; use crate::split::split; use crate::{decode::decode_block, Block, Frame, Pixel, Ref, View, P2}; use std::io::{BufReader, BufWriter, Read, Write}; @@ -77,7 +78,7 @@ pub fn encode_block(last_frame: &Frame, frame: &Frame, view: View, config: &Enco || (view_area > 64 && attention(frame, view) > config.attention_split) { let [av, bv] = split(view); - let (ab, bb) = rayon::join( + let (ab, bb) = join( || Box::new(encode_block(last_frame, frame, av, config)), || Box::new(encode_block(last_frame, frame, bv, config)), ); diff --git a/lvc/codec/src/impls.rs b/lvc/codec/src/impls.rs index 098db39..b4cc119 100644 --- a/lvc/codec/src/impls.rs +++ b/lvc/codec/src/impls.rs @@ -1,6 +1,19 @@ use crate::{Frame, Pixel, Ref, View, P2}; use std::ops::{Add, AddAssign, Index, IndexMut, Sub}; +#[cfg(feature = "parallel")] +pub use rayon::join; +#[cfg(not(feature = "parallel"))] +pub fn join<A, B, RA, RB>(oper_a: A, oper_b: B) -> (RA, RB) +where + A: FnOnce() -> RA + Send, + B: FnOnce() -> RB + Send, + RA: Send, + RB: Send, +{ + (oper_a(), oper_b()) +} + impl Frame { pub fn export(&self, view: View) -> Vec<Pixel> { let mut o = vec![]; diff --git a/lvc/codec/src/lib.rs b/lvc/codec/src/lib.rs index 5cd83b9..c764211 100644 --- a/lvc/codec/src/lib.rs +++ b/lvc/codec/src/lib.rs @@ -6,14 +6,17 @@ pub mod debug; pub mod decode; pub mod diff; pub mod encode; +pub mod frameio; pub mod huff; pub mod impls; pub mod serialize; pub mod split; -pub mod frameio; pub type PixelValue = i16; +pub use decode::{decode, Decoder}; +pub use encode::encode; + #[derive(Debug, Clone, Copy, Default, PartialEq, Eq)] pub struct Pixel { pub r: PixelValue, |