Skip to content

Commit 559251c

Browse files
authored
feat(linux): implement video recorder (#201)
- Update ImplVideoRecorder::new() to accept an ImplMonitor instance. - Spawn a thread at on_frame() to keep capturiing frames using monitor.capture_image(). - Use a RecorderWaker to signal when to wake the recording thread. - Implement start() and stop() functionality to control the recording state.
1 parent 9b033aa commit 559251c

File tree

2 files changed

+90
-16
lines changed

2 files changed

+90
-16
lines changed

src/linux/impl_monitor.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -327,6 +327,6 @@ impl ImplMonitor {
327327
}
328328

329329
pub fn video_recorder(&self) -> XCapResult<(ImplVideoRecorder, Receiver<Frame>)> {
330-
ImplVideoRecorder::new()
330+
ImplVideoRecorder::new(self.clone())
331331
}
332332
}

src/linux/impl_video_recorder.rs

Lines changed: 89 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,101 @@
1-
#![allow(unused)]
2-
3-
use std::sync::mpsc::Receiver;
4-
5-
use crate::{video_recorder::Frame, XCapResult};
1+
use super::impl_monitor::ImplMonitor;
2+
use crate::error::{XCapError, XCapResult};
3+
use crate::video_recorder::{Frame, RecorderWaker};
4+
use std::sync::mpsc::{self, Receiver, Sender};
5+
use std::sync::{Arc, Mutex};
6+
use std::thread;
7+
use std::time::Duration;
68

79
#[derive(Debug, Clone)]
8-
pub struct ImplVideoRecorder {}
10+
pub struct ImplVideoRecorder {
11+
monitor: ImplMonitor,
12+
sender: Sender<Frame>,
13+
running: Arc<Mutex<bool>>,
14+
recorder_waker: Arc<RecorderWaker>,
15+
}
916

1017
impl ImplVideoRecorder {
11-
pub fn new() -> XCapResult<(Self, Receiver<Frame>)> {
12-
unimplemented!()
18+
pub fn new(monitor: ImplMonitor) -> XCapResult<(Self, Receiver<Frame>)> {
19+
let (sender, receiver) = mpsc::channel();
20+
let recorder = Self {
21+
monitor,
22+
sender,
23+
running: Arc::new(Mutex::new(false)),
24+
recorder_waker: Arc::new(RecorderWaker::new()),
25+
};
26+
27+
recorder.on_frame()?;
28+
29+
Ok((recorder, receiver))
1330
}
1431

15-
pub fn on_frame<F>(&self, on_frame: F) -> XCapResult<()>
16-
where
17-
F: Fn(Frame) -> XCapResult<()> + Send + 'static,
18-
{
19-
unimplemented!()
32+
pub fn on_frame(&self) -> XCapResult<()> {
33+
let monitor = self.monitor.clone();
34+
let sender = self.sender.clone();
35+
let running_flag = self.running.clone();
36+
let recorder_waker = self.recorder_waker.clone();
37+
38+
thread::spawn(move || loop {
39+
if let Err(err) = recorder_waker.wait() {
40+
eprintln!("Recorder waker error: {:?}", err);
41+
break Err(err);
42+
}
43+
44+
let is_running = match running_flag.lock() {
45+
Ok(guard) => *guard,
46+
Err(e) => {
47+
eprintln!("Failed to lock running flag: {:?}", e);
48+
break Err(XCapError::from(e));
49+
}
50+
};
51+
52+
if !is_running {
53+
break Ok(());
54+
}
55+
56+
match monitor.capture_image() {
57+
Ok(image) => {
58+
let width = image.width();
59+
let height = image.height();
60+
let raw = image.into_raw();
61+
62+
let frame = Frame::new(width, height, raw);
63+
if let Err(e) = sender.send(frame) {
64+
eprintln!("Failed to send frame: {:?}", e);
65+
break Err(XCapError::new(&format!("Failed to send frame: {}", e)));
66+
}
67+
}
68+
Err(e) => {
69+
eprintln!("Failed to capture frame: {:?}", e);
70+
thread::sleep(Duration::from_millis(10));
71+
continue;
72+
}
73+
}
74+
75+
thread::sleep(Duration::from_millis(1));
76+
});
77+
78+
Ok(())
2079
}
80+
2181
pub fn start(&self) -> XCapResult<()> {
22-
unimplemented!()
82+
let mut running = self.running.lock().map_err(XCapError::from)?;
83+
if *running {
84+
return Ok(());
85+
}
86+
*running = true;
87+
88+
self.recorder_waker.wake()?;
89+
90+
Ok(())
2391
}
92+
2493
pub fn stop(&self) -> XCapResult<()> {
25-
unimplemented!()
94+
let mut running = self.running.lock().map_err(XCapError::from)?;
95+
*running = false;
96+
97+
self.recorder_waker.sleep()?;
98+
99+
Ok(())
26100
}
27101
}

0 commit comments

Comments
 (0)