mirror of
https://github.com/l1npengtul/nokhwa.git
synced 2026-07-04 10:37:26 +00:00
New platform API to simply ApiBackend and allow for custom backends on the fly
This commit is contained in:
@@ -14,7 +14,7 @@ use nokhwa_core::properties::{CameraProperties, CameraPropertyFlag, CameraProper
|
||||
use nokhwa_core::{define_back_and_fourth_control, define_back_and_fourth_frame_format};
|
||||
use nokhwa_core::error::{NokhwaError, NokhwaResult};
|
||||
use nokhwa_core::frame_format::FrameFormat;
|
||||
use nokhwa_core::types::{CameraFormat, CameraIndex, CameraInfo, FrameRate, Resolution};
|
||||
use nokhwa_core::types::{CameraFormat, CameraIndex, CameraInformation, FrameRate, Resolution};
|
||||
|
||||
const NULL_FCC: &'static [u8; 4] = &[0x00, 0x00, 0x00, 0x00];
|
||||
|
||||
|
||||
@@ -225,7 +225,7 @@ mod internal {
|
||||
use nokhwa_core::{
|
||||
error::NokhwaError,
|
||||
types::{
|
||||
ApiBackend, CameraFormat, CameraIndex, CameraInfo,
|
||||
ApiBackend, CameraFormat, CameraIndex, CameraInformation,
|
||||
FrameFormat,
|
||||
KnownCameraControlFlag, Resolution,
|
||||
},
|
||||
@@ -509,7 +509,7 @@ mod internal {
|
||||
}
|
||||
|
||||
// fuck it, use deprecated APIs
|
||||
pub fn query_avfoundation() -> Result<Vec<CameraInfo>, NokhwaError> {
|
||||
pub fn query_avfoundation() -> Result<Vec<CameraInformation>, NokhwaError> {
|
||||
Ok(AVCaptureDeviceDiscoverySession::new(vec![
|
||||
AVCaptureDeviceType::UltraWide,
|
||||
AVCaptureDeviceType::WideAngle,
|
||||
@@ -520,7 +520,7 @@ mod internal {
|
||||
.devices())
|
||||
}
|
||||
|
||||
pub fn get_raw_device_info(index: CameraIndex, device: *mut Object) -> CameraInfo {
|
||||
pub fn get_raw_device_info(index: CameraIndex, device: *mut Object) -> CameraInformation {
|
||||
let name = nsstr_to_str(unsafe { msg_send![device, localizedName] });
|
||||
let manufacturer = nsstr_to_str(unsafe { msg_send![device, manufacturer] });
|
||||
let position: AVCaptureDevicePosition = unsafe { msg_send![device, position] };
|
||||
@@ -533,7 +533,7 @@ mod internal {
|
||||
);
|
||||
let misc = nsstr_to_str(unsafe { msg_send![device, uniqueID] });
|
||||
|
||||
CameraInfo::new(name.as_ref(), &description, misc.as_ref(), index)
|
||||
CameraInformation::new(name.as_ref(), &description, misc.as_ref(), index)
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, Hash, Ord, PartialOrd, Eq, PartialEq)]
|
||||
@@ -818,7 +818,7 @@ mod internal {
|
||||
])
|
||||
}
|
||||
|
||||
pub fn devices(&self) -> Vec<CameraInfo> {
|
||||
pub fn devices(&self) -> Vec<CameraInformation> {
|
||||
let device_ns_array: *mut Object = unsafe { msg_send![self.inner, devices] };
|
||||
let objects_len: NSUInteger = unsafe { NSArray::count(device_ns_array) };
|
||||
let mut devices = Vec::with_capacity(objects_len as usize);
|
||||
@@ -836,7 +836,7 @@ mod internal {
|
||||
|
||||
pub struct AVCaptureDevice {
|
||||
inner: *mut Object,
|
||||
device: CameraInfo,
|
||||
device: CameraInformation,
|
||||
locked: bool,
|
||||
}
|
||||
|
||||
@@ -890,7 +890,7 @@ mod internal {
|
||||
})
|
||||
}
|
||||
|
||||
pub fn info(&self) -> &CameraInfo {
|
||||
pub fn info(&self) -> &CameraInformation {
|
||||
&self.device
|
||||
}
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
pub mod wmf {
|
||||
use nokhwa_core::error::NokhwaError;
|
||||
use nokhwa_core::types::{
|
||||
ApiBackend, CameraFormat, CameraIndex, CameraInfo,
|
||||
ApiBackend, CameraFormat, CameraIndex, CameraInformation,
|
||||
FrameFormat, KnownCameraControlFlag, Resolution,
|
||||
};
|
||||
use once_cell::sync::Lazy;
|
||||
@@ -295,7 +295,7 @@ pub mod wmf {
|
||||
fn activate_to_descriptors(
|
||||
index: CameraIndex,
|
||||
imf_activate: &IMFActivate,
|
||||
) -> Result<CameraInfo, NokhwaError> {
|
||||
) -> Result<CameraInformation, NokhwaError> {
|
||||
let mut pwstr_name = PWSTR(&mut 0_u16);
|
||||
let mut len_pwstrname = 0;
|
||||
let mut pwstr_symlink = PWSTR(&mut 0_u16);
|
||||
@@ -357,7 +357,7 @@ pub mod wmf {
|
||||
})?
|
||||
};
|
||||
|
||||
Ok(CameraInfo::new(
|
||||
Ok(CameraInformation::new(
|
||||
&name,
|
||||
"MediaFoundation Camera",
|
||||
&symlink,
|
||||
@@ -365,7 +365,7 @@ pub mod wmf {
|
||||
))
|
||||
}
|
||||
|
||||
pub fn query_media_foundation_descriptors() -> Result<Vec<CameraInfo>, NokhwaError> {
|
||||
pub fn query_media_foundation_descriptors() -> Result<Vec<CameraInformation>, NokhwaError> {
|
||||
let mut device_list = vec![];
|
||||
|
||||
for (index, activate_ptr) in query_activate_pointers()?.into_iter().enumerate() {
|
||||
@@ -421,7 +421,7 @@ pub mod wmf {
|
||||
|
||||
pub struct MediaFoundationDevice {
|
||||
is_open: Cell<bool>,
|
||||
device_specifier: CameraInfo,
|
||||
device_specifier: CameraInformation,
|
||||
device_format: CameraFormat,
|
||||
source_reader: IMFSourceReader,
|
||||
}
|
||||
@@ -1226,7 +1226,7 @@ pub mod wmf {
|
||||
pub mod wmf {
|
||||
use nokhwa_core::error::NokhwaError;
|
||||
use nokhwa_core::types::{
|
||||
CameraFormat, CameraIndex, CameraInfo,
|
||||
CameraFormat, CameraIndex, CameraInformation,
|
||||
};
|
||||
use std::borrow::Cow;
|
||||
use nokhwa_core::properties::{CameraControl, ControlValue, KnownCameraControl};
|
||||
@@ -1243,7 +1243,7 @@ pub mod wmf {
|
||||
))
|
||||
}
|
||||
|
||||
pub fn query_msmf() -> Result<Vec<CameraInfo>, NokhwaError> {
|
||||
pub fn query_msmf() -> Result<Vec<CameraInformation>, NokhwaError> {
|
||||
Err(NokhwaError::NotImplementedError(
|
||||
"Not on windows".to_string(),
|
||||
))
|
||||
|
||||
+27
-49
@@ -1,21 +1,10 @@
|
||||
use crate::error::{NokhwaError, NokhwaResult};
|
||||
use crate::error::{NokhwaError};
|
||||
use crate::frame_format::FrameFormat;
|
||||
use crate::properties::{ControlId, ControlValue, Properties};
|
||||
use crate::types::{CameraFormat, CameraIndex, FrameRate, Resolution};
|
||||
use crate::types::{CameraFormat, FrameRate, Resolution};
|
||||
use std::collections::HashMap;
|
||||
use crate::frame_buffer::FrameBuffer;
|
||||
use crate::stream::Stream;
|
||||
|
||||
pub trait Open {
|
||||
fn open(index: CameraIndex) -> NokhwaResult<Self> where Self: Sized;
|
||||
}
|
||||
|
||||
#[cfg(feature = "async")]
|
||||
pub trait AsyncOpen: Sized {
|
||||
async fn open_async(index: CameraIndex) -> NokhwaResult<Self>;
|
||||
}
|
||||
|
||||
|
||||
pub trait Setting {
|
||||
fn enumerate_formats(&self) -> Result<Vec<CameraFormat>, NokhwaError>;
|
||||
|
||||
@@ -35,53 +24,42 @@ pub trait Setting {
|
||||
) -> Result<(), NokhwaError>;
|
||||
}
|
||||
|
||||
// #[cfg(feature = "async")]
|
||||
// pub trait AsyncSetting {
|
||||
// async fn set_format_async(&self, camera_format: CameraFormat) -> Result<(), NokhwaError>;
|
||||
//
|
||||
// async fn set_property_async(
|
||||
// &mut self,
|
||||
// property: &CameraPropertyId,
|
||||
// value: CameraPropertyValue,
|
||||
// ) -> Result<(), NokhwaError>;
|
||||
//
|
||||
// def_camera_props_async!(
|
||||
// Brightness,
|
||||
// Contrast,
|
||||
// Hue,
|
||||
// Saturation,
|
||||
// Sharpness,
|
||||
// Gamma,
|
||||
// WhiteBalance,
|
||||
// BacklightCompensation,
|
||||
// Pan,
|
||||
// Tilt,
|
||||
// Zoom,
|
||||
// Exposure,
|
||||
// Iris,
|
||||
// Focus,
|
||||
// Facing,
|
||||
// );
|
||||
// }
|
||||
#[cfg(feature = "async")]
|
||||
pub trait AsyncSetting {
|
||||
async fn enumerate_formats_async(&self) -> Result<Vec<CameraFormat>, NokhwaError>;
|
||||
|
||||
async fn enumerate_resolution_and_frame_rates_async(
|
||||
&self,
|
||||
frame_format: FrameFormat,
|
||||
) -> Result<HashMap<Resolution, Vec<FrameRate>>, NokhwaError>;
|
||||
|
||||
async fn set_format_async(&self, camera_format: CameraFormat) -> Result<(), NokhwaError>;
|
||||
|
||||
async fn properties_async(&self) -> &Properties;
|
||||
|
||||
async fn set_property_async(
|
||||
&mut self,
|
||||
property: &ControlId,
|
||||
value: ControlValue,
|
||||
) -> Result<(), NokhwaError>;
|
||||
}
|
||||
|
||||
pub trait Capture {
|
||||
// Implementations MUST guarantee that there can only ever be one stream open at once.
|
||||
fn open_stream(&mut self) -> Result<Stream, NokhwaError>;
|
||||
|
||||
// Implementations MUST be multi-close tolerant.
|
||||
fn close_stream(&mut self) -> Result<(), NokhwaError>;
|
||||
}
|
||||
|
||||
#[cfg(feature = "async")]
|
||||
pub trait AsyncStream {
|
||||
async fn open_stream(&mut self) -> Result<(), NokhwaError>;
|
||||
async fn open_stream_async(&mut self) -> Result<Stream, NokhwaError>;
|
||||
|
||||
async fn await_frame(&mut self) -> Result<FrameBuffer, NokhwaError>;
|
||||
|
||||
async fn close_stream(&mut self) -> Result<(), NokhwaError>;
|
||||
async fn close_stream_async(&mut self) -> Result<(), NokhwaError>;
|
||||
}
|
||||
|
||||
pub trait CameraVtable: Setting + Capture {}
|
||||
|
||||
pub trait Camera: Open + CameraVtable {}
|
||||
pub trait Camera: Setting + Capture {}
|
||||
|
||||
#[cfg(feature = "async")]
|
||||
pub trait AsyncCapture: Camera + AsyncOpen + AsyncStream {}
|
||||
pub trait AsyncCamera: Camera + AsyncSetting + AsyncStream {}
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
use crate::{frame_format::FrameFormat, types::ApiBackend};
|
||||
use std::fmt::{Debug};
|
||||
use thiserror::Error;
|
||||
use crate::platform::Backends;
|
||||
|
||||
pub type NokhwaResult<T> = Result<T, NokhwaError>;
|
||||
|
||||
@@ -56,9 +57,11 @@ pub enum NokhwaError {
|
||||
#[error("Could not stop stream: {0}")]
|
||||
StreamShutdownError(String),
|
||||
#[error("This operation is not supported by backend {0}.")]
|
||||
UnsupportedOperationError(ApiBackend),
|
||||
UnsupportedOperationError(Backends),
|
||||
#[error("This operation is not implemented yet: {0}")]
|
||||
NotImplementedError(String),
|
||||
#[error("Failed To Convert: {0}")]
|
||||
ConversionError(String),
|
||||
#[error("Permission denied by user.")]
|
||||
PermissionDenied,
|
||||
}
|
||||
|
||||
@@ -35,3 +35,4 @@ pub mod traits;
|
||||
pub mod types;
|
||||
pub mod utils;
|
||||
pub mod stream;
|
||||
mod platform;
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
use crate::camera::{AsyncCamera, Camera};
|
||||
use crate::error::NokhwaResult;
|
||||
use crate::types::{CameraIndex, CameraInformation};
|
||||
|
||||
#[derive(Copy, Clone, Debug, Ord, PartialOrd, Eq, PartialEq)]
|
||||
pub enum Backends {
|
||||
Video4Linux2,
|
||||
WebWASM,
|
||||
AVFoundation,
|
||||
MicrosoftMediaFoundation,
|
||||
Custom(&'static str)
|
||||
}
|
||||
|
||||
pub trait PlatformTrait {
|
||||
const PLATFORM: Backends;
|
||||
type Camera: Camera;
|
||||
|
||||
|
||||
fn block_on_permission(&mut self) -> NokhwaResult<()>;
|
||||
|
||||
fn check_permission_given(&mut self) -> bool;
|
||||
|
||||
fn query(&mut self) -> NokhwaResult<Vec<CameraInformation>>;
|
||||
|
||||
fn open(&mut self, index: &CameraIndex) -> NokhwaResult<Self::Camera>;
|
||||
}
|
||||
|
||||
#[cfg(feature = "async")]
|
||||
pub trait AsyncPlatformTrait {
|
||||
const PLATFORM: Backends;
|
||||
type AsyncCamera: AsyncCamera;
|
||||
|
||||
|
||||
async fn await_permission(&mut self) -> NokhwaResult<()>;
|
||||
|
||||
async fn query_async(&mut self) -> NokhwaResult<Vec<CameraInformation>>;
|
||||
|
||||
async fn open_async (&mut self, index: &CameraIndex) -> NokhwaResult<Self::AsyncCamera>;
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
use crate::error::NokhwaError;
|
||||
use crate::types::CameraInfo;
|
||||
|
||||
pub trait Query {
|
||||
fn query() -> Result<Vec<CameraInfo>, NokhwaError>;
|
||||
}
|
||||
|
||||
pub trait AsyncQuery {
|
||||
async fn query() -> Result<Vec<CameraInfo>, NokhwaError>;
|
||||
}
|
||||
+28
-21
@@ -1,6 +1,6 @@
|
||||
use crate::error::{NokhwaError, NokhwaResult};
|
||||
use crate::frame_buffer::FrameBuffer;
|
||||
use flume::Receiver;
|
||||
use flume::{Receiver, TryRecvError};
|
||||
use std::sync::Arc;
|
||||
|
||||
pub trait StreamInnerTrait {
|
||||
@@ -26,12 +26,17 @@ impl Stream {
|
||||
// }
|
||||
// }
|
||||
|
||||
pub fn poll_frame(&self) -> NokhwaResult<FrameBuffer> {
|
||||
pub fn check_disconnected(&self) -> NokhwaResult<()> {
|
||||
if self.inner.receiver().is_disconnected() {
|
||||
return Err(NokhwaError::ReadFrameError(
|
||||
"stream is disconnected!".to_string(),
|
||||
));
|
||||
))
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn poll_frame(&self) -> NokhwaResult<FrameBuffer> {
|
||||
self.check_disconnected()?;
|
||||
|
||||
self.inner
|
||||
.receiver()
|
||||
@@ -39,34 +44,36 @@ impl Stream {
|
||||
.map_err(|why| NokhwaError::ReadFrameError(why.to_string()))
|
||||
}
|
||||
|
||||
pub fn try_poll_frame(&self) -> Option<NokhwaResult<FrameBuffer>> {
|
||||
if self.inner.receiver().is_disconnected() {
|
||||
return Some(Err(NokhwaError::ReadFrameError(
|
||||
"stream is disconnected!".to_string(),
|
||||
)));
|
||||
}
|
||||
pub fn try_poll_frame(&self) -> NokhwaResult<Option<FrameBuffer>> {
|
||||
self.check_disconnected()?;
|
||||
|
||||
if self.inner.receiver().is_empty() {
|
||||
return None;
|
||||
return Ok(None);
|
||||
}
|
||||
|
||||
let possible_frame = self.inner
|
||||
.receiver()
|
||||
.try_recv();
|
||||
|
||||
match possible_frame {
|
||||
Ok(f) => Ok(Some(f)),
|
||||
Err(why) => {
|
||||
match why {
|
||||
TryRecvError::Empty => Ok(None),
|
||||
TryRecvError::Disconnected => Err(NokhwaError::ReadFrameError(
|
||||
"stream is disconnected!".to_string(),
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Some(
|
||||
self.inner
|
||||
.receiver()
|
||||
.try_recv()
|
||||
.map_err(|why| NokhwaError::ReadFrameError(why.to_string())),
|
||||
)
|
||||
}
|
||||
|
||||
#[cfg(feature = "async")]
|
||||
pub async fn await_frame(&self) -> NokhwaResult<FrameBuffer> {
|
||||
use futures::TryFutureExt;
|
||||
|
||||
if self.inner.receiver().is_disconnected() {
|
||||
return Err(NokhwaError::ReadFrameError(
|
||||
"stream is disconnected!".to_string(),
|
||||
));
|
||||
}
|
||||
self.check_disconnected()?;
|
||||
|
||||
self.inner
|
||||
.receiver()
|
||||
|
||||
+53
-53
@@ -414,23 +414,23 @@ impl Display for CameraFormat {
|
||||
/// `index` is a camera's index given to it by (usually) the OS usually in the order it is known to the system.
|
||||
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd)]
|
||||
#[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
|
||||
pub struct CameraInfo {
|
||||
pub struct CameraInformation {
|
||||
human_name: String,
|
||||
description: String,
|
||||
misc: String,
|
||||
index: CameraIndex,
|
||||
}
|
||||
|
||||
impl CameraInfo {
|
||||
/// Create a new [`CameraInfo`].
|
||||
impl CameraInformation {
|
||||
/// Create a new [`CameraInformation`].
|
||||
/// # JS-WASM
|
||||
/// This is exported as a constructor for [`CameraInfo`].
|
||||
/// This is exported as a constructor for [`CameraInformation`].
|
||||
#[must_use]
|
||||
// OK, i just checkeed back on this code. WTF was I on when I wrote `&(impl AsRef<str> + ?Sized)` ????
|
||||
// I need to get on the same shit that my previous self was on, because holy shit that stuff is strong as FUCK!
|
||||
// Finally fixed this insanity. Hopefully I didnt torment anyone by actually putting this in a stable release.
|
||||
pub fn new(human_name: String, description: String, misc: String, index: CameraIndex) -> Self {
|
||||
CameraInfo {
|
||||
CameraInformation {
|
||||
human_name,
|
||||
description,
|
||||
misc,
|
||||
@@ -520,7 +520,7 @@ impl CameraInfo {
|
||||
// }
|
||||
}
|
||||
|
||||
impl Display for CameraInfo {
|
||||
impl Display for CameraInformation {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
@@ -540,50 +540,50 @@ impl Display for CameraInfo {
|
||||
// Ok(())
|
||||
// }
|
||||
|
||||
/// The list of known capture backends to the library. <br>
|
||||
/// - `Auto` - Use automatic selection.
|
||||
/// - `AVFoundation` - Uses `AVFoundation` on `MacOSX`
|
||||
/// - `Video4Linux` - `Video4Linux2`, a linux specific backend.
|
||||
/// - `UniversalVideoClass` - ***DEPRECATED*** Universal Video Class (please check [libuvc](https://github.com/libuvc/libuvc)). Platform agnostic, although on linux it needs `sudo` permissions or similar to use.
|
||||
/// - `MediaFoundation` - Microsoft Media Foundation, Windows only,
|
||||
/// - `OpenCv` - Uses `OpenCV` to capture. Platform agnostic.
|
||||
/// - `GStreamer` - ***DEPRECATED*** Uses `GStreamer` RTP to capture. Platform agnostic.
|
||||
/// - `Browser` - Uses browser APIs to capture from a webcam.
|
||||
pub enum SelectableBackend {
|
||||
Auto,
|
||||
Custom(&'static str),
|
||||
AVFoundation,
|
||||
Video4Linux,
|
||||
UniversalVideoClass,
|
||||
MediaFoundation,
|
||||
OpenCv,
|
||||
GStreamer,
|
||||
Browser,
|
||||
}
|
||||
|
||||
/// The list of known capture backends to the library. <br>
|
||||
/// - `AVFoundation` - Uses `AVFoundation` on `MacOSX`
|
||||
/// - `Video4Linux` - `Video4Linux2`, a linux specific backend.
|
||||
/// - `UniversalVideoClass` - ***DEPRECATED*** Universal Video Class (please check [libuvc](https://github.com/libuvc/libuvc)). Platform agnostic, although on linux it needs `sudo` permissions or similar to use.
|
||||
/// - `MediaFoundation` - Microsoft Media Foundation, Windows only,
|
||||
/// - `OpenCv` - Uses `OpenCV` to capture. Platform agnostic.
|
||||
/// - `GStreamer` - ***DEPRECATED*** Uses `GStreamer` RTP to capture. Platform agnostic.
|
||||
/// - `Browser` - Uses browser APIs to capture from a webcam.
|
||||
#[derive(Copy, Clone, Debug, Hash, Ord, PartialOrd, Eq, PartialEq)]
|
||||
#[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
|
||||
pub enum ApiBackend {
|
||||
Custom(&'static str),
|
||||
AVFoundation,
|
||||
Video4Linux,
|
||||
UniversalVideoClass,
|
||||
MediaFoundation,
|
||||
OpenCv,
|
||||
GStreamer,
|
||||
Browser,
|
||||
}
|
||||
|
||||
impl Display for ApiBackend {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "{self:?}")
|
||||
}
|
||||
}
|
||||
// /// The list of known capture backends to the library. <br>
|
||||
// /// - `Auto` - Use automatic selection.
|
||||
// /// - `AVFoundation` - Uses `AVFoundation` on `MacOSX`
|
||||
// /// - `Video4Linux` - `Video4Linux2`, a linux specific backend.
|
||||
// /// - `UniversalVideoClass` - ***DEPRECATED*** Universal Video Class (please check [libuvc](https://github.com/libuvc/libuvc)). Platform agnostic, although on linux it needs `sudo` permissions or similar to use.
|
||||
// /// - `MediaFoundation` - Microsoft Media Foundation, Windows only,
|
||||
// /// - `OpenCv` - Uses `OpenCV` to capture. Platform agnostic.
|
||||
// /// - `GStreamer` - ***DEPRECATED*** Uses `GStreamer` RTP to capture. Platform agnostic.
|
||||
// /// - `Browser` - Uses browser APIs to capture from a webcam.
|
||||
// pub enum SelectableBackend {
|
||||
// Auto,
|
||||
// Custom(&'static str),
|
||||
// AVFoundation,
|
||||
// Video4Linux,
|
||||
// UniversalVideoClass,
|
||||
// MediaFoundation,
|
||||
// OpenCv,
|
||||
// GStreamer,
|
||||
// Browser,
|
||||
// }
|
||||
//
|
||||
// /// The list of known capture backends to the library. <br>
|
||||
// /// - `AVFoundation` - Uses `AVFoundation` on `MacOSX`
|
||||
// /// - `Video4Linux` - `Video4Linux2`, a linux specific backend.
|
||||
// /// - `UniversalVideoClass` - ***DEPRECATED*** Universal Video Class (please check [libuvc](https://github.com/libuvc/libuvc)). Platform agnostic, although on linux it needs `sudo` permissions or similar to use.
|
||||
// /// - `MediaFoundation` - Microsoft Media Foundation, Windows only,
|
||||
// /// - `OpenCv` - Uses `OpenCV` to capture. Platform agnostic.
|
||||
// /// - `GStreamer` - ***DEPRECATED*** Uses `GStreamer` RTP to capture. Platform agnostic.
|
||||
// /// - `Browser` - Uses browser APIs to capture from a webcam.
|
||||
// #[derive(Copy, Clone, Debug, Hash, Ord, PartialOrd, Eq, PartialEq)]
|
||||
// #[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
|
||||
// pub enum ApiBackend {
|
||||
// Custom(&'static str),
|
||||
// AVFoundation,
|
||||
// Video4Linux,
|
||||
// UniversalVideoClass,
|
||||
// MediaFoundation,
|
||||
// OpenCv,
|
||||
// GStreamer,
|
||||
// Browser,
|
||||
// }
|
||||
//
|
||||
// impl Display for ApiBackend {
|
||||
// fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
// write!(f, "{self:?}")
|
||||
// }
|
||||
// }
|
||||
|
||||
@@ -26,7 +26,7 @@ use nokhwa_core::{
|
||||
pixel_format::RgbFormat,
|
||||
traits::CaptureTrait,
|
||||
types::{
|
||||
ApiBackend, CameraFormat, CameraIndex, CameraInfo,
|
||||
ApiBackend, CameraFormat, CameraIndex, CameraInformation,
|
||||
FrameFormat, RequestedFormat, RequestedFormatType, Resolution,
|
||||
},
|
||||
};
|
||||
@@ -52,7 +52,7 @@ pub struct AVFoundationCaptureDevice {
|
||||
session: Option<AVCaptureSession>,
|
||||
data_out: Option<AVCaptureVideoDataOutput>,
|
||||
data_collect: Option<AVCaptureVideoCallback>,
|
||||
info: CameraInfo,
|
||||
info: CameraInformation,
|
||||
buffer_name: CString,
|
||||
format: CameraFormat,
|
||||
frame_buffer_receiver: Arc<Receiver<(Vec<u8>, FrameFormat)>>,
|
||||
@@ -127,7 +127,7 @@ impl CaptureTrait for AVFoundationCaptureDevice {
|
||||
ApiBackend::AVFoundation
|
||||
}
|
||||
|
||||
fn camera_info(&self) -> &CameraInfo {
|
||||
fn camera_info(&self) -> &CameraInformation {
|
||||
&self.info
|
||||
}
|
||||
|
||||
@@ -401,7 +401,7 @@ impl CaptureTrait for AVFoundationCaptureDevice {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn camera_info(&self) -> &CameraInfo {
|
||||
fn camera_info(&self) -> &CameraInformation {
|
||||
todo!()
|
||||
}
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ use nokhwa_core::properties::{CameraControl, ControlValue, KnownCameraControl};
|
||||
use nokhwa_core::error::NokhwaError;
|
||||
use nokhwa_core::frame_format::FrameFormat;
|
||||
use nokhwa_core::traits::{AsyncCaptureTrait, AsyncOpenCaptureTrait, CaptureTrait, OpenCaptureTrait};
|
||||
use nokhwa_core::types::{ApiBackend, CameraFormat, CameraIndex, CameraInfo, FrameRate, Resolution};
|
||||
use nokhwa_core::types::{ApiBackend, CameraFormat, CameraIndex, CameraInformation, FrameRate, Resolution};
|
||||
|
||||
async fn resolve_to<T: JsCast>(promise: Promise) -> Result<T, NokhwaError> {
|
||||
let future = JsFuture::from(promise);
|
||||
@@ -91,7 +91,7 @@ pub enum BrowserCameraControls {
|
||||
|
||||
|
||||
pub struct BrowserCaptureDevice {
|
||||
info: CameraInfo,
|
||||
info: CameraInformation,
|
||||
group_id: String,
|
||||
device_id: String,
|
||||
format: CameraFormat,
|
||||
@@ -131,7 +131,7 @@ impl BrowserCaptureDevice {
|
||||
|
||||
let info = match device_info {
|
||||
Some(v) => {
|
||||
CameraInfo::new(&v.label(), v.kind(), &v.device_id(), index)
|
||||
CameraInformation::new(&v.label(), v.kind(), &v.device_id(), index)
|
||||
}
|
||||
None => return Err(NokhwaError::OpenDeviceError(index.to_string(), "failed to find MediaDeviceInfo".to_string())),
|
||||
};
|
||||
@@ -297,7 +297,7 @@ impl CaptureTrait for BrowserCaptureDevice {
|
||||
ApiBackend::Browser
|
||||
}
|
||||
|
||||
fn camera_info(&self) -> &CameraInfo {
|
||||
fn camera_info(&self) -> &CameraInformation {
|
||||
&self.info
|
||||
}
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ use nokhwa_core::{
|
||||
traits::CaptureTrait,
|
||||
types::{
|
||||
ApiBackend, CameraFormat, CameraIndex,
|
||||
CameraInfo, FrameFormat, RequestedFormat,
|
||||
CameraInformation, FrameFormat, RequestedFormat,
|
||||
RequestedFormatType, Resolution,
|
||||
},
|
||||
};
|
||||
@@ -35,13 +35,13 @@ use nokhwa_core::properties::{all_known_camera_controls, CameraControl, ControlV
|
||||
/// # Quirks
|
||||
/// - This does build on non-windows platforms, however when you do the backend will be empty and will return an error for any given operation.
|
||||
/// - Please check [`nokhwa-bindings-windows`](https://github.com/l1npengtul/nokhwa/tree/senpai/nokhwa-bindings-windows) source code to see the internal raw interface.
|
||||
/// - The symbolic link for the device is listed in the `misc` attribute of the [`CameraInfo`].
|
||||
/// - The symbolic link for the device is listed in the `misc` attribute of the [`CameraInformation`].
|
||||
/// - The names may contain invalid characters since they were converted from UTF16.
|
||||
/// - When you call new or drop the struct, `initialize`/`de_initialize` will automatically be called.
|
||||
#[cfg_attr(feature = "docs-features", doc(cfg(feature = "input-msmf")))]
|
||||
pub struct MediaFoundationCaptureDevice {
|
||||
inner: MediaFoundationDevice,
|
||||
info: CameraInfo,
|
||||
info: CameraInformation,
|
||||
}
|
||||
|
||||
impl MediaFoundationCaptureDevice {
|
||||
@@ -51,7 +51,7 @@ impl MediaFoundationCaptureDevice {
|
||||
pub fn new(index: &CameraIndex, camera_fmt: RequestedFormat) -> Result<Self, NokhwaError> {
|
||||
let mut mf_device = MediaFoundationDevice::new(index.clone())?;
|
||||
|
||||
let info = CameraInfo::new(
|
||||
let info = CameraInformation::new(
|
||||
&mf_device.name(),
|
||||
"MediaFoundation Camera Device",
|
||||
&mf_device.symlink(),
|
||||
@@ -114,7 +114,7 @@ impl CaptureTrait for MediaFoundationCaptureDevice {
|
||||
ApiBackend::MediaFoundation
|
||||
}
|
||||
|
||||
fn camera_info(&self) -> &CameraInfo {
|
||||
fn camera_info(&self) -> &CameraInformation {
|
||||
&self.info
|
||||
}
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ use nokhwa_core::{
|
||||
error::NokhwaError,
|
||||
traits::CaptureTrait,
|
||||
types::{
|
||||
ApiBackend, CameraFormat, CameraIndex, CameraInfo,
|
||||
ApiBackend, CameraFormat, CameraIndex, CameraInformation,
|
||||
FrameFormat, RequestedFormat, Resolution,
|
||||
},
|
||||
};
|
||||
@@ -71,14 +71,14 @@ pub fn known_camera_control_to_video_capture_property(
|
||||
/// - If the [`OpenCvCaptureDevice`] is initialized as a `IPCamera`, the [`CameraFormat`]'s `index` value will be [`u32::MAX`](std::u32::MAX) (4294967295).
|
||||
/// - `OpenCV` does not support camera querying. Camera Name and Camera supported resolution/fps/fourcc is a [`UnsupportedOperationError`](NokhwaError::UnsupportedOperationError).
|
||||
/// Note: [`resolution()`](crate::camera_traits::CaptureTrait::resolution()), [`frame_format()`](crate::camera_traits::CaptureTrait::frame_format()), and [`frame_rate()`](crate::camera_traits::CaptureTrait::frame_rate()) is not affected.
|
||||
/// - [`CameraInfo`]'s human name will be "`OpenCV` Capture Device {location}"
|
||||
/// - [`CameraInfo`]'s description will contain the Camera's Index or IP.
|
||||
/// - [`CameraInformation`]'s human name will be "`OpenCV` Capture Device {location}"
|
||||
/// - [`CameraInformation`]'s description will contain the Camera's Index or IP.
|
||||
/// - The API Preference order is the native OS API (linux => `v4l2`, mac => `AVFoundation`, windows => `MSMF`) than [`CAP_AUTO`](https://docs.opencv.org/4.5.2/d4/d15/group__videoio__flags__base.html#gga023786be1ee68a9105bf2e48c700294da77ab1fe260fd182f8ec7655fab27a31d)
|
||||
#[cfg_attr(feature = "docs-features", doc(cfg(feature = "input-opencv")))]
|
||||
pub struct OpenCvCaptureDevice {
|
||||
camera_format: CameraFormat,
|
||||
camera_location: CameraIndex,
|
||||
camera_info: CameraInfo,
|
||||
camera_info: CameraInformation,
|
||||
api_preference: i32,
|
||||
video_capture: VideoCapture,
|
||||
}
|
||||
@@ -124,7 +124,7 @@ impl OpenCvCaptureDevice {
|
||||
|
||||
set_properties(&mut video_capture, camera_format)?;
|
||||
|
||||
let camera_info = CameraInfo::new(
|
||||
let camera_info = CameraInformation::new(
|
||||
format!("OpenCV Capture Device {index}").as_str(),
|
||||
index.to_string().as_str(),
|
||||
"",
|
||||
@@ -289,7 +289,7 @@ impl CaptureTrait for OpenCvCaptureDevice {
|
||||
ApiBackend::OpenCv
|
||||
}
|
||||
|
||||
fn camera_info(&self) -> &CameraInfo {
|
||||
fn camera_info(&self) -> &CameraInformation {
|
||||
&self.camera_info
|
||||
}
|
||||
|
||||
|
||||
@@ -17,12 +17,12 @@ use nokhwa_core::{
|
||||
error::{NokhwaError, NokhwaResult},
|
||||
frame_format::FrameFormat,
|
||||
properties::CameraProperties,
|
||||
types::{CameraFormat, CameraIndex, CameraInfo, FrameRate, Resolution}
|
||||
types::{CameraFormat, CameraIndex, CameraInformation, FrameRate, Resolution}
|
||||
};
|
||||
|
||||
pub struct V4L2CaptureDevice {
|
||||
device_inner: Arc<DeviceInner>,
|
||||
camera_info: CameraInfo,
|
||||
camera_info: CameraInformation,
|
||||
format: Option<CameraFormat>,
|
||||
properties: Option<CameraProperties>,
|
||||
stream_running: bool,
|
||||
@@ -32,7 +32,7 @@ impl Open for V4L2CaptureDevice {
|
||||
fn open(index: CameraIndex) -> NokhwaResult<Self> {
|
||||
let device = DeviceInner::new(index.as_index()? as usize).map_err(|why| NokhwaError::OpenDeviceError(index.to_string(), why.to_string()))?;
|
||||
let caps = device.inner().query_caps().map_err(|why| NokhwaError::OpenDeviceError(index.to_string(), why.to_string()))?;
|
||||
let camera_info = CameraInfo::new(caps.card, caps.bus, caps.driver, index);
|
||||
let camera_info = CameraInformation::new(caps.card, caps.bus, caps.driver, index);
|
||||
Ok(Self {
|
||||
device_inner: Arc::new(device),
|
||||
camera_info,
|
||||
|
||||
+2
-2
@@ -23,7 +23,7 @@ use nokhwa_core::{
|
||||
pixel_format::FormatDecoder,
|
||||
traits::CaptureTrait,
|
||||
types::{
|
||||
ApiBackend, CameraFormat, CameraIndex, CameraInfo
|
||||
ApiBackend, CameraFormat, CameraIndex, CameraInformation
|
||||
, RequestedFormatType, Resolution,
|
||||
},
|
||||
};
|
||||
@@ -58,7 +58,7 @@ impl CaptureTrait for Camera {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn camera_info(&self) -> &CameraInfo {
|
||||
fn camera_info(&self) -> &CameraInformation {
|
||||
todo!()
|
||||
}
|
||||
|
||||
|
||||
+20
-20
@@ -16,7 +16,7 @@
|
||||
|
||||
use nokhwa_core::{
|
||||
error::NokhwaError,
|
||||
types::{ApiBackend, CameraInfo},
|
||||
types::{ApiBackend, CameraInformation},
|
||||
};
|
||||
|
||||
/// Gets the native [`ApiBackend`]
|
||||
@@ -34,15 +34,15 @@ pub fn native_api_backend() -> Option<ApiBackend> {
|
||||
/// Query the system for a list of available devices. Please refer to the API Backends that support `Query`) <br>
|
||||
/// Usually the order goes Native -> UVC -> Gstreamer.
|
||||
/// # Quirks
|
||||
/// - `Media Foundation`: The symbolic link for the device is listed in the `misc` attribute of the [`CameraInfo`].
|
||||
/// - `Media Foundation`: The symbolic link for the device is listed in the `misc` attribute of the [`CameraInformation`].
|
||||
/// - `Media Foundation`: The names may contain invalid characters since they were converted from UTF16.
|
||||
/// - `AVFoundation`: The ID of the device is stored in the `misc` attribute of the [`CameraInfo`].
|
||||
/// - `AVFoundation`: The ID of the device is stored in the `misc` attribute of the [`CameraInformation`].
|
||||
/// - `AVFoundation`: There is lots of miscellaneous info in the `desc` attribute.
|
||||
/// - `WASM`: The `misc` field contains the device ID and group ID are seperated by a space (' ')
|
||||
/// # Errors
|
||||
/// If you use an unsupported API (check the README or crate root for more info), incompatible backend for current platform, incompatible platform, or insufficient permissions, etc
|
||||
/// this will error.
|
||||
pub fn query(api: ApiBackend) -> Result<Vec<CameraInfo>, NokhwaError> {
|
||||
pub fn query(api: ApiBackend) -> Result<Vec<CameraInformation>, NokhwaError> {
|
||||
match api {
|
||||
ApiBackend::Auto => {
|
||||
// determine platform
|
||||
@@ -108,19 +108,19 @@ pub fn query(api: ApiBackend) -> Result<Vec<CameraInfo>, NokhwaError> {
|
||||
// TODO: More
|
||||
|
||||
#[cfg(all(feature = "input-v4l", target_os = "linux"))]
|
||||
fn query_v4l() -> Result<Vec<CameraInfo>, NokhwaError> {
|
||||
fn query_v4l() -> Result<Vec<CameraInformation>, NokhwaError> {
|
||||
nokhwa_bindings_linux::query()
|
||||
}
|
||||
|
||||
#[cfg(any(not(feature = "input-v4l"), not(target_os = "linux")))]
|
||||
fn query_v4l() -> Result<Vec<CameraInfo>, NokhwaError> {
|
||||
fn query_v4l() -> Result<Vec<CameraInformation>, NokhwaError> {
|
||||
Err(NokhwaError::UnsupportedOperationError(
|
||||
ApiBackend::Video4Linux,
|
||||
))
|
||||
}
|
||||
|
||||
#[cfg(feature = "input-uvc")]
|
||||
fn query_uvc() -> Result<Vec<CameraInfo>, NokhwaError> {
|
||||
fn query_uvc() -> Result<Vec<CameraInformation>, NokhwaError> {
|
||||
use crate::CameraIndex;
|
||||
use uvc::Device;
|
||||
|
||||
@@ -168,7 +168,7 @@ fn query_uvc() -> Result<Vec<CameraInfo>, NokhwaError> {
|
||||
))
|
||||
.clone();
|
||||
|
||||
camera_info_vec.push(CameraInfo::new(
|
||||
camera_info_vec.push(CameraInformation::new(
|
||||
name.clone(),
|
||||
usb_dev
|
||||
.description
|
||||
@@ -193,14 +193,14 @@ fn query_uvc() -> Result<Vec<CameraInfo>, NokhwaError> {
|
||||
|
||||
#[cfg(not(feature = "input-uvc"))]
|
||||
#[allow(deprecated)]
|
||||
fn query_uvc() -> Result<Vec<CameraInfo>, NokhwaError> {
|
||||
fn query_uvc() -> Result<Vec<CameraInformation>, NokhwaError> {
|
||||
Err(NokhwaError::UnsupportedOperationError(
|
||||
ApiBackend::UniversalVideoClass,
|
||||
))
|
||||
}
|
||||
|
||||
#[cfg(feature = "input-gst")]
|
||||
fn query_gstreamer() -> Result<Vec<CameraInfo>, NokhwaError> {
|
||||
fn query_gstreamer() -> Result<Vec<CameraInformation>, NokhwaError> {
|
||||
use gstreamer::{
|
||||
prelude::{DeviceExt, DeviceMonitorExt, DeviceMonitorExtManual},
|
||||
Caps, DeviceMonitor,
|
||||
@@ -241,14 +241,14 @@ fn query_gstreamer() -> Result<Vec<CameraInfo>, NokhwaError> {
|
||||
)));
|
||||
}
|
||||
let mut counter = 0;
|
||||
let devices: Vec<CameraInfo> = device_monitor
|
||||
let devices: Vec<CameraInformation> = device_monitor
|
||||
.devices()
|
||||
.iter_mut()
|
||||
.map(|gst_dev| {
|
||||
let name = DeviceExt::display_name(gst_dev);
|
||||
let class = DeviceExt::device_class(gst_dev);
|
||||
counter += 1;
|
||||
CameraInfo::new(&name, &class, "", CameraIndex::Index(counter - 1))
|
||||
CameraInformation::new(&name, &class, "", CameraIndex::Index(counter - 1))
|
||||
})
|
||||
.collect();
|
||||
device_monitor.stop();
|
||||
@@ -257,7 +257,7 @@ fn query_gstreamer() -> Result<Vec<CameraInfo>, NokhwaError> {
|
||||
|
||||
#[cfg(not(feature = "input-gst"))]
|
||||
#[allow(deprecated)]
|
||||
fn query_gstreamer() -> Result<Vec<CameraInfo>, NokhwaError> {
|
||||
fn query_gstreamer() -> Result<Vec<CameraInformation>, NokhwaError> {
|
||||
Err(NokhwaError::UnsupportedOperationError(
|
||||
ApiBackend::GStreamer,
|
||||
))
|
||||
@@ -265,12 +265,12 @@ fn query_gstreamer() -> Result<Vec<CameraInfo>, NokhwaError> {
|
||||
|
||||
// please refer to https://docs.microsoft.com/en-us/windows/win32/medfound/enumerating-video-capture-devices
|
||||
#[cfg(all(feature = "input-msmf", target_os = "windows"))]
|
||||
fn query_msmf() -> Result<Vec<CameraInfo>, NokhwaError> {
|
||||
fn query_msmf() -> Result<Vec<CameraInformation>, NokhwaError> {
|
||||
nokhwa_bindings_windows::wmf::query_media_foundation_descriptors()
|
||||
}
|
||||
|
||||
#[cfg(any(not(feature = "input-msmf"), not(target_os = "windows")))]
|
||||
fn query_msmf() -> Result<Vec<CameraInfo>, NokhwaError> {
|
||||
fn query_msmf() -> Result<Vec<CameraInformation>, NokhwaError> {
|
||||
Err(NokhwaError::UnsupportedOperationError(
|
||||
ApiBackend::MediaFoundation,
|
||||
))
|
||||
@@ -280,26 +280,26 @@ fn query_msmf() -> Result<Vec<CameraInfo>, NokhwaError> {
|
||||
feature = "input-avfoundation",
|
||||
any(target_os = "macos", target_os = "ios")
|
||||
))]
|
||||
fn query_avfoundation() -> Result<Vec<CameraInfo>, NokhwaError> {
|
||||
fn query_avfoundation() -> Result<Vec<CameraInformation>, NokhwaError> {
|
||||
use nokhwa_bindings_macos::query_avfoundation;
|
||||
|
||||
Ok(query_avfoundation()?
|
||||
.into_iter()
|
||||
.collect::<Vec<CameraInfo>>())
|
||||
.collect::<Vec<CameraInformation>>())
|
||||
}
|
||||
|
||||
#[cfg(not(all(
|
||||
feature = "input-avfoundation",
|
||||
any(target_os = "macos", target_os = "ios")
|
||||
)))]
|
||||
fn query_avfoundation() -> Result<Vec<CameraInfo>, NokhwaError> {
|
||||
fn query_avfoundation() -> Result<Vec<CameraInformation>, NokhwaError> {
|
||||
Err(NokhwaError::UnsupportedOperationError(
|
||||
ApiBackend::AVFoundation,
|
||||
))
|
||||
}
|
||||
|
||||
#[cfg(feature = "input-jscam")]
|
||||
fn query_wasm() -> Result<Vec<CameraInfo>, NokhwaError> {
|
||||
fn query_wasm() -> Result<Vec<CameraInformation>, NokhwaError> {
|
||||
use crate::js_camera::query_js_cameras;
|
||||
use wasm_rs_async_executor::single_threaded::block_on;
|
||||
|
||||
@@ -307,6 +307,6 @@ fn query_wasm() -> Result<Vec<CameraInfo>, NokhwaError> {
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "input-jscam"))]
|
||||
fn query_wasm() -> Result<Vec<CameraInfo>, NokhwaError> {
|
||||
fn query_wasm() -> Result<Vec<CameraInformation>, NokhwaError> {
|
||||
Err(NokhwaError::UnsupportedOperationError(ApiBackend::Browser))
|
||||
}
|
||||
|
||||
+4
-4
@@ -19,7 +19,7 @@ use nokhwa_core::{
|
||||
frame_buffer::FrameBuffer,
|
||||
error::NokhwaError,
|
||||
types::{
|
||||
ApiBackend, CameraFormat, CameraIndex, CameraInfo,
|
||||
ApiBackend, CameraFormat, CameraIndex, CameraInformation,
|
||||
FrameFormat, RequestedFormat, RequestedFormatType, Resolution,
|
||||
},
|
||||
};
|
||||
@@ -60,7 +60,7 @@ pub struct CallbackCamera {
|
||||
frame_callback: HeldCallbackType,
|
||||
last_frame_captured: AtomicLock<FrameBuffer>,
|
||||
die_bool: Arc<AtomicBool>,
|
||||
current_camera: CameraInfo,
|
||||
current_camera: CameraInformation,
|
||||
handle: AtomicLock<Option<JoinHandle<()>>>,
|
||||
}
|
||||
|
||||
@@ -160,8 +160,8 @@ impl CallbackCamera {
|
||||
.set_backend(new_backend)
|
||||
}
|
||||
|
||||
/// Gets the camera information such as Name and Index as a [`CameraInfo`].
|
||||
pub fn info(&self) -> &CameraInfo {
|
||||
/// Gets the camera information such as Name and Index as a [`CameraInformation`].
|
||||
pub fn info(&self) -> &CameraInformation {
|
||||
&self.current_camera
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user