opencv_rs_core/
video_capture.rs1use std::path::Path;
4use std::sync::Arc;
5
6use crate::{MatView, PixelFormat, VideoCaptureError};
7
8#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
10pub enum Backend {
11 Auto,
13 Ffmpeg,
15}
16
17#[derive(Debug, Clone)]
19pub struct CapturedFrame {
20 pub width: u32,
22 pub height: u32,
24 pub pixel_format: PixelFormat,
26 pub data: Arc<[u8]>,
28}
29
30impl MatView for CapturedFrame {
31 fn width(&self) -> u32 {
32 self.width
33 }
34 fn height(&self) -> u32 {
35 self.height
36 }
37 fn channels(&self) -> u32 {
38 self.pixel_format.channels()
39 }
40 fn pixel_format(&self) -> PixelFormat {
41 self.pixel_format
42 }
43 fn data(&self) -> &[u8] {
44 &self.data
45 }
46}
47
48pub trait VideoCapturePort: Send + Sync {
50 fn open(
52 &self,
53 path: &Path,
54 backend: Backend,
55 ) -> Result<Box<dyn VideoStream>, VideoCaptureError>;
56}
57
58pub trait VideoStream: Send {
60 fn read_frame(&mut self) -> Result<CapturedFrame, VideoCaptureError>;
63 fn fps(&self) -> Result<f64, VideoCaptureError>;
65 fn seek_to_start(&mut self) -> Result<(), VideoCaptureError>;
67}
68
69#[cfg(test)]
70mod tests {
71 use super::*;
72
73 #[test]
74 fn captured_frame_exposes_mat_view() {
75 let frame = CapturedFrame {
78 width: 2,
79 height: 3,
80 pixel_format: PixelFormat::Bgr8,
81 data: Arc::from(vec![0u8; 2 * 3 * 3].into_boxed_slice()),
82 };
83 assert_eq!(frame.width(), 2);
84 assert_eq!(frame.height(), 3);
85 assert_eq!(frame.channels(), 3);
86 assert_eq!(frame.pixel_format(), PixelFormat::Bgr8);
87 assert_eq!(frame.data().len(), 18);
88 }
89
90 #[test]
91 fn backend_equality_is_value_wise() {
92 assert_eq!(Backend::Auto, Backend::Auto);
93 assert_ne!(Backend::Auto, Backend::Ffmpeg);
94 }
95}