blob: 0c3755e43c2ac034e7a770d465488daea1bf09ef [file] [log] [blame]
//! This example program demonstrates how to use the API using the `vicodec`
//! virtual codec driver.
//!
//! There are two variants doing the same thing: one using the higher-level
//! `device` abstraction (used by default), the other using the low-level
//! `ioctl` abstraction (used if `--use_ioctl` is specified).
mod device_api;
mod ioctl_api;
use std::path::Path;
use std::sync::atomic::{AtomicBool, Ordering};
use std::{fs::File, io::Write, sync::Arc};
use clap::{App, Arg};
use v4l2r::memory::MemoryType;
fn main() {
env_logger::init();
let matches = App::new("vicodec example")
.arg(
Arg::with_name("use_ioctl")
.long("use_ioctl")
.help("Use the lower-level ioctl interface"),
)
.arg(
Arg::with_name("num_frames")
.long("stop_after")
.takes_value(true)
.help("Stop after encoding this number of buffers"),
)
.arg(
Arg::with_name("device")
.required(true)
.help("Path to the vicodec device file"),
)
.arg(
Arg::with_name("output_file")
.long("save")
.required(false)
.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 memory to use for the OUTPUT queue (mmap or user)"),
)
.arg(
Arg::with_name("capture_mem")
.long("capture_mem")
.required(false)
.takes_value(true)
.default_value("mmap")
.help("Type of memory to use for the CAPTURE queue (mmap)"),
)
.get_matches();
let device_path = matches.value_of("device").unwrap_or("/dev/video0");
let use_ioctl = matches.is_present("use_ioctl");
let stop_after = match clap::value_t!(matches.value_of("num_frames"), usize) {
Ok(v) => Some(v),
Err(e) if e.kind == clap::ErrorKind::ArgumentNotFound => None,
Err(e) => panic!("Invalid value for stop_after: {}", e),
};
let mut output_file = matches
.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") => MemoryType::Mmap,
Some("user") => MemoryType::UserPtr,
_ => panic!("Invalid value for output_mem"),
};
let capture_mem = match matches.value_of("capture_mem") {
Some("mmap") => MemoryType::Mmap,
_ => panic!("Invalid value for capture_mem"),
};
let save_closure = |b: &[u8]| {
if let Some(ref mut output) = output_file {
output
.write_all(b)
.expect("Error while writing output data");
}
};
let lets_quit = Arc::new(AtomicBool::new(false));
// Setup the Ctrl+c handler.
{
let lets_quit_handler = lets_quit.clone();
ctrlc::set_handler(move || {
lets_quit_handler.store(true, Ordering::SeqCst);
})
.expect("Failed to set Ctrl-C handler.");
}
if use_ioctl {
println!("Using ioctl interface");
ioctl_api::run(
Path::new(&device_path),
output_mem,
capture_mem,
lets_quit,
stop_after,
save_closure,
);
} else {
println!("Using device interface");
device_api::run(
Path::new(&device_path),
output_mem,
capture_mem,
lets_quit,
stop_after,
save_closure,
)
}
}