mirror of
https://github.com/l1npengtul/nokhwa.git
synced 2026-07-04 02:27:26 +00:00
fix opencv, v4l2, jscam, deprecate gst, ipcam
This commit is contained in:
+3
-21
@@ -27,15 +27,13 @@ input-avfoundation = ["nokhwa-bindings-macos"]
|
||||
# Re-enable it once soundness has been proven + mozjpeg is updated to 0.9.x
|
||||
# input-uvc = ["uvc", "uvc/vendor", "usb_enumeration", "lazy_static"]
|
||||
input-opencv = ["opencv", "opencv/rgb", "rgb"]
|
||||
input-ipcam = ["input-opencv"]
|
||||
input-gst = ["gstreamer", "glib", "gstreamer-app", "gstreamer-video", "regex", "parking_lot"]
|
||||
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 = []
|
||||
small-wasm = []
|
||||
docs-only = ["input-v4l", "input-opencv", "input-ipcam", "input-gst", "input-msmf", "input-avfoundation", "input-jscam","output-wgpu", "output-threaded"]
|
||||
docs-nolink = ["glib/dox", "gstreamer-app/dox", "gstreamer/dox", "gstreamer-video/dox", "opencv/docs-only"]
|
||||
docs-only = ["input-v4l", "input-opencv", "input-msmf", "input-avfoundation", "input-jscam","output-wgpu", "output-threaded"]
|
||||
docs-nolink = ["opencv/docs-only"]
|
||||
docs-features = []
|
||||
test-fail-warning = []
|
||||
|
||||
@@ -76,7 +74,7 @@ version = "0.14"
|
||||
optional = true
|
||||
|
||||
[dependencies.opencv]
|
||||
version = "0.70"
|
||||
version = "0.72"
|
||||
default-features = false
|
||||
features = ["videoio"]
|
||||
optional = true
|
||||
@@ -95,22 +93,6 @@ version = "0.2"
|
||||
path = "nokhwa-bindings-macos"
|
||||
optional = true
|
||||
|
||||
[dependencies.gstreamer]
|
||||
version = "0.18"
|
||||
optional = true
|
||||
|
||||
[dependencies.gstreamer-app]
|
||||
version = "0.18"
|
||||
optional = true
|
||||
|
||||
[dependencies.gstreamer-video]
|
||||
version = "0.18"
|
||||
optional = true
|
||||
|
||||
[dependencies.glib]
|
||||
version = "0.15"
|
||||
optional = true
|
||||
|
||||
[dependencies.regex]
|
||||
version = "1.4.6"
|
||||
optional = true
|
||||
|
||||
@@ -11,7 +11,6 @@ default = ["nokhwa/default"]
|
||||
input-msmf = ["nokhwa/input-msmf"]
|
||||
input-v4l = ["nokhwa/input-v4l"]
|
||||
input-opencv = ["nokhwa/input-opencv"]
|
||||
input-gst = ["nokhwa/input-gst"]
|
||||
input-avfoundation = ["nokhwa/input-avfoundation"]
|
||||
|
||||
[dependencies]
|
||||
|
||||
@@ -1244,8 +1244,6 @@ pub mod wmf {
|
||||
))
|
||||
}
|
||||
|
||||
struct Empty;
|
||||
|
||||
pub struct MediaFoundationDevice {
|
||||
camera: CameraIndex,
|
||||
}
|
||||
@@ -1317,7 +1315,7 @@ pub mod wmf {
|
||||
))
|
||||
}
|
||||
|
||||
pub fn raw_bytes(&mut self) -> Result<Cow<'a, [u8]>, NokhwaError> {
|
||||
pub fn raw_bytes(&mut self) -> Result<Cow<[u8]>, NokhwaError> {
|
||||
Err(NokhwaError::NotImplementedError(
|
||||
"Only on Windows".to_string(),
|
||||
))
|
||||
@@ -1326,7 +1324,7 @@ pub mod wmf {
|
||||
pub fn stop_stream(&mut self) {}
|
||||
}
|
||||
|
||||
impl<'a> Drop for MediaFoundationDevice<'a> {
|
||||
impl Drop for MediaFoundationDevice {
|
||||
fn drop(&mut self) {}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,7 +46,7 @@ pub trait FormatDecoder: Clone + Sized + Send + Sync {
|
||||
) -> Result<(), NokhwaError>;
|
||||
}
|
||||
|
||||
/// A Zero-Size-Type that contains the definition to convert a given image stream to an RGB888 in the [`Buffer`](crate::buffer::Buffer)'s [`.to_image()`](crate::buffer::Buffer::to_image)
|
||||
/// A Zero-Size-Type that contains the definition to convert a given image stream to an RGB888 in the [`Buffer`](crate::buffer::Buffer)'s [`.decode_image()`](crate::buffer::Buffer::decode_image)
|
||||
///
|
||||
/// ```.ignore
|
||||
/// use image::{ImageBuffer, Rgb};
|
||||
@@ -114,7 +114,7 @@ impl FormatDecoder for RgbFormat {
|
||||
}
|
||||
}
|
||||
|
||||
/// A Zero-Size-Type that contains the definition to convert a given image stream to an RGBA8888 in the [`Buffer`](crate::buffer::Buffer)'s [`.to_image()`](crate::buffer::Buffer::to_image)
|
||||
/// A Zero-Size-Type that contains the definition to convert a given image stream to an RGBA8888 in the [`Buffer`](crate::buffer::Buffer)'s [`.decode_image()`](crate::buffer::Buffer::decode_image)
|
||||
///
|
||||
/// ```.ignore
|
||||
/// use image::{ImageBuffer, Rgba};
|
||||
@@ -194,7 +194,7 @@ impl FormatDecoder for RgbAFormat {
|
||||
}
|
||||
}
|
||||
|
||||
/// A Zero-Size-Type that contains the definition to convert a given image stream to an Luma8(Grayscale 8-bit) in the [`Buffer`](crate::buffer::Buffer)'s [`.to_image()`](crate::buffer::Buffer::to_image)
|
||||
/// A Zero-Size-Type that contains the definition to convert a given image stream to an Luma8(Grayscale 8-bit) in the [`Buffer`](crate::buffer::Buffer)'s [`.decode_image()`](crate::buffer::Buffer::decode_image)
|
||||
///
|
||||
/// ```.ignore
|
||||
/// use image::{ImageBuffer, Luma};
|
||||
@@ -291,7 +291,7 @@ impl FormatDecoder for LumaFormat {
|
||||
}
|
||||
}
|
||||
|
||||
/// A Zero-Size-Type that contains the definition to convert a given image stream to an LumaA8(Grayscale 8-bit with 8-bit alpha) in the [`Buffer`](crate::buffer::Buffer)'s [`.to_image()`](crate::buffer::Buffer::to_image)
|
||||
/// A Zero-Size-Type that contains the definition to convert a given image stream to an LumaA8(Grayscale 8-bit with 8-bit alpha) in the [`Buffer`](crate::buffer::Buffer)'s [`.decode_image()`](crate::buffer::Buffer::decode_image)
|
||||
///
|
||||
/// ```.ignore
|
||||
/// use image::{ImageBuffer, LumaA};
|
||||
|
||||
@@ -35,7 +35,7 @@ use wgpu::{
|
||||
///
|
||||
/// **Note**:
|
||||
/// - Backends, if not provided with a camera format, will be spawned with 640x480@15 FPS, MJPEG [`CameraFormat`].
|
||||
/// - Behaviour can differ from backend to backend. While the [`Camera`](crate::camera::Camera) struct abstracts most of this away, if you plan to use the raw backend structs please read the `Quirks` section of each backend.
|
||||
/// - Behaviour can differ from backend to backend. While the Camera struct abstracts most of this away, if you plan to use the raw backend structs please read the `Quirks` section of each backend.
|
||||
/// - If you call [`stop_stream()`](CaptureBackendTrait::stop_stream()), you will usually need to call [`open_stream()`](CaptureBackendTrait::open_stream()) to get more frames from the camera.
|
||||
pub trait CaptureBackendTrait {
|
||||
/// Returns the current backend used.
|
||||
@@ -62,7 +62,7 @@ pub trait CaptureBackendTrait {
|
||||
|
||||
/// A hashmap of [`Resolution`]s mapped to framerates. Not sorted!
|
||||
/// # Errors
|
||||
/// This will error if the camera is not queryable or a query operation has failed. Some backends will error this out as a Unsupported Operation ([`UnsupportedOperationError`](crate::NokhwaError::UnsupportedOperationError)).
|
||||
/// This will error if the camera is not queryable or a query operation has failed. Some backends will error this out as a Unsupported Operation ([`UnsupportedOperationError`](crate::error::NokhwaError::UnsupportedOperationError)).
|
||||
fn compatible_list_by_resolution(
|
||||
&mut self,
|
||||
fourcc: FrameFormat,
|
||||
@@ -86,7 +86,7 @@ pub trait CaptureBackendTrait {
|
||||
|
||||
/// A Vector of compatible [`FrameFormat`]s. Will only return 2 elements at most.
|
||||
/// # Errors
|
||||
/// This will error if the camera is not queryable or a query operation has failed. Some backends will error this out as a Unsupported Operation ([`UnsupportedOperationError`](crate::NokhwaError::UnsupportedOperationError)).
|
||||
/// This will error if the camera is not queryable or a query operation has failed. Some backends will error this out as a Unsupported Operation ([`UnsupportedOperationError`](crate::error::NokhwaError::UnsupportedOperationError)).
|
||||
fn compatible_fourcc(&mut self) -> Result<Vec<FrameFormat>, NokhwaError>;
|
||||
|
||||
/// Gets the current camera resolution (See: [`Resolution`], [`CameraFormat`]). This will force refresh to the current latest if it has changed.
|
||||
|
||||
@@ -1,240 +0,0 @@
|
||||
/*
|
||||
* Copyright 2022 l1npengtul <l1npengtul@protonmail.com> / The Nokhwa Contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
use crate::js_camera::{ JSCamera};
|
||||
use nokhwa_core::{
|
||||
error::NokhwaError,
|
||||
traits::CaptureBackendTrait,
|
||||
types::{
|
||||
ApiBackend, CameraControl, CameraFormat, CameraIndex, CameraInfo, ControlValueSetter,
|
||||
FrameFormat, KnownCameraControl, Resolution, RequestedFormat,
|
||||
},
|
||||
};
|
||||
use std::{borrow::Cow, collections::HashMap};
|
||||
|
||||
/// Captures using the Browser API. This internally wraps [`JSCamera`].
|
||||
///
|
||||
/// # Quirks
|
||||
/// - `FourCC` setting is ignored
|
||||
/// - Cannot get compatible resolution(s).
|
||||
/// - CameraControl(s) are not supported.
|
||||
/// - All frame capture is done by creating (then destorying) a canvas on the DOM.
|
||||
/// - Many methods are blocking on user input.
|
||||
pub struct BrowserCaptureDevice {
|
||||
camera: JSCamera,
|
||||
info: CameraInfo,
|
||||
}
|
||||
|
||||
impl BrowserCaptureDevice {
|
||||
// WARN: blocking on pass integer for index
|
||||
/// Creates a new camera from an [`CameraIndex`]. It can take [`CameraIndex::Index`] or [`CameraIndex::String`] (NOTE: blocks on [`CameraIndex::Index`])
|
||||
///
|
||||
/// # Errors
|
||||
/// If the device is not found, browser not supported, or camera is over-constrained this will error.
|
||||
pub fn new(index: &CameraIndex, requested: RequestedFormat) -> Result<Self, NokhwaError> {
|
||||
// let (group_id, device_id) = match &index {
|
||||
// CameraIndex::Index(i) => {
|
||||
// let query_devices =
|
||||
// wasm_rs_async_executor::single_threaded::block_on(query_js_cameras())?;
|
||||
// match query_devices.into_iter().nth(*i as usize) {
|
||||
// Some(info) => {
|
||||
// let ids = info
|
||||
// .to_string()
|
||||
// .split(' ')
|
||||
// .map(ToString::to_string)
|
||||
// .collect::<Vec<String>>();
|
||||
// match (ids.get(0), ids.get(1)) {
|
||||
// (Some(group_id), Some(device_id)) => {
|
||||
// (group_id.clone(), device_id.clone())
|
||||
// }
|
||||
// (_, _) => {
|
||||
// return Err(NokhwaError::OpenDeviceError(
|
||||
// "Invalid Index".to_string(),
|
||||
// index.to_string(),
|
||||
// ))
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// None => {
|
||||
// return Err(NokhwaError::OpenDeviceError(
|
||||
// "Device not found".to_string(),
|
||||
// index.to_string(),
|
||||
// ))
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// CameraIndex::String(id) => {
|
||||
// let ids = id
|
||||
// .to_string()
|
||||
// .split(' ')
|
||||
// .map(ToString::to_string)
|
||||
// .collect::<Vec<String>>();
|
||||
// match (ids.get(0), ids.get(1)) {
|
||||
// (Some(group_id), Some(device_id)) => (group_id.clone(), device_id.clone()),
|
||||
// (_, _) => {
|
||||
// return Err(NokhwaError::OpenDeviceError(
|
||||
// "Invalid Index".to_string(),
|
||||
// index.to_string(),
|
||||
// ))
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// };
|
||||
|
||||
// let camera_format = cam_fmt.unwrap_or_default();
|
||||
|
||||
// let constraints = JSCameraConstraintsBuilder::new()
|
||||
// .frame_rate(camera_format.frame_rate())
|
||||
// .resolution(camera_format.resolution())
|
||||
// .aspect_ratio(f64::from(camera_format.width()) / f64::from(camera_format.height()))
|
||||
// .group_id(&group_id)
|
||||
// .group_id_exact(true)
|
||||
// .device_id(&device_id)
|
||||
// .device_id_exact(true)
|
||||
// .resize_mode(JSCameraResizeMode::Any)
|
||||
// .build();
|
||||
|
||||
// let camera = wasm_rs_async_executor::single_threaded::block_on(JSCamera::new(constraints))?;
|
||||
|
||||
// let info = (|| {
|
||||
// let cameras = wasm_rs_async_executor::single_threaded::block_on(query_js_cameras())?;
|
||||
// let giddid = format!("{} {}", group_id, device_id);
|
||||
// for cam in cameras {
|
||||
// if cam.misc() == giddid {
|
||||
// return Ok(cam);
|
||||
// }
|
||||
// }
|
||||
// Ok(CameraInfo::new("", "videoinput", &giddid, index.clone()))
|
||||
// })()?;
|
||||
// Ok(BrowserCaptureDevice { camera, info })
|
||||
Err(NokhwaError::NotImplementedError("TODO".to_string()))
|
||||
}
|
||||
|
||||
/// Creates a new camera from an [`CameraIndex`] and raw parts. It can take [`CameraIndex::Index`] or [`CameraIndex::String`] (NOTE: blocks on [`CameraIndex::Index`])
|
||||
///
|
||||
/// # Errors
|
||||
/// If the device is not found, browser not supported, or camera is over-constrained this will error.
|
||||
#[deprecated(since = "0.10.0", note = "please use `new` instead.")]
|
||||
pub fn new_with(
|
||||
index: &CameraIndex,
|
||||
width: u32,
|
||||
height: u32,
|
||||
fps: u32,
|
||||
fourcc: FrameFormat,
|
||||
) -> Result<Self, NokhwaError> {
|
||||
Err(NokhwaError::NotImplementedError("TODO".to_string()))
|
||||
// Self::new(
|
||||
// index,
|
||||
// Some(CameraFormat::new(Resolution::new(width, height), fourcc, fps)),
|
||||
// )
|
||||
}
|
||||
}
|
||||
|
||||
impl CaptureBackendTrait for BrowserCaptureDevice {
|
||||
fn backend(&self) -> ApiBackend {
|
||||
ApiBackend::Browser
|
||||
}
|
||||
|
||||
fn camera_info(&self) -> &CameraInfo {
|
||||
&self.info
|
||||
}
|
||||
|
||||
fn refresh_camera_format(&mut self) -> Result<(), NokhwaError> {
|
||||
self.camera.measure_resolution()?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn camera_format(&self) -> CameraFormat {
|
||||
let constraints = self.camera.constraints();
|
||||
// CameraFormat::new(constraints.resolution(), , constraints.frame_rate())
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn set_camera_format(&mut self, new_fmt: CameraFormat) -> Result<(), NokhwaError> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn compatible_list_by_resolution(
|
||||
&mut self,
|
||||
fourcc: FrameFormat,
|
||||
) -> Result<HashMap<Resolution, Vec<u32>>, NokhwaError> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn compatible_fourcc(&mut self) -> Result<Vec<FrameFormat>, NokhwaError> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn resolution(&self) -> Resolution {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn set_resolution(&mut self, new_res: Resolution) -> Result<(), NokhwaError> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn frame_rate(&self) -> u32 {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn set_frame_rate(&mut self, new_fps: u32) -> Result<(), NokhwaError> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn frame_format(&self) -> FrameFormat {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn set_frame_format(&mut self, fourcc: FrameFormat) -> Result<(), NokhwaError> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn camera_control(&self, control: KnownCameraControl) -> Result<CameraControl, NokhwaError> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn camera_controls(&self) -> Result<Vec<CameraControl>, NokhwaError> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn set_camera_control(
|
||||
&mut self,
|
||||
id: KnownCameraControl,
|
||||
value: ControlValueSetter,
|
||||
) -> Result<(), NokhwaError> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn open_stream(&mut self) -> Result<(), NokhwaError> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn is_stream_open(&self) -> bool {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn frame(&mut self) -> Result<nokhwa_core::buffer::Buffer, NokhwaError> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn frame_raw(&mut self) -> Result<Cow<[u8]>, NokhwaError> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn stop_stream(&mut self) -> Result<(), NokhwaError> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
+16
-16
@@ -62,23 +62,23 @@ mod uvc_backend;
|
||||
#[cfg(feature = "input-uvc")]
|
||||
#[cfg_attr(feature = "docs-features", doc(cfg(feature = "input-uvc")))]
|
||||
pub use uvc_backend::UVCCaptureDevice;
|
||||
#[cfg(feature = "input-gst")]
|
||||
mod gst_backend;
|
||||
#[cfg(feature = "input-gst")]
|
||||
#[cfg_attr(feature = "docs-features", doc(cfg(feature = "input-gst")))]
|
||||
pub use gst_backend::GStreamerCaptureDevice;
|
||||
#[cfg(feature = "input-jscam")]
|
||||
mod browser_backend;
|
||||
#[cfg(feature = "input-jscam")]
|
||||
#[cfg_attr(feature = "docs-features", doc(cfg(feature = "input-jscam")))]
|
||||
pub use browser_backend::BrowserCaptureDevice;
|
||||
// #[cfg(feature = "input-gst")]
|
||||
// mod gst_backend;
|
||||
// #[cfg(feature = "input-gst")]
|
||||
// #[cfg_attr(feature = "docs-features", doc(cfg(feature = "input-gst")))]
|
||||
// pub use gst_backend::GStreamerCaptureDevice;
|
||||
// #[cfg(feature = "input-jscam")]
|
||||
// mod browser_backend;
|
||||
// #[cfg(feature = "input-jscam")]
|
||||
// #[cfg_attr(feature = "docs-features", doc(cfg(feature = "input-jscam")))]
|
||||
// pub use browser_backend::BrowserCaptureDevice;
|
||||
/// A camera that uses `OpenCV` to access IP (rtsp/http) on the local network
|
||||
#[cfg(feature = "input-ipcam")]
|
||||
#[cfg_attr(feature = "docs-features", doc(cfg(feature = "input-ipcam")))]
|
||||
mod network_camera;
|
||||
#[cfg(feature = "input-ipcam")]
|
||||
#[cfg_attr(feature = "docs-features", doc(cfg(feature = "input-ipcam")))]
|
||||
pub use network_camera::NetworkCamera;
|
||||
// #[cfg(feature = "input-ipcam")]
|
||||
// #[cfg_attr(feature = "docs-features", doc(cfg(feature = "input-ipcam")))]
|
||||
// mod network_camera;
|
||||
// #[cfg(feature = "input-ipcam")]
|
||||
// #[cfg_attr(feature = "docs-features", doc(cfg(feature = "input-ipcam")))]
|
||||
// pub use network_camera::NetworkCamera;
|
||||
#[cfg(feature = "input-opencv")]
|
||||
mod opencv_backend;
|
||||
#[cfg(feature = "input-opencv")]
|
||||
|
||||
@@ -34,7 +34,7 @@ use opencv::{
|
||||
};
|
||||
use std::{borrow::Cow, collections::HashMap};
|
||||
|
||||
/// Attempts to convert a [`KnownCameraControl`] into a OpenCV video capture property.
|
||||
/// Attempts to convert a [`KnownCameraControl`] into a `OpenCV` video capture property.
|
||||
/// If the associated control is not found, this will return `Err`
|
||||
pub fn known_camera_control_to_video_capture_property(
|
||||
ctrl: KnownCameraControl,
|
||||
@@ -100,6 +100,7 @@ impl OpenCvCaptureDevice {
|
||||
/// If the backend fails to open the camera (e.g. Device does not exist at specified index/ip), Camera does not support specified [`CameraFormat`], and/or other `OpenCV` Error, this will error.
|
||||
/// # Panics
|
||||
/// If the API u32 -> i32 fails this will error
|
||||
#[allow(clippy::cast_possible_wrap)]
|
||||
pub fn new(index: &CameraIndex, cam_fmt: RequestedFormat) -> Result<Self, NokhwaError> {
|
||||
let api_pref = if index.is_string() {
|
||||
CAP_ANY
|
||||
@@ -112,7 +113,7 @@ impl OpenCvCaptureDevice {
|
||||
CameraIndex::String(ip) => VideoCapture::from_file(ip.as_str(), api_pref),
|
||||
}
|
||||
.map_err(|why| {
|
||||
NokhwaError::OpenDeviceError(format!("Failed to open {}", index), why.to_string())
|
||||
NokhwaError::OpenDeviceError(format!("Failed to open {index}"), why.to_string())
|
||||
})?;
|
||||
|
||||
let camera_format =
|
||||
@@ -125,7 +126,7 @@ impl OpenCvCaptureDevice {
|
||||
set_properties(&mut video_capture, camera_format)?;
|
||||
|
||||
let camera_info = CameraInfo::new(
|
||||
format!("OpenCV Capture Device {}", index).as_str(),
|
||||
format!("OpenCV Capture Device {index}").as_str(),
|
||||
index.to_string().as_str(),
|
||||
"",
|
||||
index.clone(),
|
||||
@@ -215,7 +216,7 @@ impl OpenCvCaptureDevice {
|
||||
};
|
||||
|
||||
for pixel in frame_data_vec.iter() {
|
||||
let pixel_slice: &[u8; 3] = &**pixel;
|
||||
let pixel_slice: &[u8; 3] = pixel;
|
||||
raw_vec.push(pixel_slice[2]);
|
||||
raw_vec.push(pixel_slice[1]);
|
||||
raw_vec.push(pixel_slice[0]);
|
||||
@@ -293,15 +294,17 @@ impl CaptureBackendTrait for OpenCvCaptureDevice {
|
||||
&self.camera_info
|
||||
}
|
||||
|
||||
#[allow(clippy::cast_lossless)]
|
||||
fn refresh_camera_format(&mut self) -> Result<(), NokhwaError> {
|
||||
let width = self
|
||||
.video_capture
|
||||
.set(CAP_PROP_FRAME_WIDTH, self.camera_format.width() as f64)
|
||||
.map_err(|why| NokhwaError::SetPropertyError {
|
||||
property: "Resolution Width".to_string(),
|
||||
value: self.camera_format.to_string(),
|
||||
error: why.to_string(),
|
||||
})? as u32;
|
||||
let width = u32::from(
|
||||
self.video_capture
|
||||
.set(CAP_PROP_FRAME_WIDTH, self.camera_format.width() as f64)
|
||||
.map_err(|why| NokhwaError::SetPropertyError {
|
||||
property: "Resolution Width".to_string(),
|
||||
value: self.camera_format.to_string(),
|
||||
error: why.to_string(),
|
||||
})?,
|
||||
);
|
||||
let height = self
|
||||
.video_capture
|
||||
.set(CAP_PROP_FRAME_HEIGHT, self.camera_format.height() as f64)
|
||||
@@ -427,6 +430,8 @@ impl CaptureBackendTrait for OpenCvCaptureDevice {
|
||||
Err(NokhwaError::UnsupportedOperationError(ApiBackend::OpenCv))
|
||||
}
|
||||
|
||||
#[allow(clippy::cast_precision_loss)]
|
||||
#[allow(clippy::cast_lossless)]
|
||||
fn set_camera_control(
|
||||
&mut self,
|
||||
id: KnownCameraControl,
|
||||
@@ -435,7 +440,7 @@ impl CaptureBackendTrait for OpenCvCaptureDevice {
|
||||
let control_val = match value {
|
||||
ControlValueSetter::Integer(i) => i as f64,
|
||||
ControlValueSetter::Float(f) => f,
|
||||
ControlValueSetter::Boolean(b) => b as u8 as f64,
|
||||
ControlValueSetter::Boolean(b) => u8::from(b) as f64,
|
||||
val => {
|
||||
return Err(NokhwaError::SetPropertyError {
|
||||
property: "Camera Control".to_string(),
|
||||
@@ -480,10 +485,7 @@ impl CaptureBackendTrait for OpenCvCaptureDevice {
|
||||
fn open_stream(&mut self) -> Result<(), NokhwaError> {
|
||||
match self.camera_location.clone() {
|
||||
CameraIndex::Index(idx) => {
|
||||
match self
|
||||
.video_capture
|
||||
.open_1(idx as i32, get_api_pref_int() as i32)
|
||||
{
|
||||
match self.video_capture.open_1(idx as i32, get_api_pref_int()) {
|
||||
Ok(open) => {
|
||||
if open {
|
||||
return Ok(());
|
||||
@@ -494,7 +496,7 @@ impl CaptureBackendTrait for OpenCvCaptureDevice {
|
||||
}
|
||||
Err(why) => Err(NokhwaError::OpenDeviceError(
|
||||
idx.to_string(),
|
||||
format!("Failed to open device: {}", why),
|
||||
format!("Failed to open device: {why}"),
|
||||
)),
|
||||
}
|
||||
}
|
||||
@@ -567,7 +569,7 @@ fn get_api_pref_int() -> i32 {
|
||||
// If anyone else wants to tackle this monster, please do.
|
||||
fn set_properties(vc: &mut VideoCapture, camera_format: CameraFormat) -> Result<(), NokhwaError> {
|
||||
if !vc
|
||||
.set(CAP_PROP_FRAME_WIDTH, camera_format.width() as f64)
|
||||
.set(CAP_PROP_FRAME_WIDTH, f64::from(camera_format.width()))
|
||||
.map_err(|why| NokhwaError::SetPropertyError {
|
||||
property: "Resolution Width".to_string(),
|
||||
value: camera_format.to_string(),
|
||||
@@ -581,7 +583,7 @@ fn set_properties(vc: &mut VideoCapture, camera_format: CameraFormat) -> Result<
|
||||
});
|
||||
}
|
||||
if !vc
|
||||
.set(CAP_PROP_FRAME_HEIGHT, camera_format.height() as f64)
|
||||
.set(CAP_PROP_FRAME_HEIGHT, f64::from(camera_format.height()))
|
||||
.map_err(|why| NokhwaError::SetPropertyError {
|
||||
property: "Resolution Height".to_string(),
|
||||
value: camera_format.to_string(),
|
||||
@@ -595,7 +597,7 @@ fn set_properties(vc: &mut VideoCapture, camera_format: CameraFormat) -> Result<
|
||||
});
|
||||
}
|
||||
if !vc
|
||||
.set(CAP_PROP_FPS, camera_format.frame_rate() as f64)
|
||||
.set(CAP_PROP_FPS, f64::from(camera_format.frame_rate()))
|
||||
.map_err(|why| NokhwaError::SetPropertyError {
|
||||
property: "FPS".to_string(),
|
||||
value: camera_format.to_string(),
|
||||
|
||||
@@ -773,7 +773,7 @@ fn fourcc_to_frameformat(fourcc: FourCC) -> Option<FrameFormat> {
|
||||
"MJPG" => Some(FrameFormat::MJPEG),
|
||||
"GRAY" => Some(FrameFormat::GRAY),
|
||||
"RGB3" => Some(FrameFormat::RAWRGB),
|
||||
"NV12" => Some(FrameFormat::NV12)
|
||||
"NV12" => Some(FrameFormat::NV12),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
+34
-35
@@ -95,7 +95,7 @@ fn media_devices(navigator: &Navigator) -> Result<MediaDevices, NokhwaError> {
|
||||
Ok(media) => Ok(media),
|
||||
Err(why) => Err(NokhwaError::StructureError {
|
||||
structure: "MediaDevices".to_string(),
|
||||
error: format!("{:?}", why),
|
||||
error: format!("{why:?}"),
|
||||
}),
|
||||
}
|
||||
}
|
||||
@@ -115,7 +115,7 @@ fn document_select_elem(doc: &Document, element: &str) -> Result<Element, Nokhwa
|
||||
Some(elem) => Ok(elem),
|
||||
None => {
|
||||
return Err(NokhwaError::StructureError {
|
||||
structure: format!("Document {}", element),
|
||||
structure: format!("Document {element}"),
|
||||
error: "None".to_string(),
|
||||
})
|
||||
}
|
||||
@@ -178,7 +178,7 @@ fn set_autoplay_inline(element: &Element) -> Result<(), NokhwaError> {
|
||||
return Err(NokhwaError::SetPropertyError {
|
||||
property: "Video-autoplay".to_string(),
|
||||
value: "autoplay".to_string(),
|
||||
error: format!("{:?}", why),
|
||||
error: format!("{why:?}"),
|
||||
});
|
||||
}
|
||||
|
||||
@@ -186,7 +186,7 @@ fn set_autoplay_inline(element: &Element) -> Result<(), NokhwaError> {
|
||||
return Err(NokhwaError::SetPropertyError {
|
||||
property: "Video-playsinline".to_string(),
|
||||
value: "playsinline".to_string(),
|
||||
error: format!("{:?}", why),
|
||||
error: format!("{why:?}"),
|
||||
});
|
||||
}
|
||||
|
||||
@@ -217,12 +217,12 @@ pub async fn request_permission() -> Result<(), NokhwaError> {
|
||||
.for_each(|track| MediaStreamTrack::from(track).stop());
|
||||
Ok(())
|
||||
}
|
||||
Err(why) => Err(NokhwaError::OpenStreamError(format!("{:?}", why))),
|
||||
Err(why) => Err(NokhwaError::OpenStreamError(format!("{why:?}"))),
|
||||
}
|
||||
}
|
||||
Err(why) => Err(NokhwaError::StructureError {
|
||||
structure: "UserMediaPermission".to_string(),
|
||||
error: format!("{:?}", why),
|
||||
error: format!("{why:?}"),
|
||||
}),
|
||||
}
|
||||
}
|
||||
@@ -334,13 +334,13 @@ pub async fn query_js_cameras() -> Result<Vec<CameraInfo>, NokhwaError> {
|
||||
}
|
||||
Err(why) => Err(NokhwaError::StructureError {
|
||||
structure: "EnumerateDevicesFuture".to_string(),
|
||||
error: format!("{:?}", why),
|
||||
error: format!("{why:?}"),
|
||||
}),
|
||||
}
|
||||
}
|
||||
Err(why) => Err(NokhwaError::StructureError {
|
||||
structure: "EnumerateDevices".to_string(),
|
||||
error: format!("{:?}", why),
|
||||
error: format!("{why:?}"),
|
||||
}),
|
||||
}
|
||||
}
|
||||
@@ -438,14 +438,14 @@ impl Display for JSCameraSupportedCapabilities {
|
||||
JSCameraSupportedCapabilities::ResizeMode => "resizeMode",
|
||||
};
|
||||
|
||||
write!(f, "{}", cap)
|
||||
write!(f, "{cap}")
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for JSCameraSupportedCapabilities {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
let str = self.to_string();
|
||||
write!(f, "{}", str)
|
||||
write!(f, "{str}")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -502,14 +502,14 @@ impl Display for JSCameraFacingMode {
|
||||
JSCameraFacingMode::Right => "right",
|
||||
JSCameraFacingMode::Any => "any",
|
||||
};
|
||||
write!(f, "{}", cap)
|
||||
write!(f, "{cap}")
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for JSCameraFacingMode {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
let str = self.to_string();
|
||||
write!(f, "{}", str)
|
||||
write!(f, "{str}")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -536,14 +536,14 @@ impl Display for JSCameraResizeMode {
|
||||
JSCameraResizeMode::Any => "",
|
||||
};
|
||||
|
||||
write!(f, "{}", cap)
|
||||
write!(f, "{cap}")
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for JSCameraResizeMode {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
let str = self.to_string();
|
||||
write!(f, "{}", str)
|
||||
write!(f, "{str}")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1837,7 +1837,7 @@ impl JSCamera {
|
||||
#[cfg_attr(feature = "output-wasm", wasm_bindgen(js_name = captureFrameRawData))]
|
||||
pub fn js_frame_raw(&mut self) -> Result<Box<[u8]>, JsValue> {
|
||||
match self.frame_raw() {
|
||||
Ok(frame) => Ok(frame.to_vec().into_iter().collect()),
|
||||
Ok(frame) => Ok(frame.iter().copied().collect()),
|
||||
Err(why) => Err(JsValue::from(why.to_string())),
|
||||
}
|
||||
}
|
||||
@@ -1915,7 +1915,7 @@ impl JSCamera {
|
||||
let navigator = window.navigator();
|
||||
let media_devices = media_devices(&navigator)?;
|
||||
|
||||
let stream: MediaStream = match media_devices.get_user_media_with_constraints(&*constraints)
|
||||
let stream: MediaStream = match media_devices.get_user_media_with_constraints(&constraints)
|
||||
{
|
||||
Ok(promise) => {
|
||||
let future = JsFuture::from(promise);
|
||||
@@ -1927,7 +1927,7 @@ impl JSCamera {
|
||||
Err(why) => {
|
||||
return Err(NokhwaError::StructureError {
|
||||
structure: "MediaDevicesGetUserMediaJsFuture".to_string(),
|
||||
error: format!("{:?}", why),
|
||||
error: format!("{why:?}"),
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -1935,7 +1935,7 @@ impl JSCamera {
|
||||
Err(why) => {
|
||||
return Err(NokhwaError::StructureError {
|
||||
structure: "MediaDevicesGetUserMedia".to_string(),
|
||||
error: format!("{:?}", why),
|
||||
error: format!("{why:?}"),
|
||||
})
|
||||
}
|
||||
};
|
||||
@@ -2060,7 +2060,7 @@ impl JSCamera {
|
||||
video_element.set_width(self.resolution().width());
|
||||
video_element.set_height(self.resolution().height());
|
||||
video_element.set_src_object(Some(&self.media_stream()));
|
||||
video_element.set_id(&format!("{}-video", html_id));
|
||||
video_element.set_id(&format!("{html_id}-video"));
|
||||
|
||||
return match selected_element.append_child(&Node::from(video_element)) {
|
||||
Ok(n) => {
|
||||
@@ -2070,7 +2070,7 @@ impl JSCamera {
|
||||
}
|
||||
Err(why) => Err(NokhwaError::StructureError {
|
||||
structure: "Attach Error".to_string(),
|
||||
error: format!("{:?}", why),
|
||||
error: format!("{why:?}"),
|
||||
}),
|
||||
};
|
||||
}
|
||||
@@ -2155,7 +2155,7 @@ impl JSCamera {
|
||||
Err(why) => {
|
||||
return Err(NokhwaError::StructureError {
|
||||
structure: "HtmlCanvasElement Context 2D".to_string(),
|
||||
error: format!("{:?}", why),
|
||||
error: format!("{why:?}"),
|
||||
});
|
||||
}
|
||||
};
|
||||
@@ -2206,7 +2206,7 @@ impl JSCamera {
|
||||
self.resolution().width().into(),
|
||||
self.resolution().height().into(),
|
||||
) {
|
||||
return Err(NokhwaError::ReadFrameError(format!("{:?}", why)));
|
||||
return Err(NokhwaError::ReadFrameError(format!("{why:?}")));
|
||||
}
|
||||
|
||||
match context.get_image_data(
|
||||
@@ -2217,7 +2217,7 @@ impl JSCamera {
|
||||
) {
|
||||
Ok(data) => log_1(&jsv!(data)),
|
||||
Err(why) => {
|
||||
return Err(NokhwaError::ReadFrameError(format!("{:?}", why)));
|
||||
return Err(NokhwaError::ReadFrameError(format!("{why:?}")));
|
||||
}
|
||||
};
|
||||
} else {
|
||||
@@ -2226,7 +2226,7 @@ impl JSCamera {
|
||||
Err(why) => {
|
||||
return Err(NokhwaError::StructureError {
|
||||
structure: "Document Video Element".to_string(),
|
||||
error: format!("{:?}", why.as_string()),
|
||||
error: format!("{why:?}"),
|
||||
})
|
||||
}
|
||||
};
|
||||
@@ -2264,15 +2264,14 @@ impl JSCamera {
|
||||
self.resolution().width().into(),
|
||||
self.resolution().height().into(),
|
||||
) {
|
||||
return Err(NokhwaError::ReadFrameError(format!("{:?}", why)));
|
||||
return Err(NokhwaError::ReadFrameError(format!("{why:?}")));
|
||||
}
|
||||
|
||||
match document.body() {
|
||||
Some(body) => {
|
||||
if let Err(why) = body.remove_child(&video_element) {
|
||||
return Err(NokhwaError::ReadFrameError(format!(
|
||||
"Failed to remove video: {:?}",
|
||||
why
|
||||
"Failed to remove video: {why:?}"
|
||||
)));
|
||||
}
|
||||
}
|
||||
@@ -2313,12 +2312,12 @@ impl JSCamera {
|
||||
|
||||
new_canvas.set_width(self.resolution().width());
|
||||
new_canvas.set_height(self.resolution().height());
|
||||
new_canvas.set_id(&format!("{}-canvas", html_id));
|
||||
new_canvas.set_id(&format!("{html_id}-canvas"));
|
||||
|
||||
if let Err(why) = selected_element.append_child(&new_canvas) {
|
||||
return Err(NokhwaError::StructureError {
|
||||
structure: "HtmlCanvasElement".to_string(),
|
||||
error: format!("add child: {:?}", why),
|
||||
error: format!("add child: {why:?}"),
|
||||
});
|
||||
}
|
||||
|
||||
@@ -2335,7 +2334,7 @@ impl JSCamera {
|
||||
Err(why) => {
|
||||
return Err(NokhwaError::StructureError {
|
||||
structure: "CanvasRenderingContext2d".to_string(),
|
||||
error: format!("context: {:?}", why),
|
||||
error: format!("context: {why:?}"),
|
||||
});
|
||||
}
|
||||
};
|
||||
@@ -2386,7 +2385,7 @@ impl JSCamera {
|
||||
Err(why) => {
|
||||
return Err(NokhwaError::StructureError {
|
||||
structure: "CanvasRenderingContext2d".to_string(),
|
||||
error: format!("context: {:?}", why),
|
||||
error: format!("context: {why:?}"),
|
||||
});
|
||||
}
|
||||
};
|
||||
@@ -2449,7 +2448,7 @@ impl JSCamera {
|
||||
) {
|
||||
Ok(data) => data,
|
||||
Err(why) => {
|
||||
return Err(NokhwaError::ReadFrameError(format!("{:?}", why)));
|
||||
return Err(NokhwaError::ReadFrameError(format!("{why:?}")));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -2479,7 +2478,7 @@ impl JSCamera {
|
||||
|
||||
match canvas.to_data_url_with_type_and_encoder_options(mime_type, &image_quality) {
|
||||
Ok(uri) => Ok(uri),
|
||||
Err(why) => Err(NokhwaError::ReadFrameError(format!("{:?}", why))),
|
||||
Err(why) => Err(NokhwaError::ReadFrameError(format!("{why:?}"))),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2672,7 +2671,7 @@ impl JSCamera {
|
||||
Err(why) => {
|
||||
return Err(NokhwaError::StructureError {
|
||||
structure: "MediaDevicesGetUserMediaJsFuture".to_string(),
|
||||
error: format!("{:?}", why),
|
||||
error: format!("{why:?}"),
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -2680,7 +2679,7 @@ impl JSCamera {
|
||||
Err(why) => {
|
||||
return Err(NokhwaError::StructureError {
|
||||
structure: "MediaDevicesGetUserMedia".to_string(),
|
||||
error: format!("{:?}", why),
|
||||
error: format!("{why:?}"),
|
||||
})
|
||||
}
|
||||
};
|
||||
|
||||
+7
-7
@@ -45,13 +45,13 @@ mod query;
|
||||
#[cfg_attr(feature = "docs-features", doc(cfg(feature = "output-threaded")))]
|
||||
pub mod threaded;
|
||||
|
||||
#[cfg(feature = "input-ipcam")]
|
||||
#[cfg_attr(feature = "docs-features", doc(cfg(feature = "input-ipcam")))]
|
||||
#[deprecated(
|
||||
since = "0.10.0",
|
||||
note = "please use `Camera` with `CameraIndex::String` and `input-opencv` enabled."
|
||||
)]
|
||||
pub use backends::capture::NetworkCamera;
|
||||
// #[cfg(feature = "input-ipcam")]
|
||||
// #[cfg_attr(feature = "docs-features", doc(cfg(feature = "input-ipcam")))]
|
||||
// #[deprecated(
|
||||
// since = "0.10.0",
|
||||
// note = "please use `Camera` with `CameraIndex::String` and `input-opencv` enabled."
|
||||
// )]
|
||||
// pub use backends::capture::NetworkCamera;
|
||||
pub use camera::Camera;
|
||||
pub use init::*;
|
||||
pub use nokhwa_core::buffer::Buffer;
|
||||
|
||||
+4
-2
@@ -372,8 +372,10 @@ impl CallbackCamera {
|
||||
}
|
||||
|
||||
/// Sets the control to `control` in the camera.
|
||||
/// Usually, the pipeline is calling [`camera_control()`](crate::CaptureBackendTrait::camera_control()), getting a camera control that way
|
||||
/// then calling one of the methods to set the value: [`set_value()`](CameraControl::set_value()) or [`with_value()`](CameraControl::with_value()).
|
||||
/// Usually, the pipeline is calling [`camera_control()`](crate::CaptureBackendTrait::camera_control()),
|
||||
/// getting a camera control that way
|
||||
/// then constructing a (`ControlValueSetter`)[crate::types::ControlValueSetter] with
|
||||
/// the new value you want by calling [crate::types::CameraControl::]
|
||||
/// # Errors
|
||||
/// If the `control` is not supported, the value is invalid (less than min, greater than max, not in step), or there was an error setting the control,
|
||||
/// this will error.
|
||||
|
||||
Reference in New Issue
Block a user