问题
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.
- Save the CVPixelBuffer frame as property of FLTCam
@property(readwrite, atomic) CVPixelBufferRef volatile lastFramePixelBuffer;
- Save lastFramePixelBuffer in captureOutput, after (l350) CFRetain(newBuffer);
_lastFramePixelBuffer = newBuffer;
- 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