mirror of
https://github.com/l1npengtul/nokhwa.git
synced 2026-07-04 02:27:26 +00:00
finished AVFoundation base update, prepare for CameraControl update
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
<component name="ProjectRunConfigurationManager">
|
||||
<configuration default="false" name="Clippy Main" type="CargoCommandRunConfiguration" factoryName="Cargo Command">
|
||||
<option name="command" value="clippy --features "output-wgpu"" />
|
||||
<option name="command" value="clippy --features "output-wgpu, input-avfoundation"" />
|
||||
<option name="workingDirectory" value="file://$PROJECT_DIR$" />
|
||||
<option name="channel" value="STABLE" />
|
||||
<option name="requiredFeatures" value="true" />
|
||||
|
||||
@@ -198,13 +198,14 @@ use objc::{
|
||||
runtime::{Class, Object, Protocol, Sel, BOOL, YES},
|
||||
};
|
||||
use once_cell::sync::Lazy;
|
||||
use std::collections::HashSet;
|
||||
use std::{
|
||||
borrow::Cow,
|
||||
cmp::Ordering,
|
||||
collections::HashSet,
|
||||
convert::TryFrom,
|
||||
error::Error,
|
||||
ffi::{c_void, CStr, CString},
|
||||
ffi::{c_void, CStr},
|
||||
sync::{Arc, Mutex},
|
||||
};
|
||||
|
||||
const UTF8_ENCODING: usize = 4;
|
||||
@@ -325,8 +326,6 @@ fn compare_ns_string(this: *mut Object, other: core_media::NSString) -> bool {
|
||||
}
|
||||
}
|
||||
|
||||
fn default_callback(_: bool) {}
|
||||
|
||||
pub type CompressionData<'a> = (Cow<'a, [u8]>, FrameFormat);
|
||||
pub type DataPipe<'a> = (Sender<CompressionData<'a>>, Receiver<CompressionData<'a>>);
|
||||
|
||||
@@ -335,14 +334,21 @@ static CALLBACK_CLASS: Lazy<&'static Class> = Lazy::new(|| {
|
||||
let mut decl = ClassDecl::new("MyCaptureCallback", class!(NSObject)).unwrap();
|
||||
|
||||
// frame stack
|
||||
decl.add_ivar::<*mut c_void>("_fnptr"); // oooh scary provenannce-breaking BULLSHIT AAAAAA I LOVE TYPE ERASURE
|
||||
// oooh scary provenannce-breaking BULLSHIT AAAAAA I LOVE TYPE ERASURE
|
||||
decl.add_ivar::<*const c_void>("_arcmutptr"); // ArkMutex, the not-arknights totally not gacha totally not ripoff new vidya game from l-pleasestop-npengtul
|
||||
// KILL ME KILL ME KILL ME PLEASE KILL ME I DONT WANT TO LIVE ANYMORE
|
||||
// i draw myself getting hurt and murdered in various ways to distract from my urges self harm
|
||||
|
||||
extern "C" fn my_callback_get_fnptr(this: &Object, _: Sel) -> *mut c_void {
|
||||
unsafe { *this.get_ivar("_fnptr") }
|
||||
extern "C" fn my_callback_get_arcmutptr(this: &Object, _: Sel) -> *const c_void {
|
||||
unsafe { *this.get_ivar("_arcmutptr") }
|
||||
}
|
||||
extern "C" fn my_callback_set_fnptr(this: &mut Object, _: Sel, new_fnptr: *mut c_void) {
|
||||
extern "C" fn my_callback_set_arcmutptr(
|
||||
this: &mut Object,
|
||||
_: Sel,
|
||||
new_arcmutptr: *const c_void,
|
||||
) {
|
||||
unsafe {
|
||||
this.set_ivar("_fnptr", new_fnptr);
|
||||
this.set_ivar("_arcmutptr", new_arcmutptr);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -383,18 +389,18 @@ static CALLBACK_CLASS: Lazy<&'static Class> = Lazy::new(|| {
|
||||
|
||||
unsafe { CVPixelBufferUnlockBaseAddress(image_buffer, 0) };
|
||||
// oooooh scarey unsafe
|
||||
// FIXME: FnMut is not boundary safe.
|
||||
// Revery back fo `fn()`
|
||||
let function_cvoid: *mut c_void = unsafe { msg_send![this, fnptr] };
|
||||
let mut boxed_fn = unsafe {
|
||||
// AAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
// https://c.tenor.com/0e_zWtFLOzQAAAAC/needy-streamer-overload-needy-girl-overdose.gif
|
||||
std::mem::transmute_copy::<
|
||||
*mut c_void,
|
||||
Box<dyn FnMut(Vec<u8>, FrameFormat) + Send + Sync + 'static>,
|
||||
>(&function_cvoid)
|
||||
// AAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
// https://c.tenor.com/0e_zWtFLOzQAAAAC/needy-streamer-overload-needy-girl-overdose.gif
|
||||
let bufferlck_cv: *mut c_void = unsafe { msg_send![this, bufferPtr] };
|
||||
let buffer_mutex = unsafe {
|
||||
std::mem::transmute::<*const c_void, Arc<Mutex<(Vec<u8>, FrameFormat)>>>(
|
||||
bufferlck_cv,
|
||||
)
|
||||
};
|
||||
boxed_fn(buffer_as_vec, fourcc);
|
||||
let lock = buffer_mutex.lock();
|
||||
if let Ok(mut buffer) = lock {
|
||||
*buffer = (buffer_as_vec, fourcc);
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(non_snake_case)]
|
||||
@@ -409,12 +415,12 @@ static CALLBACK_CLASS: Lazy<&'static Class> = Lazy::new(|| {
|
||||
|
||||
unsafe {
|
||||
decl.add_method(
|
||||
sel!(fnptr),
|
||||
my_callback_get_fnptr as extern "C" fn(&Object, Sel) -> *mut c_void,
|
||||
sel!(bufferPtr),
|
||||
my_callback_get_arcmutptr as extern "C" fn(&Object, Sel) -> *const c_void,
|
||||
);
|
||||
decl.add_method(
|
||||
sel!(setFnPtr:),
|
||||
my_callback_set_fnptr as extern "C" fn(&mut Object, Sel, *mut c_void),
|
||||
sel!(SetBufferPtr:),
|
||||
my_callback_set_arcmutptr as extern "C" fn(&mut Object, Sel, *const c_void),
|
||||
);
|
||||
decl.add_method(
|
||||
sel!(captureOutput:didOutputSampleBuffer:fromConnection:),
|
||||
@@ -659,16 +665,18 @@ pub struct AVCaptureVideoCallback {
|
||||
impl AVCaptureVideoCallback {
|
||||
pub fn new(
|
||||
device_spec: &CStr,
|
||||
callback: Box<dyn FnMut(Vec<u8>, FrameFormat) + Send + Sync + 'static>,
|
||||
buffer: Arc<Mutex<(Vec<u8>, FrameFormat)>>,
|
||||
) -> Result<Self, NokhwaError> {
|
||||
let cls = &CALLBACK_CLASS as &Class;
|
||||
let delegate: *mut Object = unsafe { msg_send![cls, alloc] };
|
||||
let delegate: *mut Object = unsafe { msg_send![delegate, init] };
|
||||
|
||||
let fnptr_pinned = Box::leak(callback);
|
||||
|
||||
let buffer_as_ptr = unsafe {
|
||||
std::mem::transmute::<*const Mutex<(Vec<u8>, FrameFormat)>, *const c_void>(
|
||||
Arc::into_raw(buffer),
|
||||
)
|
||||
};
|
||||
unsafe {
|
||||
let _: () = msg_send![delegate, setFnPtr: fnptr_pinned];
|
||||
let _: () = msg_send![delegate, setBufferPtr: buffer_as_ptr];
|
||||
}
|
||||
|
||||
let queue =
|
||||
@@ -684,6 +692,10 @@ impl AVCaptureVideoCallback {
|
||||
pub fn inner(&self) -> *mut Object {
|
||||
self.delegate
|
||||
}
|
||||
|
||||
pub fn queue(&self) -> &NSObject {
|
||||
&self.queue
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for AVCaptureVideoCallback {
|
||||
@@ -840,7 +852,7 @@ impl AVCaptureDevice {
|
||||
}
|
||||
|
||||
impl AVCaptureDevice {
|
||||
pub fn new(index: CameraIndex) -> Result<Self, NokhwaError> {
|
||||
pub fn new(index: &CameraIndex) -> Result<Self, NokhwaError> {
|
||||
match &index {
|
||||
CameraIndex::Index(idx) => {
|
||||
let devices = AVCaptureDeviceDiscoverySession::new(
|
||||
@@ -855,7 +867,10 @@ impl AVCaptureDevice {
|
||||
.devices();
|
||||
|
||||
match devices.get(*idx as usize) {
|
||||
Some(device) => Ok(AVCaptureDevice::from_id(&device.misc(), Some(index))?),
|
||||
Some(device) => Ok(AVCaptureDevice::from_id(
|
||||
&device.misc(),
|
||||
Some(index.clone()),
|
||||
)?),
|
||||
None => Err(NokhwaError::OpenDeviceError(
|
||||
idx.to_string(),
|
||||
"Not Found".to_string(),
|
||||
@@ -878,7 +893,7 @@ impl AVCaptureDevice {
|
||||
));
|
||||
}
|
||||
let camera_info = get_raw_device_info(
|
||||
index_hint.unwrap_or(CameraIndex::String(id.to_string())),
|
||||
index_hint.unwrap_or_else(|| CameraIndex::String(id.to_string())),
|
||||
capture,
|
||||
);
|
||||
Ok(AVCaptureDevice {
|
||||
@@ -1069,18 +1084,10 @@ impl AVCaptureVideoDataOutput {
|
||||
|
||||
pub fn add_delegate(&self, delegate: &AVCaptureVideoCallback) -> Result<(), NokhwaError> {
|
||||
unsafe {
|
||||
let avf_queue_str = match CString::new("avf_queue") {
|
||||
Ok(avf) => avf.into_raw(),
|
||||
Err(_) => {
|
||||
// should not happen
|
||||
return Err(NokhwaError::GeneralError("String contains null? This is a bug, please report it: https://github.com/l1npengtul/nokhwa".to_string()));
|
||||
}
|
||||
};
|
||||
|
||||
let _: () = msg_send![
|
||||
self.inner,
|
||||
setSampleBufferDelegate: delegate.delegate
|
||||
queue: avf_queue_str
|
||||
queue: delegate.queue().0
|
||||
];
|
||||
};
|
||||
Ok(())
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
//! Core type definitions for `nokhwa`
|
||||
|
||||
extern crate core;
|
||||
|
||||
pub mod buffer;
|
||||
pub mod error;
|
||||
pub mod pixel_format;
|
||||
|
||||
@@ -247,4 +247,13 @@ pub trait CaptureBackendTrait {
|
||||
fn stop_stream(&mut self) -> Result<(), NokhwaError>;
|
||||
}
|
||||
|
||||
impl<T> From<T> for Box<dyn CaptureBackendTrait>
|
||||
where
|
||||
T: CaptureBackendTrait + 'static,
|
||||
{
|
||||
fn from(capbackend: T) -> Self {
|
||||
Box::new(capbackend)
|
||||
}
|
||||
}
|
||||
|
||||
pub trait VirtualBackendTrait {}
|
||||
|
||||
@@ -96,6 +96,12 @@ impl RequestedFormat {
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for RequestedFormat {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "{:?}", self)
|
||||
}
|
||||
}
|
||||
|
||||
/// Describes the index of the camera.
|
||||
/// - Index: A numbered index
|
||||
/// - String: A string, used for IPCameras.
|
||||
|
||||
@@ -14,28 +14,25 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
use image::{Frame, ImageBuffer, Rgb};
|
||||
use nokhwa_bindings_macos::{
|
||||
AVCaptureDevice, AVCaptureDeviceInput, AVCaptureSession, AVCaptureVideoCallback,
|
||||
AVCaptureVideoDataOutput,
|
||||
};
|
||||
use nokhwa_core::buffer::Buffer;
|
||||
use nokhwa_core::{
|
||||
buffer::Buffer,
|
||||
error::NokhwaError,
|
||||
traits::CaptureBackendTrait,
|
||||
types::{
|
||||
mjpeg_to_rgb, yuyv422_to_rgb, ApiBackend, CameraControl, CameraFormat, CameraIndex,
|
||||
CameraInfo, ControlValueSetter, FrameFormat, KnownCameraControl, RequestedFormat,
|
||||
Resolution,
|
||||
ApiBackend, CameraControl, CameraFormat, CameraIndex, CameraInfo, ControlValueSetter,
|
||||
FrameFormat, KnownCameraControl, RequestedFormat, Resolution,
|
||||
},
|
||||
};
|
||||
use std::sync::LockResult;
|
||||
use std::ffi::CString;
|
||||
use std::{
|
||||
borrow::Cow,
|
||||
collections::HashMap,
|
||||
sync::{Arc, Mutex},
|
||||
};
|
||||
use std::ffi::CString;
|
||||
|
||||
/// The backend struct that interfaces with V4L2.
|
||||
/// To see what this does, please see [`CaptureBackendTrait`].
|
||||
@@ -53,9 +50,9 @@ pub struct AVFoundationCaptureDevice {
|
||||
data_out: Option<AVCaptureVideoDataOutput>,
|
||||
data_collect: Option<AVCaptureVideoCallback>,
|
||||
info: CameraInfo,
|
||||
buffername: CString,
|
||||
buffer_name: CString,
|
||||
format: CameraFormat,
|
||||
framebuf: Arc<Mutex<(Vec<u8>, FrameFormat)>>,
|
||||
frame_buffer_lock: Arc<Mutex<(Vec<u8>, FrameFormat)>>,
|
||||
}
|
||||
|
||||
impl AVFoundationCaptureDevice {
|
||||
@@ -64,13 +61,22 @@ impl AVFoundationCaptureDevice {
|
||||
/// If `camera_format` is `None`, it will be spawned with with 640x480@15 FPS, MJPEG [`CameraFormat`] default.
|
||||
/// # Errors
|
||||
/// This function will error if the camera is currently busy or if `AVFoundation` can't read device information, or permission was not given by the user.
|
||||
pub fn new(index: CameraIndex, req_fmt: RequestedFormat) -> Result<Self, NokhwaError> {
|
||||
pub fn new(index: &CameraIndex, req_fmt: RequestedFormat) -> Result<Self, NokhwaError> {
|
||||
let mut device = AVCaptureDevice::new(index)?;
|
||||
device.lock()?;
|
||||
let formats = device.supported_formats()?;
|
||||
let camera_fmt = req_fmt.fulfill(&formats)?;
|
||||
let camera_fmt = req_fmt.fulfill(&formats).ok_or_else(|| {
|
||||
NokhwaError::OpenDeviceError("Cannot fulfill request".to_string(), req_fmt.to_string())
|
||||
})?;
|
||||
device.set_all(camera_fmt)?;
|
||||
let device_descriptor = device.
|
||||
let device_descriptor = device.info().clone();
|
||||
let buffername =
|
||||
CString::new(format!("{}_INDEX{}_", device_descriptor, index)).map_err(|why| {
|
||||
NokhwaError::StructureError {
|
||||
structure: "CString Buffername".to_string(),
|
||||
error: why.to_string(),
|
||||
}
|
||||
})?;
|
||||
|
||||
Ok(AVFoundationCaptureDevice {
|
||||
device,
|
||||
@@ -78,10 +84,10 @@ impl AVFoundationCaptureDevice {
|
||||
session: None,
|
||||
data_out: None,
|
||||
data_collect: None,
|
||||
info: ,
|
||||
buffername: ,
|
||||
format: camera_format,
|
||||
framebuf: Arc::new(Mutex::new((vec![], FrameFormat::MJPEG))),
|
||||
info: device_descriptor,
|
||||
buffer_name: buffername,
|
||||
format: camera_fmt,
|
||||
frame_buffer_lock: Arc::new(Mutex::new((vec![], FrameFormat::MJPEG))),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -90,6 +96,7 @@ impl AVFoundationCaptureDevice {
|
||||
/// # Errors
|
||||
/// This function will error if the camera is currently busy or if `AVFoundation` can't read device information, or permission was not given by the user.
|
||||
#[deprecated(since = "0.10.0", note = "please use `new` instead.")]
|
||||
#[allow(clippy::cast_possible_truncation)]
|
||||
pub fn new_with(
|
||||
index: usize,
|
||||
width: u32,
|
||||
@@ -99,7 +106,7 @@ impl AVFoundationCaptureDevice {
|
||||
) -> Result<Self, NokhwaError> {
|
||||
let camera_format = CameraFormat::new_from(width, height, fourcc, fps);
|
||||
AVFoundationCaptureDevice::new(
|
||||
CameraIndex::Index(index as u32),
|
||||
&CameraIndex::Index(index as u32),
|
||||
RequestedFormat::Exact(camera_format),
|
||||
)
|
||||
}
|
||||
@@ -123,7 +130,7 @@ impl CaptureBackendTrait for AVFoundationCaptureDevice {
|
||||
}
|
||||
|
||||
fn set_camera_format(&mut self, new_fmt: CameraFormat) -> Result<(), NokhwaError> {
|
||||
self.device.set_all(new_fmt.into())?;
|
||||
self.device.set_all(new_fmt)?;
|
||||
self.format = new_fmt;
|
||||
Ok(())
|
||||
}
|
||||
@@ -144,7 +151,7 @@ impl CaptureBackendTrait for AVFoundationCaptureDevice {
|
||||
match res_list.get_mut(&format.resolution()) {
|
||||
Some(fpses) => Vec::push(fpses, format.frame_rate()),
|
||||
None => {
|
||||
vec![format.frame_rate()]
|
||||
res_list.insert(format.resolution(), vec![format.frame_rate()]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -156,7 +163,7 @@ impl CaptureBackendTrait for AVFoundationCaptureDevice {
|
||||
.device
|
||||
.supported_formats()?
|
||||
.into_iter()
|
||||
.map(|fmt| FrameFormat::from(fmt.fourcc))
|
||||
.map(|fmt| fmt.format())
|
||||
.collect::<Vec<FrameFormat>>();
|
||||
formats.sort();
|
||||
formats.dedup();
|
||||
@@ -221,18 +228,11 @@ impl CaptureBackendTrait for AVFoundationCaptureDevice {
|
||||
session.begin_configuration();
|
||||
session.add_input(&input)?;
|
||||
|
||||
let mut frame_mutex = self.framebuf.clone();
|
||||
|
||||
let func_callback: Box<dyn FnMut(Vec<u8>, FrameFormat) + Send + Sync + 'static> =
|
||||
Box::new(|data: Vec<u8>, frame_format: FrameFormat| {
|
||||
if let Ok(lck) = frame_mutex.lock() {
|
||||
*lck = (data, frame_format);
|
||||
}
|
||||
});
|
||||
|
||||
let videocallback = AVCaptureVideoCallback::new(func_callback)?;
|
||||
let frame_mutex = self.frame_buffer_lock.clone();
|
||||
let bufname = &self.buffer_name;
|
||||
let videocallback = AVCaptureVideoCallback::new(bufname, frame_mutex)?;
|
||||
let output = AVCaptureVideoDataOutput::new();
|
||||
output.add_delegate(&callback)?;
|
||||
output.add_delegate(&videocallback)?;
|
||||
session.add_output(&output)?;
|
||||
session.commit_configuration();
|
||||
session.start()?;
|
||||
@@ -266,19 +266,14 @@ impl CaptureBackendTrait for AVFoundationCaptureDevice {
|
||||
}
|
||||
|
||||
fn frame_raw(&mut self) -> Result<Cow<[u8]>, NokhwaError> {
|
||||
let mut framebuffer_empty = match self.framebuf.lock() {
|
||||
Ok(f) => {
|
||||
if f.0.is_empty() {
|
||||
true
|
||||
}
|
||||
false
|
||||
}
|
||||
let mut framebuffer_empty = match self.frame_buffer_lock.lock() {
|
||||
Ok(f) => f.0.is_empty(),
|
||||
Err(why) => return Err(NokhwaError::ReadFrameError(why.to_string())),
|
||||
};
|
||||
|
||||
loop {
|
||||
if framebuffer_empty {
|
||||
match self.framebuf.lock() {
|
||||
match self.frame_buffer_lock.lock() {
|
||||
Ok(f) => framebuffer_empty = f.0.is_empty(),
|
||||
Err(why) => return Err(NokhwaError::ReadFrameError(why.to_string())),
|
||||
}
|
||||
@@ -287,13 +282,13 @@ impl CaptureBackendTrait for AVFoundationCaptureDevice {
|
||||
}
|
||||
}
|
||||
|
||||
match self.framebuf.lock() {
|
||||
Ok(f) => {
|
||||
match self.frame_buffer_lock.lock() {
|
||||
Ok(mut f) => {
|
||||
let mut new_frame = vec![];
|
||||
std::mem::swap(&mut new_frame, &mut f.0);
|
||||
Ok(Cow::from(new_frame))
|
||||
}
|
||||
Err(why) => return Err(NokhwaError::ReadFrameError(why.to_string())),
|
||||
Err(why) => Err(NokhwaError::ReadFrameError(why.to_string())),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -13,21 +13,18 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
use image::{ImageBuffer, Rgb};
|
||||
use nokhwa_bindings_windows::wmf::MediaFoundationDevice;
|
||||
use nokhwa_core::buffer::Buffer;
|
||||
use nokhwa_core::types::ControlValueSetter;
|
||||
use nokhwa_core::{
|
||||
buffer::Buffer,
|
||||
error::NokhwaError,
|
||||
traits::CaptureBackendTrait,
|
||||
types::{
|
||||
all_known_camera_controls, mjpeg_to_rgb, yuyv422_to_rgb, ApiBackend, CameraControl,
|
||||
CameraFormat, CameraIndex, CameraInfo, FrameFormat, KnownCameraControl,
|
||||
KnownCameraControlFlag, RequestedFormat, Resolution,
|
||||
all_known_camera_controls, ApiBackend, CameraControl, CameraFormat, CameraIndex,
|
||||
CameraInfo, ControlValueSetter, FrameFormat, KnownCameraControl, RequestedFormat,
|
||||
Resolution,
|
||||
},
|
||||
};
|
||||
use std::{any::Any, borrow::Cow, collections::HashMap};
|
||||
use std::{borrow::Cow, collections::HashMap};
|
||||
|
||||
/// The backend that deals with Media Foundation on Windows.
|
||||
/// To see what this does, please see [`CaptureBackendTrait`].
|
||||
@@ -50,14 +47,14 @@ impl<'a> MediaFoundationCaptureDevice<'a> {
|
||||
/// Creates a new capture device using the Media Foundation backend. Indexes are gives to devices by the OS, and usually numbered by order of discovery.
|
||||
/// # Errors
|
||||
/// This function will error if Media Foundation fails to get the device.
|
||||
pub fn new(index: CameraIndex, camera_fmt: RequestedFormat) -> Result<Self, NokhwaError> {
|
||||
pub fn new(index: &CameraIndex, camera_fmt: RequestedFormat) -> Result<Self, NokhwaError> {
|
||||
let mut mf_device = MediaFoundationDevice::new(index.clone())?;
|
||||
|
||||
let info = CameraInfo::new(
|
||||
&mf_device.name(),
|
||||
&"MediaFoundation Camera Device".to_string(),
|
||||
&mf_device.symlink(),
|
||||
index,
|
||||
index.clone(),
|
||||
);
|
||||
|
||||
let availible = mf_device
|
||||
@@ -91,7 +88,7 @@ impl<'a> MediaFoundationCaptureDevice<'a> {
|
||||
/// This function will error if Media Foundation fails to get the device.
|
||||
#[deprecated(since = "0.10", note = "please use `new` instead.")]
|
||||
pub fn new_with(
|
||||
index: CameraIndex,
|
||||
index: &CameraIndex,
|
||||
width: u32,
|
||||
height: u32,
|
||||
fps: u32,
|
||||
|
||||
@@ -100,7 +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
|
||||
pub fn new(index: CameraIndex, cfmt: RequestedFormat) -> Result<Self, NokhwaError> {
|
||||
pub fn new(index: &CameraIndex, cfmt: RequestedFormat) -> Result<Self, NokhwaError> {
|
||||
let api_pref = if index.is_string() {
|
||||
CAP_ANY
|
||||
} else {
|
||||
@@ -132,7 +132,7 @@ impl OpenCvCaptureDevice {
|
||||
|
||||
Ok(OpenCvCaptureDevice {
|
||||
camera_format,
|
||||
camera_location: index,
|
||||
camera_location: index.clone(),
|
||||
camera_info,
|
||||
api_preference: api,
|
||||
video_capture,
|
||||
|
||||
@@ -19,7 +19,6 @@ use nokhwa_core::types::{CameraFormat, CameraInfo};
|
||||
use nokhwa_core::{
|
||||
buffer::Buffer,
|
||||
error::NokhwaError,
|
||||
pixel_format::FormatDecoder,
|
||||
traits::CaptureBackendTrait,
|
||||
types::{
|
||||
mjpeg_to_rgb, yuyv422_to_rgb, ApiBackend, CameraControl, CameraIndex,
|
||||
@@ -116,7 +115,7 @@ impl<'a> V4LCaptureDevice<'a> {
|
||||
/// If `camera_format` is not `None`, the camera will try to use it when you call [`init()`](crate::CaptureBackendTrait::init).
|
||||
/// # Errors
|
||||
/// This function will error if the camera is currently busy or if `V4L2` can't read device information.
|
||||
pub fn new(index: CameraIndex, cam_fmt: RequestedFormat) -> Result<Self, NokhwaError> {
|
||||
pub fn new(index: &CameraIndex, cam_fmt: RequestedFormat) -> Result<Self, NokhwaError> {
|
||||
let mut device = match Device::new(index.as_index()? as usize) {
|
||||
Ok(dev) => dev,
|
||||
Err(why) => {
|
||||
|
||||
+1
-1
@@ -437,7 +437,7 @@ macro_rules! cap_impl_fn {
|
||||
fn [< init_ $backend_name>](idx: &CameraIndex, setting: RequestedFormat) -> Option<Result<Box<dyn CaptureBackendTrait>, NokhwaError>> {
|
||||
use crate::backends::capture::$backend;
|
||||
match <$backend>::$init_fn(idx, setting) {
|
||||
Ok(cap) => Some(Ok(cp.into())),
|
||||
Ok(cap) => Some(Ok(cap.into())),
|
||||
Err(why) => Some(Err(why)),
|
||||
}
|
||||
}
|
||||
|
||||
+5
-6
@@ -26,10 +26,11 @@ fn init_avfoundation(callback: impl Fn(bool) + Send + 'static) {
|
||||
feature = "input-avfoundation",
|
||||
any(target_os = "macos", target_os = "ios")
|
||||
))]
|
||||
fn init_avfoundation(callback: impl Fn(bool) + Send + 'static) {
|
||||
fn init_avfoundation(callback: impl Fn(bool) + Send + Sync + 'static) {
|
||||
use nokhwa_bindings_macos::request_permission_with_callback;
|
||||
|
||||
request_permission_with_callback(callback);
|
||||
let boxed: Box<dyn Fn(bool) + Send + Sync + 'static> = Box::new(callback);
|
||||
request_permission_with_callback(boxed);
|
||||
}
|
||||
|
||||
#[cfg(not(all(
|
||||
@@ -45,9 +46,7 @@ fn status_avfoundation() -> bool {
|
||||
any(target_os = "macos", target_os = "ios")
|
||||
))]
|
||||
fn status_avfoundation() -> bool {
|
||||
use nokhwa_bindings_macos::avfoundation::{
|
||||
current_authorization_status, AVAuthorizationStatus,
|
||||
};
|
||||
use nokhwa_bindings_macos::{current_authorization_status, AVAuthorizationStatus};
|
||||
|
||||
matches!(
|
||||
current_authorization_status(),
|
||||
@@ -60,7 +59,7 @@ fn status_avfoundation() -> bool {
|
||||
///
|
||||
/// The `on_complete` is called after initialization (a.k.a User granted permission). The callback's argument
|
||||
/// is weather the initialization was successful or not
|
||||
pub fn nokhwa_initialize(on_complete: impl Fn(bool) + Send + 'static) {
|
||||
pub fn nokhwa_initialize(on_complete: impl Fn(bool) + Send + Sync + 'static) {
|
||||
init_avfoundation(on_complete);
|
||||
}
|
||||
|
||||
|
||||
+2
-3
@@ -298,11 +298,10 @@ fn query_msmf() -> Result<Vec<CameraInfo>, NokhwaError> {
|
||||
any(target_os = "macos", target_os = "ios")
|
||||
))]
|
||||
fn query_avfoundation() -> Result<Vec<CameraInfo>, NokhwaError> {
|
||||
use nokhwa_bindings_macos::avfoundation::query_avfoundation as q_avf;
|
||||
use nokhwa_bindings_macos::query_avfoundation;
|
||||
|
||||
Ok(q_avf()?
|
||||
Ok(query_avfoundation()?
|
||||
.into_iter()
|
||||
.map(CameraInfo::from)
|
||||
.collect::<Vec<CameraInfo>>())
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user