use std::fmt;
use std::sync::Arc;
use super::output::QualityInfo;
pub const DEFAULT_LIVE_JOIN_FRAGMENTS: usize = 2;
pub const DEFAULT_MAX_FRAGMENT_FAILURES: u32 = 5;
pub const DEFAULT_MAX_MANIFEST_FAILURES: u32 = 5;
pub const DEFAULT_MAX_REFRESH_MISSES: u32 = 5;
pub const DEFAULT_BACKOFF_MS: [u64; 4] = [250, 500, 1_000, 2_000];
pub const DEFAULT_BACKOFF_CAP_MS: u64 = 4_000;
pub const DEFAULT_JITTER_SEED: u64 = 0;
pub const DEFAULT_REFRESH_MIN_US: u64 = 500_000;
pub const DEFAULT_REFRESH_MAX_US: u64 = 5_000_000;
pub const SYNTHETIC_MOVIE_TIMESCALE: u32 = 90_000;
type SelectFn = dyn Fn(&[QualityInfo]) -> usize + Send + Sync;
#[derive(Clone)]
pub struct QualitySelector(Arc<SelectFn>);
impl QualitySelector {
pub fn new(f: impl Fn(&[QualityInfo]) -> usize + Send + Sync + 'static) -> Self {
Self(Arc::new(f))
}
pub fn first() -> Self {
Self::new(|_| 0)
}
pub(crate) fn choose(&self, qualities: &[QualityInfo]) -> usize {
(self.0)(qualities).min(qualities.len().saturating_sub(1))
}
}
impl fmt::Debug for QualitySelector {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str("QualitySelector(..)")
}
}
#[derive(Debug, Clone)]
#[non_exhaustive]
pub struct SmoothConfig {
pub live_join_fragments: usize,
pub max_fragment_failures: u32,
pub max_manifest_failures: u32,
pub max_refresh_misses: u32,
pub backoff_ms: Vec<u64>,
pub backoff_cap_ms: u64,
pub jitter_seed: u64,
pub refresh_min_us: u64,
pub refresh_max_us: u64,
pub video_quality: QualitySelector,
}
impl Default for SmoothConfig {
fn default() -> Self {
Self {
live_join_fragments: DEFAULT_LIVE_JOIN_FRAGMENTS,
max_fragment_failures: DEFAULT_MAX_FRAGMENT_FAILURES,
max_manifest_failures: DEFAULT_MAX_MANIFEST_FAILURES,
max_refresh_misses: DEFAULT_MAX_REFRESH_MISSES,
backoff_ms: DEFAULT_BACKOFF_MS.to_vec(),
backoff_cap_ms: DEFAULT_BACKOFF_CAP_MS,
jitter_seed: DEFAULT_JITTER_SEED,
refresh_min_us: DEFAULT_REFRESH_MIN_US,
refresh_max_us: DEFAULT_REFRESH_MAX_US,
video_quality: QualitySelector::first(),
}
}
}
impl SmoothConfig {
#[must_use]
pub fn with_live_join_fragments(mut self, live_join_fragments: usize) -> Self {
self.live_join_fragments = live_join_fragments;
self
}
#[must_use]
pub fn with_max_fragment_failures(mut self, max_fragment_failures: u32) -> Self {
self.max_fragment_failures = max_fragment_failures;
self
}
#[must_use]
pub fn with_max_manifest_failures(mut self, max_manifest_failures: u32) -> Self {
self.max_manifest_failures = max_manifest_failures;
self
}
#[must_use]
pub fn with_max_refresh_misses(mut self, max_refresh_misses: u32) -> Self {
self.max_refresh_misses = max_refresh_misses;
self
}
#[must_use]
pub fn with_backoff_ms(mut self, backoff_ms: Vec<u64>) -> Self {
self.backoff_ms = backoff_ms;
self
}
#[must_use]
pub fn with_backoff_cap_ms(mut self, backoff_cap_ms: u64) -> Self {
self.backoff_cap_ms = backoff_cap_ms;
self
}
#[must_use]
pub fn with_jitter_seed(mut self, jitter_seed: u64) -> Self {
self.jitter_seed = jitter_seed;
self
}
#[must_use]
pub fn with_refresh_min_us(mut self, refresh_min_us: u64) -> Self {
self.refresh_min_us = refresh_min_us;
self
}
#[must_use]
pub fn with_refresh_max_us(mut self, refresh_max_us: u64) -> Self {
self.refresh_max_us = refresh_max_us;
self
}
#[must_use]
pub fn with_video_quality(mut self, video_quality: QualitySelector) -> Self {
self.video_quality = video_quality;
self
}
}