1#[cfg(target_os = "windows")]
2mod win32 {
3 pub mod audio;
4 pub mod camera;
5 pub mod screen;
6}
7
8#[cfg(target_os = "linux")]
9mod linux {
10 pub mod audio;
11 pub mod camera;
12 pub mod screen;
13}
14
15#[cfg(target_os = "macos")]
16mod macos {
17 pub mod audio;
18 pub mod camera;
19 pub mod screen;
20}
21
22#[cfg(target_os = "windows")]
23pub use self::win32::{
24 audio::{AudioCapture, AudioCaptureError},
25 camera::{CameraCapture, CameraCaptureError},
26 screen::{ScreenCapture, ScreenCaptureError},
27};
28
29#[cfg(target_os = "linux")]
30pub use self::linux::{
31 audio::{AudioCapture, AudioCaptureError},
32 camera::{CameraCapture, CameraCaptureError},
33 screen::{ScreenCapture, ScreenCaptureError},
34};
35
36#[cfg(target_os = "macos")]
37pub use self::macos::{
38 audio::{AudioCapture, AudioCaptureError},
39 camera::{CameraCapture, CameraCaptureError},
40 screen::{ScreenCapture, ScreenCaptureError},
41};
42
43#[cfg(target_os = "windows")]
44use common::win32::Direct3DDevice;
45
46use common::{
47 frame::{AudioFrame, VideoFrame},
48 Size,
49};
50
51use serde::{Deserialize, Serialize};
52use thiserror::Error;
53
54#[derive(Debug, Error)]
55pub enum CaptureError {
56 #[error(transparent)]
57 AudioCaptureError(#[from] AudioCaptureError),
58 #[error(transparent)]
59 ScreenCaptureError(#[from] ScreenCaptureError),
60 #[error(transparent)]
61 CameraCaptureError(#[from] CameraCaptureError),
62}
63
64pub trait FrameArrived: Sync + Send {
65 type Frame;
67
68 fn sink(&mut self, frame: &Self::Frame) -> bool;
71}
72
73pub trait CaptureHandler: Sync + Send {
74 type Error;
75
76 type Frame;
78
79 type CaptureOptions;
82
83 fn get_sources() -> Result<Vec<Source>, Self::Error>;
85
86 fn stop(&self) -> Result<(), Self::Error>;
88
89 fn start<S: FrameArrived<Frame = Self::Frame> + 'static>(
92 &self,
93 options: Self::CaptureOptions,
94 arrived: S,
95 ) -> Result<(), Self::Error>;
96}
97
98#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)]
100pub enum SourceType {
101 Camera,
104 Screen,
107 Audio,
109}
110
111#[derive(Debug, Clone, Deserialize, Serialize)]
113pub struct Source {
114 pub id: String,
117 pub name: String,
118 pub index: usize,
122 pub kind: SourceType,
123 pub is_default: bool,
126}
127
128#[derive(Debug, Clone)]
129pub struct VideoCaptureSourceDescription {
130 #[cfg(target_os = "windows")]
131 pub direct3d: Direct3DDevice,
132 pub hardware: bool,
136 pub source: Source,
137 pub size: Size,
138 pub fps: u8,
139}
140
141#[derive(Debug, Clone)]
142pub struct AudioCaptureSourceDescription {
143 pub source: Source,
144 pub sample_rate: u32,
145}
146
147pub struct SourceCaptureOptions<T, P> {
148 pub description: P,
149 pub arrived: T,
150}
151
152pub struct CaptureOptions<V, A>
153where
154 V: FrameArrived<Frame = VideoFrame>,
155 A: FrameArrived<Frame = AudioFrame>,
156{
157 pub video: Option<SourceCaptureOptions<V, VideoCaptureSourceDescription>>,
158 pub audio: Option<SourceCaptureOptions<A, AudioCaptureSourceDescription>>,
159}
160
161impl<V, A> Default for CaptureOptions<V, A>
162where
163 V: FrameArrived<Frame = VideoFrame>,
164 A: FrameArrived<Frame = AudioFrame>,
165{
166 fn default() -> Self {
167 Self {
168 video: None,
169 audio: None,
170 }
171 }
172}
173
174enum CaptureImplement {
175 Camera(CameraCapture),
176 Screen(ScreenCapture),
177 Audio(AudioCapture),
178}
179
180#[derive(Default)]
182pub struct Capture(Vec<CaptureImplement>);
183
184impl Capture {
185 #[allow(unreachable_patterns)]
188 pub fn get_sources(kind: SourceType) -> Result<Vec<Source>, CaptureError> {
189 log::info!("capture get sources, kind={:?}", kind);
190
191 Ok(match kind {
192 SourceType::Camera => CameraCapture::get_sources()?,
193 SourceType::Screen => ScreenCapture::get_sources()?,
194 SourceType::Audio => AudioCapture::get_sources()?,
195 _ => Vec::new(),
196 })
197 }
198
199 pub fn start<V, A>(
202 CaptureOptions { video, audio }: CaptureOptions<V, A>,
203 ) -> Result<Self, CaptureError>
204 where
205 V: FrameArrived<Frame = VideoFrame> + 'static,
206 A: FrameArrived<Frame = AudioFrame> + 'static,
207 {
208 let mut devices = Vec::with_capacity(3);
209
210 if let Some(SourceCaptureOptions {
211 description,
212 arrived,
213 }) = video
214 {
215 match description.source.kind {
216 SourceType::Camera => {
217 let camera = CameraCapture::default();
218 camera.start(description, arrived)?;
219 devices.push(CaptureImplement::Camera(camera));
220 }
221 SourceType::Screen => {
222 let screen = ScreenCapture::default();
223 screen.start(description, arrived)?;
224 devices.push(CaptureImplement::Screen(screen));
225 }
226 _ => (),
227 }
228 }
229
230 if let Some(SourceCaptureOptions {
231 description,
232 arrived,
233 }) = audio
234 {
235 let audio = AudioCapture::default();
236 audio.start(description, arrived)?;
237 devices.push(CaptureImplement::Audio(audio));
238 }
239
240 Ok(Self(devices))
241 }
242
243 pub fn close(&self) -> Result<(), CaptureError> {
245 for item in self.0.iter() {
246 match item {
247 CaptureImplement::Screen(it) => it.stop()?,
248 CaptureImplement::Camera(it) => it.stop()?,
249 CaptureImplement::Audio(it) => it.stop()?,
250 };
251 }
252
253 log::info!("close capture");
254
255 Ok(())
256 }
257}
258
259impl Drop for Capture {
260 fn drop(&mut self) {
261 log::info!("capture drop");
262
263 drop(self.close());
264 }
265}