forked from dcuddeback/gphoto-rs
/
video.rs
115 lines (97 loc) · 2.86 KB
/
video.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
use ::context::Context;
use ::camera::Camera;
use ::handle::prelude::*;
/// Capture a video
pub struct Video
{
fifo_path: String,
fifo_fd: i32,
camfile: *mut ::gphoto2::CameraFile,
}
/*
/// Video output type
pub enum OutputType
{
/// No output
none,
/// Pipe to Stdout
stdout,
/// Pipe to fifio
fifo(path, fd),
/// Write to file
file(path, fd),
}*/
impl Drop for Video
{
fn drop(&mut self) {
unsafe {
println!("+++++++++++++++++ Dropping Video: {:?}", self.camfile);
// TODO: check if null before unref
::gphoto2::gp_file_unref(self.camfile);
}
}
}
impl Video
{
pub fn new_fifo(fifo_path: &str) -> Self
{
Video {
fifo_path: fifo_path.to_owned(),
fifo_fd: -1,
camfile: std::ptr::null_mut()
}
}
/// Start video capture
pub fn start(&mut self)
{
println!("Camera stream starting...");
unsafe {
// Stdout
//let fd = unsafe { ::libc::STDOUT_FILENO };
// Create fifo
let filename = std::ffi::CString::new(self.fifo_path.clone()).unwrap();
libc::unlink(filename.as_ptr());
let ret = libc::mkfifo(filename.as_ptr(), 0o644);
if ret < 0 {
println!("Failed to mkfifo: {ret}");
}
// Open via libc to retrieve the fd
self.fifo_fd = ::libc::open(filename.as_ptr(), libc::O_RDWR, 0o644); // | O_NONBLOCK
if self.fifo_fd < 0 {
println!("Failed to open fifo")
//return Err(::error::from_libgphoto2(::gphoto2::GP_ERROR_FILE_EXISTS));
}
// Bind fifo_fd to camfile
match ::gphoto2::gp_file_new_from_fd(&mut self.camfile as *mut _, self.fifo_fd) {
::gphoto2::GP_OK => {},
err => {
println!("gp_file_new_from_fd error: {err}");
//return Err(::error::from_libgphoto2(err))
}
}
}
println!("Camera stream started");
}
/// Stop video
pub fn stop(&mut self)
{
unsafe {
// Delete fifo
let filename = std::ffi::CString::new(self.fifo_path.clone()).unwrap();
libc::unlink(filename.as_ptr());
// Unref camfile
::gphoto2::gp_file_unref(self.camfile);
}
}
/// Poll camera for next frame
/// Pipes frame directly to output
///
/// Note: This command will block if the output is a FIFO, and no consumer
/// is attached to the fifo (such as ffmpeg).
pub fn poll(&mut self, camera: &mut Camera, context: &mut Context) -> ::Result<()>
{
Ok(try_unsafe!(::gphoto2::gp_camera_capture_preview(camera.as_mut_ptr(),
self.camfile,
context.as_mut_ptr())))
}
}