pub(crate) mod decoder;
pub(crate) mod encoder;
use std::path::PathBuf;
use edgefirst_v4l2::device::{self, Device};
use edgefirst_v4l2::queue::BufType;
use crate::CodecError;
pub(crate) fn device_error(e: edgefirst_v4l2::Error) -> CodecError {
let source = match e.errno() {
Some(errno) => std::io::Error::from_raw_os_error(errno as i32),
None => std::io::Error::other(e.to_string()),
};
CodecError::Device {
op: e.op().to_owned(),
source,
}
}
pub(crate) struct M2mDevice {
pub dev: Device,
pub output: BufType,
pub capture: BufType,
}
impl M2mDevice {
pub fn open(path: &std::path::Path) -> Option<Self> {
let dev = Device::open(path).ok()?;
let caps = dev.capabilities();
if !caps.is_m2m() || !caps.has_streaming() {
return None;
}
let output = caps.output_buf_type()?;
let capture = caps.capture_buf_type()?;
Some(Self {
dev,
output,
capture,
})
}
pub fn multiplanar(&self) -> bool {
self.output.is_multiplanar()
}
pub fn lists(&self, buf_type: BufType, fourcc: u32) -> bool {
self.dev
.formats(buf_type)
.is_ok_and(|f| f.iter().any(|f| f.fourcc == fourcc))
}
}
pub(crate) fn candidates(env: &str) -> Vec<PathBuf> {
if let Some(path) = std::env::var_os(env) {
return vec![PathBuf::from(path)];
}
device::enumerate()
.unwrap_or_default()
.into_iter()
.filter(|node| {
node.capabilities
.as_ref()
.is_ok_and(|c| c.is_m2m() && c.has_streaming())
})
.map(|node| node.path)
.collect()
}