1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
//! 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**
//!
//! 3. `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:
//!
//! ```no_run
//! 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
//! );
//!}
//!```
//!
// Every call is a Linux ioctl, so elsewhere the crate is an empty stub and
// moq-video only depends on it there.
pub use ;