mod dmabuf;
mod mmap;
mod userptr;
pub use dmabuf::*;
pub use mmap::*;
pub use userptr::*;
use crate::{
bindings::{self, v4l2_buffer__bindgen_ty_1, v4l2_plane__bindgen_ty_1},
ioctl::{PlaneMapping, QueryBufPlane},
};
use enumn::N;
use std::os::unix::io::AsFd;
use std::{fmt::Debug, ops::Deref};
#[derive(Debug, Clone, Copy, PartialEq, Eq, N)]
#[repr(u32)]
pub enum MemoryType {
Mmap = bindings::v4l2_memory_V4L2_MEMORY_MMAP,
UserPtr = bindings::v4l2_memory_V4L2_MEMORY_USERPTR,
Overlay = bindings::v4l2_memory_V4L2_MEMORY_OVERLAY,
DmaBuf = bindings::v4l2_memory_V4L2_MEMORY_DMABUF,
}
pub trait Memory: 'static {
const MEMORY_TYPE: MemoryType;
type RawBacking;
unsafe fn get_plane_buffer_backing(m: &bindings::v4l2_plane__bindgen_ty_1)
-> &Self::RawBacking;
unsafe fn get_single_planar_buffer_backing(
m: &bindings::v4l2_buffer__bindgen_ty_1,
) -> &Self::RawBacking;
unsafe fn get_plane_buffer_backing_mut(
m: &mut bindings::v4l2_plane__bindgen_ty_1,
) -> &mut Self::RawBacking;
unsafe fn get_single_planar_buffer_backing_mut(
m: &mut bindings::v4l2_buffer__bindgen_ty_1,
) -> &mut Self::RawBacking;
}
pub trait SelfBacked: Memory + Default {}
pub trait Imported: Memory {}
pub trait PlaneHandle: Debug + Send + 'static {
type Memory: Memory;
fn fill_v4l2_plane(&self, plane: &mut bindings::v4l2_plane);
}
pub trait Mappable: PlaneHandle {
fn map<D: AsFd>(device: &D, plane_info: &QueryBufPlane) -> Option<PlaneMapping>;
}
pub trait BufferHandles: Send + Debug + 'static {
type SupportedMemoryType: Into<MemoryType> + Send + Clone + Copy;
fn len(&self) -> usize;
fn fill_v4l2_plane(&self, index: usize, plane: &mut bindings::v4l2_plane);
fn is_empty(&self) -> bool {
self.len() == 0
}
}
impl<P, Q> BufferHandles for Q
where
P: PlaneHandle,
Q: Send + Debug + 'static + Deref<Target = [P]>,
{
type SupportedMemoryType = MemoryType;
fn len(&self) -> usize {
self.deref().len()
}
fn fill_v4l2_plane(&self, index: usize, plane: &mut bindings::v4l2_plane) {
self.deref()[index].fill_v4l2_plane(plane);
}
}
pub trait PrimitiveBufferHandles: BufferHandles {
type HandleType: PlaneHandle;
const MEMORY_TYPE: Self::SupportedMemoryType;
}
impl<P, Q> PrimitiveBufferHandles for Q
where
P: PlaneHandle,
Q: Send + Debug + 'static + Deref<Target = [P]>,
{
type HandleType = P;
const MEMORY_TYPE: Self::SupportedMemoryType = P::Memory::MEMORY_TYPE;
}
impl From<(&v4l2_buffer__bindgen_ty_1, MemoryType)> for v4l2_plane__bindgen_ty_1 {
fn from((m, memory): (&v4l2_buffer__bindgen_ty_1, MemoryType)) -> Self {
match memory {
MemoryType::Mmap => v4l2_plane__bindgen_ty_1 {
mem_offset: unsafe { m.offset },
},
MemoryType::UserPtr => v4l2_plane__bindgen_ty_1 {
userptr: unsafe { m.userptr },
},
MemoryType::DmaBuf => v4l2_plane__bindgen_ty_1 {
fd: unsafe { m.fd },
},
MemoryType::Overlay => Default::default(),
}
}
}
impl From<(&v4l2_plane__bindgen_ty_1, MemoryType)> for v4l2_buffer__bindgen_ty_1 {
fn from((m, memory): (&v4l2_plane__bindgen_ty_1, MemoryType)) -> Self {
match memory {
MemoryType::Mmap => v4l2_buffer__bindgen_ty_1 {
offset: unsafe { m.mem_offset },
},
MemoryType::UserPtr => v4l2_buffer__bindgen_ty_1 {
userptr: unsafe { m.userptr },
},
MemoryType::DmaBuf => v4l2_buffer__bindgen_ty_1 {
fd: unsafe { m.fd },
},
MemoryType::Overlay => Default::default(),
}
}
}
#[cfg(test)]
mod tests {
use crate::bindings::v4l2_buffer__bindgen_ty_1;
use crate::bindings::v4l2_plane__bindgen_ty_1;
use crate::memory::MemoryType;
#[test]
fn plane_m_to_buffer_m() {
let plane_m = v4l2_plane__bindgen_ty_1 {
mem_offset: 0xfeedc0fe,
};
assert_eq!(
unsafe { v4l2_buffer__bindgen_ty_1::from((&plane_m, MemoryType::Mmap)).offset },
0xfeedc0fe
);
let plane_m = v4l2_plane__bindgen_ty_1 {
userptr: 0xfeedc0fe,
};
assert_eq!(
unsafe { v4l2_buffer__bindgen_ty_1::from((&plane_m, MemoryType::UserPtr)).userptr },
0xfeedc0fe
);
let plane_m = v4l2_plane__bindgen_ty_1 { fd: 0x76543210 };
assert_eq!(
unsafe { v4l2_buffer__bindgen_ty_1::from((&plane_m, MemoryType::DmaBuf)).fd },
0x76543210
);
}
#[test]
fn buffer_m_to_plane_m() {
let buffer_m = v4l2_buffer__bindgen_ty_1 { offset: 0xfeedc0fe };
assert_eq!(
unsafe { v4l2_plane__bindgen_ty_1::from((&buffer_m, MemoryType::Mmap)).mem_offset },
0xfeedc0fe
);
let buffer_m = v4l2_buffer__bindgen_ty_1 {
userptr: 0xfeedc0fe,
};
assert_eq!(
unsafe { v4l2_plane__bindgen_ty_1::from((&buffer_m, MemoryType::UserPtr)).userptr },
0xfeedc0fe
);
let buffer_m = v4l2_buffer__bindgen_ty_1 { fd: 0x76543210 };
assert_eq!(
unsafe { v4l2_plane__bindgen_ty_1::from((&buffer_m, MemoryType::DmaBuf)).fd },
0x76543210
);
}
}