@@ -17,6 +17,7 @@ const BOLA_MIN_LOW_BUFFER: f64 = 3.0;
1717const BOLA_MAX_LOW_BUFFER : f64 = 10.0 ;
1818const ABANDON_MIN_PROGRESS_DURATION_MS : f64 = 500.0 ;
1919const ABANDON_MIN_PROGRESS_SAMPLES : u32 = 3 ;
20+ const ABANDON_MIN_REPLACEMENT_GAIN_S : f64 = 0.25 ;
2021
2122impl AdaptiveQualitySelector {
2223 /// Creates new `AdaptiveQualitySelector`.
@@ -113,11 +114,24 @@ impl AdaptiveQualitySelector {
113114 pending_bytes_total : Option < u32 > ,
114115 progress_duration_ms : f64 ,
115116 progress_samples : u32 ,
116- buffer_level : f64 ,
117+ playback_rate : f64 ,
118+ segment_duration : Option < f64 > ,
119+ buffer_starvation_delay : f64 ,
117120 ) -> bool {
121+ if !playback_rate. is_finite ( ) || playback_rate <= 0. || buffer_starvation_delay <= 0. {
122+ return false ;
123+ }
124+
125+ let min_progress_duration_ms = segment_duration
126+ . filter ( |duration| duration. is_finite ( ) && * duration > 0. )
127+ . map ( |duration| 1000. * ( duration / ( playback_rate * 2. ) ) )
128+ . filter ( |duration| duration. is_finite ( ) && * duration > 0. )
129+ . map ( |duration| duration. max ( ABANDON_MIN_PROGRESS_DURATION_MS ) )
130+ . unwrap_or ( ABANDON_MIN_PROGRESS_DURATION_MS ) ;
131+
118132 if !pending_quality. is_better_than ( desired_quality)
119133 || desired_variant_bandwidth >= pending_variant_bandwidth
120- || progress_duration_ms < ABANDON_MIN_PROGRESS_DURATION_MS
134+ || progress_duration_ms < min_progress_duration_ms
121135 || progress_samples < ABANDON_MIN_PROGRESS_SAMPLES
122136 {
123137 return false ;
@@ -145,8 +159,9 @@ impl AdaptiveQualitySelector {
145159 let remaining_download_time = ( remaining_bytes as f64 ) * 8. / measured_bandwidth;
146160 let replacement_download_time = replacement_total_bytes * 8. / measured_bandwidth;
147161
148- remaining_download_time > buffer_level
149- && replacement_download_time + 0.25 < remaining_download_time
162+ remaining_download_time > buffer_starvation_delay
163+ && replacement_download_time < buffer_starvation_delay
164+ && replacement_download_time + ABANDON_MIN_REPLACEMENT_GAIN_S < remaining_download_time
150165 }
151166
152167 pub ( crate ) fn reset ( & mut self ) {
@@ -232,3 +247,72 @@ fn compute_bola_variant_id(
232247 } )
233248 . map ( |( variant, _) | variant. id ( ) )
234249}
250+
251+ #[ cfg( test) ]
252+ mod tests {
253+ use super :: AdaptiveQualitySelector ;
254+ use crate :: media_element:: SegmentQualityContext ;
255+
256+ #[ test]
257+ fn does_not_abandon_before_half_a_segment_elapsed ( ) {
258+ let selector = AdaptiveQualitySelector :: new ( 5_000_000. ) ;
259+ let pending_quality = SegmentQualityContext :: new ( 2. , 10 ) ;
260+ let desired_quality = SegmentQualityContext :: new ( 1. , 11 ) ;
261+
262+ assert ! ( !selector. should_abandon_media_request(
263+ & pending_quality,
264+ & desired_quality,
265+ 4_000_000 ,
266+ 2_000_000 ,
267+ 400_000 ,
268+ Some ( 1_000_000 ) ,
269+ 1_900. ,
270+ 4 ,
271+ 1. ,
272+ Some ( 4. ) ,
273+ 3. ,
274+ ) ) ;
275+ }
276+
277+ #[ test]
278+ fn abandons_when_replacement_beats_starvation_and_remaining_time ( ) {
279+ let selector = AdaptiveQualitySelector :: new ( 5_000_000. ) ;
280+ let pending_quality = SegmentQualityContext :: new ( 2. , 10 ) ;
281+ let desired_quality = SegmentQualityContext :: new ( 1. , 11 ) ;
282+
283+ assert ! ( selector. should_abandon_media_request(
284+ & pending_quality,
285+ & desired_quality,
286+ 4_000_000 ,
287+ 1_000_000 ,
288+ 250_000 ,
289+ Some ( 1_000_000 ) ,
290+ 2_100. ,
291+ 4 ,
292+ 1. ,
293+ Some ( 4. ) ,
294+ 3. ,
295+ ) ) ;
296+ }
297+
298+ #[ test]
299+ fn does_not_abandon_when_replacement_would_miss_starvation_deadline ( ) {
300+ let selector = AdaptiveQualitySelector :: new ( 5_000_000. ) ;
301+ let pending_quality = SegmentQualityContext :: new ( 2. , 10 ) ;
302+ let desired_quality = SegmentQualityContext :: new ( 1. , 11 ) ;
303+
304+ assert ! ( !selector. should_abandon_media_request(
305+ & pending_quality,
306+ & desired_quality,
307+ 4_000_000 ,
308+ 2_000_000 ,
309+ 250_000 ,
310+ Some ( 1_000_000 ) ,
311+ 2_100. ,
312+ 4 ,
313+ 1. ,
314+ Some ( 4. ) ,
315+ 1.8 ,
316+ ) ) ;
317+ }
318+ }
0 commit comments