Skip to main content

Crate moq_v4l

Crate moq_v4l 

Source
Expand description

Safe bindings for the kernel’s Video4Linux 2 (v4l2) API, forked from the v4l crate with the videodev2.h bindings checked in, so a build needs neither libclang nor the kernel headers. Only the v4l2 backend survived the fork: every call is an ioctl on the device node, nothing links libv4l.

§Overview

Video devices on Linux can be accessed by path or by index (which then corresponds to a path), e.g. “/dev/video0” for the device which first became known to the system.

There are three methods of dealing with (capture) device memory:

  • MMAP (memory region in device memory or kernel space, mapped into userspace)
  • User pointer (memory region allocated in host memory, written into by the kernel)
  • DMA (direct memory access for memory transfer without involving the CPU)

The following schematic shows the mmap and userptr mechanisms:

mmap

  1. device --[MAP]--> kernel --[MAP]--> user
  2. device --[DMA]--> kernel --[MAP]--> user

userptr

  1. device --[DMA]--> user

It is important to note that user pointer is for device-to-user memory transfer whereas DMA is for device-to-device transfer, e.g. directly uploading a captured frame into GPU memory.

As you can see, user pointer and DMA are potential candidates for zero-copy applications where buffers should be writable. If a read-only buffer is good enough, MMAP buffers are fine and do not incur any copy overhead either. Most (if not all) devices reporting streaming I/O capabilities support MMAP buffer sharing, but not all support user pointer access.

The regular user of this crate will mainly be interested in frame capturing. Here is a very brief example of streaming I/O with memory mapped buffers:

use moq_v4l::buffer::Type;
use moq_v4l::io::traits::CaptureStream;
use moq_v4l::prelude::*;

let mut dev = Device::new(0).expect("Failed to open device");

let mut stream =
    MmapStream::with_buffers(&mut dev, Type::VideoCapture, 4).expect("Failed to create buffer stream");

loop {
    let (buf, meta) = stream.next().unwrap();
    println!(
        "Buffer size: {}, seq: {}, timestamp: {}",
       buf.len(),
       meta.sequence,
       meta.timestamp
   );
}

Re-exports§

pub use capability::Capabilities;
pub use control::Control;
pub use device::Device;
pub use format::Format;
pub use format::FourCC;
pub use fraction::Fraction;
pub use frameinterval::FrameInterval;
pub use framesize::FrameSize;
pub use memory::Memory;
pub use timestamp::Timestamp;

Modules§

buffer
capability
context
control
device
format
fraction
frameinterval
framesize
io
memory
parameters
prelude
sys
Raw videodev2.h bindings, generated by bindgen via bindgen.sh and checked in. The output is plain C-ABI struct, enum, and constant definitions with no layout tests, and timeval / timespec come from libc, so one file serves every Linux target.
timestamp
v4l2
video