| // Copyright 2014 The Flutter Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #import "AppDelegate.h" |
| |
| @interface AppDelegate () |
| @property (atomic) uint64_t textureId; |
| @property (atomic) int framesProduced; |
| @property (atomic) int framesConsumed; |
| @property (atomic) int lastFrameConsumed; |
| @property (atomic) double startTime; |
| @property (atomic) double endTime; |
| @property (atomic) double frameRate; |
| @property (atomic) double frameStartTime; |
| @property (atomic) NSTimer* timer; |
| |
| - (void)tick:(NSTimer*)timer; |
| @end |
| |
| @implementation AppDelegate |
| |
| - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { |
| FlutterViewController* flutterController = |
| (FlutterViewController*)self.window.rootViewController; |
| FlutterMethodChannel* channel = |
| [FlutterMethodChannel methodChannelWithName:@"texture" |
| binaryMessenger:flutterController]; |
| [channel setMethodCallHandler:^(FlutterMethodCall* call, FlutterResult result) { |
| if ([@"start" isEqualToString:call.method]) { |
| _framesProduced = 0; |
| _framesConsumed = 0; |
| _frameRate = 1.0 / [(NSNumber*) call.arguments intValue]; |
| _timer = [NSTimer scheduledTimerWithTimeInterval:_frameRate |
| target:self |
| selector:@selector(tick:) |
| userInfo:nil |
| repeats:YES]; |
| _startTime = [[NSDate date] timeIntervalSince1970]; |
| result(nil); |
| } else if ([@"stop" isEqualToString:call.method]) { |
| [_timer invalidate]; |
| _endTime = [[NSDate date] timeIntervalSince1970]; |
| result(nil); |
| } else if ([@"getProducedFrameRate" isEqualToString:call.method]) { |
| result(@(_framesProduced / (_endTime - _startTime))); |
| } else if ([@"getConsumedFrameRate" isEqualToString:call.method]) { |
| result(@(_framesConsumed / (_endTime - _startTime))); |
| } else { |
| result(FlutterMethodNotImplemented); |
| } |
| }]; |
| _textureId = [flutterController registerTexture:self]; |
| return [super application:application didFinishLaunchingWithOptions:launchOptions]; |
| } |
| |
| - (void)tick:(NSTimer*)timer { |
| FlutterViewController* flutterController = |
| (FlutterViewController*)self.window.rootViewController; |
| [flutterController textureFrameAvailable:_textureId]; |
| _frameStartTime = [[NSDate date] timeIntervalSince1970]; |
| // We just pretend to be producing a frame. |
| _framesProduced++; |
| } |
| |
| - (CVPixelBufferRef)copyPixelBuffer { |
| double now = [[NSDate date] timeIntervalSince1970]; |
| if (now < _frameStartTime |
| || _frameStartTime + _frameRate < now |
| || _framesProduced == _lastFrameConsumed) return nil; |
| _framesConsumed++; |
| _lastFrameConsumed = _framesProduced; |
| // We just pretend to be handing over the produced frame to the consumer. |
| return nil; |
| } |
| @end |