From 784f76fbda71ddacae7382e30bfaa9bf2f42eb5c Mon Sep 17 00:00:00 2001 From: l1npengtul Date: Thu, 3 Jun 2021 15:21:04 +0900 Subject: [PATCH] work on opencv --- src/backends/capture/opencv_backend.rs | 115 ++++++++++++++++++++++++- src/lib.rs | 2 - 2 files changed, 113 insertions(+), 4 deletions(-) diff --git a/src/backends/capture/opencv_backend.rs b/src/backends/capture/opencv_backend.rs index 4224d7a..e9cd1d3 100644 --- a/src/backends/capture/opencv_backend.rs +++ b/src/backends/capture/opencv_backend.rs @@ -1,5 +1,6 @@ -use crate::{CameraFormat, CameraInfo, NokhwaError}; -use opencv::videoio::{VideoCapture, CAP_ANY, CAP_AVFOUNDATION, CAP_MSMF, CAP_V4L2}; +use crate::{CameraFormat, CameraInfo, FrameFormat, NokhwaError, Resolution}; +use opencv::{prelude::Detail_NoBundleAdjusterTrait, videoio::{CAP_ANY, CAP_AVFOUNDATION, CAP_MSMF, CAP_PROP_FOURCC, CAP_V4L2, VideoCapture, VideoCaptureProperties, VideoCaptureTrait, VideoWriter}}; +use std::{convert::TryInto, ops::Deref}; /// The backend struct that interfaces with `OpenCV`. Note that an `opencv` matching the version that this was either compiled on must be present on the user's machine. (usually 4.5.2 or greater) /// For more information, please see [`opencv-rust`](https://github.com/twistedfall/opencv-rust) and [`OpenCV VideoCapture Docs`](https://docs.opencv.org/4.5.2/d8/dfe/classcv_1_1VideoCapture.html). @@ -23,6 +24,20 @@ impl OpenCvCaptureDevice { camera_format: Option, api_pref: Option, ) -> Result { + let api = match api_pref { + Some(a) => a as i32, + None => get_api_pref_int() as i32, + }; + let mut video_capture = match location { + CameraIndexType::Index(idx) => match VideoCapture::new(idx as i32, api) { + Ok(vc) => vc, + Err(why) => return Err(NokhwaError::CouldntOpenDevice(why.to_string())), + }, + CameraIndexType::IPCamera(ip) => match VideoCapture::from_file(ip.deref(), api) { + Ok(vc) => vc, + Err(why) => return Err(NokhwaError::CouldntOpenDevice(why.to_string())), + }, + }; } } @@ -46,3 +61,99 @@ fn get_api_pref_int() -> u32 { &_ => CAP_ANY as u32, } } +fn set_properties( + vc: &mut VideoCapture, + res: Resolution, + fps: u32, + frame_fmt: FrameFormat +) -> Result<(), NokhwaError> { + set_property_fourcc(vc, frame_fmt)?; + set_property_res(vc, res)?; + set_property_fps(vc, fps)?; + Ok(()) +} + +fn set_property_res( + vc: &mut VideoCapture, + res: Resolution, +) -> Result<(), NokhwaError> { + match vc.set( + VideoCaptureProperties::CAP_PROP_FRAME_HEIGHT as i32, + f64::from(res.height()), + ) { + Ok(r) => { + if !r { + return Err(NokhwaError::CouldntSetProperty { property: "Resolution Height".to_string(), value: res.height().to_string(), error: "OpenCV bool assert failure".to_string() }) + } + } + Err(why) => { + return Err(NokhwaError::CouldntSetProperty { property: "Resolution Height".to_string(), value: res.height().to_string(), error: why.to_string() }) + } + } + + match vc.set( + VideoCaptureProperties::CAP_PROP_FRAME_WIDTH as i32, + f64::from(res.width()), + ) { + Ok(r) => { + if !r { + return Err(NokhwaError::CouldntSetProperty { property: "Resolution Width".to_string(), value: res.width().to_string(), error: "OpenCV bool assert failure".to_string() }) + } + } + Err(why) => { + return Err(NokhwaError::CouldntSetProperty { property: "Resolution Width".to_string(), value: res.width().to_string(), error: why.to_string() }) + } + } + + Ok(()) +} + +fn set_property_fps(vc: &mut VideoCapture, fps: u32) -> Result<(), NokhwaError> { + match vc.set(VideoCaptureProperties::CAP_PROP_FPS as i32, f64::from(fps)) { + Ok(r) => { + if !r { + return Err(NokhwaError::CouldntSetProperty { property: "Framerate".to_string(), value: fps.to_string(), error: "OpenCV bool assert failure".to_string() }) + } + } + Err(why) => { + return Err(NokhwaError::CouldntSetProperty { property: "Framerate".to_string(), value: fps.to_string(), error: why.to_string() }) + } + } + Ok(()) +} + +fn set_property_fourcc(vc: &mut VideoCapture, frame_fmt: FrameFormat) -> Result<(), NokhwaError> { + let fourcc = match frame_fmt { + FrameFormat::MJPEG => { + f64::from( + match VideoWriter::fourcc('M' as i8, 'J' as i8, 'P' as i8, 'G' as i8) { + Ok(fcc) => fcc, + Err(why) => return Err(NokhwaError::CouldntSetProperty { property: "FourCC".to_string(), value: "MJPG".to_string(), error: why.to_string() }) + } + ) + } + FrameFormat::YUYV => { + f64::from( + match VideoWriter::fourcc('Y' as i8, 'U' as i8, 'Y' as i8, 'V' as i8) { + Ok(fcc) => fcc, + Err(why) => return Err(NokhwaError::CouldntSetProperty { property: "FourCC".to_string(), value: "YUYV".to_string(), error: why.to_string() }) + } + ) + } + }; + + match vc.set( + CAP_PROP_FOURCC as i32, + f64::from(VideoWriter::fourcc('M' as i8, 'J' as i8, 'P' as i8, 'G' as i8).unwrap()), + ) { + Ok(r) => { + if !r { + return Err(NokhwaError::CouldntSetProperty { property: "FourCC".to_string(), value: format!("FrameFormat: {}, OpenCV FourCC {}", frame_fmt, fourcc), error: "OpenCV bool assert failure".to_string() }) + } + } + Err(why) => { + return Err(NokhwaError::CouldntSetProperty { property: "FourCC".to_string(), value: format!("FrameFormat: {}, OpenCV FourCC {}", frame_fmt, fourcc), error: why.to_string() }) + } + } + Ok(()) +} diff --git a/src/lib.rs b/src/lib.rs index 76d672e..5c38f36 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,7 +1,5 @@ #![deny(clippy::pedantic)] #![warn(clippy::all)] -#![allow(clippy::upper_case_acronyms)] -#![allow(clippy::must_use_candidate)] //! # nokhwa //! Nokhwa(녹화): Korean word meaning "to record".