Skip to content

Commit

Permalink
multiplane capture stream
Browse files Browse the repository at this point in the history
  • Loading branch information
illegalprime committed May 3, 2023
1 parent 7ddabd3 commit 7391c14
Show file tree
Hide file tree
Showing 3 changed files with 81 additions and 26 deletions.
9 changes: 9 additions & 0 deletions src/buffer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,15 @@ pub enum Type {
Private = 0x80,
}

impl Type {
pub fn planar(&self) -> bool {
match self {
Type::VideoCaptureMplane | Type::VideoOutputMplane => true,
_ => false,
}
}
}

bitflags! {
#[allow(clippy::unreadable_literal)]
pub struct Flags: u32 {
Expand Down
66 changes: 52 additions & 14 deletions src/io/mmap/arena.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,9 @@ use crate::v4l_sys::*;
/// 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<Vec<&'a mut [u8]>>,
pub buf_type: buffer::Type,
pub planes: Vec<Vec<v4l2_plane>>,
}

impl<'a> Arena<'a> {
Expand All @@ -31,6 +32,7 @@ impl<'a> Arena<'a> {
handle,
bufs: Vec::new(),
buf_type,
planes: Vec::new(),
}
}

Expand All @@ -51,6 +53,24 @@ impl<'a> Arena<'a> {
}

pub fn allocate(&mut self, count: u32) -> io::Result<u32> {
let num_planes = if !self.buf_type.planar() {
1
} else {
// we need to get the number of image planes from the format
let mut v4l2_fmt: v4l2_format;
unsafe {
v4l2_fmt = mem::zeroed();
v4l2_fmt.type_ = self.buf_type as u32;
v4l2::ioctl(
self.handle.fd(),
v4l2::vidioc::VIDIOC_G_FMT,
&mut v4l2_fmt as *mut _ as *mut std::os::raw::c_void,
)?;

v4l2_fmt.fmt.pix_mp.num_planes as usize
}
};

let mut v4l2_reqbufs = v4l2_requestbuffers {
count,
..self.requestbuffers_desc()
Expand All @@ -64,29 +84,45 @@ impl<'a> Arena<'a> {
}

for index in 0..v4l2_reqbufs.count {
let mut v4l2_planes: Vec<v4l2_plane> = Vec::new();
unsafe {
v4l2_planes.resize(num_planes as usize, mem::zeroed());
}
let mut v4l2_buf = v4l2_buffer {
index,
..self.buffer_desc()
};
if self.buf_type.planar() {
v4l2_buf.length = num_planes as u32;
v4l2_buf.m.planes = v4l2_planes.as_mut_ptr();
}
unsafe {
v4l2::ioctl(
self.handle.fd(),
v4l2::vidioc::VIDIOC_QUERYBUF,
&mut v4l2_buf as *mut _ as *mut std::os::raw::c_void,
)?;

let ptr = v4l2::mmap(
ptr::null_mut(),
v4l2_buf.length as usize,
libc::PROT_READ | libc::PROT_WRITE,
libc::MAP_SHARED,
self.handle.fd(),
v4l2_buf.m.offset as libc::off_t,
)?;
// each plane has to be mapped separately
let mut planes = Vec::new();
for plane in &v4l2_planes {
let ptr = v4l2::mmap(
ptr::null_mut(),
plane.length as usize,
libc::PROT_READ | libc::PROT_WRITE,
libc::MAP_SHARED,
self.handle.fd(),
plane.m.mem_offset as libc::off_t,
)?;

planes.push(slice::from_raw_parts_mut::<u8>(
ptr as *mut u8, plane.length as usize
));
}

let slice =
slice::from_raw_parts_mut::<u8>(ptr as *mut u8, v4l2_buf.length as usize);
self.bufs.push(slice);
// finally, add the buffer (with all its planes) to the set
self.bufs.push(planes);
self.planes.push(v4l2_planes);
}
}

Expand All @@ -95,8 +131,10 @@ impl<'a> Arena<'a> {

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())?;
for plane in buf {
unsafe {
v4l2::munmap(plane.as_ptr() as *mut core::ffi::c_void, buf.len())?;
}
}
}

Expand Down
32 changes: 20 additions & 12 deletions src/io/mmap/stream.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use std::time::Duration;
use std::{io, mem, sync::Arc};

use crate::buffer::{Metadata, Type};
use crate::device::{Device, Handle};
use crate::device::{PlanarDevice, Handle};
use crate::io::mmap::arena::Arena;
use crate::io::traits::{CaptureStream, OutputStream, Stream as StreamTrait};
use crate::memory::Memory;
Expand Down Expand Up @@ -44,11 +44,15 @@ impl<'a> Stream<'a> {
/// let stream = Stream::new(&dev, Type::VideoCapture);
/// }
/// ```
pub fn new(dev: &Device, buf_type: Type) -> io::Result<Self> {
pub fn new<const M: bool>(
dev: &PlanarDevice<M>, buf_type: Type
) -> io::Result<Self> {
Stream::with_buffers(dev, buf_type, 4)
}

pub fn with_buffers(dev: &Device, buf_type: Type, buf_count: u32) -> io::Result<Self> {
pub fn with_buffers<const M: bool>(
dev: &PlanarDevice<M>, buf_type: Type, buf_count: u32
) -> io::Result<Self> {
let mut arena = Arena::new(dev.handle(), buf_type);
let count = arena.allocate(buf_count)?;
let mut buf_meta = Vec::new();
Expand Down Expand Up @@ -80,12 +84,18 @@ impl<'a> Stream<'a> {
self.timeout = None;
}

fn buffer_desc(&self) -> v4l2_buffer {
v4l2_buffer {
fn buffer_desc(&mut self, index: usize) -> v4l2_buffer {
let mut v4l2_buf = v4l2_buffer {
index: index as u32,
type_: self.buf_type as u32,
memory: Memory::Mmap as u32,
..unsafe { mem::zeroed() }
};
if self.buf_type.planar() {
v4l2_buf.length = self.arena.planes[index].len() as u32;
v4l2_buf.m.planes = self.arena.planes[index].as_mut_ptr();
}
v4l2_buf
}
}

Expand All @@ -108,7 +118,7 @@ impl<'a> Drop for Stream<'a> {
}

impl<'a> StreamTrait for Stream<'a> {
type Item = [u8];
type Item = Vec<&'a mut [u8]>;

fn start(&mut self) -> io::Result<()> {
unsafe {
Expand Down Expand Up @@ -142,8 +152,7 @@ impl<'a> StreamTrait for Stream<'a> {
impl<'a, 'b> CaptureStream<'b> for Stream<'a> {
fn queue(&mut self, index: usize) -> io::Result<()> {
let mut v4l2_buf = v4l2_buffer {
index: index as u32,
..self.buffer_desc()
..self.buffer_desc(index)
};

unsafe {
Expand All @@ -158,7 +167,7 @@ impl<'a, 'b> CaptureStream<'b> for Stream<'a> {
}

fn dequeue(&mut self) -> io::Result<usize> {
let mut v4l2_buf = self.buffer_desc();
let mut v4l2_buf = self.buffer_desc(0);

if self.handle.poll(libc::POLLIN, self.timeout.unwrap_or(-1))? == 0 {
// This condition can only happen if there was a timeout.
Expand Down Expand Up @@ -212,8 +221,7 @@ impl<'a, 'b> CaptureStream<'b> for Stream<'a> {
impl<'a, 'b> OutputStream<'b> for Stream<'a> {
fn queue(&mut self, index: usize) -> io::Result<()> {
let mut v4l2_buf = v4l2_buffer {
index: index as u32,
..self.buffer_desc()
..self.buffer_desc(index)
};
unsafe {
// output settings
Expand Down Expand Up @@ -244,7 +252,7 @@ impl<'a, 'b> OutputStream<'b> for Stream<'a> {
}

fn dequeue(&mut self) -> io::Result<usize> {
let mut v4l2_buf = self.buffer_desc();
let mut v4l2_buf = self.buffer_desc(0);

unsafe {
v4l2::ioctl(
Expand Down

0 comments on commit 7391c14

Please sign in to comment.