diff --git a/.gitignore b/.gitignore index 4fffb2f..3239a16 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ /target /Cargo.lock +**/target \ No newline at end of file diff --git a/Cargo.toml b/Cargo.toml index 65af174..f3b9634 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,6 +14,7 @@ members = [ "crates/streamfer-core", "crates/streamfer-engine", "crates/streamfer-plugin", + "crates/streamfer-plugin-nvdec", ] [dependencies] diff --git a/crates/streamfer-engine/Cargo.toml b/crates/streamfer-engine/Cargo.toml index d442da8..644f8b9 100644 --- a/crates/streamfer-engine/Cargo.toml +++ b/crates/streamfer-engine/Cargo.toml @@ -4,8 +4,11 @@ version = "0.1.0" edition = "2021" [dependencies] +anyhow = { version = "1.0.75", features = ["backtrace"] } cargo-component-bindings = "0.0.0" -wasmtime = "13.0.0" +thiserror = "1.0.49" +wasmtime = { version = "13.0.0", features = ["component-model"] } +wasmtime-wasi = "13.0.0" wit-bindgen = "0.12.0" [package.metadata.component] diff --git a/crates/streamfer-engine/example-module/Cargo.lock b/crates/streamfer-engine/example-module/Cargo.lock new file mode 100644 index 0000000..e634241 --- /dev/null +++ b/crates/streamfer-engine/example-module/Cargo.lock @@ -0,0 +1,417 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "anyhow" +version = "1.0.75" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitflags" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4682ae6287fcf752ecaabbfcc7b6f9b72aa33933dc23a554d853aea8eea8635" + +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + +[[package]] +name = "example-module" +version = "0.1.0" +dependencies = [ + "wit-bindgen", +] + +[[package]] +name = "form_urlencoded" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a62bc1cf6f830c2ec14a513a9fb124d0a213a629668a4186f329db21fe045652" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "hashbrown" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7dfda62a12f55daeae5015f81b0baea145391cb4520f86c248fc615d72640d12" + +[[package]] +name = "heck" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" +dependencies = [ + "unicode-segmentation", +] + +[[package]] +name = "id-arena" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25a2bc672d1148e28034f176e01fffebb08b35768468cc954630da77a1449005" + +[[package]] +name = "idna" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c" +dependencies = [ + "unicode-bidi", + "unicode-normalization", +] + +[[package]] +name = "indexmap" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8adf3ddd720272c6ea8bf59463c04e0f93d0bbf7c5439b691bca2987e0270897" +dependencies = [ + "equivalent", + "hashbrown", + "serde", +] + +[[package]] +name = "itoa" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" + +[[package]] +name = "leb128" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "884e2677b40cc8c339eaefcb701c32ef1fd2493d71118dc0ca4b6a736c93bd67" + +[[package]] +name = "log" +version = "0.4.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" + +[[package]] +name = "memchr" +version = "2.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" + +[[package]] +name = "percent-encoding" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" + +[[package]] +name = "proc-macro2" +version = "1.0.67" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d433d9f1a3e8c1263d9456598b16fec66f4acc9a74dacffd35c7bb09b3a1328" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "pulldown-cmark" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77a1a2f1f0a7ecff9c31abbe177637be0e97a0aef46cf8738ece09327985d998" +dependencies = [ + "bitflags 1.3.2", + "memchr", + "unicase", +] + +[[package]] +name = "quote" +version = "1.0.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "ryu" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" + +[[package]] +name = "semver" +version = "1.0.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad977052201c6de01a8ef2aa3378c4bd23217a056337d1d6da40468d267a4fb0" + +[[package]] +name = "serde" +version = "1.0.188" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf9e0fcba69a370eed61bcf2b728575f726b50b55cba78064753d708ddc7549e" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.188" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4eca7ac642d82aa35b60049a6eccb4be6be75e599bd2e9adb5f875a737654af2" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.107" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b420ce6e3d8bd882e9b243c6eed35dbc9a6110c9769e74b584e0d68d1f20c65" +dependencies = [ + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "smallvec" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "942b4a808e05215192e39f4ab80813e599068285906cc91aa64f923db842bd5a" + +[[package]] +name = "spdx" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b19b32ed6d899ab23174302ff105c1577e45a06b08d4fe0a9dd13ce804bbbf71" +dependencies = [ + "smallvec", +] + +[[package]] +name = "syn" +version = "2.0.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7303ef2c05cd654186cb250d29049a24840ca25d2747c25c0381c8d9e2f582e8" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "tinyvec" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + +[[package]] +name = "unicase" +version = "2.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7d2d4dafb69621809a81864c9c1b864479e1235c0dd4e199924b9742439ed89" +dependencies = [ + "version_check", +] + +[[package]] +name = "unicode-bidi" +version = "0.3.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "unicode-normalization" +version = "0.1.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "unicode-segmentation" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36" + +[[package]] +name = "unicode-xid" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" + +[[package]] +name = "url" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "143b538f18257fac9cad154828a57c6bf5157e1aa604d4816b5995bf6de87ae5" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", +] + +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + +[[package]] +name = "wasm-encoder" +version = "0.33.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34180c89672b3e4825c3a8db4b61a674f1447afd5fe2445b2d22c3d8b6ea086c" +dependencies = [ + "leb128", +] + +[[package]] +name = "wasm-metadata" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f2c051ef041d348324b01ff0419f6f6593f094b4897d93c9cf52d5d1ac879ba" +dependencies = [ + "anyhow", + "indexmap", + "serde", + "serde_json", + "spdx", + "wasm-encoder", + "wasmparser", +] + +[[package]] +name = "wasmparser" +version = "0.113.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "286049849b5a5bd09a8773171be96824afabffc7cc3df6caaf33a38db6cd07ae" +dependencies = [ + "indexmap", + "semver", +] + +[[package]] +name = "wit-bindgen" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4f7c5d6f59ae013fc4c013c76eab667844a46e86b51987acb71b1e32953211a" +dependencies = [ + "bitflags 2.4.0", + "wit-bindgen-rust-macro", +] + +[[package]] +name = "wit-bindgen-core" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f0371c47784e7559efb422f74473e395b49f7101725584e2673657e0b4fc104" +dependencies = [ + "anyhow", + "wit-component", + "wit-parser", +] + +[[package]] +name = "wit-bindgen-rust" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eeab5a09a85b1641690922ce05d79d868a2f2e78e9415a5302f58b9846fab8f1" +dependencies = [ + "anyhow", + "heck", + "wasm-metadata", + "wit-bindgen-core", + "wit-bindgen-rust-lib", + "wit-component", +] + +[[package]] +name = "wit-bindgen-rust-lib" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a13c89c9c1a93e164318745841026f63f889376f38664f86a7f678930280e728" +dependencies = [ + "heck", + "wit-bindgen-core", +] + +[[package]] +name = "wit-bindgen-rust-macro" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a70c97e09751a9a95a592bd8ef84e953e5cdce6ebbfdb35ceefa5cc511da3b71" +dependencies = [ + "anyhow", + "proc-macro2", + "syn", + "wit-bindgen-core", + "wit-bindgen-rust", + "wit-bindgen-rust-lib", + "wit-component", +] + +[[package]] +name = "wit-component" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e2bf941487fc5afa9e3fc94761f6b80ecef5a2bed6239b959d23d9de69e3448" +dependencies = [ + "anyhow", + "bitflags 2.4.0", + "indexmap", + "log", + "serde", + "serde_json", + "wasm-encoder", + "wasm-metadata", + "wasmparser", + "wit-parser", +] + +[[package]] +name = "wit-parser" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a39edca9abb16309def3843af73b58d47d243fe33a9ceee572446bcc57556b9a" +dependencies = [ + "anyhow", + "id-arena", + "indexmap", + "log", + "pulldown-cmark", + "semver", + "serde", + "serde_json", + "unicode-xid", + "url", +] diff --git a/crates/streamfer-engine/example-module/Cargo.toml b/crates/streamfer-engine/example-module/Cargo.toml new file mode 100644 index 0000000..451f209 --- /dev/null +++ b/crates/streamfer-engine/example-module/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "example-module" +version = "0.1.0" +edition = "2021" + +[lib] +crate-type = ["cdylib"] + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +[workspace] + +[dependencies] +wit-bindgen = "0.12.0" diff --git a/crates/streamfer-engine/example-module/example-component.wasm b/crates/streamfer-engine/example-module/example-component.wasm new file mode 100644 index 0000000..9433e97 Binary files /dev/null and b/crates/streamfer-engine/example-module/example-component.wasm differ diff --git a/crates/streamfer-engine/example-module/src/lib.rs b/crates/streamfer-engine/example-module/src/lib.rs new file mode 100644 index 0000000..f5a0b2a --- /dev/null +++ b/crates/streamfer-engine/example-module/src/lib.rs @@ -0,0 +1,17 @@ +wit_bindgen::generate!({ + world: "streamfer", + + exports: { + world: Streamfer, + }, +}); + +struct Streamfer; + +impl Guest for Streamfer { + fn run() -> Result { + let caps = streamfer::main::infer::get_capabilities(); + println!("{:?}", caps); + Ok(caps.len() as _) + } +} diff --git a/crates/streamfer-engine/example-module/wasi_snapshot_preview1.command.wasm b/crates/streamfer-engine/example-module/wasi_snapshot_preview1.command.wasm new file mode 100644 index 0000000..b1baf57 Binary files /dev/null and b/crates/streamfer-engine/example-module/wasi_snapshot_preview1.command.wasm differ diff --git a/crates/streamfer-engine/example-module/wasi_snapshot_preview1.reactor.wasm b/crates/streamfer-engine/example-module/wasi_snapshot_preview1.reactor.wasm new file mode 100644 index 0000000..1900544 Binary files /dev/null and b/crates/streamfer-engine/example-module/wasi_snapshot_preview1.reactor.wasm differ diff --git a/crates/streamfer-engine/example-module/wasi_snapshot_preview1.wasm b/crates/streamfer-engine/example-module/wasi_snapshot_preview1.wasm new file mode 100755 index 0000000..cb0395a Binary files /dev/null and b/crates/streamfer-engine/example-module/wasi_snapshot_preview1.wasm differ diff --git a/crates/streamfer-engine/example-module/wit b/crates/streamfer-engine/example-module/wit new file mode 120000 index 0000000..8c60207 --- /dev/null +++ b/crates/streamfer-engine/example-module/wit @@ -0,0 +1 @@ +../wit \ No newline at end of file diff --git a/crates/streamfer-engine/examples/component.rs b/crates/streamfer-engine/examples/component.rs new file mode 100644 index 0000000..df24a80 --- /dev/null +++ b/crates/streamfer-engine/examples/component.rs @@ -0,0 +1,10 @@ +use std::sync::Arc; + +use streamfer_engine::Engine; + +fn main() { + let engine = Arc::new(Engine::new().unwrap()); + let wasm = std::fs::read("./example-module/example-component.wasm").unwrap(); + let mut module = engine.load_module(&wasm).unwrap(); + module.run().unwrap(); +} diff --git a/crates/streamfer-engine/src/lib.rs b/crates/streamfer-engine/src/lib.rs index 1c7feb3..ed226ed 100644 --- a/crates/streamfer-engine/src/lib.rs +++ b/crates/streamfer-engine/src/lib.rs @@ -1 +1,75 @@ -cargo_component_bindings::generate!(); +use std::sync::Arc; + +use streamfer::main::infer::Cap; +use wasmtime::{component::*, Store}; + +wasmtime::component::bindgen!("streamfer"); + +pub struct State {} + +impl streamfer::main::infer::Host for State { + fn get_capabilities(&mut self) -> wasmtime::Result> { + Ok(vec![Cap::CapCodecH264]) + } +} + +#[derive(Debug, thiserror::Error)] +pub enum Error { + #[error("WasmtimeError: {0}")] + WasmtimeError(#[from] wasmtime::Error), +} + +pub struct Engine { + wasmtime_engine: wasmtime::Engine, +} + +impl Engine { + pub fn new() -> Result { + let mut config = wasmtime::Config::new(); + config.wasm_component_model(true).parallel_compilation(true); + config.wasm_threads(true); + + Ok(Self { + wasmtime_engine: wasmtime::Engine::new(&config)?, + }) + } + + pub fn load_module(self: Arc, wasm: &[u8]) -> Result { + let component = Component::from_binary(&self.wasmtime_engine, wasm)?; + let mut store = Store::new(&self.wasmtime_engine, State {}); + let mut linker = Linker::new(&self.wasmtime_engine); + + Streamfer::add_to_linker(&mut linker, |s: &mut State| s)?; + + let (streamfer, _) = Streamfer::instantiate(&mut store, &component, &linker)?; + + Module::new(self.clone(), streamfer, store) + } +} + +pub struct Module { + engine: Arc, + streamfer: Streamfer, + store: Store, +} + +impl Module { + fn new(engine: Arc, streamfer: Streamfer, store: Store) -> Result { + Ok(Module { + engine, + streamfer, + store, + }) + } + + pub fn run(&mut self) -> Result<(), Error> { + let mut results = [Val::Bool(false)]; + self.streamfer + .run + .call(&mut self.store, &[], &mut results)?; + + println!("{:?}", results); + + Ok(()) + } +} diff --git a/crates/streamfer-engine/wit/streamfer.wit b/crates/streamfer-engine/wit/streamfer.wit index a97c828..dedfb13 100644 --- a/crates/streamfer-engine/wit/streamfer.wit +++ b/crates/streamfer-engine/wit/streamfer.wit @@ -1,6 +1,8 @@ package streamfer:main + world streamfer { - export infer + import infer + export run: func() -> result } \ No newline at end of file diff --git a/crates/streamfer-plugin-nvdec/Cargo.toml b/crates/streamfer-plugin-nvdec/Cargo.toml index 6dfa024..57721c7 100644 --- a/crates/streamfer-plugin-nvdec/Cargo.toml +++ b/crates/streamfer-plugin-nvdec/Cargo.toml @@ -3,6 +3,8 @@ name = "streamfer-plugin-nvdec" version = "0.1.0" edition = "2021" -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +[lib] +crate-type = ["cdylib"] [dependencies] +tokio = { version = "1.32.0", features = ["time"] } diff --git a/crates/streamfer-plugin-nvdec/src/lib.rs b/crates/streamfer-plugin-nvdec/src/lib.rs index 7d12d9a..14d3bbc 100644 --- a/crates/streamfer-plugin-nvdec/src/lib.rs +++ b/crates/streamfer-plugin-nvdec/src/lib.rs @@ -1,14 +1,60 @@ -pub fn add(left: usize, right: usize) -> usize { - left + right +use std::{future::Future, time::Duration}; + +#[no_mangle] +pub static VERSION: &str = "0.1.0"; + +#[no_mangle] +pub static VENDOR: &str = "nvidia"; + +#[no_mangle] +pub static COMPONENTS: &[&str] = &["decoder"]; + +#[repr(C)] +#[derive(Debug)] +pub struct DeviceInfo { + pub index: u32, + pub name: String, } -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn it_works() { - let result = add(2, 2); - assert_eq!(result, 4); - } +#[repr(C)] +#[derive(Debug)] +pub struct Device { + pub index: u32, + pub name: String, + pub memory: DeviceMemory, +} + +#[repr(C)] +#[derive(Debug, Clone, Copy)] +pub struct DeviceMemory { + pub address_space: u64, + pub total_size: u64, + pub free_size: u64, + pub mappable_to: &'static [u64], +} + +#[no_mangle] +pub fn probe() -> Result, &'static str> { + Ok(vec![DeviceInfo { + index: 0, + name: String::from("CPU"), + }]) +} + +#[no_mangle] +pub fn init_device(index: u32) -> Box>> { + Box::new(async move { + // tokio::time::sleep(Duration::from_millis(100)).await; + + Ok(Device { + index, + name: String::from("CPU0"), + memory: DeviceMemory { + address_space: 0, + total_size: 100, + free_size: 100, + mappable_to: &[], + }, + }) + }) } diff --git a/crates/streamfer-plugin/Cargo.toml b/crates/streamfer-plugin/Cargo.toml index 121b7f2..d877b8f 100644 --- a/crates/streamfer-plugin/Cargo.toml +++ b/crates/streamfer-plugin/Cargo.toml @@ -6,3 +6,8 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +dlopen2 = "0.6.1" +thiserror = "1.0.49" + +[dev-dependencies] +tokio = { version = "1.32.0", features = ["macros", "rt"] } diff --git a/crates/streamfer-plugin/examples/demo.rs b/crates/streamfer-plugin/examples/demo.rs new file mode 100644 index 0000000..1e48826 --- /dev/null +++ b/crates/streamfer-plugin/examples/demo.rs @@ -0,0 +1,8 @@ +#[tokio::main(flavor = "current_thread")] +async fn main() { + let mut manager = streamfer_plugin::PluginManager::new(); + let plug = manager + .load("/home/andrey/workspace/andreytkachenko/streamfer/target/release/") + .await + .unwrap(); +} diff --git a/crates/streamfer-plugin/src/lib.rs b/crates/streamfer-plugin/src/lib.rs index 7d12d9a..99f9b23 100644 --- a/crates/streamfer-plugin/src/lib.rs +++ b/crates/streamfer-plugin/src/lib.rs @@ -1,14 +1,178 @@ -pub fn add(left: usize, right: usize) -> usize { - left + right +use std::{future::Future, path::Path}; + +use dlopen2::{ + raw::Library, + wrapper::{Container, WrapperApi}, +}; +const COMPONENT_VIDEO_DECODER: &str = "video_decoder_v1"; +const COMPONENT_INFERENCE: &str = "inference_v1"; +const COMPONENT_PIXEL_OPS: &str = "pixel_ops_v1"; +const COMPONENT_TENSOR_OPS: &str = "tensor_ops_v1"; + +#[repr(C)] +#[derive(Debug, PartialEq, Eq)] +pub struct MemoryBlock { + pub address_space: u64, + pub address: u64, + pub align: u64, + pub length: u64, + pub row_stride: Option, + pub row_length: Option, } -#[cfg(test)] -mod tests { - use super::*; +#[repr(C)] +#[derive(Debug, PartialEq, Eq)] +pub struct MemoryMap<'a> { + pub block: MemoryBlock, + pub slice: &'a [u8], +} - #[test] - fn it_works() { - let result = add(2, 2); - assert_eq!(result, 4); +#[repr(C)] +#[derive(Debug, Clone, Copy)] +pub struct DeviceMemory { + pub address_space: u64, + pub total_size: u64, + pub free_size: u64, + pub mappable_to: &'static [u64], +} + +#[repr(C)] +#[derive(Debug)] +pub struct DeviceInfo { + pub index: u32, + pub name: String, +} + +#[repr(C)] +#[derive(Debug)] +pub struct Device { + pub index: u32, + pub name: String, + pub memory: DeviceMemory, +} + +#[derive(WrapperApi)] +struct PluginApi<'a> { + #[dlopen2_name = "VERSION"] + version: &'a &'static str, + + #[dlopen2_name = "VENDOR"] + vendor: &'a &'static str, + + #[dlopen2_name = "COMPONENTS"] + components: &'a &'static [&'static str], + + probe: fn() -> Result, u64>, + + init_device: fn(dev: u32) -> Box>>, + // mem_read_async: fn(mem: &MemoryBlock) -> Result, + // mem_read_poll: fn(task: usize, cx: &mut Context<'_>) -> Poll, u64>>, + + // mem_write_async: fn( + // data: &[u8], + // device: &DeviceMemory, + // row_lenght: Option, + // row_stride: Option, + // cx: &mut Context<'_>, + // ) -> Poll>, + + // mem_alloc_async: fn( + // lenght: u64, + // device: &DeviceMemory, + // row_lenght: Option, + // row_stride: Option, + // cx: &mut Context<'_>, + // ) -> Result, + + // mem_clone_async: fn(mem: &MemoryBlock, cx: &mut Context<'_>) -> Poll>, + + // mem_copy_async: fn( + // dst: &mut MemoryBlock, + // src: &MemoryBlock, + // cx: &mut Context<'_>, + // ) -> Poll>, + + // mem_map_async: fn(mem: MemoryBlock, cx: &mut Context<'_>) -> Poll, u64>>, + + // mem_unmap_async: fn(mmap: MemoryMap, cx: &mut Context<'_>) -> Poll>, + + // mem_free: fn(mem: MemoryBlock) -> Result<(), u64>, + + // describe_error: fn(errno: u64) -> Option<&'a str>, +} + +#[repr(C)] +struct DecoderConfig {} + +#[repr(C)] +struct DeviceCapabilities {} + +#[repr(C)] +struct DecodedFrame { + id: u64, + device: u64, + width: u16, + height: u16, + channels: u8, +} + +// #[derive(WrapperApi)] +// struct DecoderApi<'a> { +// decoder_enumerate_devices: fn() -> Result, u64>, +// decoder_device_capabilities: fn(device: u64) -> Result, +// decoder_create: fn(device: u64, config: DecoderConfig) -> Result<*const (), u64>, +// decoder_enqueue: +// fn(decoder: *const (), data: &[u8], timestamp: u64, last_one: bool) -> Result<(), u64>, +// decoder_dequeue: fn(decoder: *const ()) -> Result, +// } + +pub struct DecoderPlugin {} + +impl DecoderPlugin { + pub fn load() {} +} + +#[derive(Debug, thiserror::Error)] +pub enum Error { + #[error("DlOpenError: {0}")] + DlOpenError(#[from] dlopen2::Error), +} + +pub struct Plugin<'a> { + lib: Library, + base: PluginApi<'a>, + // decoder: Option>, + // inference: Option>, + // image_ops: Option>, + // pixel_ops: Option>, + // tensor_ops: Option>, +} + +pub struct PluginManager {} + +impl PluginManager { + pub fn new() -> Self { + Self {} + } + + pub async fn load>(&mut self, prefix: P) -> Result<(), Error> { + let mut path = prefix.as_ref().to_owned(); + path.push("libstreamfer_plugin_nvdec.so"); + + let plugin: Container = unsafe { Container::load(path) }?; + + let devices = plugin.probe().unwrap(); + + println!("{:?} {:?} {:?}", plugin.version, plugin.components, devices); + + println!("{:?}", Box::into_pin(plugin.init_device(0)).await.unwrap()); + + Ok(()) + } +} + +impl Default for PluginManager { + fn default() -> Self { + Self::new() } }