mirror of
https://github.com/l1npengtul/nokhwa.git
synced 2026-07-04 02:27:26 +00:00
0.10 preliminary work
This commit is contained in:
+15
-22
@@ -10,6 +10,10 @@ repository = "https://github.com/l1npengtul/nokhwa"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[workspace]
|
||||
members = ["nokhwa-bindings-macos", "nokhwa-bindings-windows"]
|
||||
exclude = ["examples/threaded-capture", "examples/capture"]
|
||||
|
||||
[lib]
|
||||
crate-type = ["cdylib", "rlib"]
|
||||
|
||||
@@ -28,7 +32,7 @@ input-jscam = ["web-sys", "js-sys", "wasm-bindgen-futures", "wasm-bindgen", "was
|
||||
output-wgpu = ["wgpu"]
|
||||
output-wasm = ["input-jscam"]
|
||||
output-threaded = ["parking_lot"]
|
||||
small-wasm = ["wee_alloc"]
|
||||
small-wasm = []
|
||||
docs-only = ["input-v4l", "input-opencv", "input-ipcam", "input-gst", "input-msmf", "input-avfoundation", "input-jscam","output-wgpu", "output-wasm", "output-threaded"]
|
||||
docs-nolink = ["glib/dox", "gstreamer-app/dox", "gstreamer/dox", "gstreamer-video/dox", "opencv/docs-only"]
|
||||
docs-features = []
|
||||
@@ -37,35 +41,29 @@ test-fail-warning = []
|
||||
[dependencies]
|
||||
thiserror = "1.0"
|
||||
paste = "1.0"
|
||||
anymap = "1.0.0-beta.2"
|
||||
enum_dispatch = "0.3"
|
||||
|
||||
[dependencies.flume]
|
||||
version = "0.10"
|
||||
optional = true
|
||||
|
||||
[dependencies.image]
|
||||
version = "0.23"
|
||||
version = "0.24"
|
||||
default-features = false
|
||||
|
||||
[target.'cfg(not(target_arch = "wasm"))'.dependencies.mozjpeg]
|
||||
[dependencies.mozjpeg]
|
||||
version = "0.9"
|
||||
optional = true
|
||||
|
||||
[target.'cfg(target_os = "linux")'.dependencies.v4l]
|
||||
[dependencies.v4l]
|
||||
version = "0.12"
|
||||
optional = true
|
||||
|
||||
[target.'cfg(target_os = "linux")'.dependencies.v4l2-sys-mit]
|
||||
[dependencies.v4l2-sys-mit]
|
||||
version = "0.2"
|
||||
optional = true
|
||||
|
||||
[dependencies.ouroboros]
|
||||
version = "0.14"
|
||||
optional = true
|
||||
|
||||
# [dependencies.uvc]
|
||||
# version = "0.2"
|
||||
# optional = true
|
||||
|
||||
[dependencies.usb_enumeration]
|
||||
version = "0.1.2"
|
||||
optional = true
|
||||
@@ -75,17 +73,17 @@ version = "^0.12"
|
||||
optional = true
|
||||
|
||||
[dependencies.opencv]
|
||||
version = "0.62"
|
||||
version = "0.63"
|
||||
features = ["clang-runtime"]
|
||||
optional = true
|
||||
|
||||
[dependencies.nokhwa-bindings-windows]
|
||||
version = "0.3"
|
||||
version = "0.3.4"
|
||||
path = "nokhwa-bindings-windows"
|
||||
optional = true
|
||||
|
||||
[dependencies.nokhwa-bindings-macos]
|
||||
version = "0.1"
|
||||
version = "0.1.1"
|
||||
path = "nokhwa-bindings-macos"
|
||||
optional = true
|
||||
|
||||
@@ -111,7 +109,6 @@ optional = true
|
||||
|
||||
[dependencies.web-sys]
|
||||
version = "0.3"
|
||||
# why
|
||||
features = [
|
||||
"console",
|
||||
"CanvasRenderingContext2d",
|
||||
@@ -146,12 +143,8 @@ optional = true
|
||||
version = "0.9"
|
||||
optional = true
|
||||
|
||||
[dependencies.wee_alloc]
|
||||
version = "0.4"
|
||||
optional = true
|
||||
|
||||
[dependencies.parking_lot]
|
||||
version = "0.11"
|
||||
version = "0.12"
|
||||
optional = true
|
||||
|
||||
[dependencies.lazy_static]
|
||||
|
||||
Vendored
-135
@@ -1,135 +0,0 @@
|
||||
pipeline {
|
||||
agent {
|
||||
node {
|
||||
label 'ci_linux'
|
||||
}
|
||||
|
||||
}
|
||||
stages {
|
||||
stage('Sanity Check') {
|
||||
steps {
|
||||
echo '$BUILD_TAG'
|
||||
scmSkip(deleteBuild: true, skipPattern: '.*\\[ci skip\\].*')
|
||||
}
|
||||
}
|
||||
|
||||
stage('Cargo RustFMT') {
|
||||
agent {
|
||||
node {
|
||||
label 'ci_linux'
|
||||
}
|
||||
|
||||
}
|
||||
steps {
|
||||
scmSkip(deleteBuild: true, skipPattern: '.*\\[ci skip\\].*')
|
||||
sh 'rustup update stable'
|
||||
sh 'cargo fmt --all -- --check'
|
||||
}
|
||||
}
|
||||
|
||||
stage('Build, Clippy') {
|
||||
parallel {
|
||||
stage('V4L2') {
|
||||
agent {
|
||||
node {
|
||||
label 'ci_linux'
|
||||
}
|
||||
|
||||
}
|
||||
steps {
|
||||
scmSkip(skipPattern: '.*\\[ci skip\\].*', deleteBuild: true)
|
||||
sh 'rustup update stable'
|
||||
sh 'cargo clippy --features "input-v4l, output-wgpu, test-fail-warning"'
|
||||
}
|
||||
}
|
||||
|
||||
stage('Media Foundation') {
|
||||
agent {
|
||||
node {
|
||||
label 'ci_windows'
|
||||
}
|
||||
|
||||
}
|
||||
steps {
|
||||
scmSkip(skipPattern: '.*\\[ci skip\\].*', deleteBuild: true)
|
||||
pwsh(script: 'rustup update stable', returnStatus: true)
|
||||
pwsh(script: 'cargo clippy --features "input-msmf, output-wgpu, test-fail-warning"', returnStatus: true, returnStdout: true)
|
||||
}
|
||||
}
|
||||
|
||||
stage('AVFoundation') {
|
||||
steps {
|
||||
sh 'echo TODO'
|
||||
}
|
||||
}
|
||||
|
||||
stage('libUVC') {
|
||||
agent {
|
||||
node {
|
||||
label 'ci_linux'
|
||||
}
|
||||
|
||||
}
|
||||
steps {
|
||||
scmSkip(skipPattern: '.*\\[ci skip\\].*', deleteBuild: true)
|
||||
sh 'rustup update stable'
|
||||
sh 'cargo clippy --features "input-uvc, output-wgpu, test-fail-warning"'
|
||||
}
|
||||
}
|
||||
|
||||
stage('OpenCV IPCamera') {
|
||||
agent {
|
||||
node {
|
||||
label 'ci_linux'
|
||||
}
|
||||
|
||||
}
|
||||
steps {
|
||||
scmSkip(skipPattern: '.*\\[ci skip\\].*', deleteBuild: true)
|
||||
sh 'rustup update stable'
|
||||
sh 'cargo clippy --features "input-opencv, input-ipcam, output-wgpu, test-fail-warning"'
|
||||
}
|
||||
}
|
||||
|
||||
stage('GStreamer') {
|
||||
agent {
|
||||
node {
|
||||
label 'ci_linux'
|
||||
}
|
||||
|
||||
}
|
||||
steps {
|
||||
scmSkip(skipPattern: '.*\\[ci skip\\].*', deleteBuild: true)
|
||||
sh 'rustup update nightly'
|
||||
sh 'cargo clippy --features "input-gst, output-wgpu, test-fail-warning"'
|
||||
}
|
||||
}
|
||||
|
||||
stage('JSCamera/WASM') {
|
||||
steps {
|
||||
scmSkip(skipPattern: '.*\\[ci skip\\].*', deleteBuild: true)
|
||||
sh 'rustup update stable'
|
||||
sh 'wasm-pack build --release -- --features "input-jscam, output-wasm, test-fail-warning" --no-default-features'
|
||||
sh 'cargo clippy --features "input-jscam, output-wasm, test-fail-warning" --no-default-features'
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
stage('RustDOC') {
|
||||
agent {
|
||||
node {
|
||||
label 'ci_linux'
|
||||
}
|
||||
|
||||
}
|
||||
steps {
|
||||
scmSkip(skipPattern: '.*\\[ci skip\\].*', deleteBuild: true)
|
||||
sh 'rustup update nightly'
|
||||
sh 'cargo +nightly doc --features "docs-only, docs-nolink, docs-features, test-fail-warning" --no-deps --release'
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1303,6 +1303,7 @@ pub mod avfoundation {
|
||||
pub enum AVFourCC {
|
||||
YUV2,
|
||||
MJPEG,
|
||||
GRAY8,
|
||||
}
|
||||
|
||||
// Localized Name
|
||||
|
||||
@@ -155,7 +155,7 @@ impl GStreamerCaptureDevice {
|
||||
}
|
||||
}
|
||||
|
||||
impl CaptureBackendTrait for GStreamerCaptureDevice {
|
||||
impl GStreamerCaptureDevice {
|
||||
fn backend(&self) -> CaptureAPIBackend {
|
||||
CaptureAPIBackend::GStreamer
|
||||
}
|
||||
|
||||
@@ -35,6 +35,7 @@ use v4l::{
|
||||
|
||||
use std::any::Any;
|
||||
pub use v4l::control::{Control, Description, Flags};
|
||||
use v4l::video::Output;
|
||||
|
||||
/// Generates a camera control from a device and a description of control
|
||||
/// # Error
|
||||
@@ -212,6 +213,7 @@ impl<'a> V4LCaptureDevice<'a> {
|
||||
let fourcc = match camera_format.format() {
|
||||
FrameFormat::MJPEG => FourCC::new(b"MJPG"),
|
||||
FrameFormat::YUYV => FourCC::new(b"YUYV"),
|
||||
FrameFormat::GRAY8 => FourCC::new(b"GRAY"),
|
||||
};
|
||||
|
||||
let new_param = Parameters::with_fps(camera_format.frame_rate());
|
||||
@@ -284,6 +286,7 @@ impl<'a> V4LCaptureDevice<'a> {
|
||||
let format = match fourcc {
|
||||
FrameFormat::MJPEG => FourCC::new(b"MJPG"),
|
||||
FrameFormat::YUYV => FourCC::new(b"YUYV"),
|
||||
FrameFormat::GRAY8 => FourCC::new("GRAY"),
|
||||
};
|
||||
|
||||
match v4l::video::Capture::enum_framesizes(&self.device, format) {
|
||||
@@ -311,6 +314,7 @@ impl<'a> V4LCaptureDevice<'a> {
|
||||
}
|
||||
|
||||
/// Get the inner device (immutable) for e.g. Controls
|
||||
/// apps bloodtests contact css images index index.html injectionsupplies transfem transmasc
|
||||
#[allow(clippy::must_use_candidate)]
|
||||
pub fn inner_device(&self) -> &Device {
|
||||
&self.device
|
||||
@@ -320,6 +324,18 @@ impl<'a> V4LCaptureDevice<'a> {
|
||||
pub fn inner_device_mut(&mut self) -> &mut Device {
|
||||
&mut self.device
|
||||
}
|
||||
|
||||
/// Force refreshes the inner [`CameraFormat`] state.
|
||||
pub fn force_refresh_camera_format(&mut self) -> Result<(), NokhwaError> {
|
||||
match (self.device.params(), self.device.format()) {
|
||||
(Ok(params), Ok(format)) => {
|
||||
let new_format = CameraFormat::new(params.capabilities.)
|
||||
}
|
||||
(_, _) => {
|
||||
return Err(NokhwaError::GetPropertyError { property: "parameters".to_string(), error: why.to_string() })
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> CaptureBackendTrait for V4LCaptureDevice<'a> {
|
||||
@@ -409,6 +425,7 @@ impl<'a> CaptureBackendTrait for V4LCaptureDevice<'a> {
|
||||
let format = match fourcc {
|
||||
FrameFormat::MJPEG => FourCC::new(b"MJPG"),
|
||||
FrameFormat::YUYV => FourCC::new(b"YUYV"),
|
||||
FrameFormat::GRAY8 => {}
|
||||
};
|
||||
let mut res_map = HashMap::new();
|
||||
for res in resolutions {
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright 2022 l1npengtul <l1npengtul@protonmail.com> / The Nokhwa Contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
use crate::pixel_format::{PixelFormat, PixelFormats};
|
||||
use crate::{FrameFormat, NokhwaError, Resolution};
|
||||
use image::ImageBuffer;
|
||||
|
||||
#[derive(Clone, Debug, Default, Hash, PartialOrd, PartialEq)]
|
||||
#[cfg_attr("serde", Serialize, Deserialize)]
|
||||
pub struct Buffer {
|
||||
resolution: Resolution,
|
||||
buffer: Vec<u8>,
|
||||
|
||||
}
|
||||
|
||||
impl Buffer {
|
||||
pub fn new(res: Resolution, buf: Vec<u8>) -> Self {
|
||||
Self {
|
||||
resolution: res,
|
||||
buffer: buf,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_image_with_custom_format<I>(self) -> Result<ImageBuffer<I::Output, Vec<u8>>, NokhwaError>
|
||||
where
|
||||
I: PixelFormat,
|
||||
{
|
||||
ImageBuffer::from_raw(
|
||||
self.resolution.width_x,
|
||||
self.resolution.height_y,
|
||||
self.buffer,
|
||||
).ok_or(NokhwaError::ProcessFrameError {
|
||||
src: ,
|
||||
destination: "".to_string(),
|
||||
error: "".to_string()
|
||||
})
|
||||
}
|
||||
}
|
||||
+19
-10
@@ -29,14 +29,19 @@ use wgpu::{
|
||||
};
|
||||
|
||||
/// The main `Camera` struct. This is the struct that abstracts over all the backends, providing a simplified interface for use.
|
||||
pub struct Camera {
|
||||
pub struct Camera<C>
|
||||
where
|
||||
C: CaptureBackendTrait,
|
||||
{
|
||||
idx: usize,
|
||||
backend: Box<dyn CaptureBackendTrait>,
|
||||
backend: C,
|
||||
backend_api: CaptureAPIBackend,
|
||||
}
|
||||
|
||||
#[allow(clippy::nonminimal_bool)]
|
||||
impl Camera {
|
||||
impl Camera<C>
|
||||
where
|
||||
C: CaptureBackendTrait,
|
||||
{
|
||||
/// Create a new camera from an `index` and `format`
|
||||
/// # Errors
|
||||
/// This will error if you either have a bad platform configuration (e.g. `input-v4l` but not on linux) or the backend cannot create the camera (e.g. permission denied).
|
||||
@@ -386,6 +391,7 @@ impl Camera {
|
||||
FrameFormat::YUYV => {
|
||||
crate::utils::buf_yuyv422_to_rgb(&raw_frame, buffer, convert_rgba)?
|
||||
}
|
||||
FrameFormat::GRAY8 => {}
|
||||
};
|
||||
|
||||
Ok(())
|
||||
@@ -459,7 +465,10 @@ impl Camera {
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for Camera {
|
||||
impl Drop for Camera<C>
|
||||
where
|
||||
C: CaptureBackendTrait,
|
||||
{
|
||||
fn drop(&mut self) {
|
||||
self.stop_stream().unwrap();
|
||||
}
|
||||
@@ -496,7 +505,7 @@ macro_rules! cap_impl_fn {
|
||||
$(
|
||||
paste::paste! {
|
||||
#[cfg ($cfg) ]
|
||||
fn [< init_ $backend_name>](idx: usize, setting: Option<CameraFormat>) -> Option<Result<Box<dyn CaptureBackendTrait>, NokhwaError>> {
|
||||
fn [< init_ $backend_name>]<C: CaptureBackendTrait>(idx: usize, setting: Option<CameraFormat>) -> Option<Result<C, NokhwaError>> {
|
||||
use crate::backends::capture::$backend;
|
||||
match <$backend>::$init_fn(idx, setting) {
|
||||
Ok(cap) => Some(Ok(Box::new(cap))),
|
||||
@@ -504,7 +513,7 @@ macro_rules! cap_impl_fn {
|
||||
}
|
||||
}
|
||||
#[cfg(not( $cfg ))]
|
||||
fn [< init_ $backend_name>](_idx: usize, _setting: Option<CameraFormat>) -> Option<Result<Box<dyn CaptureBackendTrait>, NokhwaError>> {
|
||||
fn [< init_ $backend_name>]<C: CaptureBackendTrait>(_idx: usize, _setting: Option<CameraFormat>) -> Option<Result<C, NokhwaError>> {
|
||||
None
|
||||
}
|
||||
}
|
||||
@@ -603,11 +612,11 @@ cap_impl_fn! {
|
||||
(AVFoundationCaptureDevice, new, all(feature = "input-avfoundation", any(target_os = "macos", target_os = "ios")), avfoundation)
|
||||
}
|
||||
|
||||
fn init_camera(
|
||||
fn init_camera<C: CaptureBackendTrait + Send + Sync>(
|
||||
index: usize,
|
||||
format: Option<CameraFormat>,
|
||||
backend: CaptureAPIBackend,
|
||||
) -> Result<Box<dyn CaptureBackendTrait>, NokhwaError> {
|
||||
) -> Result<C, NokhwaError> {
|
||||
let camera_backend = cap_impl_matches! {
|
||||
backend, index, format,
|
||||
("input-v4l", Video4Linux, init_v4l),
|
||||
@@ -621,4 +630,4 @@ fn init_camera(
|
||||
}
|
||||
|
||||
#[cfg(feature = "output-threaded")]
|
||||
unsafe impl Send for Camera {}
|
||||
unsafe impl Send for Camera<C> where C: CaptureBackendTrait {}
|
||||
|
||||
@@ -21,6 +21,7 @@ use crate::{
|
||||
};
|
||||
use image::{buffer::ConvertBuffer, ImageBuffer, Rgb, RgbaImage};
|
||||
|
||||
use crate::pixel_format::PixelFormat;
|
||||
use std::{any::Any, borrow::Cow, collections::HashMap};
|
||||
#[cfg(feature = "output-wgpu")]
|
||||
use wgpu::{
|
||||
@@ -36,7 +37,10 @@ use wgpu::{
|
||||
/// - Backends, if not provided with a camera format, will be spawned with 640x480@15 FPS, MJPEG [`CameraFormat`].
|
||||
/// - Behaviour can differ from backend to backend. While the [`Camera`](crate::camera::Camera) struct abstracts most of this away, if you plan to use the raw backend structs please read the `Quirks` section of each backend.
|
||||
/// - If you call [`stop_stream()`](CaptureBackendTrait::stop_stream()), you will usually need to call [`open_stream()`](CaptureBackendTrait::open_stream()) to get more frames from the camera.
|
||||
pub trait CaptureBackendTrait: Send {
|
||||
pub trait CaptureBackendTrait {
|
||||
/// Initializes the camera. You must call this before any other function.
|
||||
fn init(&mut self) -> Result<CameraFormat, NokhwaError>;
|
||||
|
||||
/// Returns the current backend used.
|
||||
fn backend(&self) -> CaptureAPIBackend;
|
||||
|
||||
@@ -209,7 +213,7 @@ pub trait CaptureBackendTrait: Send {
|
||||
queue: &WgpuQueue,
|
||||
label: Option<&'a str>,
|
||||
) -> Result<WgpuTexture, NokhwaError> {
|
||||
use std::num::NonZeroU32;
|
||||
use std::{convert::TryFrom, num::NonZeroU32};
|
||||
let frame = self.frame()?;
|
||||
let rgba_frame: RgbaImage = frame.convert();
|
||||
|
||||
|
||||
@@ -21,6 +21,8 @@ use thiserror::Error;
|
||||
#[allow(clippy::module_name_repetitions)]
|
||||
#[derive(Error, Debug, Clone)]
|
||||
pub enum NokhwaError {
|
||||
#[error("Unitialized Camera. Call `init()` first!")]
|
||||
UnitializedError,
|
||||
#[error("Could not initialize {backend}: {error}")]
|
||||
InitializeError {
|
||||
backend: CaptureAPIBackend,
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
|
||||
/// Raw access to each of Nokhwa's backends.
|
||||
pub mod backends;
|
||||
pub mod buffer;
|
||||
mod camera;
|
||||
mod camera_traits;
|
||||
mod error;
|
||||
@@ -40,6 +41,7 @@ pub mod js_camera;
|
||||
#[cfg(feature = "input-ipcam")]
|
||||
#[cfg_attr(feature = "docs-features", doc(cfg(feature = "input-ipcam")))]
|
||||
pub mod network_camera;
|
||||
pub mod pixel_format;
|
||||
mod query;
|
||||
/// A camera that runs in a different thread and can call your code based on callbacks.
|
||||
#[cfg(feature = "output-threaded")]
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright 2022 l1npengtul <l1npengtul@protonmail.com> / The Nokhwa Contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
use crate::buffer_output::{BufferOutput, GrayU8, RgbU8};
|
||||
use image::{Luma, Pixel, Rgb};
|
||||
use std::fmt::Debug;
|
||||
use std::hash::Hash;
|
||||
|
||||
pub trait PixelFormat: Copy + Clone + Debug + Default + Hash + Send + Sync {
|
||||
type Output: Pixel;
|
||||
|
||||
const CODE: &'static str;
|
||||
|
||||
fn code(&self) -> &'static str {
|
||||
CODE
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, Default, Hash)]
|
||||
pub struct Mjpeg;
|
||||
|
||||
impl PixelFormat for Mjpeg {
|
||||
type Output = Rgb<u8>;
|
||||
|
||||
const CODE: &'static str = "MJPG";
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, Default, Hash)]
|
||||
pub struct Yuyv;
|
||||
|
||||
impl PixelFormat for Yuyv {
|
||||
type Output = Rgb<u8>;
|
||||
|
||||
const CODE: &'static str = "YUYV";
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, Default, Hash)]
|
||||
pub struct Gray;
|
||||
|
||||
impl PixelFormat for Gray {
|
||||
type Output = Luma<u8>;
|
||||
|
||||
const CODE: &'static str = "GRAY";
|
||||
}
|
||||
@@ -49,6 +49,7 @@ use nokhwa_bindings_windows::{
|
||||
use uvc::StreamFormat;
|
||||
#[cfg(all(feature = "input-v4l", target_os = "linux"))]
|
||||
use v4l::{control::Description, Format, FourCC};
|
||||
use crate::pixel_format::PixelFormat;
|
||||
|
||||
/// Describes a frame format (i.e. how the bytes themselves are encoded). Often called `FourCC`.
|
||||
/// - YUYV is a mathematical color space. You can read more [here.](https://en.wikipedia.org/wiki/YCbCr)
|
||||
@@ -59,6 +60,7 @@ use v4l::{control::Description, Format, FourCC};
|
||||
pub enum FrameFormat {
|
||||
MJPEG,
|
||||
YUYV,
|
||||
GRAY8,
|
||||
}
|
||||
|
||||
impl Display for FrameFormat {
|
||||
@@ -70,10 +72,19 @@ impl Display for FrameFormat {
|
||||
FrameFormat::YUYV => {
|
||||
write!(f, "YUYV")
|
||||
}
|
||||
FrameFormat::GRAY8 => {
|
||||
write!(f, "GRAY8")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<P> From<P> for FrameFormat where P: PixelFormat {
|
||||
fn from(px: P) -> Self {
|
||||
match P::
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "input-uvc")]
|
||||
impl From<FrameFormat> for uvc::FrameFormat {
|
||||
fn from(ff: FrameFormat) -> Self {
|
||||
@@ -93,6 +104,7 @@ impl From<MFFrameFormat> for FrameFormat {
|
||||
match mf_ff {
|
||||
MFFrameFormat::MJPEG => FrameFormat::MJPEG,
|
||||
MFFrameFormat::YUYV => FrameFormat::YUYV,
|
||||
MFFrameFormat::GRAY8 => FrameFormat::GRAY8,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -106,6 +118,7 @@ impl From<FrameFormat> for MFFrameFormat {
|
||||
match ff {
|
||||
FrameFormat::MJPEG => MFFrameFormat::MJPEG,
|
||||
FrameFormat::YUYV => MFFrameFormat::YUYV,
|
||||
FrameFormat::GRAY8 => MFFrameFormat::GRAY8, //FIXME
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -126,6 +139,7 @@ impl From<AVFourCC> for FrameFormat {
|
||||
match av_fcc {
|
||||
AVFourCC::YUV2 => FrameFormat::YUYV,
|
||||
AVFourCC::MJPEG => FrameFormat::MJPEG,
|
||||
AVFourCC::GRAY8 => FrameFormat::GRAY8,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -146,6 +160,7 @@ impl From<FrameFormat> for AVFourCC {
|
||||
match ff {
|
||||
FrameFormat::MJPEG => AVFourCC::MJPEG,
|
||||
FrameFormat::YUYV => AVFourCC::YUV2,
|
||||
FrameFormat::GRAY8 => AVFourCC::GRAY8,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -419,6 +434,7 @@ impl From<CameraFormat> for Format {
|
||||
let pxfmt = match cam_fmt.format() {
|
||||
FrameFormat::MJPEG => FourCC::new(b"MJPG"),
|
||||
FrameFormat::YUYV => FourCC::new(b"YUYV"),
|
||||
FrameFormat::GRAY8 => FourCC::new(b"GREY"),
|
||||
};
|
||||
|
||||
Format::new(cam_fmt.width(), cam_fmt.height(), pxfmt)
|
||||
|
||||
Reference in New Issue
Block a user