📄 rig/src/source.rs
//! The frame-source abstractions shared by live capture, replay, and
//! synthetic generation.
//!
//! Two stages, two traits:
//!
//! * [`DepthSource`] emits raw depth frames (millimetre depth maps plus
//!   RGB, as a Kinect reports them) — capture, recordings, and the
//!   synthetic dataset all speak this;
//! * [`FrameSource`] emits processed frames carrying the assembled
//!   [`SplatBatch`] — what the renderer and sinks consume. `splatgen`
//!   bridges the two.

use anyhow::Result;

use crate::camera::Camera;
use crate::splat::SplatBatch;

/// One processed rig frame, ready for rendering.
///
/// In the MVP (and the synthetic dataset) a frame is simply the freshly
/// constructed Gaussian list; recorded RGB/depth data rides along from
/// build-order step 2 on.
#[derive(Debug, Clone, PartialEq)]
pub struct Frame {
    /// Frame timestamp in seconds since the source started. Synthetic
    /// sources use deterministic timestamps (frame index / fps).
    pub timestamp_secs: f64,
    pub splats: SplatBatch,
}

/// A source of processed rig frames — the seam where live capture, replay
/// of recorded datasets, and synthetic generation are interchangeable.
///
/// Implementations must be deterministic when replaying: the same frame
/// sequence every run, so tests and recordings behave identically.
pub trait FrameSource {
    fn next_frame(&mut self) -> Result<Frame>;
}

/// One raw depth-camera frame, as the sensors report it.
#[derive(Debug, Clone, PartialEq)]
pub struct DepthFrame {
    /// Frame timestamp in seconds since the source started.
    pub timestamp_secs: f64,
    /// Depth in millimetres, row-major, `width * height` at the depth
    /// camera's resolution. Zero marks an invalid pixel (no return),
    /// like the Kinect reports.
    pub depth_mm: Vec<u16>,
    /// RGB, 3 bytes per pixel, row-major, same resolution.
    pub rgb: Vec<u8>,
}

/// A source of raw depth frames: the seam where live capture, replay of
/// recordings, and the synthetic dataset are interchangeable.
///
/// Implementations must be deterministic when replaying.
pub trait DepthSource {
    /// The depth camera the frames come from (intrinsics, pose,
    /// resolution).
    fn camera(&self) -> &Camera;
    fn next_depth_frame(&mut self) -> Result<DepthFrame>;
}