moq_v4l/lib.rs
1//! Safe bindings for the kernel's Video4Linux 2 (v4l2) API, forked from the
2//! `v4l` crate with the `videodev2.h` bindings checked in, so a build needs
3//! neither libclang nor the kernel headers. Only the `v4l2` backend survived
4//! the fork: every call is an ioctl on the device node, nothing links libv4l.
5//!
6//! # Overview
7//!
8//! Video devices on Linux can be accessed by path or by index (which then corresponds to a path),
9//! e.g. "/dev/video0" for the device which first became known to the system.
10//!
11//! There are three methods of dealing with (capture) device memory:
12//! * `MMAP` (memory region in device memory or kernel space, mapped into userspace)
13//! * `User` pointer (memory region allocated in host memory, written into by the kernel)
14//! * `DMA` (direct memory access for memory transfer without involving the CPU)
15//!
16//! The following schematic shows the `mmap` and `userptr` mechanisms:
17//!
18//! **mmap**
19//!
20//! 1. `device --[MAP]--> kernel --[MAP]--> user`
21//! 2. `device --[DMA]--> kernel --[MAP]--> user`
22//!
23//! **userptr**
24//!
25//! 3. `device --[DMA]--> user`
26//!
27//!
28//! It is important to note that user pointer is for device-to-user memory transfer whereas
29//! DMA is for device-to-device transfer, e.g. directly uploading a captured frame into GPU
30//! memory.
31//!
32//! As you can see, user pointer and DMA are potential candidates for zero-copy applications where
33//! buffers should be writable. If a read-only buffer is good enough, MMAP buffers are fine and
34//! do not incur any copy overhead either. Most (if not all) devices reporting streaming I/O
35//! capabilities support MMAP buffer sharing, but not all support user pointer access.
36//!
37//! The regular user of this crate will mainly be interested in frame capturing.
38//! Here is a very brief example of streaming I/O with memory mapped buffers:
39//!
40//! ```no_run
41//! use moq_v4l::buffer::Type;
42//! use moq_v4l::io::traits::CaptureStream;
43//! use moq_v4l::prelude::*;
44//!
45//! let mut dev = Device::new(0).expect("Failed to open device");
46//!
47//! let mut stream =
48//! MmapStream::with_buffers(&mut dev, Type::VideoCapture, 4).expect("Failed to create buffer stream");
49//!
50//! loop {
51//! let (buf, meta) = stream.next().unwrap();
52//! println!(
53//! "Buffer size: {}, seq: {}, timestamp: {}",
54//! buf.len(),
55//! meta.sequence,
56//! meta.timestamp
57//! );
58//!}
59//!```
60//!
61
62// Every call is a Linux ioctl, so elsewhere the crate is an empty stub and
63// moq-video only depends on it there.
64#![cfg(target_os = "linux")]
65
66pub mod sys;
67
68pub mod v4l2;
69
70pub mod buffer;
71pub mod capability;
72pub mod context;
73pub mod control;
74pub mod device;
75pub mod format;
76pub mod fraction;
77pub mod frameinterval;
78pub mod framesize;
79pub mod memory;
80pub mod parameters;
81pub mod timestamp;
82pub mod video;
83
84pub mod io;
85
86pub use {
87 capability::Capabilities,
88 control::Control,
89 device::Device,
90 format::{Format, FourCC},
91 fraction::Fraction,
92 frameinterval::FrameInterval,
93 framesize::FrameSize,
94 memory::Memory,
95 timestamp::Timestamp,
96};
97
98pub mod prelude {
99 pub use crate::device::Device;
100 pub use crate::io::{mmap::Stream as MmapStream, userptr::Stream as UserptrStream};
101}