Skip to content

Commit a55ac7c

Browse files
committed
buffer: Merge metadata and memory into single Buffer struct
v4l2 users coming from other languages will be used to all the data being in one place, which is what the C API mandates anyways. Let's stick to the original data layout for simplicity. Signed-off-by: Christopher N. Hesse <[email protected]>
1 parent 62fc9e4 commit a55ac7c

8 files changed

+91
-72
lines changed

examples/glium.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -134,12 +134,13 @@ fn main() -> io::Result<()> {
134134
Stream::<Mmap>::with_buffers(&dev, Type::VideoCapture, buffer_count).unwrap();
135135

136136
loop {
137-
let (buf, _) = stream.next().unwrap();
137+
let buf = stream.next().unwrap();
138138
let data = match &format.fourcc.repr {
139139
b"RGB3" => buf.to_vec(),
140140
b"MJPG" => {
141141
// Decode the JPEG frame to RGB
142-
let mut decoder = jpeg::Decoder::new(buf);
142+
let slice: &[u8] = buf;
143+
let mut decoder = jpeg::Decoder::new(slice);
143144
decoder.decode().expect("failed to decode JPEG")
144145
}
145146
_ => panic!("invalid buffer pixelformat"),

examples/stream_capture_mmap.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ fn main() -> io::Result<()> {
3333
let mut megabytes_ps: f64 = 0.0;
3434
for i in 0..count {
3535
let t0 = Instant::now();
36-
let (buf, meta) = stream.next()?;
36+
let buf = stream.next()?;
3737
let duration_us = t0.elapsed().as_micros();
3838

3939
let cur = buf.len() as f64 / 1_048_576.0 * 1_000_000.0 / duration_us as f64;
@@ -47,9 +47,9 @@ fn main() -> io::Result<()> {
4747
}
4848

4949
println!("Buffer");
50-
println!(" sequence : {}", meta.sequence);
51-
println!(" timestamp : {}", meta.timestamp);
52-
println!(" flags : {}", meta.flags);
50+
println!(" sequence : {}", buf.sequence);
51+
println!(" timestamp : {}", buf.timestamp);
52+
println!(" flags : {}", buf.flags);
5353
println!(" length : {}", buf.len());
5454
}
5555

examples/stream_capture_userptr.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ fn main() -> io::Result<()> {
3333
let mut megabytes_ps: f64 = 0.0;
3434
for i in 0..count {
3535
let t0 = Instant::now();
36-
let (buf, meta) = stream.next()?;
36+
let buf = stream.next()?;
3737
let duration_us = t0.elapsed().as_micros();
3838

3939
let cur = buf.len() as f64 / 1_048_576.0 * 1_000_000.0 / duration_us as f64;
@@ -47,9 +47,9 @@ fn main() -> io::Result<()> {
4747
}
4848

4949
println!("Buffer");
50-
println!(" sequence : {}", meta.sequence);
51-
println!(" timestamp : {}", meta.timestamp);
52-
println!(" flags : {}", meta.flags);
50+
println!(" sequence : {}", buf.sequence);
51+
println!(" timestamp : {}", buf.timestamp);
52+
println!(" flags : {}", buf.flags);
5353
println!(" length : {}", buf.len());
5454
}
5555

examples/stream_forward_mmap.rs

+12-12
Original file line numberDiff line numberDiff line change
@@ -59,18 +59,18 @@ fn main() -> io::Result<()> {
5959
let mut megabytes_ps: f64 = 0.0;
6060
for i in 0..count {
6161
let t0 = Instant::now();
62-
let (buf_in, buf_in_meta) = CaptureStream::next(&mut cap_stream)?;
63-
let (buf_out, buf_out_meta) = OutputStream::next(&mut out_stream)?;
62+
let buf_in = CaptureStream::next(&mut cap_stream)?;
63+
let buf_out = OutputStream::next(&mut out_stream)?;
6464

6565
// Output devices generally cannot know the exact size of the output buffers for
6666
// compressed formats (e.g. MJPG). They will however allocate a size that is always
6767
// large enough to hold images of the format in question. We know how big a buffer we need
6868
// since we control the input buffer - so just enforce that size on the output buffer.
69-
let buf_out = &mut buf_out[0..buf_in.len()];
69+
let slice_out = &mut buf_out[0..buf_in.len()];
7070

71-
buf_out.copy_from_slice(buf_in);
72-
buf_out_meta.field = 0;
73-
buf_out_meta.bytesused = buf_in_meta.bytesused;
71+
slice_out.copy_from_slice(buf_in);
72+
buf_out.field = 0;
73+
buf_out.bytesused = buf_in.bytesused;
7474
let duration_us = t0.elapsed().as_micros();
7575

7676
let cur = buf_in.len() as f64 / 1_048_576.0 * 1_000_000.0 / duration_us as f64;
@@ -84,12 +84,12 @@ fn main() -> io::Result<()> {
8484
}
8585

8686
println!("Buffer");
87-
println!(" sequence [in] : {}", buf_in_meta.sequence);
88-
println!(" sequence [out] : {}", buf_out_meta.sequence);
89-
println!(" timestamp [in] : {}", buf_in_meta.timestamp);
90-
println!(" timestamp [out] : {}", buf_out_meta.timestamp);
91-
println!(" flags [in] : {}", buf_in_meta.flags);
92-
println!(" flags [out] : {}", buf_out_meta.flags);
87+
println!(" sequence [in] : {}", buf_in.sequence);
88+
println!(" sequence [out] : {}", buf_out.sequence);
89+
println!(" timestamp [in] : {}", buf_in.timestamp);
90+
println!(" timestamp [out] : {}", buf_out.timestamp);
91+
println!(" flags [in] : {}", buf_in.flags);
92+
println!(" flags [out] : {}", buf_out.flags);
9393
println!(" length [in] : {}", buf_in.len());
9494
println!(" length [out] : {}", buf_out.len());
9595
}

src/buffer.rs

+35-3
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1-
use std::fmt;
1+
use std::{
2+
fmt,
3+
ops::{Deref, DerefMut},
4+
};
25

36
use crate::timestamp::Timestamp;
47

@@ -98,8 +101,10 @@ impl fmt::Display for Flags {
98101
}
99102

100103
/// Buffer metadata, mostly used not to convolute the main buffer structs
101-
#[derive(Copy, Clone, Default)]
102-
pub struct Metadata {
104+
#[derive(Debug)]
105+
pub struct Buffer<T> {
106+
/// Backing memory
107+
pub memory: T,
103108
/// Number of bytes occupied by the data in the buffer
104109
pub bytesused: u32,
105110
/// Buffer flags
@@ -111,3 +116,30 @@ pub struct Metadata {
111116
/// Sequence number, counting the frames
112117
pub sequence: u32,
113118
}
119+
120+
impl<T> Buffer<T> {
121+
pub(crate) fn new(memory: T) -> Self {
122+
Buffer {
123+
memory,
124+
bytesused: 0,
125+
flags: Flags::from(0),
126+
field: 0,
127+
timestamp: Timestamp::default(),
128+
sequence: 0,
129+
}
130+
}
131+
}
132+
133+
impl<T> Deref for Buffer<T> {
134+
type Target = T;
135+
136+
fn deref(&self) -> &Self::Target {
137+
&self.memory
138+
}
139+
}
140+
141+
impl<T> DerefMut for Buffer<T> {
142+
fn deref_mut(&mut self) -> &mut Self::Target {
143+
&mut self.memory
144+
}
145+
}

src/io/mod.rs

+27-39
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use std::{
1111

1212
use v4l2_sys::{v4l2_buffer, v4l2_format, v4l2_requestbuffers};
1313

14-
use crate::buffer::{Metadata, Type};
14+
use crate::buffer::{Buffer, Type};
1515
use crate::device::{Device, Handle};
1616
use crate::io::traits::{CaptureStream, OutputStream, Stream as StreamTrait};
1717
use crate::memory::{Memory, Mmap, UserPtr};
@@ -23,7 +23,7 @@ use crate::v4l2;
2323
/// In case of errors during unmapping, we panic because there is memory corruption going on.
2424
pub(crate) struct Arena<T> {
2525
handle: Arc<Handle>,
26-
pub bufs: Vec<T>,
26+
pub bufs: Vec<Buffer<T>>,
2727
pub buf_mem: Memory,
2828
pub buf_type: Type,
2929
}
@@ -119,7 +119,8 @@ impl<'a> Arena<Mmap<'a>> {
119119

120120
let slice =
121121
slice::from_raw_parts_mut::<u8>(ptr as *mut u8, v4l2_buf.length as usize);
122-
self.bufs.push(Mmap(slice));
122+
let buf = Buffer::new(Mmap(slice));
123+
self.bufs.push(buf);
123124
}
124125
}
125126

@@ -171,8 +172,8 @@ You may want to use this crate with the raw v4l2 FFI bindings instead!\n"
171172
let count = self.request(count)?;
172173
for _ in 0..count {
173174
let size = unsafe { v4l2_fmt.fmt.pix.sizeimage };
174-
let buf = vec![0u8; size as usize];
175-
self.bufs.push(UserPtr(buf));
175+
let buf = Buffer::new(UserPtr(vec![0u8; size as usize]));
176+
self.bufs.push(buf);
176177
}
177178

178179
Ok(count)
@@ -187,7 +188,6 @@ pub struct Stream<T> {
187188
arena: Arena<T>,
188189
arena_index: usize,
189190
buf_type: Type,
190-
buf_meta: Vec<Metadata>,
191191
timeout: Option<i32>,
192192

193193
active: bool,
@@ -220,16 +220,13 @@ impl<'a> Stream<Mmap<'a>> {
220220

221221
pub fn with_buffers(dev: &Device, buf_type: Type, buf_count: u32) -> io::Result<Self> {
222222
let mut arena = Arena::<Mmap<'a>>::new(dev.handle(), buf_type);
223-
let count = arena.allocate(buf_count)?;
224-
let mut buf_meta = Vec::new();
225-
buf_meta.resize(count as usize, Metadata::default());
223+
let _count = arena.allocate(buf_count)?;
226224

227225
Ok(Stream {
228226
handle: dev.handle(),
229227
arena,
230228
arena_index: 0,
231229
buf_type,
232-
buf_meta,
233230
active: false,
234231
timeout: None,
235232
})
@@ -263,16 +260,13 @@ impl Stream<UserPtr> {
263260

264261
pub fn with_buffers(dev: &Device, buf_type: Type, buf_count: u32) -> io::Result<Self> {
265262
let mut arena = Arena::<UserPtr>::new(dev.handle(), buf_type);
266-
let count = arena.allocate(buf_count)?;
267-
let mut buf_meta = Vec::new();
268-
buf_meta.resize(count as usize, Metadata::default());
263+
let _count = arena.allocate(buf_count)?;
269264

270265
Ok(Stream {
271266
handle: dev.handle(),
272267
arena,
273268
arena_index: 0,
274269
buf_type,
275-
buf_meta,
276270
active: false,
277271
timeout: None,
278272
})
@@ -323,7 +317,7 @@ impl<T> Drop for Stream<T> {
323317
}
324318

325319
impl<T> StreamTrait for Stream<T> {
326-
type Item = [u8];
320+
type Item = Buffer<T>;
327321

328322
fn start(&mut self) -> io::Result<()> {
329323
unsafe {
@@ -394,18 +388,17 @@ where
394388
}
395389
self.arena_index = v4l2_buf.index as usize;
396390

397-
self.buf_meta[self.arena_index] = Metadata {
398-
bytesused: v4l2_buf.bytesused,
399-
flags: v4l2_buf.flags.into(),
400-
field: v4l2_buf.field,
401-
timestamp: v4l2_buf.timestamp.into(),
402-
sequence: v4l2_buf.sequence,
403-
};
391+
let buf = &mut self.arena.bufs[self.arena_index];
392+
buf.bytesused = v4l2_buf.bytesused;
393+
buf.flags = v4l2_buf.flags.into();
394+
buf.field = v4l2_buf.field;
395+
buf.timestamp = v4l2_buf.timestamp.into();
396+
buf.sequence = v4l2_buf.sequence;
404397

405398
Ok(self.arena_index)
406399
}
407400

408-
fn next(&'a mut self) -> io::Result<(&Self::Item, &Metadata)> {
401+
fn next(&'a mut self) -> io::Result<&Self::Item> {
409402
if !self.active {
410403
// Enqueue all buffers once on stream start
411404
for index in 0..self.arena.bufs.len() {
@@ -421,9 +414,7 @@ where
421414

422415
// The index used to access the buffer elements is given to us by v4l2, so we assume it
423416
// will always be valid.
424-
let bytes = &self.arena.bufs[self.arena_index];
425-
let meta = &self.buf_meta[self.arena_index];
426-
Ok((bytes, meta))
417+
Ok(&self.arena.bufs[self.arena_index])
427418
}
428419
}
429420

@@ -442,8 +433,8 @@ where
442433
// MetaData.bytesused is initialized to 0. For an output device, when bytesused is
443434
// set to 0 v4l2 will set it to the size of the plane:
444435
// https://www.kernel.org/doc/html/v4.15/media/uapi/v4l/buffer.html#struct-v4l2-plane
445-
v4l2_buf.bytesused = self.buf_meta[index].bytesused;
446-
v4l2_buf.field = self.buf_meta[index].field;
436+
v4l2_buf.bytesused = self.arena.bufs[index].bytesused;
437+
v4l2_buf.field = self.arena.bufs[index].field;
447438

448439
if self
449440
.handle
@@ -476,18 +467,17 @@ where
476467
}
477468
self.arena_index = v4l2_buf.index as usize;
478469

479-
self.buf_meta[self.arena_index] = Metadata {
480-
bytesused: v4l2_buf.bytesused,
481-
flags: v4l2_buf.flags.into(),
482-
field: v4l2_buf.field,
483-
timestamp: v4l2_buf.timestamp.into(),
484-
sequence: v4l2_buf.sequence,
485-
};
470+
let buf = &mut self.arena.bufs[self.arena_index];
471+
buf.bytesused = v4l2_buf.bytesused;
472+
buf.flags = v4l2_buf.flags.into();
473+
buf.field = v4l2_buf.field;
474+
buf.timestamp = v4l2_buf.timestamp.into();
475+
buf.sequence = v4l2_buf.sequence;
486476

487477
Ok(self.arena_index)
488478
}
489479

490-
fn next(&'a mut self) -> io::Result<(&mut Self::Item, &mut Metadata)> {
480+
fn next(&'a mut self) -> io::Result<&mut Self::Item> {
491481
let init = !self.active;
492482
if !self.active {
493483
self.start()?;
@@ -503,8 +493,6 @@ where
503493

504494
// The index used to access the buffer elements is given to us by v4l2, so we assume it
505495
// will always be valid.
506-
let bytes = &mut self.arena.bufs[self.arena_index];
507-
let meta = &mut self.buf_meta[self.arena_index];
508-
Ok((bytes, meta))
496+
Ok(&mut self.arena.bufs[self.arena_index])
509497
}
510498
}

src/io/traits.rs

+2-4
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
use std::io;
22

3-
use crate::buffer::Metadata;
4-
53
/// Streaming I/O
64
pub trait Stream {
75
type Item: ?Sized;
@@ -22,7 +20,7 @@ pub trait CaptureStream<'a>: Stream {
2220

2321
/// Fetch a new frame by first queueing and then dequeueing.
2422
/// First time initialization is performed if necessary.
25-
fn next(&'a mut self) -> io::Result<(&Self::Item, &Metadata)>;
23+
fn next(&'a mut self) -> io::Result<&Self::Item>;
2624
}
2725

2826
pub trait OutputStream<'a>: Stream {
@@ -34,5 +32,5 @@ pub trait OutputStream<'a>: Stream {
3432

3533
/// Dump a new frame by first queueing and then dequeueing.
3634
/// First time initialization is performed if necessary.
37-
fn next(&'a mut self) -> io::Result<(&mut Self::Item, &mut Metadata)>;
35+
fn next(&'a mut self) -> io::Result<&mut Self::Item>;
3836
}

src/lib.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -56,12 +56,12 @@
5656
//! Stream::<Mmap>::with_buffers(&mut dev, Type::VideoCapture, 4).expect("Failed to create buffer stream");
5757
//!
5858
//! loop {
59-
//! let (buf, meta) = stream.next().unwrap();
59+
//! let buf = stream.next().unwrap();
6060
//! println!(
6161
//! "Buffer size: {}, seq: {}, timestamp: {}",
62-
//! buf.len(),
63-
//! meta.sequence,
64-
//! meta.timestamp
62+
//! buf.memory.len(),
63+
//! buf.sequence,
64+
//! buf.timestamp
6565
//! );
6666
//!}
6767
//!```

0 commit comments

Comments
 (0)