smooth_runtime/client/
config.rs1use std::fmt;
4use std::sync::Arc;
5
6use super::output::QualityInfo;
7
8pub const DEFAULT_LIVE_JOIN_FRAGMENTS: usize = 2;
10pub const DEFAULT_MAX_FRAGMENT_FAILURES: u32 = 5;
13pub const DEFAULT_MAX_MANIFEST_FAILURES: u32 = 5;
15pub const DEFAULT_MAX_REFRESH_MISSES: u32 = 5;
17pub const DEFAULT_BACKOFF_MS: [u64; 4] = [250, 500, 1_000, 2_000];
19pub const DEFAULT_BACKOFF_CAP_MS: u64 = 4_000;
21pub const DEFAULT_JITTER_SEED: u64 = 0;
23pub const DEFAULT_REFRESH_MIN_US: u64 = 500_000;
25pub const DEFAULT_REFRESH_MAX_US: u64 = 5_000_000;
27pub const SYNTHETIC_MOVIE_TIMESCALE: u32 = 90_000;
29
30type SelectFn = dyn Fn(&[QualityInfo]) -> usize + Send + Sync;
31
32#[derive(Clone)]
34pub struct QualitySelector(Arc<SelectFn>);
35
36impl QualitySelector {
37 pub fn new(f: impl Fn(&[QualityInfo]) -> usize + Send + Sync + 'static) -> Self {
39 Self(Arc::new(f))
40 }
41
42 pub fn first() -> Self {
44 Self::new(|_| 0)
45 }
46
47 pub(crate) fn choose(&self, qualities: &[QualityInfo]) -> usize {
48 (self.0)(qualities).min(qualities.len().saturating_sub(1))
49 }
50}
51
52impl fmt::Debug for QualitySelector {
53 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
54 f.write_str("QualitySelector(..)")
55 }
56}
57
58#[derive(Debug, Clone)]
61#[non_exhaustive]
62pub struct SmoothConfig {
63 pub live_join_fragments: usize,
65 pub max_fragment_failures: u32,
67 pub max_manifest_failures: u32,
69 pub max_refresh_misses: u32,
71 pub backoff_ms: Vec<u64>,
73 pub backoff_cap_ms: u64,
75 pub jitter_seed: u64,
81 pub refresh_min_us: u64,
83 pub refresh_max_us: u64,
85 pub video_quality: QualitySelector,
87}
88
89impl Default for SmoothConfig {
90 fn default() -> Self {
91 Self {
92 live_join_fragments: DEFAULT_LIVE_JOIN_FRAGMENTS,
93 max_fragment_failures: DEFAULT_MAX_FRAGMENT_FAILURES,
94 max_manifest_failures: DEFAULT_MAX_MANIFEST_FAILURES,
95 max_refresh_misses: DEFAULT_MAX_REFRESH_MISSES,
96 backoff_ms: DEFAULT_BACKOFF_MS.to_vec(),
97 backoff_cap_ms: DEFAULT_BACKOFF_CAP_MS,
98 jitter_seed: DEFAULT_JITTER_SEED,
99 refresh_min_us: DEFAULT_REFRESH_MIN_US,
100 refresh_max_us: DEFAULT_REFRESH_MAX_US,
101 video_quality: QualitySelector::first(),
102 }
103 }
104}
105
106impl SmoothConfig {
107 #[must_use]
109 pub fn with_live_join_fragments(mut self, live_join_fragments: usize) -> Self {
110 self.live_join_fragments = live_join_fragments;
111 self
112 }
113
114 #[must_use]
116 pub fn with_max_fragment_failures(mut self, max_fragment_failures: u32) -> Self {
117 self.max_fragment_failures = max_fragment_failures;
118 self
119 }
120
121 #[must_use]
123 pub fn with_max_manifest_failures(mut self, max_manifest_failures: u32) -> Self {
124 self.max_manifest_failures = max_manifest_failures;
125 self
126 }
127
128 #[must_use]
130 pub fn with_max_refresh_misses(mut self, max_refresh_misses: u32) -> Self {
131 self.max_refresh_misses = max_refresh_misses;
132 self
133 }
134
135 #[must_use]
137 pub fn with_backoff_ms(mut self, backoff_ms: Vec<u64>) -> Self {
138 self.backoff_ms = backoff_ms;
139 self
140 }
141
142 #[must_use]
144 pub fn with_backoff_cap_ms(mut self, backoff_cap_ms: u64) -> Self {
145 self.backoff_cap_ms = backoff_cap_ms;
146 self
147 }
148
149 #[must_use]
151 pub fn with_jitter_seed(mut self, jitter_seed: u64) -> Self {
152 self.jitter_seed = jitter_seed;
153 self
154 }
155
156 #[must_use]
158 pub fn with_refresh_min_us(mut self, refresh_min_us: u64) -> Self {
159 self.refresh_min_us = refresh_min_us;
160 self
161 }
162
163 #[must_use]
165 pub fn with_refresh_max_us(mut self, refresh_max_us: u64) -> Self {
166 self.refresh_max_us = refresh_max_us;
167 self
168 }
169
170 #[must_use]
172 pub fn with_video_quality(mut self, video_quality: QualitySelector) -> Self {
173 self.video_quality = video_quality;
174 self
175 }
176}