Skip to content

Commit 384e7fb

Browse files
committed
io: Introduce new Queue type to replace Arena/Stream
The notion of a "queue" is closer to the actual V4L2 streaming I/O implementation detail. The new type design should allow us to model planar buffers as well in the future. Signed-off-by: Christopher N. Hesse <raymanfx@gmail.com>
1 parent 17c2871 commit 384e7fb

File tree

6 files changed

+542
-30
lines changed

6 files changed

+542
-30
lines changed

examples/io_capture.rs

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
use std::io;
2+
use std::time::Instant;
3+
4+
use v4l::buffer::Type;
5+
use v4l::io::Queue;
6+
use v4l::prelude::*;
7+
use v4l::video::Capture;
8+
9+
fn main() -> io::Result<()> {
10+
let path = "/dev/video0";
11+
println!("Using device: {}\n", path);
12+
13+
// Capture 4 frames by default
14+
let count = 4;
15+
16+
let dev = Device::with_path(path)?;
17+
let format = dev.format()?;
18+
let params = dev.params()?;
19+
println!("Active format:\n{}", format);
20+
println!("Active parameters:\n{}", params);
21+
22+
// set up a queue
23+
let mut queue = Queue::with_mmap(dev.handle(), Type::VideoCapture, 4)?;
24+
25+
// enqueue all buffers once
26+
for i in 0..queue.len() {
27+
let buf = queue.query_buf(i as u32)?;
28+
queue.enqueue(&buf)?;
29+
}
30+
31+
// start streaming
32+
let mut queue = queue.start_stream()?;
33+
34+
// warm up
35+
let buf = queue.dequeue()?;
36+
let _ = queue.enqueue(&buf)?;
37+
38+
let start = Instant::now();
39+
let mut megabytes_ps: f64 = 0.0;
40+
for i in 0..count {
41+
let t0 = Instant::now();
42+
43+
// check whether there's something for us to do
44+
dev.handle().poll(libc::POLLIN, -1)?;
45+
46+
// remove a buffer from the drivers' outgoing queue
47+
let buf = queue.dequeue()?;
48+
49+
let duration_us = t0.elapsed().as_micros();
50+
51+
let cur = buf.bytesused as f64 / 1_048_576.0 * 1_000_000.0 / duration_us as f64;
52+
if i == 0 {
53+
megabytes_ps = cur;
54+
} else {
55+
// ignore the first measurement
56+
let prev = megabytes_ps * (i as f64 / (i + 1) as f64);
57+
let now = cur * (1.0 / (i + 1) as f64);
58+
megabytes_ps = prev + now;
59+
}
60+
61+
println!("Buffer");
62+
println!(" sequence : {}", buf.sequence);
63+
println!(" timestamp : {}", buf.timestamp);
64+
println!(" flags : {}", buf.flags);
65+
println!(" length : {}", buf.bytesused);
66+
67+
// once we're done with it, add the buffer to the drivers' incoming queue
68+
queue.enqueue(&buf)?;
69+
}
70+
71+
println!();
72+
println!("FPS: {}", count as f64 / start.elapsed().as_secs_f64());
73+
println!("MB/s: {}", megabytes_ps);
74+
75+
Ok(())
76+
}

src/buffer.rs

Lines changed: 49 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
use bitflags::bitflags;
2-
use std::fmt;
2+
use std::{convert::TryInto, fmt, mem};
33

4-
use crate::timestamp::Timestamp;
4+
use v4l2_sys::v4l2_buffer;
5+
6+
use crate::{memory::Memory, timestamp::Timestamp};
57

68
/// Buffer type
79
///
@@ -99,8 +101,12 @@ impl fmt::Display for Flags {
99101
}
100102

101103
/// Buffer metadata, mostly used not to convolute the main buffer structs
102-
#[derive(Copy, Clone, Default)]
104+
#[derive(Copy, Clone)]
103105
pub struct Metadata {
106+
/// Number of the buffer
107+
pub index: u32,
108+
/// Type of the buffer
109+
pub type_: u32,
104110
/// Number of bytes occupied by the data in the buffer
105111
pub bytesused: u32,
106112
/// Buffer flags
@@ -111,4 +117,44 @@ pub struct Metadata {
111117
pub timestamp: Timestamp,
112118
/// Sequence number, counting the frames
113119
pub sequence: u32,
120+
/// Memory type, depending on streaming I/O method
121+
pub memory: Memory,
122+
/// Single-planar API: size of the buffer (not payload!)
123+
/// Multi-planar API: number of planes
124+
pub length: u32,
125+
}
126+
127+
impl From<v4l2_buffer> for Metadata {
128+
fn from(buf: v4l2_buffer) -> Self {
129+
Self {
130+
index: buf.index,
131+
type_: buf.type_,
132+
bytesused: buf.bytesused,
133+
flags: buf.flags.into(),
134+
field: buf.field,
135+
timestamp: buf.timestamp.into(),
136+
sequence: buf.sequence,
137+
memory: buf.memory.try_into().unwrap(),
138+
length: buf.length,
139+
}
140+
}
141+
}
142+
143+
impl Into<v4l2_buffer> for Metadata {
144+
fn into(self) -> v4l2_buffer {
145+
unsafe {
146+
v4l2_buffer {
147+
index: self.index,
148+
type_: self.type_,
149+
bytesused: self.bytesused,
150+
flags: self.flags.into(),
151+
field: self.field,
152+
timestamp: self.timestamp.into(),
153+
sequence: self.sequence,
154+
memory: self.memory as u32,
155+
length: self.length,
156+
..mem::zeroed()
157+
}
158+
}
159+
}
114160
}

src/io/mmap/stream.rs

Lines changed: 3 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ impl<'a> Stream<'a> {
5252
let mut arena = Arena::new(dev.handle(), buf_type);
5353
let count = arena.allocate(buf_count)?;
5454
let mut buf_meta = Vec::new();
55-
buf_meta.resize(count as usize, Metadata::default());
55+
buf_meta.resize(count as usize, unsafe { Metadata { ..mem::zeroed() } });
5656

5757
Ok(Stream {
5858
handle: dev.handle(),
@@ -175,14 +175,7 @@ impl<'a, 'b> CaptureStream<'b> for Stream<'a> {
175175
)?;
176176
}
177177
self.arena_index = v4l2_buf.index as usize;
178-
179-
self.buf_meta[self.arena_index] = Metadata {
180-
bytesused: v4l2_buf.bytesused,
181-
flags: v4l2_buf.flags.into(),
182-
field: v4l2_buf.field,
183-
timestamp: v4l2_buf.timestamp.into(),
184-
sequence: v4l2_buf.sequence,
185-
};
178+
self.buf_meta[self.arena_index] = Metadata::from(v4l2_buf);
186179

187180
Ok(self.arena_index)
188181
}
@@ -254,14 +247,7 @@ impl<'a, 'b> OutputStream<'b> for Stream<'a> {
254247
)?;
255248
}
256249
self.arena_index = v4l2_buf.index as usize;
257-
258-
self.buf_meta[self.arena_index] = Metadata {
259-
bytesused: v4l2_buf.bytesused,
260-
flags: v4l2_buf.flags.into(),
261-
field: v4l2_buf.field,
262-
timestamp: v4l2_buf.timestamp.into(),
263-
sequence: v4l2_buf.sequence,
264-
};
250+
self.buf_meta[self.arena_index] = Metadata::from(v4l2_buf);
265251

266252
Ok(self.arena_index)
267253
}

0 commit comments

Comments
 (0)