use std::path::Path;
use std::sync::Arc;
use crate::{MatView, PixelFormat, VideoCaptureError};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum Backend {
Auto,
Ffmpeg,
}
#[derive(Debug, Clone)]
pub struct CapturedFrame {
pub width: u32,
pub height: u32,
pub pixel_format: PixelFormat,
pub data: Arc<[u8]>,
}
impl MatView for CapturedFrame {
fn width(&self) -> u32 {
self.width
}
fn height(&self) -> u32 {
self.height
}
fn channels(&self) -> u32 {
self.pixel_format.channels()
}
fn pixel_format(&self) -> PixelFormat {
self.pixel_format
}
fn data(&self) -> &[u8] {
&self.data
}
}
pub trait VideoCapturePort: Send + Sync {
fn open(
&self,
path: &Path,
backend: Backend,
) -> Result<Box<dyn VideoStream>, VideoCaptureError>;
}
pub trait VideoStream: Send {
fn read_frame(&mut self) -> Result<CapturedFrame, VideoCaptureError>;
fn fps(&self) -> Result<f64, VideoCaptureError>;
fn seek_to_start(&mut self) -> Result<(), VideoCaptureError>;
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn captured_frame_exposes_mat_view() {
let frame = CapturedFrame {
width: 2,
height: 3,
pixel_format: PixelFormat::Bgr8,
data: Arc::from(vec![0u8; 2 * 3 * 3].into_boxed_slice()),
};
assert_eq!(frame.width(), 2);
assert_eq!(frame.height(), 3);
assert_eq!(frame.channels(), 3);
assert_eq!(frame.pixel_format(), PixelFormat::Bgr8);
assert_eq!(frame.data().len(), 18);
}
#[test]
fn backend_equality_is_value_wise() {
assert_eq!(Backend::Auto, Backend::Auto);
assert_ne!(Backend::Auto, Backend::Ffmpeg);
}
}