mecha10-video 0.1.25

WebRTC video streaming for Mecha10 - camera frame capture and broadcasting
Documentation
/// Frame types for camera streaming
///
/// Provides shared types for camera frames that can be used across
/// WebRTC streaming, Redis pub/sub, and other video processing pipelines.
use anyhow::Result;
use std::sync::Arc;
use tokio::sync::broadcast;

/// Image format for camera data
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ImageFormat {
    /// JPEG-compressed image
    Jpeg,
    /// Raw RGB pixels (width × height × 3 bytes)
    Rgb,
}

/// Camera frame received from source (Godot, physical camera, etc.)
///
/// Uses Arc<Vec<u8>> for image_bytes to enable zero-copy sharing across:
/// - Broadcast channel (multiple WebRTC subscribers)
/// - Encoder thread
/// - Redis publishing
#[derive(Debug, Clone)]
pub struct CameraFrame {
    pub camera_id: String,
    pub width: u32,
    pub height: u32,
    pub timestamp: u64,
    /// Image bytes (JPEG or RGB depending on format)
    /// Wrapped in Arc for zero-copy sharing between subscribers
    pub image_bytes: Arc<Vec<u8>>,
    /// Image format
    pub format: ImageFormat,
}

/// Frame broadcaster that distributes frames to multiple connections
///
/// Uses tokio broadcast channel to efficiently distribute frames
/// to multiple WebRTC connections without copying frame data.
pub struct FrameBroadcaster {
    tx: broadcast::Sender<CameraFrame>,
}

impl FrameBroadcaster {
    /// Create a new frame broadcaster
    ///
    /// # Arguments
    /// * `capacity` - Channel capacity (use 1 for minimal latency)
    pub fn new(capacity: usize) -> Self {
        let (tx, _) = broadcast::channel(capacity);
        Self { tx }
    }

    /// Broadcast a frame to all subscribers
    ///
    /// Returns Ok even if there are no receivers (expected during startup).
    pub fn broadcast(&self, frame: CameraFrame) -> Result<()> {
        // Send returns error if there are no receivers, which is fine
        let _ = self.tx.send(frame);
        Ok(())
    }

    /// Subscribe to receive frames
    ///
    /// Returns a new receiver that will get all future frames.
    /// Multiple subscribers can exist simultaneously.
    pub fn subscribe(&self) -> broadcast::Receiver<CameraFrame> {
        self.tx.subscribe()
    }
}