fwht_encoder: allow mmap of userptr memory types for OUTPUT queue
diff --git a/examples/fwht_encoder/main.rs b/examples/fwht_encoder/main.rs
index 6f0ecb5..03043eb 100644
--- a/examples/fwht_encoder/main.rs
+++ b/examples/fwht_encoder/main.rs
@@ -10,7 +10,12 @@
use std::{cell::RefCell, collections::VecDeque, time::Instant};
use v4l2::{
- device::queue::{direction::Capture, dqbuf::DQBuffer, qbuf::OutputQueueable},
+ device::queue::{
+ direction::Capture,
+ dqbuf::DQBuffer,
+ dual_queue::{DualBufferHandles, DualQBuffer, DualSupportedMemoryType},
+ qbuf::OutputQueueable,
+ },
encoder::*,
memory::{MMAPHandle, MMAPProvider, UserPtrHandle},
};
@@ -40,6 +45,14 @@
.takes_value(true)
.help("Save the encoded stream to a file"),
)
+ .arg(
+ Arg::with_name("output_mem")
+ .long("output_mem")
+ .required(false)
+ .takes_value(true)
+ .default_value("user")
+ .help("Type of output memory to use (mmap or user)"),
+ )
.get_matches();
let device_path = matches.value_of("device").unwrap_or("/dev/video0");
@@ -54,6 +67,12 @@
.value_of("output_file")
.map(|s| File::create(s).expect("Invalid output file specified."));
+ let output_mem = match matches.value_of("output_mem") {
+ Some("mmap") => DualSupportedMemoryType::MMAP,
+ Some("user") => DualSupportedMemoryType::UserPtr,
+ _ => panic!("Invalid value for output_mem"),
+ };
+
let lets_quit = Arc::new(AtomicBool::new(false));
// Setup the Ctrl+c handler.
{
@@ -120,18 +139,33 @@
const NUM_BUFFERS: usize = 2;
- let free_buffers: VecDeque<_> =
- std::iter::repeat(vec![0u8; output_format.plane_fmt[0].sizeimage as usize])
- .take(NUM_BUFFERS)
- .collect();
+ let free_buffers: Option<VecDeque<_>> = match output_mem {
+ DualSupportedMemoryType::MMAP => None,
+ DualSupportedMemoryType::UserPtr => Some(
+ std::iter::repeat(vec![0u8; output_format.plane_fmt[0].sizeimage as usize])
+ .take(NUM_BUFFERS)
+ .collect(),
+ ),
+ };
let free_buffers = RefCell::new(free_buffers);
- let input_done_cb = |buffer: CompletedOutputBuffer<Vec<UserPtrHandle<Vec<u8>>>>| {
- let mut handles = match buffer {
+ let input_done_cb = |buffer: CompletedOutputBuffer<DualBufferHandles>| {
+ let handles = match buffer {
CompletedOutputBuffer::Dequeued(mut buf) => buf.take_handles().unwrap(),
CompletedOutputBuffer::Canceled(buf) => buf.plane_handles,
};
- free_buffers.borrow_mut().push_back(handles.remove(0).0);
+ match handles {
+ // We have nothing to do for MMAP buffers.
+ DualBufferHandles::MMAP(_) => {}
+ // For user-allocated memory, return the buffer to the free list.
+ DualBufferHandles::User(mut u) => {
+ free_buffers
+ .borrow_mut()
+ .as_mut()
+ .unwrap()
+ .push_back(u.remove(0).0);
+ }
+ };
};
let mut total_size = 0usize;
@@ -167,8 +201,7 @@
};
let mut encoder = encoder
- // TODO split between allocate OUTPUT and allocate CAPTURE.
- .allocate_output_buffers::<Vec<UserPtrHandle<Vec<u8>>>>(NUM_BUFFERS)
+ .allocate_output_buffers_generic::<DualBufferHandles>(output_mem, NUM_BUFFERS)
.expect("Failed to allocate OUTPUT buffers")
.allocate_capture_buffers(NUM_BUFFERS, MMAPProvider::new(&capture_format))
.expect("Failed to allocate CAPTURE buffers")
@@ -190,17 +223,36 @@
Err(GetBufferError::PollError(e)) if e.kind() == io::ErrorKind::Interrupted => break,
Err(e) => panic!(e),
};
- let mut buffer = free_buffers
- .borrow_mut()
- .pop_front()
- .expect("No backing buffer to bind");
- frame_gen
- .next_frame(&mut buffer)
- .expect("Failed to generate frame");
- let bytes_used = buffer.len();
- v4l2_buffer
- .queue_with_handles(vec![UserPtrHandle::from(buffer)], &[bytes_used])
- .expect("Failed to queue input frame");
+ match v4l2_buffer {
+ DualQBuffer::MMAP(buf) => {
+ let mut mapping = buf
+ .get_plane_mapping(0)
+ .expect("Failed to get MMAP mapping");
+ frame_gen
+ .next_frame(&mut mapping)
+ .expect("Failed to generate frame");
+ let bytes_used = mapping.len();
+ buf.queue(&[bytes_used])
+ .expect("Failed to queue input frame");
+ }
+ DualQBuffer::User(buf) => {
+ let mut buffer = free_buffers
+ .borrow_mut()
+ .as_mut()
+ .unwrap()
+ .pop_front()
+ .expect("No backing buffer to bind");
+ frame_gen
+ .next_frame(&mut buffer)
+ .expect("Failed to generate frame");
+ let bytes_used = buffer.len();
+ buf.queue_with_handles(
+ DualBufferHandles::from(vec![UserPtrHandle::from(buffer)]),
+ &[bytes_used],
+ )
+ .expect("Failed to queue input frame");
+ }
+ }
}
encoder.stop().unwrap();
@@ -209,5 +261,5 @@
println!();
// All the OUTPUT buffers should have been returned
- assert_eq!(free_buffers.borrow().len(), NUM_BUFFERS);
+ assert_eq!(free_buffers.borrow().as_ref().unwrap().len(), NUM_BUFFERS);
}