@@ -415,7 +415,7 @@ struct Slot {
415415 switcher : Switcher ,
416416 state : Option < SlotState > ,
417417 switching_started_at : Option < Instant > ,
418- keyframe_req_count : u32 ,
418+ keyframe_retries : usize ,
419419 waker : Option < Waker > ,
420420}
421421
@@ -427,7 +427,7 @@ impl Slot {
427427 switcher : Switcher :: new ( rtp:: VIDEO_FREQUENCY ) ,
428428 state : Some ( SlotState :: Idle ) ,
429429 switching_started_at : None ,
430- keyframe_req_count : 0 ,
430+ keyframe_retries : 0 ,
431431 waker : None ,
432432 }
433433 }
@@ -472,7 +472,7 @@ impl Slot {
472472 receiver. channel . reset ( ) ;
473473 receiver. request_keyframe ( KeyframeRequestKind :: Fir ) ;
474474 self . switching_started_at = Some ( Instant :: now ( ) ) ;
475- self . keyframe_req_count = 1 ;
475+ self . keyframe_retries = 0 ;
476476
477477 tracing:: info!(
478478 mid = %self . mid,
@@ -549,32 +549,45 @@ impl Slot {
549549 }
550550
551551 fn poll_slow ( & mut self , now : Instant ) {
552+ const KEYFRAME_RETRY_DELAYS_MS : [ u64 ; 4 ] = [ 500 , 1000 , 2000 , 4000 ] ;
553+
554+ // Chrome shares keyframe request throttling for all simulcast streams &
555+ // Our keyframe request might get lost in the middle. Retry some to at least
556+ // reduce the probability to miss the keyframe.
552557 let Some ( started_at) = self . switching_started_at else {
553558 return ;
554559 } ;
555560
556- if self . keyframe_req_count >= 5 {
561+ if self . keyframe_retries >= KEYFRAME_RETRY_DELAYS_MS . len ( ) {
557562 return ;
558563 }
559564
560- let deadline = started_at + Duration :: from_secs ( 1 ) * self . keyframe_req_count ;
565+ let current_delay_ms = KEYFRAME_RETRY_DELAYS_MS [ self . keyframe_retries ] ;
566+ let deadline = started_at + Duration :: from_millis ( current_delay_ms) ;
561567 if deadline > now {
562568 return ;
563569 }
564570
565- self . keyframe_req_count += 1 ;
566- let Some ( receiver) = self . target_receiver ( ) else {
567- return ;
568- } ;
569- receiver. request_keyframe ( KeyframeRequestKind :: Fir ) ;
571+ self . keyframe_retries += 1 ;
572+ if let Some ( receiver) = self . target_receiver ( ) {
573+ tracing:: warn!(
574+ receiver = %receiver,
575+ "Switch slow. Retrying keyframe request (attempt {}/{}). Elapsed: {:?}" ,
576+ self . keyframe_retries,
577+ KEYFRAME_RETRY_DELAYS_MS . len( ) ,
578+ now. duration_since( started_at)
579+ ) ;
580+
581+ receiver. request_keyframe ( KeyframeRequestKind :: Fir ) ;
582+ }
570583 }
571584
572585 #[ inline]
573586 fn transition_to ( & mut self , new_state : SlotState ) {
574587 match & new_state {
575588 SlotState :: Streaming { .. } => {
576589 self . switching_started_at = None ;
577- self . keyframe_req_count = 0 ;
590+ self . keyframe_retries = 0 ;
578591 }
579592 _ => { }
580593 }
0 commit comments