fix opencv, v4l2, jscam, deprecate gst, ipcam

This commit is contained in:
l1npengtul
2022-11-06 13:04:22 +09:00
parent 745d3f03a6
commit b5b013172d
12 changed files with 97 additions and 355 deletions
+3 -21
View File
@@ -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
-1
View File
@@ -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]
+2 -4
View File
@@ -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) {}
}
}
+4 -4
View File
@@ -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};
+3 -3
View File
@@ -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.
-240
View File
@@ -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
View File
@@ -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")]
+23 -21
View File
@@ -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(),
+1 -1
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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.