Properly fix the camera threading bugs

This commit is contained in:
Lior Halphon
2024-06-12 13:35:35 +03:00
parent 60ff8577bb
commit eebdbbfd5b

View File

@@ -54,6 +54,8 @@
UIButton *_cameraPositionButton; UIButton *_cameraPositionButton;
__weak GCController *_lastController; __weak GCController *_lastController;
dispatch_queue_t _cameraQueue;
} }
static void loadBootROM(GB_gameboy_t *gb, GB_boot_rom_t type) static void loadBootROM(GB_gameboy_t *gb, GB_boot_rom_t type)
@@ -263,6 +265,8 @@ static void rumbleCallback(GB_gameboy_t *gb, double amp)
forControlEvents:UIControlEventTouchUpInside]; forControlEvents:UIControlEventTouchUpInside];
[_backgroundView addSubview:_cameraPositionButton]; [_backgroundView addSubview:_cameraPositionButton];
_cameraQueue = dispatch_queue_create("SameBoy Camera Queue", NULL);
[UNUserNotificationCenter currentNotificationCenter].delegate = self; [UNUserNotificationCenter currentNotificationCenter].delegate = self;
[self verifyEntitlements]; [self verifyEntitlements];
@@ -1130,61 +1134,66 @@ didReceiveNotificationResponse:(UNNotificationResponse *)response
- (void)cameraRequestUpdate - (void)cameraRequestUpdate
{ {
@try { dispatch_async(dispatch_get_main_queue(), ^{
if (!_cameraSession) { if (!_cameraSession) {
NSError *error; dispatch_async(_cameraQueue, ^{
AVCaptureDevice *device = [self captureDevice]; @try {
AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice: device error: &error]; if (!_cameraSession) {
NSError *error;
if (!input) { AVCaptureDevice *device = [self captureDevice];
GB_camera_updated(&_gb); AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice: device error: &error];
return;
} if (!input) {
GB_camera_updated(&_gb);
_cameraOutput = [[AVCaptureVideoDataOutput alloc] init]; return;
[_cameraOutput setVideoSettings: @{(id)kCVPixelBufferPixelFormatTypeKey: @(kCVPixelFormatType_32BGRA)}]; }
[_cameraOutput setSampleBufferDelegate:self
queue:dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0)]; _cameraOutput = [[AVCaptureVideoDataOutput alloc] init];
[_cameraOutput setVideoSettings: @{(id)kCVPixelBufferPixelFormatTypeKey: @(kCVPixelFormatType_32BGRA)}];
[_cameraOutput setSampleBufferDelegate:self
queue:_cameraQueue];
_cameraSession = [AVCaptureSession new];
_cameraSession.sessionPreset = AVCaptureSessionPreset352x288;
[_cameraSession addInput: input]; _cameraSession = [AVCaptureSession new];
[_cameraSession addOutput: _cameraOutput]; _cameraSession.sessionPreset = AVCaptureSessionPreset352x288;
_cameraConnection = [_cameraOutput connectionWithMediaType: AVMediaTypeVideo];
_cameraConnection.videoOrientation = AVCaptureVideoOrientationPortrait; [_cameraSession addInput: input];
[_cameraSession startRunning]; [_cameraSession addOutput: _cameraOutput];
_cameraConnection = [_cameraOutput connectionWithMediaType: AVMediaTypeVideo];
_cameraConnection.videoOrientation = AVCaptureVideoOrientationPortrait;
[_cameraSession startRunning];
}
}
@catch (NSException *exception) {
/* I have not tested camera support on many devices, so we catch exceptions just in case. */
GB_camera_updated(&_gb);
}
});
} }
}
@catch (NSException *exception) {
/* I have not tested camera support on many devices, so we catch exceptions just in case. */
GB_camera_updated(&_gb);
}
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
_cameraNeedsUpdate = true; _cameraNeedsUpdate = true;
[_disableCameraTimer invalidate]; [_disableCameraTimer invalidate];
dispatch_async(dispatch_get_main_queue(), ^{ if (!_cameraPositionButton.alpha) {
if (!_cameraPositionButton.alpha) { [UIView animateWithDuration:0.25 animations:^{
_cameraPositionButton.alpha = 1;
}];
}
_disableCameraTimer = [NSTimer scheduledTimerWithTimeInterval:1
repeats:false
block:^(NSTimer *timer) {
if (_cameraPositionButton.alpha) {
[UIView animateWithDuration:0.25 animations:^{ [UIView animateWithDuration:0.25 animations:^{
_cameraPositionButton.alpha = 1; _cameraPositionButton.alpha = 0;
}]; }];
} }
_disableCameraTimer = [NSTimer scheduledTimerWithTimeInterval:1 dispatch_async(_cameraQueue, ^{
repeats:false
block:^(NSTimer *timer) {
if (_cameraPositionButton.alpha) {
[UIView animateWithDuration:0.25 animations:^{
_cameraPositionButton.alpha = 0;
}];
}
[_cameraSession stopRunning]; [_cameraSession stopRunning];
_cameraSession = nil; _cameraSession = nil;
_cameraConnection = nil; _cameraConnection = nil;
_cameraOutput = nil; _cameraOutput = nil;
}]; });
}); }];
}); });
} }
@@ -1270,16 +1279,17 @@ didReceiveNotificationResponse:(UNNotificationResponse *)response
- (void)rotateCamera - (void)rotateCamera
{ {
_cameraPosition ^= AVCaptureDevicePositionBack ^ AVCaptureDevicePositionFront; dispatch_async(_cameraQueue, ^{
[_cameraSession stopRunning]; _cameraPosition ^= AVCaptureDevicePositionBack ^ AVCaptureDevicePositionFront;
_cameraSession = nil; [_cameraSession stopRunning];
_cameraConnection = nil; _cameraSession = nil;
_cameraOutput = nil; _cameraConnection = nil;
if (_cameraNeedsUpdate) { _cameraOutput = nil;
_cameraNeedsUpdate = false; if (_cameraNeedsUpdate) {
GB_camera_updated(&_gb); _cameraNeedsUpdate = false;
} GB_camera_updated(&_gb);
}
});
} }
@end @end