diff --git a/CHANGELOG.md b/CHANGELOG.md index b6d1da5..435452f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,15 +1,24 @@ # 0.10.0 - Split core types and traits into `nokhwa-core` + - Now you can use `nokhwa`'s Camera types in your own packages, to e.g. create `nokhwa` extensions or use `nokhwa`'s decoders. - Removed support for JS Bindings - This is due to lack of support for non-C style enums in `wasm-bindgen`. + - You can still use `nokhwa` in the browser, you just can't use it from JS. - New CameraControl API - Deprecated `raw_camera_control` API - New RequestedFormat API - Removed Network Camera - Network Camera is now supported through OpenCV Camera instead. - New Buffer API - - PixelFormat API +- New PixelFormat API - Callback Camera: Removed `Result` from the `index()` and `camera_info()` API. +- AVFoundation Improvements +- Split V4L2 into its own crate +- New Formats: + - NV12 + - RAWRGB + - GRAY +- Added warning about decoding reducing performance - After a year in development, We hope it was worth the wait. # 0.9.0 diff --git a/Cargo.toml b/Cargo.toml index 0f67f78..df60ca8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "nokhwa" -version = "0.10.0-rc.3" +version = "0.10.0" authors = ["l1npengtul "] edition = "2021" description = "A Simple-to-use, cross-platform Rust Webcam Capture Library" diff --git a/nokhwa-bindings-macos/Cargo.toml b/nokhwa-bindings-macos/Cargo.toml index 9092538..37e57e1 100644 --- a/nokhwa-bindings-macos/Cargo.toml +++ b/nokhwa-bindings-macos/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "nokhwa-bindings-macos" -version = "0.2.0-rc.2" +version = "0.2.0" edition = "2018" authors = ["l1npengtul"] license = "Apache-2.0" diff --git a/nokhwa-bindings-windows/Cargo.toml b/nokhwa-bindings-windows/Cargo.toml index 9c20210..40ffacd 100644 --- a/nokhwa-bindings-windows/Cargo.toml +++ b/nokhwa-bindings-windows/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "nokhwa-bindings-windows" -version = "0.4.0-rc.2" +version = "0.4.0" authors = ["l1npengtul"] edition = "2021" license = "Apache-2.0" diff --git a/nokhwa-core/Cargo.toml b/nokhwa-core/Cargo.toml index dee7dcb..3141756 100644 --- a/nokhwa-core/Cargo.toml +++ b/nokhwa-core/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "nokhwa-core" -version = "0.1.0-rc.2" +version = "0.1.0" authors = ["l1npengtul "] edition = "2021" description = "Core type definitions for nokhwa" diff --git a/nokhwa-core/src/buffer.rs b/nokhwa-core/src/buffer.rs index c3f8661..547f00a 100644 --- a/nokhwa-core/src/buffer.rs +++ b/nokhwa-core/src/buffer.rs @@ -22,8 +22,10 @@ use crate::{ use bytes::Bytes; use image::ImageBuffer; -/// A buffer returned by a camera to accomodate custom decoding. +/// A buffer returned by a camera to accommodate custom decoding. /// Contains information of Resolution, the buffer's [`FrameFormat`], and the buffer. +/// +/// Note that decoding on the main thread **will** decrease your performance and lead to dropped frames. #[derive(Clone, Debug, Hash, PartialOrd, PartialEq, Eq)] pub struct Buffer { resolution: Resolution, @@ -34,6 +36,7 @@ pub struct Buffer { impl Buffer { /// Creates a new buffer with a [`&[u8]`]. #[must_use] + #[inline] pub fn new(res: Resolution, buf: &[u8], source_frame_format: FrameFormat) -> Self { Self { resolution: res, @@ -69,6 +72,7 @@ impl Buffer { /// Decodes a image with allocation using the provided [`FormatDecoder`]. /// # Errors /// Will error when the decoding fails. + #[inline] pub fn decode_image( &self, ) -> Result>, NokhwaError> { @@ -86,6 +90,7 @@ impl Buffer { /// Decodes a image with allocation using the provided [`FormatDecoder`] into a `buffer`. /// # Errors /// Will error when the decoding fails, or the provided buffer is too small. + #[inline] pub fn decode_image_to_buffer( &self, buffer: &mut [u8], diff --git a/nokhwa-core/src/pixel_format.rs b/nokhwa-core/src/pixel_format.rs index 696eb0d..71708e6 100644 --- a/nokhwa-core/src/pixel_format.rs +++ b/nokhwa-core/src/pixel_format.rs @@ -29,6 +29,7 @@ pub trait FormatDecoder: Clone + Sized + Send + Sync { /// Allocates and returns a `Vec` /// # Errors /// If the data is malformed, or the source [`FrameFormat`] is incompatible, this will error. + #[inline] fn write_output( fcc: FrameFormat, resolution: Resolution, @@ -38,6 +39,7 @@ pub trait FormatDecoder: Clone + Sized + Send + Sync { /// Writes to a user provided buffer. /// # Errors /// If the data is malformed, the source [`FrameFormat`] is incompatible, or the user-alloted buffer is not large enough, this will error. + #[inline] fn write_output_buffer( fcc: FrameFormat, resolution: Resolution, diff --git a/nokhwa-core/src/types.rs b/nokhwa-core/src/types.rs index 1c4a6e9..e0797b9 100644 --- a/nokhwa-core/src/types.rs +++ b/nokhwa-core/src/types.rs @@ -1472,6 +1472,7 @@ impl Display for ApiBackend { /// - The input data is of the right size, does not exceed bounds, and/or the final size matches with the initial size. #[cfg(all(feature = "mjpeg", not(target_arch = "wasm")))] #[cfg_attr(feature = "docs-features", doc(cfg(feature = "mjpeg")))] +#[inline] pub fn mjpeg_to_rgb(data: &[u8], rgba: bool) -> Result, NokhwaError> { use mozjpeg::Decompress; @@ -1534,6 +1535,7 @@ pub fn mjpeg_to_rgb(_data: &[u8], _rgba: bool) -> Result, NokhwaError> { /// If the decoding fails (e.g. invalid MJPEG stream), the buffer is not large enough, or you are doing this on `WebAssembly`, this will error. #[cfg(all(feature = "mjpeg", not(target_arch = "wasm")))] #[cfg_attr(feature = "docs-features", doc(cfg(feature = "mjpeg")))] +#[inline] pub fn buf_mjpeg_to_rgb(data: &[u8], dest: &mut [u8], rgba: bool) -> Result<(), NokhwaError> { use mozjpeg::Decompress; @@ -1593,6 +1595,7 @@ pub fn buf_mjpeg_to_rgb(_data: &[u8], _dest: &mut [u8], _rgba: bool) -> Result<( } /// Returns the predicted size of the destination YUYV422 buffer. +#[inline] pub fn yuyv422_predicted_size(size: usize, rgba: bool) -> usize { let pixel_size = if rgba { 4 } else { 3 }; // yuyv yields 2 3-byte pixels per yuyv chunk @@ -1608,6 +1611,7 @@ pub fn yuyv422_predicted_size(size: usize, rgba: bool) -> usize { /// Converts a YUYV 4:2:2 datastream to a RGB888 Stream. [For further reading](https://en.wikipedia.org/wiki/YUV#Converting_between_Y%E2%80%B2UV_and_RGB) /// # Errors /// This may error when the data stream size is not divisible by 4, a i32 -> u8 conversion fails, or it fails to read from a certain index. +#[inline] pub fn yuyv422_to_rgb(data: &[u8], rgba: bool) -> Result, NokhwaError> { let pixel_size = if rgba { 4 } else { 3 }; // yuyv yields 2 3-byte pixels per yuyv chunk @@ -1622,6 +1626,7 @@ pub fn yuyv422_to_rgb(data: &[u8], rgba: bool) -> Result, NokhwaError> { /// Same as [`yuyv422_to_rgb`] but with a destination buffer instead of a return `Vec` /// # Errors /// If the stream is invalid YUYV, or the destination buffer is not large enough, this will error. +#[inline] pub fn buf_yuyv422_to_rgb(data: &[u8], dest: &mut [u8], rgba: bool) -> Result<(), NokhwaError> { if data.len() % 4 != 0 { return Err(NokhwaError::ProcessFrameError { @@ -1732,6 +1737,7 @@ pub fn yuyv444_to_rgba(y: i32, u: i32, v: i32) -> [u8; 4] { /// Converts a YUYV 4:2:0 bi-planar (NV12) datastream to a RGB888 Stream. [For further reading](https://en.wikipedia.org/wiki/YUV#Converting_between_Y%E2%80%B2UV_and_RGB) /// # Errors /// This may error when the data stream size is wrong. +#[inline] pub fn nv12_to_rgb( resolution: Resolution, data: &[u8], @@ -1750,6 +1756,7 @@ pub fn nv12_to_rgb( /// # Errors /// This may error when the data stream size is wrong. #[allow(clippy::similar_names)] +#[inline] pub fn buf_nv12_to_rgb( resolution: Resolution, data: &[u8], diff --git a/src/camera.rs b/src/camera.rs index c137964..92e91cf 100644 --- a/src/camera.rs +++ b/src/camera.rs @@ -81,6 +81,17 @@ impl Camera { ) } + /// Allows creation of a [`Camera`] with a custom backend. This is useful if you are creating e.g. a custom module. + /// + /// You **must** have set a format beforehand. + pub fn with_custom( + idx: CameraIndex, + api: ApiBackend, + device: Box, + ) -> Self { + Self { idx, api, device } + } + /// Gets the current Camera's index. #[must_use] pub fn index(&self) -> &CameraIndex { diff --git a/src/init.rs b/src/init.rs index 2db827a..2c4854f 100644 --- a/src/init.rs +++ b/src/init.rs @@ -53,6 +53,7 @@ fn status_avfoundation() -> bool { ) } +// todo: make this work on browser code /// Initialize `nokhwa` /// It is your responsibility to call this function before anything else, but only on `MacOS`. /// diff --git a/src/threaded.rs b/src/threaded.rs index 2e819a4..258289a 100644 --- a/src/threaded.rs +++ b/src/threaded.rs @@ -96,6 +96,24 @@ impl CallbackCamera { }) } + /// Allows creation of a [`Camera`] with a custom backend. This is useful if you are creating e.g. a custom module. + /// + /// You **must** have set a format beforehand. + pub fn with_custom(camera: Camera, callback: impl FnMut(Buffer) + Send + 'static) -> Self { + CallbackCamera { + camera: Arc::new(Mutex::new(camera)), + frame_callback: Arc::new(Mutex::new(Box::new(callback))), + last_frame_captured: Arc::new(Mutex::new(Buffer::new( + Resolution::new(0, 0), + &vec![], + FrameFormat::GRAY, + ))), + die_bool: Arc::new(Default::default()), + current_camera, + handle: Arc::new(Mutex::new(None)), + } + } + /// Gets the current Camera's index. pub fn index(&self) -> &CameraIndex { &self.current_camera.index()