What's the best way to launch a periodic task in iOS camera to use frames data?

倾然丶 夕夏残阳落幕 提交于 2020-07-10 10:25:27

问题


I am building a cross-platform tool that uses frames from camera to do some work on them. I'm starting from this code-base, which is the camera Flutter plugin. My goal is to have a periodic task (running every 200ms or so) that does some work in parallel (so it does not interfere with frame-rate). For this, my goal is to store every frame that comes from camera and, when the task is triggered, last stored frame is used for some calculations.

Below, I'll show what I've done, but I think this is not the right way to do it and that it is not truly running on a separate thread.

  1. Save the CVPixelBuffer frame as property of FLTCam
    @property(readwrite, atomic) CVPixelBufferRef volatile lastFramePixelBuffer;
  1. Save lastFramePixelBuffer in captureOutput, after (l350) CFRetain(newBuffer);
    _lastFramePixelBuffer = newBuffer;
  1. Launch periodic task in camera start
  [self startTimedTask]; //in [camera start]
- (void)startTimedTask  //start periodic task in 5 seconds
{
    dispatch_async(dispatch_get_main_queue(), ^{
        NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:5 target:self selector:@selector(startTimedTaskRepeat) userInfo:nil repeats:NO];
    });
}

- (void)startTimedTaskRepeat  // trigger periodic task every 0.2secs
{
    dispatch_async(dispatch_get_main_queue(), ^{
        NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:0.2 target:self selector:@selector(performBackgroundTask) userInfo:nil repeats:YES];
    });
}

- (void)performBackgroundTask 
{
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
        //Do background work
        [self doBackgroundWork];
    });
}

- (void)doBackgroundWork{  // the task, which takes about 100ms
    CVPixelBufferRef frame = _pixelBufferToInfere;
    CFRetain(frame);
    NSLog(@"Image size is: H = %zd", CVPixelBufferGetHeight(frame));NSLog(@"Image size is: W = %zd", CVPixelBufferGetWidth(frame));
    [self calculate:frame]; 
    CFRelease(frame);    
}

I want to know the best way to achieve this parallel computing and the most recent frame "caching" in a reliable and safe way, right now the interval between executions of the task seems inconsistent and fps seem to get a little lower.


回答1:


For periodic tasks you can use CADisplayLink.

like

@property (nonatomic) CADisplayLink *displaylink;

-(void)updateAnimationStatus {
    if ( !self.displayLink ) {
        self.displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(updatePulse)];
        self.displayLink.preferredFramesPerSecond = 24;
        [self.displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
    } else {
        [self.displayLink invalidate];
        self.displayLink = nil;
    }
}

-(void)updatePulse {
    // your stuff to be done periodicaly
}


来源:https://stackoverflow.com/questions/62795428/whats-the-best-way-to-launch-a-periodic-task-in-ios-camera-to-use-frames-data

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!