From 7494981595712cf42681823e8fd79977b9b5f9dc Mon Sep 17 00:00:00 2001 From: metamuffin Date: Thu, 9 Mar 2023 22:01:20 +0100 Subject: web! --- lvc/Cargo.lock | 98 ++++++++++++++++++++++++++++++++++++++++++++ lvc/Cargo.toml | 4 +- lvc/app/src/bin/main.rs | 3 +- lvc/codec-web/Cargo.toml | 13 ++++++ lvc/codec-web/src/lib.rs | 64 +++++++++++++++++++++++++++++ lvc/codec-web/web/.gitignore | 2 + lvc/codec-web/web/index.html | 11 +++++ lvc/codec-web/web/main.ts | 18 ++++++++ lvc/codec/Cargo.toml | 7 +++- lvc/codec/src/decode.rs | 56 ++++++++++++++++--------- lvc/codec/src/encode.rs | 3 +- lvc/codec/src/impls.rs | 13 ++++++ lvc/codec/src/lib.rs | 5 ++- 13 files changed, 270 insertions(+), 27 deletions(-) create mode 100644 lvc/codec-web/Cargo.toml create mode 100644 lvc/codec-web/src/lib.rs create mode 100644 lvc/codec-web/web/.gitignore create mode 100644 lvc/codec-web/web/index.html create mode 100644 lvc/codec-web/web/main.ts (limited to 'lvc') diff --git a/lvc/Cargo.lock b/lvc/Cargo.lock index aa2f8b5..cd51668 100644 --- a/lvc/Cargo.lock +++ b/lvc/Cargo.lock @@ -22,6 +22,12 @@ version = "1.3.2" 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" @@ -78,6 +84,26 @@ dependencies = [ "os_str_bytes", ] +[[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" @@ -191,6 +217,15 @@ dependencies = [ "windows-sys", ] +[[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" @@ -203,6 +238,15 @@ version = "0.1.4" 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" @@ -356,6 +400,60 @@ version = "0.9.4" 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" 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> = RwLock::new(None); + +struct State { + buffer: VecDeque, + 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 { + 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 @@ + + + + + + + bv1 web player + + + + 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 @@ +/// + +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(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 { 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, -- cgit v1.2.3-70-g09d2