#[cfg(target_os = "linux")]
mod internal {
use nokhwa_core::{
buffer::Buffer,
error::NokhwaError,
traits::CaptureBackendTrait,
types::{
ApiBackend, CameraControl, CameraFormat, CameraIndex, CameraInfo,
ControlValueDescription, ControlValueSetter, FrameFormat, KnownCameraControl,
KnownCameraControlFlag, RequestedFormat, RequestedFormatType, Resolution,
},
};
use std::{
borrow::Cow,
collections::HashMap,
io::{self, ErrorKind},
};
use v4l::{
control::{Control, Flags, Type, Value},
frameinterval::FrameIntervalEnum,
framesize::FrameSizeEnum,
io::traits::CaptureStream,
prelude::MmapStream,
video::{capture::Parameters, Capture},
Device, Format, FourCC,
};
use v4l2_sys_mit::{
V4L2_CID_BACKLIGHT_COMPENSATION, V4L2_CID_BRIGHTNESS, V4L2_CID_CONTRAST, V4L2_CID_EXPOSURE,
V4L2_CID_FOCUS_RELATIVE, V4L2_CID_GAIN, V4L2_CID_GAMMA, V4L2_CID_HUE,
V4L2_CID_IRIS_RELATIVE, V4L2_CID_PAN_RELATIVE, V4L2_CID_SATURATION, V4L2_CID_SHARPNESS,
V4L2_CID_TILT_RELATIVE, V4L2_CID_WHITE_BALANCE_TEMPERATURE, V4L2_CID_ZOOM_RELATIVE,
};
#[allow(clippy::cast_possible_truncation)]
pub fn known_camera_control_to_id(ctrl: KnownCameraControl) -> u32 {
match ctrl {
KnownCameraControl::Brightness => V4L2_CID_BRIGHTNESS,
KnownCameraControl::Contrast => V4L2_CID_CONTRAST,
KnownCameraControl::Hue => V4L2_CID_HUE,
KnownCameraControl::Saturation => V4L2_CID_SATURATION,
KnownCameraControl::Sharpness => V4L2_CID_SHARPNESS,
KnownCameraControl::Gamma => V4L2_CID_GAMMA,
KnownCameraControl::WhiteBalance => V4L2_CID_WHITE_BALANCE_TEMPERATURE,
KnownCameraControl::BacklightComp => V4L2_CID_BACKLIGHT_COMPENSATION,
KnownCameraControl::Gain => V4L2_CID_GAIN,
KnownCameraControl::Pan => V4L2_CID_PAN_RELATIVE,
KnownCameraControl::Tilt => V4L2_CID_TILT_RELATIVE,
KnownCameraControl::Zoom => V4L2_CID_ZOOM_RELATIVE,
KnownCameraControl::Exposure => V4L2_CID_EXPOSURE,
KnownCameraControl::Iris => V4L2_CID_IRIS_RELATIVE,
KnownCameraControl::Focus => V4L2_CID_FOCUS_RELATIVE,
KnownCameraControl::Other(id) => id as u32,
}
}
#[allow(clippy::cast_lossless)]
pub fn id_to_known_camera_control(id: u32) -> KnownCameraControl {
match id {
V4L2_CID_BRIGHTNESS => KnownCameraControl::Brightness,
V4L2_CID_CONTRAST => KnownCameraControl::Contrast,
V4L2_CID_HUE => KnownCameraControl::Hue,
V4L2_CID_SATURATION => KnownCameraControl::Saturation,
V4L2_CID_SHARPNESS => KnownCameraControl::Sharpness,
V4L2_CID_GAMMA => KnownCameraControl::Gamma,
V4L2_CID_WHITE_BALANCE_TEMPERATURE => KnownCameraControl::WhiteBalance,
V4L2_CID_BACKLIGHT_COMPENSATION => KnownCameraControl::BacklightComp,
V4L2_CID_GAIN => KnownCameraControl::Gain,
V4L2_CID_PAN_RELATIVE => KnownCameraControl::Pan,
V4L2_CID_TILT_RELATIVE => KnownCameraControl::Tilt,
V4L2_CID_ZOOM_RELATIVE => KnownCameraControl::Zoom,
V4L2_CID_EXPOSURE => KnownCameraControl::Exposure,
V4L2_CID_IRIS_RELATIVE => KnownCameraControl::Iris,
V4L2_CID_FOCUS_RELATIVE => KnownCameraControl::Focus,
id => KnownCameraControl::Other(id as u128),
}
}
#[allow(clippy::unnecessary_wraps)]
#[allow(clippy::cast_possible_truncation)]
pub fn query() -> Result<Vec<CameraInfo>, NokhwaError> {
Ok({
let camera_info: Vec<CameraInfo> = v4l::context::enum_devices()
.iter()
.map(|node| {
CameraInfo::new(
&node
.name()
.unwrap_or(format!("{}", node.path().to_string_lossy())),
&format!("Video4Linux Device @ {}", node.path().to_string_lossy()),
"",
CameraIndex::Index(node.index() as u32),
)
})
.collect();
camera_info
})
}
pub struct V4LCaptureDevice<'a> {
camera_format: CameraFormat,
camera_info: CameraInfo,
device: Device,
stream_handle: Option<MmapStream<'a>>,
}
impl<'a> V4LCaptureDevice<'a> {
#[allow(clippy::too_many_lines)]
pub fn new(index: &CameraIndex, cam_fmt: RequestedFormat) -> Result<Self, NokhwaError> {
let index = index.clone();
let device = match Device::new(index.as_index()? as usize) {
Ok(dev) => dev,
Err(why) => {
return Err(NokhwaError::OpenDeviceError(
index.to_string(),
format!("V4L2 Error: {}", why),
))
}
};
let mut camera_formats = vec![];
let frame_formats = match device.enum_formats() {
Ok(formats) => {
let mut frame_format_vec = vec![];
formats
.iter()
.for_each(|fmt| frame_format_vec.push(fmt.fourcc));
frame_format_vec.dedup();
Ok(frame_format_vec)
}
Err(why) => Err(NokhwaError::GetPropertyError {
property: "FrameFormat".to_string(),
error: why.to_string(),
}),
}?;
for ff in frame_formats {
let framefmt = match fourcc_to_frameformat(ff) {
Some(s) => s,
None => continue,
};
let mut formats = device
.enum_framesizes(ff)
.map_err(|why| NokhwaError::GetPropertyError {
property: "ResolutionList".to_string(),
error: why.to_string(),
})?
.into_iter()
.flat_map(|x| {
match x.size {
FrameSizeEnum::Discrete(d) => {
[Resolution::new(d.width, d.height)].to_vec()
}
FrameSizeEnum::Stepwise(s) => (s.min_width..s.max_width)
.step_by(s.step_width as usize)
.zip((s.min_height..s.max_height).step_by(s.step_height as usize))
.map(|(x, y)| Resolution::new(x, y))
.collect(),
}
})
.flat_map(|res| {
device
.enum_frameintervals(ff, res.x(), res.y())
.unwrap_or_default()
.into_iter()
.flat_map(|x| match x.interval {
FrameIntervalEnum::Discrete(dis) => {
if dis.numerator == 1 {
vec![CameraFormat::new(
Resolution::new(x.width, x.height),
framefmt,
dis.denominator,
)]
} else {
vec![]
}
}
FrameIntervalEnum::Stepwise(step) => {
let mut intvec = vec![];
for fstep in (step.min.numerator..step.max.numerator)
.step_by(step.step.numerator as usize)
{
if step.max.denominator != 1 || step.min.denominator != 1 {
intvec.push(CameraFormat::new(
Resolution::new(x.width, x.height),
framefmt,
fstep,
));
}
}
intvec
}
})
})
.collect::<Vec<CameraFormat>>();
camera_formats.append(&mut formats);
}
let format = cam_fmt
.fulfill(&camera_formats)
.ok_or(NokhwaError::GetPropertyError {
property: "CameraFormat".to_string(),
error: "Failed to Fufill".to_string(),
})?;
if let Err(why) = device.set_format(&Format::new(
format.width(),
format.height(),
frameformat_to_fourcc(format.format()),
)) {
return Err(NokhwaError::SetPropertyError {
property: "Resolution, FrameFormat".to_string(),
value: format.to_string(),
error: why.to_string(),
});
}
if let Err(why) = device.set_params(&Parameters::with_fps(format.frame_rate())) {
return Err(NokhwaError::SetPropertyError {
property: "Frame rate".to_string(),
value: format.frame_rate().to_string(),
error: why.to_string(),
});
}
let device_caps = device
.query_caps()
.map_err(|why| NokhwaError::GetPropertyError {
property: "Device Capabilities".to_string(),
error: why.to_string(),
})?;
let mut v4l2 = V4LCaptureDevice {
camera_format: format,
camera_info: CameraInfo::new(
&device_caps.card,
&device_caps.driver,
&format!("{} {:?}", device_caps.bus, device_caps.version),
index,
),
device,
stream_handle: None,
};
v4l2.force_refresh_camera_format()?;
if v4l2.camera_format() != format {
return Err(NokhwaError::SetPropertyError {
property: "CameraFormat".to_string(),
value: String::new(),
error: "Not same/Rejected".to_string(),
});
}
Ok(v4l2)
}
#[deprecated(since = "0.10.0", note = "please use `new` instead.")]
#[allow(clippy::needless_pass_by_value)]
pub fn new_with(
index: CameraIndex,
width: u32,
height: u32,
fps: u32,
fourcc: FrameFormat,
) -> Result<Self, NokhwaError> {
let camera_format = CameraFormat::new_from(width, height, fourcc, fps);
V4LCaptureDevice::new(
&index,
RequestedFormat::with_formats(
RequestedFormatType::Exact(camera_format),
vec![camera_format.format()].as_slice(),
),
)
}
fn get_resolution_list(&self, fourcc: FrameFormat) -> Result<Vec<Resolution>, NokhwaError> {
let format = frameformat_to_fourcc(fourcc);
match self.device.enum_framesizes(format) {
Ok(frame_sizes) => {
let mut resolutions = vec![];
for frame_size in frame_sizes {
match frame_size.size {
FrameSizeEnum::Discrete(dis) => {
resolutions.push(Resolution::new(dis.width, dis.height));
}
FrameSizeEnum::Stepwise(step) => {
resolutions.push(Resolution::new(step.min_width, step.min_height));
resolutions.push(Resolution::new(step.max_width, step.max_height));
}
}
}
Ok(resolutions)
}
Err(why) => Err(NokhwaError::GetPropertyError {
property: "Resolutions".to_string(),
error: why.to_string(),
}),
}
}
pub fn force_refresh_camera_format(&mut self) -> Result<(), NokhwaError> {
match self.device.format() {
Ok(format) => {
let frame_format = fourcc_to_frameformat(format.fourcc).ok_or(
NokhwaError::GetPropertyError {
property: "FrameFormat".to_string(),
error: "unsupported".to_string(),
},
)?;
let fps = match self.device.params() {
Ok(params) => {
if params.interval.numerator != 1
|| params.interval.denominator % params.interval.numerator != 0
{
return Err(NokhwaError::GetPropertyError {
property: "V4L2 FrameRate".to_string(),
error: format!(
"Framerate not whole number: {} / {}",
params.interval.denominator, params.interval.numerator
),
});
}
if params.interval.numerator == 1 {
params.interval.denominator
} else {
params.interval.denominator / params.interval.numerator
}
}
Err(why) => {
return Err(NokhwaError::GetPropertyError {
property: "V4L2 FrameRate".to_string(),
error: why.to_string(),
})
}
};
self.camera_format = CameraFormat::new(
Resolution::new(format.width, format.height),
frame_format,
fps,
);
Ok(())
}
Err(why) => Err(NokhwaError::GetPropertyError {
property: "parameters".to_string(),
error: why.to_string(),
}),
}
}
}
impl<'a> CaptureBackendTrait for V4LCaptureDevice<'a> {
fn backend(&self) -> ApiBackend {
ApiBackend::Video4Linux
}
fn camera_info(&self) -> &CameraInfo {
&self.camera_info
}
fn refresh_camera_format(&mut self) -> Result<(), NokhwaError> {
self.force_refresh_camera_format()
}
fn camera_format(&self) -> CameraFormat {
self.camera_format
}
fn set_camera_format(&mut self, new_fmt: CameraFormat) -> Result<(), NokhwaError> {
let prev_format = match Capture::format(&self.device) {
Ok(fmt) => fmt,
Err(why) => {
return Err(NokhwaError::GetPropertyError {
property: "Resolution, FrameFormat".to_string(),
error: why.to_string(),
})
}
};
let prev_fps = match Capture::params(&self.device) {
Ok(fps) => fps,
Err(why) => {
return Err(NokhwaError::GetPropertyError {
property: "Frame rate".to_string(),
error: why.to_string(),
})
}
};
let v4l_fcc = match new_fmt.format() {
FrameFormat::MJPEG => FourCC::new(b"MJPG"),
FrameFormat::YUYV => FourCC::new(b"YUYV"),
FrameFormat::GRAY => FourCC::new(b"GRAY"),
FrameFormat::RAWRGB => FourCC::new(b"RGB3"),
FrameFormat::NV12 => FourCC::new(b"NV12"),
};
let format = Format::new(new_fmt.width(), new_fmt.height(), v4l_fcc);
let frame_rate = Parameters::with_fps(new_fmt.frame_rate());
if let Err(why) = Capture::set_format(&self.device, &format) {
return Err(NokhwaError::SetPropertyError {
property: "Resolution, FrameFormat".to_string(),
value: format.to_string(),
error: why.to_string(),
});
}
if let Err(why) = Capture::set_params(&self.device, &frame_rate) {
return Err(NokhwaError::SetPropertyError {
property: "Frame rate".to_string(),
value: frame_rate.to_string(),
error: why.to_string(),
});
}
if self.stream_handle.is_some() {
return match self.open_stream() {
Ok(_) => Ok(()),
Err(why) => {
if let Err(why) = Capture::set_format(&self.device, &prev_format) {
return Err(NokhwaError::SetPropertyError {
property: format!("Attempt undo due to stream acquisition failure with error {}. Resolution, FrameFormat", why),
value: prev_format.to_string(),
error: why.to_string(),
});
}
if let Err(why) = Capture::set_params(&self.device, &prev_fps) {
return Err(NokhwaError::SetPropertyError {
property:
format!("Attempt undo due to stream acquisition failure with error {}. Frame rate", why),
value: prev_fps.to_string(),
error: why.to_string(),
});
}
Err(why)
}
};
}
self.camera_format = new_fmt;
self.force_refresh_camera_format()?;
if self.camera_format != new_fmt {
return Err(NokhwaError::SetPropertyError {
property: "CameraFormat".to_string(),
value: new_fmt.to_string(),
error: "Rejected".to_string(),
});
}
Ok(())
}
fn compatible_list_by_resolution(
&mut self,
fourcc: FrameFormat,
) -> Result<HashMap<Resolution, Vec<u32>>, NokhwaError> {
let resolutions = self.get_resolution_list(fourcc)?;
let format = frameformat_to_fourcc(fourcc);
let mut res_map = HashMap::new();
for res in resolutions {
let mut compatible_fps = vec![];
match self
.device
.enum_frameintervals(format, res.width(), res.height())
{
Ok(intervals) => {
for interval in intervals {
match interval.interval {
FrameIntervalEnum::Discrete(dis) => {
compatible_fps.push(dis.denominator);
}
FrameIntervalEnum::Stepwise(step) => {
for fstep in (step.min.numerator..step.max.numerator)
.step_by(step.step.numerator as usize)
{
if step.max.denominator != 1 || step.min.denominator != 1 {
compatible_fps.push(fstep);
}
}
}
}
}
}
Err(why) => {
return Err(NokhwaError::GetPropertyError {
property: "Frame rate".to_string(),
error: why.to_string(),
})
}
}
res_map.insert(res, compatible_fps);
}
Ok(res_map)
}
fn compatible_fourcc(&mut self) -> Result<Vec<FrameFormat>, NokhwaError> {
match self.device.enum_formats() {
Ok(formats) => {
let mut frame_format_vec = vec![];
for format in formats {
match fourcc_to_frameformat(format.fourcc) {
Some(ff) => frame_format_vec.push(ff),
None => continue,
}
}
frame_format_vec.sort();
frame_format_vec.dedup();
Ok(frame_format_vec)
}
Err(why) => Err(NokhwaError::GetPropertyError {
property: "FrameFormat".to_string(),
error: why.to_string(),
}),
}
}
fn resolution(&self) -> Resolution {
self.camera_format.resolution()
}
fn set_resolution(&mut self, new_res: Resolution) -> Result<(), NokhwaError> {
let mut new_fmt = self.camera_format;
new_fmt.set_resolution(new_res);
self.set_camera_format(new_fmt)
}
fn frame_rate(&self) -> u32 {
self.camera_format.frame_rate()
}
fn set_frame_rate(&mut self, new_fps: u32) -> Result<(), NokhwaError> {
let mut new_fmt = self.camera_format;
new_fmt.set_frame_rate(new_fps);
self.set_camera_format(new_fmt)
}
fn frame_format(&self) -> FrameFormat {
self.camera_format.format()
}
fn set_frame_format(&mut self, fourcc: FrameFormat) -> Result<(), NokhwaError> {
let mut new_fmt = self.camera_format;
new_fmt.set_format(fourcc);
self.set_camera_format(new_fmt)
}
fn camera_control(
&self,
control: KnownCameraControl,
) -> Result<CameraControl, NokhwaError> {
let controls = self.camera_controls()?;
for supported_control in controls {
if supported_control.control() == control {
return Ok(supported_control);
}
}
Err(NokhwaError::GetPropertyError {
property: control.to_string(),
error: "not found/not supported".to_string(),
})
}
#[allow(clippy::cast_possible_wrap)]
fn camera_controls(&self) -> Result<Vec<CameraControl>, NokhwaError> {
self.device
.query_controls()
.map_err(|why| NokhwaError::GetPropertyError {
property: "V4L2 Controls".to_string(),
error: why.to_string(),
})?
.into_iter()
.map(|desc| {
let id_as_kcc = id_to_known_camera_control(desc.id);
let ctrl_current = self.device.control(desc.id)?.value;
let ctrl_value_desc = match (desc.typ, ctrl_current) {
(
Type::Integer
| Type::Integer64
| Type::Menu
| Type::U8
| Type::U16
| Type::U32
| Type::IntegerMenu,
Value::Integer(current),
) => ControlValueDescription::IntegerRange {
min: desc.minimum as i64,
max: desc.maximum,
value: current,
step: desc.step as i64,
default: desc.default,
},
(Type::Boolean, Value::Boolean(current)) => {
ControlValueDescription::Boolean {
value: current,
default: desc.default != 0,
}
}
(Type::String, Value::String(current)) => ControlValueDescription::String {
value: current,
default: None,
},
_ => {
return Err(io::Error::new(
ErrorKind::Unsupported,
"what is this?????? todo: support ig",
))
}
};
let is_readonly = desc
.flags
.intersects(Flags::READ_ONLY)
.then_some(KnownCameraControlFlag::ReadOnly);
let is_writeonly = desc
.flags
.intersects(Flags::WRITE_ONLY)
.then_some(KnownCameraControlFlag::WriteOnly);
let is_disabled = desc
.flags
.intersects(Flags::DISABLED)
.then_some(KnownCameraControlFlag::Disabled);
let is_volatile = desc
.flags
.intersects(Flags::VOLATILE)
.then_some(KnownCameraControlFlag::Volatile);
let is_inactive = desc
.flags
.intersects(Flags::INACTIVE)
.then_some(KnownCameraControlFlag::Disabled);
let flags_vec = vec![
is_inactive,
is_readonly,
is_volatile,
is_disabled,
is_writeonly,
]
.into_iter()
.filter(Option::is_some)
.collect::<Option<Vec<KnownCameraControlFlag>>>()
.unwrap_or_default();
Ok(CameraControl::new(
id_as_kcc,
desc.name,
ctrl_value_desc,
flags_vec,
!desc.flags.intersects(Flags::INACTIVE),
))
})
.filter(Result::is_ok)
.collect::<Result<Vec<CameraControl>, io::Error>>()
.map_err(|x| NokhwaError::GetPropertyError {
property: "www".to_string(),
error: x.to_string(),
})
}
fn set_camera_control(
&mut self,
id: KnownCameraControl,
value: ControlValueSetter,
) -> Result<(), NokhwaError> {
let conv_value = match value.clone() {
ControlValueSetter::None => Value::None,
ControlValueSetter::Integer(i) => Value::Integer(i),
ControlValueSetter::Boolean(b) => Value::Boolean(b),
ControlValueSetter::String(s) => Value::String(s),
ControlValueSetter::Bytes(b) => Value::CompoundU8(b),
v => {
return Err(NokhwaError::SetPropertyError {
property: id.to_string(),
value: v.to_string(),
error: "not supported".to_string(),
})
}
};
self.device
.set_control(Control {
id: known_camera_control_to_id(id),
value: conv_value,
})
.map_err(|why| NokhwaError::SetPropertyError {
property: id.to_string(),
value: format!("{:?}", value),
error: why.to_string(),
})?;
let control = self.camera_control(id)?;
if control.value() != value {
return Err(NokhwaError::SetPropertyError {
property: id.to_string(),
value: format!("{:?}", value),
error: "Rejected".to_string(),
});
}
Ok(())
}
fn open_stream(&mut self) -> Result<(), NokhwaError> {
let stream = match MmapStream::new(&self.device, v4l::buffer::Type::VideoCapture) {
Ok(s) => s,
Err(why) => return Err(NokhwaError::OpenStreamError(why.to_string())),
};
self.stream_handle = Some(stream);
Ok(())
}
fn is_stream_open(&self) -> bool {
self.stream_handle.is_some()
}
fn frame(&mut self) -> Result<Buffer, NokhwaError> {
let cam_fmt = self.camera_format;
let raw_frame = self.frame_raw()?;
Ok(Buffer::new(
cam_fmt.resolution(),
&raw_frame,
cam_fmt.format(),
))
}
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)),
Err(why) => Err(NokhwaError::ReadFrameError(why.to_string())),
},
None => Err(NokhwaError::ReadFrameError(
"Stream Not Started".to_string(),
)),
}
}
fn stop_stream(&mut self) -> Result<(), NokhwaError> {
if self.stream_handle.is_some() {
self.stream_handle = None;
}
Ok(())
}
}
fn fourcc_to_frameformat(fourcc: FourCC) -> Option<FrameFormat> {
match fourcc.str().ok()? {
"YUYV" => Some(FrameFormat::YUYV),
"MJPG" => Some(FrameFormat::MJPEG),
"GRAY" => Some(FrameFormat::GRAY),
"RGB3" => Some(FrameFormat::RAWRGB),
"NV12" => Some(FrameFormat::NV12),
_ => None,
}
}
fn frameformat_to_fourcc(fourcc: FrameFormat) -> FourCC {
match fourcc {
FrameFormat::MJPEG => FourCC::new(b"MJPG"),
FrameFormat::YUYV => FourCC::new(b"YUYV"),
FrameFormat::GRAY => FourCC::new(b"GRAY"),
FrameFormat::RAWRGB => FourCC::new(b"RGB3"),
FrameFormat::NV12 => FourCC::new(b"NV12"),
}
}
}
#[cfg(not(target_os = "linux"))]
mod internal {
use nokhwa_core::buffer::Buffer;
use nokhwa_core::error::NokhwaError;
use nokhwa_core::traits::CaptureBackendTrait;
use nokhwa_core::types::{
ApiBackend, CameraControl, CameraFormat, CameraIndex, CameraInfo, ControlValueSetter,
FrameFormat, KnownCameraControl, RequestedFormat, Resolution,
};
use std::borrow::Cow;
use std::collections::HashMap;
use std::marker::PhantomData;
#[allow(clippy::cast_possible_truncation)]
pub fn known_camera_control_to_id(_ctrl: KnownCameraControl) -> u32 {
0
}
#[allow(clippy::cast_lossless)]
pub fn id_to_known_camera_control(id: u32) -> KnownCameraControl {
KnownCameraControl::Other(id as u128)
}
pub struct V4LCaptureDevice<'a> {
__holder: PhantomData<&'a str>,
}
#[allow(unused_variables)]
impl<'a> V4LCaptureDevice<'a> {
#[allow(clippy::too_many_lines)]
pub fn new(index: &CameraIndex, cam_fmt: RequestedFormat) -> Result<Self, NokhwaError> {
Err(NokhwaError::NotImplementedError(
"V4L2 only on Linux".to_string(),
))
}
#[deprecated(since = "0.10.0", note = "please use `new` instead.")]
pub fn new_with(
index: CameraIndex,
width: u32,
height: u32,
fps: u32,
fourcc: FrameFormat,
) -> Result<Self, NokhwaError> {
Err(NokhwaError::NotImplementedError(
"V4L2 only on Linux".to_string(),
))
}
pub fn force_refresh_camera_format(&mut self) -> Result<(), NokhwaError> {
Err(NokhwaError::NotImplementedError(
"V4L2 only on Linux".to_string(),
))
}
}
#[allow(unused_variables)]
impl<'a> CaptureBackendTrait for V4LCaptureDevice<'a> {
fn backend(&self) -> ApiBackend {
ApiBackend::Video4Linux
}
fn camera_info(&self) -> &CameraInfo {
todo!()
}
fn refresh_camera_format(&mut self) -> Result<(), NokhwaError> {
todo!()
}
fn camera_format(&self) -> CameraFormat {
todo!()
}
fn set_camera_format(&mut self, new_fmt: CameraFormat) -> Result<(), NokhwaError> {
todo!()
}
fn compatible_list_by_resolution(
&mut self,
fourcc: FrameFormat,
) -> Result<HashMap<Resolution, Vec<u32>>, NokhwaError> {
todo!()
}
fn compatible_fourcc(&mut self) -> Result<Vec<FrameFormat>, NokhwaError> {
todo!()
}
fn resolution(&self) -> Resolution {
todo!()
}
fn set_resolution(&mut self, new_res: Resolution) -> Result<(), NokhwaError> {
todo!()
}
fn frame_rate(&self) -> u32 {
todo!()
}
fn set_frame_rate(&mut self, new_fps: u32) -> Result<(), NokhwaError> {
todo!()
}
fn frame_format(&self) -> FrameFormat {
todo!()
}
fn set_frame_format(&mut self, fourcc: FrameFormat) -> Result<(), NokhwaError> {
todo!()
}
fn camera_control(
&self,
control: KnownCameraControl,
) -> Result<CameraControl, NokhwaError> {
todo!()
}
fn camera_controls(&self) -> Result<Vec<CameraControl>, NokhwaError> {
todo!()
}
fn set_camera_control(
&mut self,
id: KnownCameraControl,
value: ControlValueSetter,
) -> Result<(), NokhwaError> {
todo!()
}
fn open_stream(&mut self) -> Result<(), NokhwaError> {
todo!()
}
fn is_stream_open(&self) -> bool {
todo!()
}
fn frame(&mut self) -> Result<Buffer, NokhwaError> {
todo!()
}
fn frame_raw(&mut self) -> Result<Cow<[u8]>, NokhwaError> {
todo!()
}
fn stop_stream(&mut self) -> Result<(), NokhwaError> {
todo!()
}
}
}
pub use internal::*;