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:
+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:?}")
|
||||
// }
|
||||
// }
|
||||
|
||||
Reference in New Issue
Block a user