2121
2222static const NSUInteger MAX_FPS = 60 ;
2323static const NSTimeInterval FRAME_TIMEOUT = 1 .;
24+ static const NSTimeInterval FAILURE_BACKOFF_MIN = 1.0 ;
25+ static const NSTimeInterval FAILURE_BACKOFF_MAX = 10.0 ;
2426
2527static NSString *const SERVER_NAME = @" WDA MJPEG Server" ;
2628static const char *QUEUE_NAME = " JPEG Screenshots Provider Queue" ;
@@ -32,6 +34,7 @@ @interface FBMjpegServer()
3234@property (nonatomic , readonly ) NSMutableArray <GCDAsyncSocket *> *listeningClients;
3335@property (nonatomic , readonly ) FBImageProcessor *imageProcessor;
3436@property (nonatomic , readonly ) long long mainScreenID;
37+ @property (nonatomic , assign ) NSUInteger consecutiveScreenshotFailures;
3538
3639@end
3740
@@ -41,6 +44,7 @@ @implementation FBMjpegServer
4144- (instancetype )init
4245{
4346 if ((self = [super init ])) {
47+ _consecutiveScreenshotFailures = 0 ;
4448 _listeningClients = [NSMutableArray array ];
4549 dispatch_queue_attr_t queueAttributes = dispatch_queue_attr_make_with_qos_class (DISPATCH_QUEUE_SERIAL, QOS_CLASS_UTILITY, 0 );
4650 _backgroundQueue = dispatch_queue_create (QUEUE_NAME, queueAttributes);
@@ -91,10 +95,16 @@ - (void)streamScreenshot
9195 error: &error];
9296 if (nil == screenshotData) {
9397 [FBLogger logFmt: @" %@ " , error.description];
94- [self scheduleNextScreenshotWithInterval: timerInterval timeStarted: timeStarted];
98+ self.consecutiveScreenshotFailures ++;
99+ NSTimeInterval backoffSeconds = MIN (FAILURE_BACKOFF_MAX,
100+ FAILURE_BACKOFF_MIN * (1 << MIN (self.consecutiveScreenshotFailures , 4 )));
101+ uint64_t backoffInterval = (uint64_t )(backoffSeconds * NSEC_PER_SEC);
102+ [self scheduleNextScreenshotWithInterval: backoffInterval timeStarted: timeStarted];
95103 return ;
96104 }
97105
106+ self.consecutiveScreenshotFailures = 0 ;
107+
98108 CGFloat scalingFactor = FBConfiguration.mjpegScalingFactor / 100.0 ;
99109 [self .imageProcessor submitImageData: screenshotData
100110 scalingFactor: scalingFactor
0 commit comments