186 lines
5.2 KiB
Rust
186 lines
5.2 KiB
Rust
/// Core camera interface trait for dependency inversion
|
|
/// This trait provides a clean abstraction that isolates production code from capture-source concerns
|
|
use anyhow::Result;
|
|
use async_trait::async_trait;
|
|
use chrono::{DateTime, Utc};
|
|
use std::sync::Arc;
|
|
|
|
use crate::memory::frame_data::{FrameData, FrameFormat};
|
|
use std::path::PathBuf;
|
|
|
|
/// Core camera interface that both hardware and video file cameras implement
|
|
pub trait CameraInterface: Send + Sync {
|
|
/// Initialize the camera hardware or video source
|
|
fn initialize(
|
|
&mut self,
|
|
) -> std::pin::Pin<Box<dyn std::future::Future<Output = Result<()>> + Send + '_>>;
|
|
|
|
/// Capture a single frame from the camera
|
|
fn capture_frame(
|
|
&mut self,
|
|
) -> std::pin::Pin<Box<dyn std::future::Future<Output = Result<CapturedFrame>> + Send + '_>>;
|
|
|
|
/// Get camera metadata and capabilities
|
|
fn get_metadata(&self) -> CameraMetadata;
|
|
|
|
/// Check if the camera is currently active and ready
|
|
fn is_running(&self) -> bool;
|
|
|
|
/// Get current frame count
|
|
fn frame_count(&self) -> u64;
|
|
|
|
/// Gracefully shutdown the camera
|
|
fn shutdown(
|
|
&mut self,
|
|
) -> std::pin::Pin<Box<dyn std::future::Future<Output = Result<()>> + Send + '_>>;
|
|
}
|
|
|
|
/// Represents a captured frame with metadata
|
|
#[derive(Clone)]
|
|
pub struct CapturedFrame {
|
|
/// Frame data (shared for zero-copy)
|
|
pub data: Arc<FrameData>,
|
|
/// Sequential frame number
|
|
pub frame_number: u64,
|
|
/// When the frame was captured
|
|
pub capture_timestamp: DateTime<Utc>,
|
|
/// Camera-specific metadata
|
|
pub metadata: FrameMetadata,
|
|
}
|
|
|
|
/// Camera metadata describing capabilities and configuration
|
|
#[derive(Debug, Clone)]
|
|
pub struct CameraMetadata {
|
|
/// Camera identifier
|
|
pub camera_id: String,
|
|
/// Camera type (e.g. hardware backend or video file)
|
|
pub camera_type: String,
|
|
/// Supported frame formats
|
|
pub supported_formats: Vec<FrameFormat>,
|
|
/// Maximum resolution
|
|
pub max_resolution: (u32, u32),
|
|
/// Current resolution
|
|
pub current_resolution: (u32, u32),
|
|
/// Target frames per second
|
|
pub target_fps: f64,
|
|
/// Whether the camera supports real-time capture
|
|
pub is_real_time: bool,
|
|
/// Total frames available (None for continuous streams)
|
|
pub total_frames: Option<u64>,
|
|
}
|
|
|
|
/// Per-frame metadata
|
|
#[derive(Debug, Clone)]
|
|
pub struct FrameMetadata {
|
|
/// Exposure settings (if applicable)
|
|
pub exposure_ms: Option<f64>,
|
|
/// Gain settings (if applicable)
|
|
pub gain: Option<f64>,
|
|
/// Temperature readings (if available)
|
|
pub temperature_celsius: Option<f64>,
|
|
/// Any camera-specific properties
|
|
pub properties: std::collections::HashMap<String, String>,
|
|
}
|
|
|
|
/// Camera configuration that works for both hardware and video sources
|
|
#[derive(Debug, Clone)]
|
|
pub struct CameraConfig {
|
|
/// Type of camera to create
|
|
pub camera_type: CameraType,
|
|
/// Target resolution
|
|
pub resolution: (u32, u32),
|
|
/// Target frame rate
|
|
pub fps: f64,
|
|
/// Additional camera-specific settings
|
|
pub settings: std::collections::HashMap<String, String>,
|
|
}
|
|
|
|
/// Enum defining camera types (device or video file)
|
|
#[derive(Debug, Clone)]
|
|
pub enum CameraType {
|
|
/// Production hardware camera
|
|
Production {
|
|
/// Device index or identifier
|
|
device_id: String,
|
|
/// Hardware-specific backend
|
|
backend: String,
|
|
},
|
|
/// Video file camera configuration
|
|
VideoFile {
|
|
/// Absolute video file path
|
|
path: PathBuf,
|
|
/// Whether to loop playback when reaching the end
|
|
loop_playback: bool,
|
|
/// Playback speed multiplier (1.0 = realtime)
|
|
playback_speed: f64,
|
|
},
|
|
}
|
|
|
|
impl Default for CameraConfig {
|
|
fn default() -> Self {
|
|
Self {
|
|
camera_type: CameraType::Production {
|
|
device_id: "0".to_string(),
|
|
backend: "default".to_string(),
|
|
},
|
|
resolution: (1280, 720),
|
|
fps: 30.0,
|
|
settings: std::collections::HashMap::new(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl CapturedFrame {
|
|
/// Create a new captured frame
|
|
pub fn new(
|
|
data: Arc<FrameData>,
|
|
frame_number: u64,
|
|
capture_timestamp: DateTime<Utc>,
|
|
metadata: FrameMetadata,
|
|
) -> Self {
|
|
Self {
|
|
data,
|
|
frame_number,
|
|
capture_timestamp,
|
|
metadata,
|
|
}
|
|
}
|
|
|
|
/// Get frame dimensions
|
|
pub fn dimensions(&self) -> (u32, u32) {
|
|
(self.data.width, self.data.height)
|
|
}
|
|
|
|
/// Get frame data size in bytes
|
|
pub fn data_size(&self) -> usize {
|
|
self.data.data.len()
|
|
}
|
|
}
|
|
|
|
impl Default for FrameMetadata {
|
|
fn default() -> Self {
|
|
Self {
|
|
exposure_ms: None,
|
|
gain: None,
|
|
temperature_celsius: None,
|
|
properties: std::collections::HashMap::new(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl CameraMetadata {
|
|
/// Create minimal camera metadata
|
|
pub fn new(camera_id: String, camera_type: String) -> Self {
|
|
Self {
|
|
camera_id,
|
|
camera_type,
|
|
supported_formats: vec![FrameFormat::JPEG],
|
|
max_resolution: (1920, 1080),
|
|
current_resolution: (1280, 720),
|
|
target_fps: 30.0,
|
|
is_real_time: true,
|
|
total_frames: None,
|
|
}
|
|
}
|
|
}
|