diff options
author | metamuffin <metamuffin@disroot.org> | 2025-05-05 15:09:54 +0200 |
---|---|---|
committer | metamuffin <metamuffin@disroot.org> | 2025-05-05 15:09:54 +0200 |
commit | 306f96164784a8cbf405e72fa4364d6523366e95 (patch) | |
tree | 51717fc139871baa438aad806f4923669ae0896c /old/bv1/codec-web | |
parent | 9cc089e2d6e841879e430b01d2f3d92c8820523e (diff) | |
download | video-codec-experiments-306f96164784a8cbf405e72fa4364d6523366e95.tar video-codec-experiments-306f96164784a8cbf405e72fa4364d6523366e95.tar.bz2 video-codec-experiments-306f96164784a8cbf405e72fa4364d6523366e95.tar.zst |
old dir
Diffstat (limited to 'old/bv1/codec-web')
-rw-r--r-- | old/bv1/codec-web/Cargo.toml | 13 | ||||
-rw-r--r-- | old/bv1/codec-web/src/lib.rs | 60 | ||||
-rw-r--r-- | old/bv1/codec-web/web/.gitignore | 2 | ||||
-rw-r--r-- | old/bv1/codec-web/web/index.html | 14 | ||||
-rw-r--r-- | old/bv1/codec-web/web/main.ts | 69 |
5 files changed, 158 insertions, 0 deletions
diff --git a/old/bv1/codec-web/Cargo.toml b/old/bv1/codec-web/Cargo.toml new file mode 100644 index 0000000..7c1892c --- /dev/null +++ b/old/bv1/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.92" +js-sys = "0.3.69" +console_error_panic_hook = "0.1.7" diff --git a/old/bv1/codec-web/src/lib.rs b/old/bv1/codec-web/src/lib.rs new file mode 100644 index 0000000..cb2ad3c --- /dev/null +++ b/old/bv1/codec-web/src/lib.rs @@ -0,0 +1,60 @@ +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()); + + state + .decoder + .decode_frame(&mut state.buffer, &mut state.frame, debug) + .unwrap(); + + 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/old/bv1/codec-web/web/.gitignore b/old/bv1/codec-web/web/.gitignore new file mode 100644 index 0000000..93d7118 --- /dev/null +++ b/old/bv1/codec-web/web/.gitignore @@ -0,0 +1,2 @@ +/codec_web* +/bundle* diff --git a/old/bv1/codec-web/web/index.html b/old/bv1/codec-web/web/index.html new file mode 100644 index 0000000..b572671 --- /dev/null +++ b/old/bv1/codec-web/web/index.html @@ -0,0 +1,14 @@ +<!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> + <noscript>need js</noscript> + <p>loading…</p> + </body> +</html> diff --git a/old/bv1/codec-web/web/main.ts b/old/bv1/codec-web/web/main.ts new file mode 100644 index 0000000..b1b1df7 --- /dev/null +++ b/old/bv1/codec-web/web/main.ts @@ -0,0 +1,69 @@ +/// <reference lib="dom" /> + +import init, { decode_frame, decode_init } from "./codec_web.js" +console.log("init wasm"); +await init() +console.log("done"); + +index("..") + +async function index(url: string) { + const res = await fetch(url) + if (!res.ok) throw new Error("not ok"); + document.body.innerHTML = await res.text(); + const h1 = document.createElement("h1") + h1.textContent = "bv1 web player" + document.body.prepend(h1) + document.body.querySelectorAll("a").forEach(e => { + const u = url + "/" + e.textContent + e.onclick = ev => { + ev.preventDefault() + if (!u.endsWith(".bv1")) return alert("thats not bv1!") + document.body.innerHTML = "" + play(u.toString()) + } + }) +} + +async function play(url: string) { + decode_init(1920, 1080) + document.body.innerText = "downloading…" + const res = await fetch(url) + if (!res.ok) throw new Error("not ok"); + let buf: Uint8Array | undefined = new Uint8Array(await res.arrayBuffer()) + document.body.innerText = "" + + const canvas = document.createElement("canvas") + canvas.width = 1920 + canvas.height = 1080 + document.body.append(canvas) + document.body.style.backgroundColor = "#111" + const ctx = canvas.getContext("2d")! + let debug = false; + + document.body.addEventListener("keydown", ev => { + if (ev.code == "KeyD") debug = !debug; + }) + + setInterval(() => { + const frame = decode_frame(buf ?? new Uint8Array(), debug); + buf = undefined + + const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height); + const data = imageData.data; + + for (let y = 0; y < 1080; y++) { + for (let x = 0; x < 1920; x++) { + const ti = (x + y * 1920) * 4; + const si = (x + y * 1920) * 3; + data[ti + 0] = frame[si + 0] + data[ti + 1] = frame[si + 1] + data[ti + 2] = frame[si + 2] + data[ti + 3] = 255 + } + } + + ctx.putImageData(imageData, 0, 0); + + }, 1000 / 30) +} |