mirror of
https://github.com/l1npengtul/nokhwa.git
synced 2026-07-04 02:27:26 +00:00
0.10.10
This commit is contained in:
+10
-13
@@ -17,7 +17,6 @@ members = [
|
||||
"nokhwa-bindings-windows",
|
||||
"nokhwa-bindings-linux",
|
||||
"nokhwa-core",
|
||||
"examples/*",
|
||||
]
|
||||
exclude = [ "examples/jscam" ]
|
||||
|
||||
@@ -46,29 +45,27 @@ input-opencv = [
|
||||
"opencv/clang-runtime",
|
||||
"nokhwa-core/opencv-mat",
|
||||
]
|
||||
input-jscam = [
|
||||
"web-sys",
|
||||
"js-sys",
|
||||
"wasm-bindgen-futures",
|
||||
"wasm-bindgen",
|
||||
"wasm-rs-async-executor",
|
||||
]
|
||||
# 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 = [ "parking_lot", "camera-sync-impl" ]
|
||||
# output-wasm = [ "input-jscam" ]
|
||||
output-threaded = [ "parking_lot", "camera-sync-impl" ]
|
||||
camera-sync-impl = [ ]
|
||||
small-wasm = [ ]
|
||||
# small-wasm = [ ]
|
||||
docs-only = [
|
||||
"input-native",
|
||||
"input-opencv",
|
||||
"input-jscam",
|
||||
"output-wgpu",
|
||||
"output-threaded",
|
||||
"serialize",
|
||||
]
|
||||
docs-nolink = [ "nokhwa-core/docs-features" ]
|
||||
docs-features = [ ]
|
||||
test-fail-warning = [ ]
|
||||
|
||||
[dependencies]
|
||||
thiserror = "2.0"
|
||||
|
||||
@@ -5,50 +5,60 @@
|
||||
rust-overlay.url = "github:oxalica/rust-overlay";
|
||||
};
|
||||
|
||||
outputs = { self, nixpkgs, rust-overlay, flake-utils, ... }:
|
||||
flake-utils.lib.eachDefaultSystem (system:
|
||||
let
|
||||
overlays = [ (import rust-overlay) ];
|
||||
outputs = {
|
||||
self,
|
||||
nixpkgs,
|
||||
rust-overlay,
|
||||
flake-utils,
|
||||
...
|
||||
}:
|
||||
flake-utils.lib.eachDefaultSystem (
|
||||
system: let
|
||||
pkgs = import nixpkgs {
|
||||
inherit system overlays;
|
||||
inherit system;
|
||||
overlays = [rust-overlay.overlays.default];
|
||||
};
|
||||
rustbin = pkgs.rust-bin.selectLatestNightlyWith (toolchain:
|
||||
toolchain.default.override {
|
||||
extensions = ["rust-src" "clippy" "rustfmt" "miri"];
|
||||
});
|
||||
in
|
||||
{
|
||||
devShells.default = pkgs.mkShell {
|
||||
#LIBCLANG_PATH = "${pkgs.libclang.lib}/lib";
|
||||
#BINDGEN_EXTRA_CLANG_ARGS = "-isystem ${pkgs.libclang.lib}/lib/clang/${flake-utils.lib.getVersion pkgs.clang}/include";
|
||||
|
||||
nativeBuildInputs = [
|
||||
pkgs.pkg-config
|
||||
pkgs.cmake
|
||||
pkgs.vcpkg
|
||||
];
|
||||
packages = with pkgs; [
|
||||
rust-analyzer
|
||||
pkg-config
|
||||
opencv
|
||||
alsa-lib
|
||||
systemdLibs
|
||||
cmake
|
||||
fontconfig
|
||||
linuxHeaders
|
||||
rustPlatform.bindgenHook
|
||||
llvmPackages.libclang.lib
|
||||
llvmPackages.clang
|
||||
libv4l
|
||||
v4l-utils
|
||||
rustbin
|
||||
extensions = [
|
||||
"rust-src"
|
||||
"clippy"
|
||||
"rustfmt"
|
||||
"miri"
|
||||
"rust-analyzer"
|
||||
];
|
||||
LIBCLANG_PATH = "${pkgs.llvmPackages.libclang.lib}/lib";
|
||||
shellHook = ''
|
||||
export LIBCLANG_PATH = "${pkgs.llvmPackages.libclang.lib}/lib";
|
||||
cargo version
|
||||
'';
|
||||
});
|
||||
in {
|
||||
formatter = pkgs.alejandra;
|
||||
|
||||
devShells.default = pkgs.mkShell {
|
||||
packages =
|
||||
[
|
||||
rustbin
|
||||
]
|
||||
++ (with pkgs; [
|
||||
rust-analyzer
|
||||
pkg-config
|
||||
opencv
|
||||
alsa-lib
|
||||
systemdLibs
|
||||
cmake
|
||||
fontconfig
|
||||
linuxHeaders
|
||||
rustPlatform.bindgenHook
|
||||
llvmPackages.libclang.lib
|
||||
llvmPackages.clang
|
||||
libv4l
|
||||
v4l-utils
|
||||
rustbin
|
||||
]);
|
||||
|
||||
env.RUST_SRC_PATH = "${rustbin}/lib/rustlib/src/rust/library";
|
||||
env.LIBCLANG_PATH = "${pkgs.llvmPackages.libclang.lib}/lib";
|
||||
|
||||
shellHook = ''
|
||||
echo "WONDERHOOOOOY!!!!"
|
||||
'';
|
||||
};
|
||||
}
|
||||
);
|
||||
|
||||
@@ -1,23 +1,23 @@
|
||||
[package]
|
||||
name = "nokhwa-bindings-linux"
|
||||
version = "0.1.2"
|
||||
edition = "2021"
|
||||
license = "Apache-2.0"
|
||||
repository = "https://github.com/l1npengtul/nokhwa"
|
||||
name = "nokhwa-bindings-linux"
|
||||
version = "0.1.3"
|
||||
edition = "2021"
|
||||
license = "Apache-2.0"
|
||||
repository = "https://github.com/l1npengtul/nokhwa"
|
||||
description = "The V4L2 bindings crate for `nokhwa`"
|
||||
keywords = ["v4l", "v4l2", "linux", "capture", "webcam"]
|
||||
keywords = [ "v4l", "v4l2", "linux", "capture", "webcam" ]
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[features]
|
||||
# Disable arena buffer of v4l2 for the crate to work on raspberry pi with faulty v4l2 driver
|
||||
# https://github.com/l1npengtul/nokhwa/pull/121
|
||||
no-arena-buffer = []
|
||||
no-arena-buffer = [ ]
|
||||
|
||||
[dependencies]
|
||||
|
||||
[dependencies.nokhwa-core]
|
||||
version = "0.1"
|
||||
path = "../nokhwa-core"
|
||||
path = "../nokhwa-core"
|
||||
|
||||
[target.'cfg(target_os="linux")'.dependencies]
|
||||
v4l = { version = "0.14", features = ["v4l2-sys"] }
|
||||
v4l = { version = "0.14", features = [ "v4l2-sys" ] }
|
||||
|
||||
@@ -41,7 +41,7 @@ mod internal {
|
||||
control::{Control, Flags, Type, Value},
|
||||
frameinterval::FrameIntervalEnum,
|
||||
framesize::FrameSizeEnum,
|
||||
io::traits::CaptureStream,
|
||||
io::traits::{CaptureStream, Stream},
|
||||
prelude::MmapStream,
|
||||
video::{capture::Parameters, Capture},
|
||||
Device, Format, FourCC,
|
||||
@@ -885,7 +885,7 @@ mod internal {
|
||||
))
|
||||
}
|
||||
|
||||
fn frame_raw(&mut self) -> Result<Cow<[u8]>, NokhwaError> {
|
||||
fn frame_raw(&mut self) -> Result<Cow<'_, [u8]>, NokhwaError> {
|
||||
match &mut self.stream_handle {
|
||||
Some(sh) => match sh.next() {
|
||||
Ok((data, _)) => Ok(Cow::Borrowed(data)),
|
||||
@@ -1090,7 +1090,7 @@ mod internal {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn frame_raw(&mut self) -> Result<Cow<[u8]>, NokhwaError> {
|
||||
fn frame_raw(&mut self) -> Result<Cow<'_, [u8]>, NokhwaError> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
|
||||
@@ -1129,7 +1129,7 @@ pub mod wmf {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn raw_bytes(&mut self) -> Result<Cow<[u8]>, NokhwaError> {
|
||||
pub fn raw_bytes(&mut self) -> Result<Cow<'_, [u8]>, NokhwaError> {
|
||||
let mut imf_sample: Option<IMFSample> = match unsafe { MFCreateSample() } {
|
||||
Ok(sample) => Some(sample),
|
||||
Err(why) => {
|
||||
@@ -1333,7 +1333,7 @@ pub mod wmf {
|
||||
))
|
||||
}
|
||||
|
||||
pub fn raw_bytes(&mut self) -> Result<Cow<[u8]>, NokhwaError> {
|
||||
pub fn raw_bytes(&mut self) -> Result<Cow<'_, [u8]>, NokhwaError> {
|
||||
Err(NokhwaError::NotImplementedError(
|
||||
"Only on Windows".to_string(),
|
||||
))
|
||||
|
||||
@@ -117,7 +117,9 @@ impl Buffer {
|
||||
/// Most notably, the `data` **must** stay in scope for the duration of the [`Mat`](https://docs.rs/opencv/latest/opencv/core/struct.Mat.html) or bad, ***bad*** things happen.
|
||||
#[cfg(feature = "opencv-mat")]
|
||||
#[cfg_attr(feature = "docs-features", doc(cfg(feature = "opencv-mat")))]
|
||||
pub fn decode_opencv_mat<F: FormatDecoder>(&mut self) -> Result<BoxedRef<Mat>, NokhwaError> {
|
||||
pub fn decode_opencv_mat<F: FormatDecoder>(
|
||||
&mut self,
|
||||
) -> Result<BoxedRef<'_, Mat>, NokhwaError> {
|
||||
use crate::buffer::channel_defs::make_mat;
|
||||
|
||||
make_mat::<F>(self.resolution, self.buffer())
|
||||
@@ -230,7 +232,7 @@ pub mod channel_defs {
|
||||
pub(crate) fn make_mat<F>(
|
||||
resolution: Resolution,
|
||||
data: &[u8],
|
||||
) -> Result<opencv::boxed_ref::BoxedRef<opencv::core::Mat>, NokhwaError>
|
||||
) -> Result<opencv::boxed_ref::BoxedRef<'_, opencv::core::Mat>, NokhwaError>
|
||||
where
|
||||
F: FormatDecoder,
|
||||
{
|
||||
|
||||
@@ -25,7 +25,7 @@ use crate::{
|
||||
use std::{borrow::Cow, collections::HashMap};
|
||||
#[cfg(feature = "wgpu-types")]
|
||||
use wgpu::{
|
||||
Device as WgpuDevice, Extent3d, ImageCopyTexture, ImageDataLayout, Queue as WgpuQueue,
|
||||
Device as WgpuDevice, Extent3d, Queue as WgpuQueue, TexelCopyBufferLayout,
|
||||
Texture as WgpuTexture, TextureAspect, TextureDescriptor, TextureDimension, TextureFormat,
|
||||
TextureUsages,
|
||||
};
|
||||
@@ -163,7 +163,7 @@ pub trait CaptureBackendTrait {
|
||||
/// Will get a frame from the camera **without** any processing applied, meaning you will usually get a frame you need to decode yourself.
|
||||
/// # Errors
|
||||
/// If the backend fails to get the frame (e.g. already taken, busy, doesn't exist anymore), or [`open_stream()`](CaptureBackendTrait::open_stream()) has not been called yet, this will error.
|
||||
fn frame_raw(&mut self) -> Result<Cow<[u8]>, NokhwaError>;
|
||||
fn frame_raw(&mut self) -> Result<Cow<'_, [u8]>, NokhwaError>;
|
||||
|
||||
/// The minimum buffer size needed to write the current frame. If `alpha` is true, it will instead return the minimum size of the buffer with an alpha channel as well.
|
||||
/// This assumes that you are decoding to RGB/RGBA for [`FrameFormat::MJPEG`] or [`FrameFormat::YUYV`] and Luma8/LumaA8 for [`FrameFormat::GRAY`]
|
||||
@@ -190,12 +190,14 @@ pub trait CaptureBackendTrait {
|
||||
/// Directly copies a frame to a Wgpu texture. This will automatically convert the frame into a RGBA frame.
|
||||
/// # Errors
|
||||
/// If the frame cannot be captured or the resolution is 0 on any axis, this will error.
|
||||
fn frame_texture<'a>(
|
||||
fn frame_texture(
|
||||
&mut self,
|
||||
device: &WgpuDevice,
|
||||
queue: &WgpuQueue,
|
||||
label: Option<&'a str>,
|
||||
label: Option<&str>,
|
||||
) -> Result<WgpuTexture, NokhwaError> {
|
||||
use wgpu::{Origin3d, TexelCopyTextureInfoBase};
|
||||
|
||||
use crate::pixel_format::RgbAFormat;
|
||||
let frame = self.frame()?.decode_image::<RgbAFormat>()?;
|
||||
|
||||
@@ -221,14 +223,14 @@ pub trait CaptureBackendTrait {
|
||||
let height_nonzero = frame.height();
|
||||
|
||||
queue.write_texture(
|
||||
ImageCopyTexture {
|
||||
TexelCopyTextureInfoBase {
|
||||
texture: &texture,
|
||||
mip_level: 0,
|
||||
origin: wgpu::Origin3d::ZERO,
|
||||
mip_level: 1,
|
||||
origin: Origin3d { x: 0, y: 0, z: 0 },
|
||||
aspect: TextureAspect::All,
|
||||
},
|
||||
&frame,
|
||||
ImageDataLayout {
|
||||
TexelCopyBufferLayout {
|
||||
offset: 0,
|
||||
bytes_per_row: Some(width_nonzero),
|
||||
rows_per_image: Some(height_nonzero),
|
||||
|
||||
@@ -64,7 +64,7 @@ impl RequestedFormat<'_> {
|
||||
pub fn with_formats(
|
||||
requested: RequestedFormatType,
|
||||
decoder: &[FrameFormat],
|
||||
) -> RequestedFormat {
|
||||
) -> RequestedFormat<'_> {
|
||||
RequestedFormat {
|
||||
requested_format: requested,
|
||||
wanted_decoder: decoder,
|
||||
|
||||
@@ -23,14 +23,15 @@ use nokhwa_bindings_macos::{
|
||||
use nokhwa_core::{
|
||||
buffer::Buffer,
|
||||
error::NokhwaError,
|
||||
pixel_format::RgbFormat,
|
||||
traits::CaptureBackendTrait,
|
||||
types::{
|
||||
ApiBackend, CameraControl, CameraFormat, CameraIndex, CameraInfo, ControlValueSetter,
|
||||
FrameFormat, KnownCameraControl, RequestedFormat, RequestedFormatType, Resolution,
|
||||
FrameFormat, KnownCameraControl, RequestedFormat, Resolution,
|
||||
},
|
||||
};
|
||||
#[cfg(target_os = "macos")]
|
||||
use nokhwa_core::{pixel_format::RgbFormat, types::RequestedFormatType};
|
||||
#[cfg(target_os = "macos")]
|
||||
use std::{ffi::CString, sync::Arc};
|
||||
|
||||
use std::{borrow::Cow, collections::HashMap};
|
||||
@@ -287,7 +288,7 @@ impl CaptureBackendTrait for AVFoundationCaptureDevice {
|
||||
Ok(buffer)
|
||||
}
|
||||
|
||||
fn frame_raw(&mut self) -> Result<Cow<[u8]>, NokhwaError> {
|
||||
fn frame_raw(&mut self) -> Result<Cow<'_, [u8]>, NokhwaError> {
|
||||
let result = match self.frame_buffer_receiver.recv() {
|
||||
Ok(recv) => Ok(Cow::from(recv.0)),
|
||||
Err(why) => Err(NokhwaError::ReadFrameError(why.to_string())),
|
||||
@@ -480,7 +481,7 @@ impl CaptureBackendTrait for AVFoundationCaptureDevice {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn frame_raw(&mut self) -> Result<Cow<[u8]>, NokhwaError> {
|
||||
fn frame_raw(&mut self) -> Result<Cow<'_, [u8]>, NokhwaError> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
|
||||
@@ -251,7 +251,7 @@ impl CaptureBackendTrait for MediaFoundationCaptureDevice {
|
||||
))
|
||||
}
|
||||
|
||||
fn frame_raw(&mut self) -> Result<Cow<[u8]>, NokhwaError> {
|
||||
fn frame_raw(&mut self) -> Result<Cow<'_, [u8]>, NokhwaError> {
|
||||
self.inner.raw_bytes()
|
||||
}
|
||||
|
||||
|
||||
@@ -169,7 +169,7 @@ impl OpenCvCaptureDevice {
|
||||
/// # Errors
|
||||
/// If the frame is failed to be read, this will error.
|
||||
#[allow(clippy::cast_sign_loss)]
|
||||
pub fn raw_frame_vec(&mut self) -> Result<Cow<[u8]>, NokhwaError> {
|
||||
pub fn raw_frame_vec(&mut self) -> Result<Cow<'_, [u8]>, NokhwaError> {
|
||||
if !self.is_stream_open() {
|
||||
return Err(NokhwaError::ReadFrameError(
|
||||
"Stream is not open!".to_string(),
|
||||
@@ -541,7 +541,7 @@ impl CaptureBackendTrait for OpenCvCaptureDevice {
|
||||
))
|
||||
}
|
||||
|
||||
fn frame_raw(&mut self) -> Result<Cow<[u8]>, NokhwaError> {
|
||||
fn frame_raw(&mut self) -> Result<Cow<'_, [u8]>, NokhwaError> {
|
||||
let cow = self.raw_frame_vec()?;
|
||||
Ok(cow)
|
||||
}
|
||||
|
||||
+1
-1
@@ -384,7 +384,7 @@ impl Camera {
|
||||
/// Will get a frame from the camera **without** any processing applied, meaning you will usually get a frame you need to decode yourself.
|
||||
/// # Errors
|
||||
/// If the backend fails to get the frame (e.g. already taken, busy, doesn't exist anymore), or [`open_stream()`](CaptureBackendTrait::open_stream()) has not been called yet, this will error.
|
||||
pub fn frame_raw(&mut self) -> Result<Cow<[u8]>, NokhwaError> {
|
||||
pub fn frame_raw(&mut self) -> Result<Cow<'_, [u8]>, NokhwaError> {
|
||||
match self.device.frame_raw() {
|
||||
Ok(f) => Ok(f),
|
||||
Err(why) => Err(why),
|
||||
|
||||
+39
-35
@@ -32,7 +32,7 @@ use std::{
|
||||
fmt::{Debug, Display, Formatter},
|
||||
ops::Deref,
|
||||
};
|
||||
use wasm_bindgen::{JsCast, JsValue};
|
||||
use wasm_bindgen::{prelude::wasm_bindgen, JsCast, JsValue};
|
||||
use wasm_bindgen_futures::JsFuture;
|
||||
use web_sys::{
|
||||
console::log_1, CanvasRenderingContext2d, Document, Element, HtmlCanvasElement,
|
||||
@@ -41,8 +41,9 @@ use web_sys::{
|
||||
};
|
||||
#[cfg(feature = "output-wgpu")]
|
||||
use wgpu::{
|
||||
Device, Extent3d, ImageCopyTexture, ImageDataLayout, Queue, Texture, TextureAspect,
|
||||
TextureDescriptor, TextureDimension, TextureFormat, TextureUsages,
|
||||
Device as WgpuDevice, Extent3d, Queue as WgpuQueue, TexelCopyBufferLayout,
|
||||
Texture as WgpuTexture, TextureAspect, TextureDescriptor, TextureDimension, TextureFormat,
|
||||
TextureUsages,
|
||||
};
|
||||
|
||||
// why no code completion
|
||||
@@ -203,8 +204,8 @@ pub async fn request_permission() -> Result<(), NokhwaError> {
|
||||
|
||||
match media_devices.get_user_media_with_constraints(
|
||||
MediaStreamConstraints::new()
|
||||
.video(&JsValue::from_bool(true))
|
||||
.audio(&JsValue::from_bool(false)),
|
||||
.set_video(&JsValue::from_bool(true))
|
||||
.set_audio(&JsValue::from_bool(false)),
|
||||
) {
|
||||
Ok(promise) => {
|
||||
let js_future = JsFuture::from(promise);
|
||||
@@ -266,8 +267,8 @@ pub async fn query_js_cameras() -> Result<Vec<CameraInfo>, NokhwaError> {
|
||||
if media_device_info.kind() == MediaDeviceKind::Videoinput {
|
||||
match media_devices.get_user_media_with_constraints(
|
||||
MediaStreamConstraints::new()
|
||||
.audio(&jsv!(false))
|
||||
.video(&jsv!(obj!((
|
||||
.set_audio(&jsv!(false))
|
||||
.set_video(&jsv!(obj!((
|
||||
"deviceId",
|
||||
media_device_info.device_id()
|
||||
)))),
|
||||
@@ -603,8 +604,8 @@ impl JSCameraConstraintsBuilder {
|
||||
feature = "output-wasm",
|
||||
wasm_bindgen(js_name = MinResolution)
|
||||
)]
|
||||
pub fn min_resolution(mut self, min_resolution: Resolution) -> JSCameraConstraintsBuilder {
|
||||
self.min_resolution = Some(min_resolution);
|
||||
pub fn min_resolution(mut self, min_resolution: &Resolution) -> JSCameraConstraintsBuilder {
|
||||
self.min_resolution = Some(*min_resolution);
|
||||
self
|
||||
}
|
||||
|
||||
@@ -618,8 +619,8 @@ impl JSCameraConstraintsBuilder {
|
||||
feature = "output-wasm",
|
||||
wasm_bindgen(js_name = Resolution)
|
||||
)]
|
||||
pub fn resolution(mut self, new_resolution: Resolution) -> JSCameraConstraintsBuilder {
|
||||
self.preferred_resolution = new_resolution;
|
||||
pub fn resolution(mut self, new_resolution: &Resolution) -> JSCameraConstraintsBuilder {
|
||||
self.preferred_resolution = *new_resolution;
|
||||
self
|
||||
}
|
||||
|
||||
@@ -633,8 +634,8 @@ impl JSCameraConstraintsBuilder {
|
||||
feature = "output-wasm",
|
||||
wasm_bindgen(js_name = MaxResolution)
|
||||
)]
|
||||
pub fn max_resolution(mut self, max_resolution: Resolution) -> JSCameraConstraintsBuilder {
|
||||
self.min_resolution = Some(max_resolution);
|
||||
pub fn max_resolution(mut self, max_resolution: &Resolution) -> JSCameraConstraintsBuilder {
|
||||
self.min_resolution = Some(*max_resolution);
|
||||
self
|
||||
}
|
||||
|
||||
@@ -1038,8 +1039,8 @@ impl JSCameraConstraintsBuilder {
|
||||
}
|
||||
|
||||
let media_stream_constraints = MediaStreamConstraints::new()
|
||||
.audio(&jsv!(false))
|
||||
.video(&jsv!(video_object))
|
||||
.set_audio(&jsv!(false))
|
||||
.set_video(&jsv!(video_object))
|
||||
.clone();
|
||||
|
||||
JSCameraConstraints {
|
||||
@@ -2577,20 +2578,20 @@ impl JSCamera {
|
||||
#[cfg(feature = "output-wgpu")]
|
||||
/// Directly copies a frame to a Wgpu texture. This will automatically convert the frame into a RGBA frame.
|
||||
/// # Errors
|
||||
/// If the frame cannot be captured or the resolution is 0 on any axis, this will error.
|
||||
pub fn frame_texture<'a>(
|
||||
fn frame_texture(
|
||||
&mut self,
|
||||
device: &Device,
|
||||
queue: &Queue,
|
||||
label: Option<&'a str>,
|
||||
) -> Result<Texture, NokhwaError> {
|
||||
use std::num::NonZeroU32;
|
||||
let resolution = self.resolution();
|
||||
let frame = self.frame_raw()?;
|
||||
device: &WgpuDevice,
|
||||
queue: &WgpuQueue,
|
||||
label: Option<&str>,
|
||||
) -> Result<WgpuTexture, NokhwaError> {
|
||||
use wgpu::{Origin3d, TexelCopyTextureInfoBase};
|
||||
|
||||
use crate::pixel_format::RgbAFormat;
|
||||
let frame = self.frame()?.decode_image::<RgbAFormat>()?;
|
||||
|
||||
let texture_size = Extent3d {
|
||||
width: resolution.width(),
|
||||
height: resolution.height(),
|
||||
width: frame.width(),
|
||||
height: frame.height(),
|
||||
depth_or_array_layers: 1,
|
||||
};
|
||||
|
||||
@@ -2602,28 +2603,31 @@ impl JSCamera {
|
||||
dimension: TextureDimension::D2,
|
||||
format: TextureFormat::Rgba8UnormSrgb,
|
||||
usage: TextureUsages::TEXTURE_BINDING | TextureUsages::COPY_DST,
|
||||
view_formats: &[TextureFormat::Rgba8UnormSrgb],
|
||||
view_formats: &[],
|
||||
});
|
||||
|
||||
let width_nonzero = 4 * frame.width();
|
||||
|
||||
let height_nonzero = frame.height();
|
||||
|
||||
queue.write_texture(
|
||||
ImageCopyTexture {
|
||||
TexelCopyTextureInfoBase {
|
||||
texture: &texture,
|
||||
mip_level: 0,
|
||||
origin: wgpu::Origin3d::ZERO,
|
||||
mip_level: 1,
|
||||
origin: Origin3d { x: 0, y: 0, z: 0 },
|
||||
aspect: TextureAspect::All,
|
||||
},
|
||||
frame.borrow(),
|
||||
ImageDataLayout {
|
||||
&frame,
|
||||
TexelCopyBufferLayout {
|
||||
offset: 0,
|
||||
bytes_per_row: Some(4 * resolution.width()),
|
||||
rows_per_image: Some(resolution.height()),
|
||||
bytes_per_row: Some(width_nonzero),
|
||||
rows_per_image: Some(height_nonzero),
|
||||
},
|
||||
texture_size,
|
||||
);
|
||||
|
||||
Ok(texture)
|
||||
}
|
||||
|
||||
/// Checks if the stream is open.
|
||||
pub fn is_open(&self) -> bool {
|
||||
let stream = self
|
||||
|
||||
+4
-5
@@ -16,7 +16,6 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#![cfg_attr(feature = "test-fail-warning", deny(warnings))]
|
||||
#![cfg_attr(feature = "docs-features", feature(doc_cfg))]
|
||||
//! # nokhwa
|
||||
//! A Simple-to-use, cross-platform Rust Webcam Capture Library
|
||||
@@ -34,10 +33,10 @@
|
||||
pub mod backends;
|
||||
mod camera;
|
||||
mod init;
|
||||
/// A camera that uses native browser APIs meant for WASM applications.
|
||||
#[cfg(feature = "input-jscam")]
|
||||
#[cfg_attr(feature = "docs-features", doc(cfg(feature = "input-jscam")))]
|
||||
pub mod js_camera;
|
||||
// /// A camera that uses native browser APIs meant for WASM applications.
|
||||
// #[cfg(feature = "input-jscam")]
|
||||
// #[cfg_attr(feature = "docs-features", doc(cfg(feature = "input-jscam")))]
|
||||
// pub mod js_camera;
|
||||
|
||||
pub use nokhwa_core::pixel_format::FormatDecoder;
|
||||
mod query;
|
||||
|
||||
+6
-7
@@ -295,15 +295,14 @@ fn query_avfoundation() -> Result<Vec<CameraInfo>, NokhwaError> {
|
||||
))
|
||||
}
|
||||
|
||||
#[cfg(feature = "input-jscam")]
|
||||
fn query_wasm() -> Result<Vec<CameraInfo>, NokhwaError> {
|
||||
use crate::js_camera::query_js_cameras;
|
||||
use wasm_rs_async_executor::single_threaded::block_on;
|
||||
// #[cfg(feature = "input-jscam")]
|
||||
// fn query_wasm() -> Result<Vec<CameraInfo>, NokhwaError> {
|
||||
// use crate::js_camera::query_js_cameras;
|
||||
// use wasm_rs_async_executor::single_threaded::block_on;
|
||||
|
||||
block_on(query_js_cameras())
|
||||
}
|
||||
// block_on(query_js_cameras())
|
||||
// }
|
||||
|
||||
#[cfg(not(feature = "input-jscam"))]
|
||||
fn query_wasm() -> Result<Vec<CameraInfo>, NokhwaError> {
|
||||
Err(NokhwaError::UnsupportedOperationError(ApiBackend::Browser))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user