use bytes::Bytes;
use std::sync::Arc;
use std::time::Duration;
use thiserror::Error;
#[cfg(target_os = "macos")]
pub mod mac_source;
#[cfg(target_os = "macos")]
pub mod mac_encoder;
pub mod webrtc_streamer;
pub mod raw_udp_streamer;
#[derive(Error, Debug)]
pub enum StreamError {
#[error("Erreur de capture vidéo: {0}")]
CaptureError(String),
#[error("Erreur d'encodage vidéo: {0}")]
EncodeError(String),
#[error("Erreur réseau: {0}")]
NetworkError(String),
#[error("Erreur interne: {0}")]
Internal(#[from] anyhow::Error),
}
pub type Result<T> = std::result::Result<T, StreamError>;
#[derive(Debug, Clone, Copy)]
pub struct FrameMetadata {
pub width: u32,
pub height: u32,
pub presentation_timestamp: u64,
pub is_keyframe: bool,
}
pub enum FramePayload {
HardwareBuffer(Arc<dyn std::any::Any + Send + Sync>),
MemoryBuffer(Bytes),
}
pub struct Frame {
pub metadata: FrameMetadata,
pub payload: FramePayload,
}
#[derive(Debug, Clone)]
pub struct EncodedPacket {
pub data: Bytes,
pub pts_micros: u64,
pub duration_micros: u64,
pub is_keyframe: bool,
}
impl EncodedPacket {
pub fn duration(&self) -> Duration {
if self.duration_micros > 0 {
Duration::from_micros(self.duration_micros)
} else {
Duration::from_nanos(1_000_000_000 / 60)
}
}
}
#[derive(Debug, Clone)]
pub struct StreamConfig {
pub target_addr: String,
pub max_bandwidth_bps: u32,
pub drop_on_congestion: bool,
pub request_keyframe: Option<std::sync::Arc<std::sync::atomic::AtomicBool>>,
}
impl Default for StreamConfig {
fn default() -> Self {
Self {
target_addr: String::new(),
max_bandwidth_bps: 15_000_000,
drop_on_congestion: true,
request_keyframe: None,
}
}
}
#[derive(Debug, Default, Clone, Copy)]
pub struct StreamerStats {
pub packets_sent: u64,
pub packets_dropped: u64,
pub estimated_rtt_ms: Option<f32>,
}
pub trait VideoSource: Send + Sync {
fn start_capture(&mut self) -> impl std::future::Future<Output = Result<()>> + Send;
fn next_frame(&mut self) -> impl std::future::Future<Output = Result<Frame>> + Send;
fn stop_capture(&mut self) -> impl std::future::Future<Output = Result<()>> + Send;
}
pub trait VideoEncoder: Send + Sync {
fn configure(&mut self, width: u32, height: u32, bitrate: u32) -> Result<()>;
fn encode(&mut self, frame: Frame) -> Result<()>;
}
pub trait NetworkStreamer: Send + Sync {
fn backend_name(&self) -> &'static str;
fn connect(&mut self, cfg: StreamConfig)
-> impl std::future::Future<Output = Result<()>> + Send;
fn send_packet(&mut self, packet: EncodedPacket)
-> impl std::future::Future<Output = Result<()>> + Send;
fn stats(&self) -> StreamerStats;
fn disconnect(&mut self)
-> impl std::future::Future<Output = Result<()>> + Send;
}