I am creating a c++ library for use on iOS (yes, unfortunately it has to be C++) which uses AVCaptureSession to capture video frames, which are delivered via the captureOutput callback. The C++ library is my deliverable product. I have a cocoa touch application to test/demo it. So, it looks like this:
(test app) <-----> (c++ lib(AVFoundation callbacks))
The test app has UI controls and is responsible for almost all graphics. The c++ library renders frames to a UIView via OpenGL.
Are you with me? Good
Okay, first, the user presses a UIButton which makes a call into my library. This call takes 10 seconds or more to complete. So if I put the call directly behind the button click, the UI will be blocked until the library function returns:
-(IBAction)hBut:(id)sender{
[myLib foo]; // takes 10+ seconds to return
}
This is no good. The next thing I tried was to spawn a thread to call the lib:
-(void)callIntoLib{
[myLib foo];
}
-(IBAction)hBut:(id)sender{
[NSThread detach..:myLib selector:foo object:nil];
}
This no longer blocks the UI, but now the video frames callback function never fires (AVCaptureSession's captureOutput). It seems as though the main NSRunLoop has been blocked.
Next I tried the same thing, but with Grand Central Dispatch:
-(IBAction)hBut:(id)sender{
_myQueue = dispatch_queue_create("com.domain.me", NULL); // member variable
dispatch_async(_myQueue,
^{
[myLib foo];
});
}
This has the same behavior. That is, the callback for video frames doesn't fire. Lame
Why is the main NSRunLoop being blocked in the 2nd and 3rd cases? Is there a way to associate the queues with it?
Does this make sense?
Main thread runs its runLoop by itself, so events from camera were delivered to your library in the first case. Custom threads do not run runLoop, you should do that by yourself.
-(void)callIntoLib {
[myLib foo];
self.callIntoLibExecuted = YES;
}
-(void)threadBody {
@autoreleasepool {
self.callIntoLibExecuted = NO;
[self performSelector:@selector(callIntoLib)
onThread:[NSThread currentThread]
withObject:nil
waitUntilDone:NO];
while (!self.callIntoLibExecuted)
{
@autoreleasepool {
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode
beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]];
}
}
}
}
-(IBAction)hBut:(id)sender {
[NSThread detachNewThreadSelector:@selector(threadBody)
toTarget:self withObject:nil];
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With