1 //! This example program demonstrates how to use the API using the `vicodec`
2 //! virtual codec driver.
3 //!
4 //! There are two variants doing the same thing: one using the higher-level
5 //! `device` abstraction (used by default), the other using the low-level
6 //! `ioctl` abstraction (used if `--use_ioctl` is specified).
7 mod device_api;
8 mod ioctl_api;
9 
10 use std::path::Path;
11 use std::sync::atomic::{AtomicBool, Ordering};
12 use std::{fs::File, io::Write, sync::Arc};
13 
14 use clap::{App, Arg};
15 use v4l2r::memory::MemoryType;
16 
main()17 fn main() {
18     env_logger::init();
19 
20     let matches = App::new("vicodec example")
21         .arg(
22             Arg::with_name("use_ioctl")
23                 .long("use_ioctl")
24                 .help("Use the lower-level ioctl interface"),
25         )
26         .arg(
27             Arg::with_name("num_frames")
28                 .long("stop_after")
29                 .takes_value(true)
30                 .help("Stop after encoding this number of buffers"),
31         )
32         .arg(
33             Arg::with_name("device")
34                 .required(true)
35                 .help("Path to the vicodec device file"),
36         )
37         .arg(
38             Arg::with_name("output_file")
39                 .long("save")
40                 .required(false)
41                 .takes_value(true)
42                 .help("Save the encoded stream to a file"),
43         )
44         .arg(
45             Arg::with_name("output_mem")
46                 .long("output_mem")
47                 .required(false)
48                 .takes_value(true)
49                 .default_value("user")
50                 .help("Type of memory to use for the OUTPUT queue (mmap or user)"),
51         )
52         .arg(
53             Arg::with_name("capture_mem")
54                 .long("capture_mem")
55                 .required(false)
56                 .takes_value(true)
57                 .default_value("mmap")
58                 .help("Type of memory to use for the CAPTURE queue (mmap)"),
59         )
60         .get_matches();
61 
62     let device_path = matches.value_of("device").unwrap_or("/dev/video0");
63     let use_ioctl = matches.is_present("use_ioctl");
64     let stop_after = match clap::value_t!(matches.value_of("num_frames"), usize) {
65         Ok(v) => Some(v),
66         Err(e) if e.kind == clap::ErrorKind::ArgumentNotFound => None,
67         Err(e) => panic!("Invalid value for stop_after: {}", e),
68     };
69 
70     let mut output_file = matches
71         .value_of("output_file")
72         .map(|s| File::create(s).expect("Invalid output file specified."));
73 
74     let output_mem = match matches.value_of("output_mem") {
75         Some("mmap") => MemoryType::Mmap,
76         Some("user") => MemoryType::UserPtr,
77         _ => panic!("Invalid value for output_mem"),
78     };
79     let capture_mem = match matches.value_of("capture_mem") {
80         Some("mmap") => MemoryType::Mmap,
81         _ => panic!("Invalid value for capture_mem"),
82     };
83 
84     let save_closure = |b: &[u8]| {
85         if let Some(ref mut output) = output_file {
86             output
87                 .write_all(b)
88                 .expect("Error while writing output data");
89         }
90     };
91 
92     let lets_quit = Arc::new(AtomicBool::new(false));
93     // Setup the Ctrl+c handler.
94     {
95         let lets_quit_handler = lets_quit.clone();
96         ctrlc::set_handler(move || {
97             lets_quit_handler.store(true, Ordering::SeqCst);
98         })
99         .expect("Failed to set Ctrl-C handler.");
100     }
101 
102     if use_ioctl {
103         println!("Using ioctl interface");
104         ioctl_api::run(
105             Path::new(&device_path),
106             output_mem,
107             capture_mem,
108             lets_quit,
109             stop_after,
110             save_closure,
111         );
112     } else {
113         println!("Using device interface");
114         device_api::run(
115             Path::new(&device_path),
116             output_mem,
117             capture_mem,
118             lets_quit,
119             stop_after,
120             save_closure,
121         )
122     }
123 }
124