Skip to content

Commit

Permalink
memory: Create proper types for v4l2 buffer memory
Browse files Browse the repository at this point in the history
Signed-off-by: Christopher N. Hesse <raymanfx@gmail.com>
  • Loading branch information
raymanfx committed May 5, 2024
1 parent ef313ae commit 0b83491
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 18 deletions.
12 changes: 3 additions & 9 deletions src/io/mmap/arena.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use v4l2_sys::{v4l2_buffer, v4l2_requestbuffers};

use crate::buffer;
use crate::device::Handle;
use crate::memory::Memory;
use crate::memory::{Memory, Mmap};
use crate::v4l2;

/// Manage mapped buffers
Expand All @@ -13,7 +13,7 @@ use crate::v4l2;
/// In case of errors during unmapping, we panic because there is memory corruption going on.
pub struct Arena<'a> {
handle: Arc<Handle>,
pub bufs: Vec<&'a mut [u8]>,
pub bufs: Vec<Mmap<'a>>,
pub buf_type: buffer::Type,
}

Expand Down Expand Up @@ -87,20 +87,14 @@ impl<'a> Arena<'a> {

let slice =
slice::from_raw_parts_mut::<u8>(ptr as *mut u8, v4l2_buf.length as usize);
self.bufs.push(slice);
self.bufs.push(Mmap(slice));
}
}

Ok(v4l2_reqbufs.count)
}

pub fn release(&mut self) -> io::Result<()> {
for buf in &self.bufs {
unsafe {
v4l2::munmap(buf.as_ptr() as *mut core::ffi::c_void, buf.len())?;
}
}

// free all buffers by requesting 0
let mut v4l2_reqbufs = v4l2_requestbuffers {
count: 0,
Expand Down
14 changes: 6 additions & 8 deletions src/io/userptr/arena.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,15 @@ use v4l2_sys::{v4l2_format, v4l2_requestbuffers};

use crate::buffer;
use crate::device::Handle;
use crate::memory::Memory;
use crate::memory::{Memory, UserPtr};
use crate::v4l2;

/// Manage user allocated buffers
///
/// All buffers are released in the Drop impl.
pub struct Arena {
handle: Arc<Handle>,
pub bufs: Vec<Vec<u8>>,
pub bufs: Vec<UserPtr>,
pub buf_type: buffer::Type,
}

Expand Down Expand Up @@ -76,12 +76,10 @@ impl Arena {
}

// allocate the new user buffers
self.bufs.resize(v4l2_reqbufs.count as usize, Vec::new());
for i in 0..v4l2_reqbufs.count {
let buf = &mut self.bufs[i as usize];
unsafe {
buf.resize(v4l2_fmt.fmt.pix.sizeimage as usize, 0);
}
for _ in 0..v4l2_reqbufs.count {
let size = unsafe { v4l2_fmt.fmt.pix.sizeimage };
let buf = vec![0u8; size as usize];
self.bufs.push(UserPtr(buf));
}

Ok(v4l2_reqbufs.count)
Expand Down
61 changes: 60 additions & 1 deletion src/memory.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
use std::fmt;
use std::{
fmt,
ops::{Deref, DerefMut},
};

use crate::v4l2;

/// Memory used for buffer exchange
#[allow(clippy::unreadable_literal)]
Expand All @@ -21,3 +26,57 @@ impl fmt::Display for Memory {
}
}
}

/// Memory-mapped region
///
/// The backing memory is usually located somewhere on the camera hardware itself. It is mapped
/// into RAM so data can be copied. In case of capture devices, the (virtual) memory can be read.
/// In case of output devices, it can be written.
///
/// The destructor automatically unmaps the memory.
#[derive(Debug)]
pub struct Mmap<'a>(pub(crate) &'a mut [u8]);

impl Drop for Mmap<'_> {
fn drop(&mut self) {
unsafe {
// ignore errors
let _ = v4l2::munmap(self.0.as_mut_ptr() as *mut core::ffi::c_void, self.0.len());
}
}
}

impl Deref for Mmap<'_> {
type Target = [u8];

fn deref(&self) -> &Self::Target {
self.0
}
}

impl DerefMut for Mmap<'_> {
fn deref_mut(&mut self) -> &mut Self::Target {
self.0
}
}

/// Userspace memory
///
/// This memory type can be used to directly make the camera hardware write its data into the
/// user-provided buffer (which lives in userspace).
#[derive(Clone, Debug)]
pub struct UserPtr(pub(crate) Vec<u8>);

impl Deref for UserPtr {
type Target = [u8];

fn deref(&self) -> &Self::Target {
&self.0
}
}

impl DerefMut for UserPtr {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}

0 comments on commit 0b83491

Please sign in to comment.