2025-11-03 00:11:13 +08:00

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,
}
}
}