mirror of
https://github.com/mofeng-git/One-KVM.git
synced 2026-10-28 00:10:50 +08:00
chore: vendor trimmed v4l2r capture crate
This commit is contained in:
137
libs/v4l2r/src/ioctl/enum_fmt.rs
Normal file
137
libs/v4l2r/src/ioctl/enum_fmt.rs
Normal file
@@ -0,0 +1,137 @@
|
||||
//! Safe wrapper for the `VIDIOC_ENUM_FMT` ioctl.
|
||||
use super::string_from_cstr;
|
||||
use crate::bindings;
|
||||
use crate::bindings::v4l2_fmtdesc;
|
||||
use crate::{PixelFormat, QueueType};
|
||||
use bitflags::bitflags;
|
||||
use log::error;
|
||||
use nix::errno::Errno;
|
||||
use std::fmt;
|
||||
use std::os::unix::io::AsRawFd;
|
||||
use thiserror::Error;
|
||||
|
||||
bitflags! {
|
||||
/// Flags returned by the `VIDIOC_ENUM_FMT` ioctl into the `flags` field of
|
||||
/// `struct v4l2_fmtdesc`.
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub struct FormatFlags: u32 {
|
||||
const COMPRESSED = bindings::V4L2_FMT_FLAG_COMPRESSED;
|
||||
const EMULATED = bindings::V4L2_FMT_FLAG_EMULATED;
|
||||
}
|
||||
}
|
||||
/// Quickly get the Fourcc code of a format.
|
||||
impl From<v4l2_fmtdesc> for PixelFormat {
|
||||
fn from(fmtdesc: v4l2_fmtdesc) -> Self {
|
||||
fmtdesc.pixelformat.into()
|
||||
}
|
||||
}
|
||||
|
||||
/// Safe variant of the `v4l2_fmtdesc` struct, to be used with `enum_fmt`.
|
||||
#[derive(Debug)]
|
||||
pub struct FmtDesc {
|
||||
pub flags: FormatFlags,
|
||||
pub description: String,
|
||||
pub pixelformat: PixelFormat,
|
||||
}
|
||||
|
||||
impl fmt::Display for FmtDesc {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"{}: {} {}",
|
||||
self.pixelformat,
|
||||
self.description,
|
||||
if self.flags.is_empty() {
|
||||
"".into()
|
||||
} else {
|
||||
format!("({:?})", self.flags)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<v4l2_fmtdesc> for FmtDesc {
|
||||
fn from(fmtdesc: v4l2_fmtdesc) -> Self {
|
||||
FmtDesc {
|
||||
flags: FormatFlags::from_bits_truncate(fmtdesc.flags),
|
||||
description: string_from_cstr(&fmtdesc.description).unwrap_or_else(|_| "".into()),
|
||||
pixelformat: fmtdesc.pixelformat.into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
mod ioctl {
|
||||
use crate::bindings::v4l2_fmtdesc;
|
||||
nix::ioctl_readwrite!(vidioc_enum_fmt, b'V', 2, v4l2_fmtdesc);
|
||||
}
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum EnumFmtError {
|
||||
#[error("ioctl error: {0}")]
|
||||
IoctlError(#[from] nix::Error),
|
||||
}
|
||||
|
||||
impl From<EnumFmtError> for Errno {
|
||||
fn from(err: EnumFmtError) -> Self {
|
||||
match err {
|
||||
EnumFmtError::IoctlError(e) => e,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Safe wrapper around the `VIDIOC_ENUM_FMT` ioctl.
|
||||
pub fn enum_fmt<T: From<v4l2_fmtdesc>>(
|
||||
fd: &impl AsRawFd,
|
||||
queue: QueueType,
|
||||
index: u32,
|
||||
) -> Result<T, EnumFmtError> {
|
||||
let mut fmtdesc = v4l2_fmtdesc {
|
||||
type_: queue as u32,
|
||||
index,
|
||||
..Default::default()
|
||||
};
|
||||
unsafe { ioctl::vidioc_enum_fmt(fd.as_raw_fd(), &mut fmtdesc) }?;
|
||||
|
||||
Ok(T::from(fmtdesc))
|
||||
}
|
||||
|
||||
/// Iterator over the formats of the given queue. This takes a reference to the
|
||||
/// device's file descriptor so no operation that could affect the format
|
||||
/// enumeration can take place while the iterator exists.
|
||||
pub struct FormatIterator<'a, F: AsRawFd> {
|
||||
fd: &'a F,
|
||||
queue: QueueType,
|
||||
index: u32,
|
||||
}
|
||||
|
||||
impl<'a, F: AsRawFd> FormatIterator<'a, F> {
|
||||
/// Create a new iterator listing all the currently valid formats on
|
||||
/// `queue`.
|
||||
pub fn new(fd: &'a F, queue: QueueType) -> Self {
|
||||
FormatIterator {
|
||||
fd,
|
||||
queue,
|
||||
index: 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, F: AsRawFd> Iterator for FormatIterator<'a, F> {
|
||||
type Item = FmtDesc;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
match enum_fmt(self.fd, self.queue, self.index) {
|
||||
Ok(fmtdesc) => {
|
||||
self.index += 1;
|
||||
Some(fmtdesc)
|
||||
}
|
||||
// EINVAL means we have reached the last format.
|
||||
Err(EnumFmtError::IoctlError(Errno::EINVAL)) => None,
|
||||
_ => {
|
||||
error!("Unexpected return value for VIDIOC_ENUM_FMT!");
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user