diff --git a/.envrc b/.envrc new file mode 100644 index 0000000..5bf8fc1 --- /dev/null +++ b/.envrc @@ -0,0 +1,3 @@ +source_url "https://raw.githubusercontent.com/cachix/devenv/95f329d49a8a5289d31e0982652f7058a189bfca/direnvrc" "sha256-d+8cBpDfDBj41inrADaJt+bDWhOktwslgoP5YiGJ1v0=" + +use devenv \ No newline at end of file diff --git a/.gitignore b/.gitignore index d45a211..d3be8ab 100644 --- a/.gitignore +++ b/.gitignore @@ -12,3 +12,12 @@ nokhwa.iml target .DS_STORE +# Devenv +.devenv* +devenv.local.nix + +# direnv +.direnv + +# pre-commit +.pre-commit-config.yaml diff --git a/Cargo.toml b/Cargo.toml index 7b94aff..eb1cfce 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "nokhwa" -version = "0.10.4" +version = "0.10.5" authors = ["l1npengtul "] edition = "2021" description = "A Simple-to-use, cross-platform Rust Webcam Capture Library" @@ -37,7 +37,8 @@ input-opencv = ["opencv", "opencv/videoio", "opencv/rgb", "rgb", "nokhwa-core/op input-jscam = ["web-sys", "js-sys", "wasm-bindgen-futures", "wasm-bindgen", "wasm-rs-async-executor"] output-wgpu = ["wgpu", "nokhwa-core/wgpu-types"] #output-wasm = ["input-jscam"] -output-threaded = ["parking_lot"] +output-threaded = ["parking_lot", "camera-sync-impl"] +camera-sync-impl = [] small-wasm = [] docs-only = ["input-native", "input-opencv", "input-jscam","output-wgpu", "output-threaded", "serialize"] docs-nolink = ["nokhwa-core/docs-features"] @@ -57,27 +58,23 @@ version = "1.0" optional = true [dependencies.flume] -version = "0.10" +version = "0.11" optional = true [dependencies.image] -version = "0.24" +version = "0.25" default-features = false -[dependencies.v4l] -version = "0.13" -optional = true - [dependencies.usb_enumeration] version = "0.2" optional = true [dependencies.wgpu] -version = "0.16" +version = "22" optional = true [dependencies.opencv] -version = "0.81" +version = "0.93" default-features = false optional = true diff --git a/devenv.lock b/devenv.lock new file mode 100644 index 0000000..436a42f --- /dev/null +++ b/devenv.lock @@ -0,0 +1,116 @@ +{ + "nodes": { + "devenv": { + "locked": { + "dir": "src/modules", + "lastModified": 1728679870, + "owner": "cachix", + "repo": "devenv", + "rev": "c1117e089b5b78d54885603bf988d26fe88cf44e", + "type": "github" + }, + "original": { + "dir": "src/modules", + "owner": "cachix", + "repo": "devenv", + "type": "github" + } + }, + "flake-compat": { + "flake": false, + "locked": { + "lastModified": 1696426674, + "owner": "edolstra", + "repo": "flake-compat", + "rev": "0f9255e01c2351cc7d116c072cb317785dd33b33", + "type": "github" + }, + "original": { + "owner": "edolstra", + "repo": "flake-compat", + "type": "github" + } + }, + "gitignore": { + "inputs": { + "nixpkgs": [ + "pre-commit-hooks", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1709087332, + "owner": "hercules-ci", + "repo": "gitignore.nix", + "rev": "637db329424fd7e46cf4185293b9cc8c88c95394", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "gitignore.nix", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1716977621, + "owner": "cachix", + "repo": "devenv-nixpkgs", + "rev": "4267e705586473d3e5c8d50299e71503f16a6fb6", + "type": "github" + }, + "original": { + "owner": "cachix", + "ref": "rolling", + "repo": "devenv-nixpkgs", + "type": "github" + } + }, + "nixpkgs-stable": { + "locked": { + "lastModified": 1728627514, + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "c505ebf777526041d792a49d5f6dd4095ea391a7", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-24.05", + "repo": "nixpkgs", + "type": "github" + } + }, + "pre-commit-hooks": { + "inputs": { + "flake-compat": "flake-compat", + "gitignore": "gitignore", + "nixpkgs": [ + "nixpkgs" + ], + "nixpkgs-stable": "nixpkgs-stable" + }, + "locked": { + "lastModified": 1728727368, + "owner": "cachix", + "repo": "pre-commit-hooks.nix", + "rev": "eb74e0be24a11a1531b5b8659535580554d30b28", + "type": "github" + }, + "original": { + "owner": "cachix", + "repo": "pre-commit-hooks.nix", + "type": "github" + } + }, + "root": { + "inputs": { + "devenv": "devenv", + "nixpkgs": "nixpkgs", + "pre-commit-hooks": "pre-commit-hooks" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/devenv.nix b/devenv.nix new file mode 100644 index 0000000..5ce31bf --- /dev/null +++ b/devenv.nix @@ -0,0 +1,48 @@ +{ pkgs, lib, config, inputs, stdenv, ... }: + +{ + # https://devenv.sh/basics/ + env.GREET = "devenv"; + env.LIBCLANG_PATH = "${config.env.DEVENV_PROFILE}/lib/libclang.so"; + env.CPATH = "${config.env.DEVENV_PROFILE}/include"; + # https://devenv.sh/packages/ + packages = [ pkgs.git (pkgs.v4l-utils.override { withUtils = true; }) pkgs.clangStdenv pkgs.mesa + pkgs.cmake pkgs.opencv4 pkgs.systemdLibs pkgs.libudev-zero + pkgs.libudev0-shim pkgs.vcpkg pkgs.pkg-config pkgs.libclang + pkgs.fontconfig pkgs.clang-tools pkgs.linuxHeaders pkgs.gccStdenv pkgs.libcxxStdenv + pkgs.glibc_multi + ]; + + # https://devenv.sh/languages/ + languages.rust.enable = true; + # https://devenv.sh/processes/ + processes.cargo-watch.exec = "cargo-watch"; + + # https://devenv.sh/services/ + # services.postgres.enable = true; + + # https://devenv.sh/scripts/ + scripts.hello.exec = '' + echo hello from $GREET + ''; + + enterShell = '' + hello + git --version + echo ''${LIBCLANG_PATH} + echo ''${CPATH} + ''; + + # https://devenv.sh/tests/ + enterTest = '' + echo "Running tests" + git --version | grep --color=auto "${pkgs.git.version}" + ''; + + + + # https://devenv.sh/pre-commit-hooks/ + # pre-commit.hooks.shellcheck.enable = true; + + # See full reference at https://devenv.sh/reference/options/ +} \ No newline at end of file diff --git a/devenv.yaml b/devenv.yaml new file mode 100644 index 0000000..116a2ad --- /dev/null +++ b/devenv.yaml @@ -0,0 +1,15 @@ +# yaml-language-server: $schema=https://devenv.sh/devenv.schema.json +inputs: + nixpkgs: + url: github:cachix/devenv-nixpkgs/rolling + +# If you're using non-OSS software, you can set allowUnfree to true. +# allowUnfree: true + +# If you're willing to use a package that's vulnerable +# permittedInsecurePackages: +# - "openssl-1.1.1w" + +# If you have more than one devenv you can merge them +#imports: +# - ./backend diff --git a/nokhwa-bindings-linux/Cargo.toml b/nokhwa-bindings-linux/Cargo.toml index 9f7f3ce..595503a 100644 --- a/nokhwa-bindings-linux/Cargo.toml +++ b/nokhwa-bindings-linux/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "nokhwa-bindings-linux" -version = "0.1.0" +version = "0.1.1" edition = "2021" license = "Apache-2.0" repository = "https://github.com/l1npengtul/nokhwa" @@ -20,5 +20,4 @@ version = "0.1.0" path = "../nokhwa-core" [target.'cfg(target_os="linux")'.dependencies] -v4l = "0.14" -v4l2-sys-mit = "0.3" +v4l = { version = "0.14", features = ["v4l2-sys"] } diff --git a/nokhwa-bindings-linux/src/lib.rs b/nokhwa-bindings-linux/src/lib.rs index bba8fc3..23647a6 100644 --- a/nokhwa-bindings-linux/src/lib.rs +++ b/nokhwa-bindings-linux/src/lib.rs @@ -35,12 +35,12 @@ mod internal { control::{Control, Flags, Type, Value}, frameinterval::FrameIntervalEnum, framesize::FrameSizeEnum, - io::traits::{CaptureStream, Stream}, + io::traits::CaptureStream, prelude::MmapStream, video::{capture::Parameters, Capture}, Device, Format, FourCC, }; - use v4l2_sys_mit::{ + use v4l::v4l_sys::{ V4L2_CID_BACKLIGHT_COMPENSATION, V4L2_CID_BRIGHTNESS, V4L2_CID_CONTRAST, V4L2_CID_EXPOSURE, V4L2_CID_FOCUS_RELATIVE, V4L2_CID_GAIN, V4L2_CID_GAMMA, V4L2_CID_HUE, V4L2_CID_IRIS_RELATIVE, V4L2_CID_PAN_RELATIVE, V4L2_CID_SATURATION, V4L2_CID_SHARPNESS, diff --git a/nokhwa-core/Cargo.toml b/nokhwa-core/Cargo.toml index e87e2c3..eab03ce 100644 --- a/nokhwa-core/Cargo.toml +++ b/nokhwa-core/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "nokhwa-core" -version = "0.1.2" +version = "0.1.3" authors = ["l1npengtul "] edition = "2021" description = "Core type definitions for nokhwa" @@ -24,7 +24,7 @@ thiserror = "1.0" bytes = "1.3" [dependencies.image] -version = "0.24" +version = "0.25" default-features = false [dependencies.serde] @@ -33,16 +33,16 @@ features = ["derive"] optional = true [dependencies.wgpu] -version = "0.16" +version = "22" optional = true [dependencies.opencv] -version = "0.81" +version = "0.93" default-features = false optional = true [dependencies.mozjpeg] -version = "0.9" +version = "0.10" optional = true [package.metadata.docs.rs] diff --git a/nokhwa-core/src/buffer.rs b/nokhwa-core/src/buffer.rs index 37b694a..7432adb 100644 --- a/nokhwa-core/src/buffer.rs +++ b/nokhwa-core/src/buffer.rs @@ -19,7 +19,7 @@ use crate::{ pixel_format::FormatDecoder, types::{FrameFormat, Resolution}, }; -use bytes::{Buf, Bytes}; +use bytes::Bytes; use image::ImageBuffer; /// A buffer returned by a camera to accommodate custom decoding. diff --git a/nokhwa-core/src/types.rs b/nokhwa-core/src/types.rs index 874875a..4b8eeb3 100644 --- a/nokhwa-core/src/types.rs +++ b/nokhwa-core/src/types.rs @@ -1501,24 +1501,24 @@ pub fn mjpeg_to_rgb(data: &[u8], rgba: bool) -> Result, NokhwaError> { } }; - let scanlines_res: Option> = jpeg_decompress.read_scanlines_flat(); + let scanlines_res = match jpeg_decompress.read_scanlines::() { + Ok(v) => v, + Err(why) => return Err(NokhwaError::ProcessFrameError { + src: FrameFormat::MJPEG, + destination: "JPEG".to_string(), + error: why.to_string(), + }) + }; // assert!(jpeg_decompress.finish_decompress()); - if !jpeg_decompress.finish_decompress() { - return Err(NokhwaError::ProcessFrameError { + jpeg_decompress.finish().map_err(|why| { + NokhwaError::ProcessFrameError { src: FrameFormat::MJPEG, destination: "RGB888".to_string(), - error: "JPEG Decompressor did not finish.".to_string(), - }); - } - - match scanlines_res { - Some(pixels) => Ok(pixels), - None => Err(NokhwaError::ProcessFrameError { - src: FrameFormat::MJPEG, - destination: "RGB888".to_string(), - error: "Failed to get read readlines into RGB888 pixels!".to_string(), - }), - } + error: why.to_string(), + } + })?; + + Ok(scanlines_res) } #[cfg(not(all(feature = "mjpeg", not(target_arch = "wasm"))))] @@ -1573,15 +1573,21 @@ pub fn buf_mjpeg_to_rgb(data: &[u8], dest: &mut [u8], rgba: bool) -> Result<(), }); } - jpeg_decompress.read_scanlines_flat_into(dest); - // assert!(jpeg_decompress.finish_decompress()); - if !jpeg_decompress.finish_decompress() { - return Err(NokhwaError::ProcessFrameError { + jpeg_decompress.read_scanlines_into::(dest).map_err(|why| { + NokhwaError::ProcessFrameError { src: FrameFormat::MJPEG, destination: "RGB888".to_string(), - error: "JPEG Decompressor did not finish.".to_string(), - }); - } + error: why.to_string(), + } + })?; + // assert!(jpeg_decompress.finish_decompress()); + jpeg_decompress.finish().map_err(|why| { + NokhwaError::ProcessFrameError { + src: FrameFormat::MJPEG, + destination: "RGB888".to_string(), + error: why.to_string(), + } + })?; Ok(()) } diff --git a/src/camera.rs b/src/camera.rs index 92e91cf..31aca6e 100644 --- a/src/camera.rs +++ b/src/camera.rs @@ -578,5 +578,5 @@ fn init_camera( Ok(camera_backend) } -#[cfg(feature = "output-threaded")] +#[cfg(feature = "camera-sync-impl")] unsafe impl Send for Camera {}