Merge pull request #14267 from mshabunin:fix-osx-camera-auth
authorMaksim Shabunin <maksim.shabunin@gmail.com>
Fri, 5 Apr 2019 18:58:01 +0000 (21:58 +0300)
committerAlexander Alekhin <alexander.a.alekhin@gmail.com>
Fri, 5 Apr 2019 18:58:01 +0000 (21:58 +0300)
* Added authorization request to AVFoundation camera backend (OSX 10.14+)

modules/videoio/src/cap_avfoundation_mac.mm

index dfc7e64..5d49628 100644 (file)
@@ -45,7 +45,7 @@
 #include "precomp.hpp"
 #include "opencv2/imgproc.hpp"
 #include <stdio.h>
-#include <AvailabilityMacros.h>
+#include <Availability.h>
 #import <AVFoundation/AVFoundation.h>
 
 #define CV_CAP_MODE_BGR CV_FOURCC_MACRO('B','G','R','3')
@@ -324,6 +324,28 @@ void CvCaptureCAM::stopCaptureDevice() {
 int CvCaptureCAM::startCaptureDevice(int cameraNum) {
     NSAutoreleasePool *localpool = [[NSAutoreleasePool alloc] init];
 
+#if defined(__MAC_OS_X_VERSION_MAX_ALLOWED) && __MAC_OS_X_VERSION_MAX_ALLOWED >= 101400
+    AVAuthorizationStatus status = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];
+    if (status == AVAuthorizationStatusDenied)
+    {
+        fprintf(stderr, "OpenCV: camera access has been denied. Either run 'tccutil reset Camera' "
+                        "command in same terminal to reset application authorization status, "
+                        "either modify 'System Preferences -> Security & Privacy -> Camera' "
+                        "settings for your application.\n");
+        [localpool drain];
+        return 0;
+    }
+    else if (status != AVAuthorizationStatusAuthorized)
+    {
+        fprintf(stderr, "OpenCV: not authorized to capture video (status %ld), requesting...\n", status);
+        // TODO: doesn't work via ssh
+        [AVCaptureDevice requestAccessForMediaType:AVMediaTypeVideo completionHandler:^(BOOL) { /* we don't care */}];
+        // we do not wait for completion
+        [localpool drain];
+        return 0;
+    }
+#endif
+
     // get capture device
     NSArray *devices = [[AVCaptureDevice devicesWithMediaType: AVMediaTypeVideo]
             arrayByAddingObjectsFromArray:[AVCaptureDevice devicesWithMediaType:AVMediaTypeMuxed]];