diff --git a/LICENSE.md b/LICENSE.md index 3e328f1..c03d905 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2019 Defold +Copyright (c) 2019 Defold Foundation Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index a496490..3d5c9d5 100644 --- a/README.md +++ b/README.md @@ -1,67 +1,101 @@ # extension-camera -Example of interacting with the camera through native extensions. +Native extension to use device camera to capture frames. -# Disclaimer -Although we aim to provide good example functionality in this example, we cannot guarantee the quality/stability at all times. -Please regard it as just that, an example, and don't rely on this as a dependency for your production code. +# Installation -# Known issues +To use the camera extension in a Defold project this project has to be added as a [Defold library dependency](http://www.defold.com/manuals/libraries/). Open the **game.project** file and in the [Dependencies field in the Project section](https://defold.com/manuals/project-settings/#dependencies) add: + +https://github.com/defold/extension-camera/archive/master.zip + +Or point to the ZIP file of [a specific release](https://github.com/defold/extension-camera/releases). + + +# Supported platforms The currently supported platforms are: OSX + iOS # FAQ -## How do I use this extension? +## How do I reset macOS camera permission? -Add the package link (https://github.com/defold/extension-camera/archive/master.zip) -to the project setting `project.dependencies`, and you should be good to go. +To test macOS camera permission popup multiple times you can reset the permission from the terminal: -See the [manual](http://www.defold.com/manuals/libraries/) for further info. +```bash +tccutil reset Camera +``` # Lua API ## Type constants -Describes what camera should be used +Describes what camera should be used. + +```lua +camera.CAMERA_TYPE_FRONT -- Selfie +camera.CAMERA_TYPE_BACK +``` - camera.CAMERA_TYPE_FRONT -- Selfie - camera.CAMERA_TYPE_BACK ## Quality constants - camera.CAPTURE_QUALITY_HIGH - camera.CAPTURE_QUALITY_MEDIUM - camera.CAPTURE_QUALITY_LOW +```lua +camera.CAPTURE_QUALITY_HIGH +camera.CAPTURE_QUALITY_MEDIUM +camera.CAPTURE_QUALITY_LOW +``` -## camera.start_capture(type, quality) -Returns true if the capture starts well +## Status constants - if camera.start_capture(camera.CAMERA_TYPE_BACK, camera.CAPTURE_QUALITY_HIGH) then +```lua +camera.STATUS_STARTED +camera.STATUS_STOPPED +camera.STATUS_NOT_PERMITTED +camera.STATUS_ERROR +``` + + +## camera.start_capture(type, quality, callback) + +Start camera capture using the specified camera (front/back) and capture quality. This may trigger a camera usage permission popup. When the popup has been dismissed the callback will be invoked with camera start status. + +```lua +camera.start_capture(camera.CAMERA_TYPE_BACK, camera.CAPTURE_QUALITY_HIGH, function(self, status) + if status == camera.STATUS_STARTED then -- do stuff end - +end) +``` + + ## camera.stop_capture() -Stops a previously started capture session +Stops a previously started capture session. + +```lua +camera.stop_capture() +``` + ## camera.get_info() -Gets the info from the current capture session +Gets the info from the current capture session. + +```lua +local info = camera.get_info() +print("width", info.width) +print("height", info.height) +``` + - local info = camera.get_info() - print("width", info.width) - print("height", info.height) - ## camera.get_frame() -Retrieves the camera pixel buffer -This buffer has one stream named "rgb", and is of type buffer.VALUE_TYPE_UINT8 and has the value count of 1 +Retrieves the camera pixel buffer. This buffer has one stream named "rgb", and is of type `buffer.VALUE_TYPE_UINT8` and has the value count of 1. - self.cameraframe = camera.get_frame() - - +```lua +self.cameraframe = camera.get_frame() +``` diff --git a/camera/src/camera.mm b/camera/src/camera.mm index 866c2ed..dfc4065 100644 --- a/camera/src/camera.mm +++ b/camera/src/camera.mm @@ -392,42 +392,50 @@ void CameraPlatform_StartCaptureAuthorized(dmBuffer::HBuffer* buffer, CameraType void CameraPlatform_StartCapture(dmBuffer::HBuffer* buffer, CameraType type, CaptureQuality quality, CameraInfo& outparams) { - // Request permission to access the camera. - int status = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo]; - if (status == AVAuthorizationStatusAuthorized) + // Only check for permission on iOS 7+ and macOS 10.14+ + if ([AVCaptureDevice respondsToSelector:@selector(authorizationStatusForMediaType:)]) + { + // Request permission to access the camera. + int status = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo]; + if (status == AVAuthorizationStatusAuthorized) + { + // The user has previously granted access to the camera. + dmLogInfo("AVAuthorizationStatusAuthorized"); + CameraPlatform_StartCaptureAuthorized(buffer, type, quality, outparams); + } + else if (status == AVAuthorizationStatusNotDetermined) + { + dmLogInfo("AVAuthorizationStatusNotDetermined"); + // The app hasn't yet asked the user for camera access. + [AVCaptureDevice requestAccessForMediaType:AVMediaTypeVideo completionHandler:^(BOOL granted) { + if (granted) { + dmLogInfo("AVAuthorizationStatusNotDetermined - granted!"); + CameraPlatform_StartCaptureAuthorized(buffer, type, quality, outparams); + } + else + { + dmLogInfo("AVAuthorizationStatusNotDetermined - not granted!"); + Camera_QueueMessage(STATUS_NOT_PERMITTED); + } + }]; + } + else if (status == AVAuthorizationStatusDenied) + { + // The user has previously denied access. + dmLogInfo("AVAuthorizationStatusDenied"); + Camera_QueueMessage(STATUS_NOT_PERMITTED); + } + else if (status == AVAuthorizationStatusRestricted) + { + // The user can't grant access due to restrictions. + dmLogInfo("AVAuthorizationStatusRestricted"); + Camera_QueueMessage(STATUS_NOT_PERMITTED); + } + } + else { - // The user has previously granted access to the camera. - dmLogInfo("AVAuthorizationStatusAuthorized"); CameraPlatform_StartCaptureAuthorized(buffer, type, quality, outparams); } - else if (status == AVAuthorizationStatusNotDetermined) - { - dmLogInfo("AVAuthorizationStatusNotDetermined"); - // The app hasn't yet asked the user for camera access. - [AVCaptureDevice requestAccessForMediaType:AVMediaTypeVideo completionHandler:^(BOOL granted) { - if (granted) { - dmLogInfo("AVAuthorizationStatusNotDetermined - granted!"); - CameraPlatform_StartCaptureAuthorized(buffer, type, quality, outparams); - } - else - { - dmLogInfo("AVAuthorizationStatusNotDetermined - not granted!"); - Camera_QueueMessage(STATUS_NOT_PERMITTED); - } - }]; - } - else if (status == AVAuthorizationStatusDenied) - { - // The user has previously denied access. - dmLogInfo("AVAuthorizationStatusDenied"); - Camera_QueueMessage(STATUS_NOT_PERMITTED); - } - else if (status == AVAuthorizationStatusRestricted) - { - // The user can't grant access due to restrictions. - dmLogInfo("AVAuthorizationStatusRestricted"); - Camera_QueueMessage(STATUS_NOT_PERMITTED); - } } void CameraPlatform_StopCapture() diff --git a/main/main.script b/main/main.script index b1bd207..40d2ed1 100644 --- a/main/main.script +++ b/main/main.script @@ -35,11 +35,11 @@ local function start_capture(self) type=resource.TEXTURE_TYPE_2D, format=resource.TEXTURE_FORMAT_RGB, num_mip_maps=1 } + label.set_text("logo#status", "Capture Status: ON") else label.set_text("logo#status", "Capture Status: ERROR") end end) - label.set_text("logo#status", "Capture Status: ON") end function init(self) @@ -73,11 +73,11 @@ end function on_input(self, action_id, action) - --[[if (action_id == hash("space") or action_id == hash("touch")) and action.pressed then + if (action_id == hash("space") or action_id == hash("touch")) and action.pressed then if self.cameraframe == nil then start_capture(self) else stop_capture(self) end - end--]] + end end