@@ -509,6 +509,7 @@ @implementation XCWH264Encoder {
509509 BOOL _scalingActive;
510510 XCWVideoEncoderMode _encoderMode;
511511 XCWVideoEncoderMode _activeEncoderMode;
512+ BOOL _clientForeground;
512513 BOOL _lowLatencyMode;
513514 BOOL _realtimeStreamMode;
514515 CMVideoCodecType _codecType;
@@ -559,6 +560,7 @@ - (instancetype)initWithOutputHandler:(XCWH264EncoderOutputHandler)outputHandler
559560 _needsKeyFrame = YES ;
560561 _encoderMode = XCWVideoEncoderModeFromEnvironment ();
561562 _activeEncoderMode = _encoderMode;
563+ _clientForeground = YES ;
562564 _lowLatencyMode = (_encoderMode == XCWVideoEncoderModeH264Software) && XCWLowLatencyModeFromEnvironment ();
563565 _realtimeStreamMode = XCWRealtimeStreamModeFromEnvironment () || _lowLatencyMode;
564566 _codecType = XCWVideoCodecTypeForMode (_activeEncoderMode);
@@ -621,6 +623,17 @@ - (void)reconfigureForStreamQualityChange {
621623 self->_hardwareFrameIntervalUs = [self initialHardwareFrameIntervalUsLocked ];
622624 self->_hardwarePacedFrameCount = 0 ;
623625 self->_autoSoftwareFallbackUntilUs = 0 ;
626+ [self updateActiveEncoderModeForClientForegroundLockedAtTimeUs: (uint64_t )(CACurrentMediaTime () * 1000000.0 )];
627+ });
628+ }
629+
630+ - (void )setClientForeground : (BOOL )foreground {
631+ dispatch_async (_queue, ^{
632+ if (self->_clientForeground == foreground) {
633+ return ;
634+ }
635+ self->_clientForeground = foreground;
636+ [self updateActiveEncoderModeForClientForegroundLockedAtTimeUs: (uint64_t )(CACurrentMediaTime () * 1000000.0 )];
624637 });
625638}
626639
@@ -699,6 +712,7 @@ - (NSDictionary *)statsRepresentation {
699712 @" transportCodec" : XCWCodecName (self->_codecType ),
700713 @" encoderMode" : XCWVideoEncoderModeName (self->_encoderMode ),
701714 @" activeEncoderMode" : XCWVideoEncoderModeName (self->_activeEncoderMode ),
715+ @" clientForeground" : @(self->_clientForeground ),
702716 @" autoSoftwareFallbackActive" : @(autoSoftwareFallbackActive),
703717 @" autoSoftwareFallbackRemainingUs" : @(autoSoftwareFallbackRemainingUs),
704718 @" autoSoftwareFallbacks" : @(self->_autoSoftwareFallbackCount ),
@@ -781,6 +795,7 @@ - (uint64_t)initialHardwareFrameIntervalUsLocked {
781795
782796- (BOOL )isAutoSoftwareFallbackActiveLocked {
783797 return _encoderMode == XCWVideoEncoderModeAuto &&
798+ _autoSoftwareFallbackUntilUs != 0 &&
784799 _activeEncoderMode == XCWVideoEncoderModeH264Software;
785800}
786801
@@ -793,38 +808,63 @@ - (void)resetAutoFallbackLatencyStateLocked {
793808 _wasOverloaded = NO ;
794809}
795810
811+ - (void )switchActiveEncoderModeLocked : (XCWVideoEncoderMode)mode {
812+ if (_activeEncoderMode == mode) {
813+ return ;
814+ }
815+ _activeEncoderMode = mode;
816+ _codecType = XCWVideoCodecTypeForMode (_activeEncoderMode);
817+ if (_activeEncoderMode == XCWVideoEncoderModeH264Software) {
818+ _softwareFrameIntervalUs = [self initialSoftwareFrameIntervalUsLocked ];
819+ _softwareHealthyFrameCount = 0 ;
820+ _softwarePacedFrameCount = 0 ;
821+ } else {
822+ _hardwareFrameIntervalUs = [self initialHardwareFrameIntervalUsLocked ];
823+ _hardwarePacedFrameCount = 0 ;
824+ }
825+ [self invalidateCompressionSessionLocked ];
826+ [self resetAutoFallbackLatencyStateLocked ];
827+ _needsKeyFrame = YES ;
828+ }
829+
830+ - (void )updateActiveEncoderModeForClientForegroundLockedAtTimeUs : (uint64_t )nowUs {
831+ if (!_clientForeground) {
832+ [self switchActiveEncoderModeLocked: XCWVideoEncoderModeH264Software];
833+ return ;
834+ }
835+ if (_encoderMode == XCWVideoEncoderModeAuto &&
836+ _autoSoftwareFallbackUntilUs != 0 &&
837+ nowUs < _autoSoftwareFallbackUntilUs) {
838+ [self switchActiveEncoderModeLocked: XCWVideoEncoderModeH264Software];
839+ return ;
840+ }
841+ if (_encoderMode == XCWVideoEncoderModeAuto && _autoSoftwareFallbackUntilUs != 0 ) {
842+ _autoSoftwareFallbackUntilUs = 0 ;
843+ _autoHardwareRetryCount += 1 ;
844+ }
845+ [self switchActiveEncoderModeLocked: _encoderMode];
846+ }
847+
796848- (void )enterAutoSoftwareFallbackLockedAtTimeUs : (uint64_t )nowUs {
797849 if (_encoderMode != XCWVideoEncoderModeAuto ||
798850 _activeEncoderMode == XCWVideoEncoderModeH264Software) {
799851 return ;
800852 }
801- _activeEncoderMode = XCWVideoEncoderModeH264Software;
802- _codecType = XCWVideoCodecTypeForMode (_activeEncoderMode);
803853 _autoSoftwareFallbackUntilUs = nowUs + XCWAutoHardwareRetryIntervalUs;
804854 _autoSoftwareFallbackCount += 1 ;
805- _softwareFrameIntervalUs = [self initialSoftwareFrameIntervalUsLocked ];
806- _softwareHealthyFrameCount = 0 ;
807- _softwarePacedFrameCount = 0 ;
808- [self invalidateCompressionSessionLocked ];
809- [self resetAutoFallbackLatencyStateLocked ];
810- _needsKeyFrame = YES ;
855+ [self switchActiveEncoderModeLocked: XCWVideoEncoderModeH264Software];
811856}
812857
813858- (void )retryAutoHardwareIfNeededLockedAtTimeUs : (uint64_t )nowUs {
814859 if (![self isAutoSoftwareFallbackActiveLocked ] ||
860+ !_clientForeground ||
815861 _autoSoftwareFallbackUntilUs == 0 ||
816862 nowUs < _autoSoftwareFallbackUntilUs) {
817863 return ;
818864 }
819- _activeEncoderMode = XCWVideoEncoderModeAuto;
820- _codecType = XCWVideoCodecTypeForMode (_activeEncoderMode);
821865 _autoSoftwareFallbackUntilUs = 0 ;
822866 _autoHardwareRetryCount += 1 ;
823- _hardwareFrameIntervalUs = [self initialHardwareFrameIntervalUsLocked ];
824- _hardwarePacedFrameCount = 0 ;
825- [self invalidateCompressionSessionLocked ];
826- [self resetAutoFallbackLatencyStateLocked ];
827- _needsKeyFrame = YES ;
867+ [self switchActiveEncoderModeLocked: XCWVideoEncoderModeAuto];
828868}
829869
830870- (uint64_t )activeFrameIntervalUsLocked {
0 commit comments