mirror of
https://github.com/defold/extension-camera
synced 2025-06-27 18:37:43 +02:00
Merge pull request #4 from defold/dev-macos-permissions
macOS and iOS permissions
This commit is contained in:
commit
4bf2d79b4c
@ -1,6 +1,6 @@
|
|||||||
MIT License
|
MIT License
|
||||||
|
|
||||||
Copyright (c) 2019 Defold
|
Copyright (c) 2019 Defold Foundation
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
94
README.md
94
README.md
@ -1,67 +1,101 @@
|
|||||||
# extension-camera
|
# 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.
|
# Installation
|
||||||
Please regard it as just that, an example, and don't rely on this as a dependency for your production code.
|
|
||||||
|
|
||||||
# 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
|
The currently supported platforms are: OSX + iOS
|
||||||
|
|
||||||
|
|
||||||
# FAQ
|
# 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 test macOS camera permission popup multiple times you can reset the permission from the terminal:
|
||||||
to the project setting `project.dependencies`, and you should be good to go.
|
|
||||||
|
|
||||||
See the [manual](http://www.defold.com/manuals/libraries/) for further info.
|
```bash
|
||||||
|
tccutil reset Camera
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
# Lua API
|
# Lua API
|
||||||
|
|
||||||
## Type constants
|
## 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
|
## Quality constants
|
||||||
|
|
||||||
camera.CAPTURE_QUALITY_HIGH
|
```lua
|
||||||
camera.CAPTURE_QUALITY_MEDIUM
|
camera.CAPTURE_QUALITY_HIGH
|
||||||
camera.CAPTURE_QUALITY_LOW
|
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
|
-- do stuff
|
||||||
end
|
end
|
||||||
|
end)
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
## camera.stop_capture()
|
## camera.stop_capture()
|
||||||
|
|
||||||
Stops a previously started capture session
|
Stops a previously started capture session.
|
||||||
|
|
||||||
|
```lua
|
||||||
|
camera.stop_capture()
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
## camera.get_info()
|
## 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()
|
## camera.get_frame()
|
||||||
|
|
||||||
Retrieves the camera pixel buffer
|
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.
|
||||||
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()
|
||||||
|
```
|
||||||
|
8
camera/manifests/osx/Info.plist
Normal file
8
camera/manifests/osx/Info.plist
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>NSCameraUsageDescription</key>
|
||||||
|
<string>{{project.title}} would like to access the camera.</string>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
@ -26,31 +26,82 @@ struct DefoldCamera
|
|||||||
|
|
||||||
// Information about the currently set camera
|
// Information about the currently set camera
|
||||||
CameraInfo m_Params;
|
CameraInfo m_Params;
|
||||||
|
|
||||||
|
dmArray<CameraStatus> m_MessageQueue;
|
||||||
|
dmScript::LuaCallbackInfo* m_Callback;
|
||||||
|
dmMutex::HMutex m_Mutex;
|
||||||
};
|
};
|
||||||
|
|
||||||
DefoldCamera g_DefoldCamera;
|
DefoldCamera g_DefoldCamera;
|
||||||
|
|
||||||
|
void Camera_QueueMessage(CameraStatus status)
|
||||||
|
{
|
||||||
|
DM_MUTEX_SCOPED_LOCK(g_DefoldCamera.m_Mutex);
|
||||||
|
|
||||||
|
if (g_DefoldCamera.m_MessageQueue.Full())
|
||||||
|
{
|
||||||
|
g_DefoldCamera.m_MessageQueue.OffsetCapacity(1);
|
||||||
|
}
|
||||||
|
g_DefoldCamera.m_MessageQueue.Push(status);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void Camera_ProcessQueue()
|
||||||
|
{
|
||||||
|
DM_MUTEX_SCOPED_LOCK(g_DefoldCamera.m_Mutex);
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i != g_DefoldCamera.m_MessageQueue.Size(); ++i)
|
||||||
|
{
|
||||||
|
lua_State* L = dmScript::GetCallbackLuaContext(g_DefoldCamera.m_Callback);
|
||||||
|
if (!dmScript::SetupCallback(g_DefoldCamera.m_Callback))
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
CameraStatus status = g_DefoldCamera.m_MessageQueue[i];
|
||||||
|
|
||||||
|
if (status == STATUS_STARTED)
|
||||||
|
{
|
||||||
|
// Increase ref count
|
||||||
|
dmScript::LuaHBuffer luabuffer = {g_DefoldCamera.m_VideoBuffer, false};
|
||||||
|
dmScript::PushBuffer(L, luabuffer);
|
||||||
|
g_DefoldCamera.m_VideoBufferLuaRef = dmScript::Ref(L, LUA_REGISTRYINDEX);
|
||||||
|
}
|
||||||
|
else if (status == STATUS_STOPPED)
|
||||||
|
{
|
||||||
|
dmScript::Unref(L, LUA_REGISTRYINDEX, g_DefoldCamera.m_VideoBufferLuaRef); // We want it destroyed by the GC
|
||||||
|
g_DefoldCamera.m_VideoBufferLuaRef = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
lua_pushnumber(L, (lua_Number)status);
|
||||||
|
int ret = lua_pcall(L, 2, 0, 0);
|
||||||
|
if (ret != 0)
|
||||||
|
{
|
||||||
|
lua_pop(L, 1);
|
||||||
|
}
|
||||||
|
dmScript::TeardownCallback(g_DefoldCamera.m_Callback);
|
||||||
|
}
|
||||||
|
g_DefoldCamera.m_MessageQueue.SetSize(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void Camera_DestroyCallback()
|
||||||
|
{
|
||||||
|
if (g_DefoldCamera.m_Callback != 0)
|
||||||
|
{
|
||||||
|
dmScript::DestroyCallback(g_DefoldCamera.m_Callback);
|
||||||
|
g_DefoldCamera.m_Callback = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static int StartCapture(lua_State* L)
|
static int StartCapture(lua_State* L)
|
||||||
{
|
{
|
||||||
DM_LUA_STACK_CHECK(L, 1);
|
DM_LUA_STACK_CHECK(L, 0);
|
||||||
|
|
||||||
CameraType type = (CameraType) luaL_checkint(L, 1);
|
CameraType type = (CameraType) luaL_checkint(L, 1);
|
||||||
CaptureQuality quality = (CaptureQuality)luaL_checkint(L, 2);
|
CaptureQuality quality = (CaptureQuality)luaL_checkint(L, 2);
|
||||||
|
|
||||||
int status = CameraPlatform_StartCapture(&g_DefoldCamera.m_VideoBuffer, type, quality, g_DefoldCamera.m_Params);
|
Camera_DestroyCallback();
|
||||||
|
g_DefoldCamera.m_Callback = dmScript::CreateCallback(L, 3);
|
||||||
|
|
||||||
lua_pushboolean(L, status > 0);
|
CameraPlatform_StartCapture(&g_DefoldCamera.m_VideoBuffer, type, quality, g_DefoldCamera.m_Params);
|
||||||
if( status == 0 )
|
|
||||||
{
|
|
||||||
dmLogError("capture failed!\n");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Increase ref count
|
|
||||||
dmScript::LuaHBuffer luabuffer = {g_DefoldCamera.m_VideoBuffer, false};
|
|
||||||
dmScript::PushBuffer(L, luabuffer);
|
|
||||||
g_DefoldCamera.m_VideoBufferLuaRef = dmScript::Ref(L, LUA_REGISTRYINDEX);
|
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -59,13 +110,7 @@ static int StopCapture(lua_State* L)
|
|||||||
{
|
{
|
||||||
DM_LUA_STACK_CHECK(L, 0);
|
DM_LUA_STACK_CHECK(L, 0);
|
||||||
|
|
||||||
int status = CameraPlatform_StopCapture();
|
CameraPlatform_StopCapture();
|
||||||
if( !status )
|
|
||||||
{
|
|
||||||
return luaL_error(L, "Failed to stop capture. Was it started?");
|
|
||||||
}
|
|
||||||
|
|
||||||
dmScript::Unref(L, LUA_REGISTRYINDEX, g_DefoldCamera.m_VideoBufferLuaRef); // We want it destroyed by the GC
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -94,7 +139,14 @@ static int GetInfo(lua_State* L)
|
|||||||
static int GetFrame(lua_State* L)
|
static int GetFrame(lua_State* L)
|
||||||
{
|
{
|
||||||
DM_LUA_STACK_CHECK(L, 1);
|
DM_LUA_STACK_CHECK(L, 1);
|
||||||
lua_rawgeti(L,LUA_REGISTRYINDEX, g_DefoldCamera.m_VideoBufferLuaRef);
|
if (g_DefoldCamera.m_VideoBufferLuaRef != 0)
|
||||||
|
{
|
||||||
|
lua_rawgeti(L, LUA_REGISTRYINDEX, g_DefoldCamera.m_VideoBufferLuaRef);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
lua_pushnil(L);
|
||||||
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -113,9 +165,9 @@ static void LuaInit(lua_State* L)
|
|||||||
int top = lua_gettop(L);
|
int top = lua_gettop(L);
|
||||||
luaL_register(L, MODULE_NAME, Module_methods);
|
luaL_register(L, MODULE_NAME, Module_methods);
|
||||||
|
|
||||||
#define SETCONSTANT(name) \
|
#define SETCONSTANT(name) \
|
||||||
lua_pushnumber(L, (lua_Number) name); \
|
lua_pushnumber(L, (lua_Number) name); \
|
||||||
lua_setfield(L, -2, #name);\
|
lua_setfield(L, -2, #name);\
|
||||||
|
|
||||||
SETCONSTANT(CAMERA_TYPE_FRONT)
|
SETCONSTANT(CAMERA_TYPE_FRONT)
|
||||||
SETCONSTANT(CAMERA_TYPE_BACK)
|
SETCONSTANT(CAMERA_TYPE_BACK)
|
||||||
@ -124,7 +176,12 @@ static void LuaInit(lua_State* L)
|
|||||||
SETCONSTANT(CAPTURE_QUALITY_MEDIUM)
|
SETCONSTANT(CAPTURE_QUALITY_MEDIUM)
|
||||||
SETCONSTANT(CAPTURE_QUALITY_HIGH)
|
SETCONSTANT(CAPTURE_QUALITY_HIGH)
|
||||||
|
|
||||||
#undef SETCONSTANT
|
SETCONSTANT(STATUS_STARTED)
|
||||||
|
SETCONSTANT(STATUS_STOPPED)
|
||||||
|
SETCONSTANT(STATUS_NOT_PERMITTED)
|
||||||
|
SETCONSTANT(STATUS_ERROR)
|
||||||
|
|
||||||
|
#undef SETCONSTANT
|
||||||
|
|
||||||
lua_pop(L, 1);
|
lua_pop(L, 1);
|
||||||
assert(top == lua_gettop(L));
|
assert(top == lua_gettop(L));
|
||||||
@ -132,12 +189,20 @@ static void LuaInit(lua_State* L)
|
|||||||
|
|
||||||
dmExtension::Result AppInitializeCamera(dmExtension::AppParams* params)
|
dmExtension::Result AppInitializeCamera(dmExtension::AppParams* params)
|
||||||
{
|
{
|
||||||
|
dmLogInfo("Registered %s Extension", MODULE_NAME);
|
||||||
return dmExtension::RESULT_OK;
|
return dmExtension::RESULT_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
dmExtension::Result InitializeCamera(dmExtension::Params* params)
|
dmExtension::Result InitializeCamera(dmExtension::Params* params)
|
||||||
{
|
{
|
||||||
LuaInit(params->m_L);
|
LuaInit(params->m_L);
|
||||||
|
g_DefoldCamera.m_Mutex = dmMutex::New();
|
||||||
|
return dmExtension::RESULT_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static dmExtension::Result UpdateCamera(dmExtension::Params* params)
|
||||||
|
{
|
||||||
|
Camera_ProcessQueue();
|
||||||
return dmExtension::RESULT_OK;
|
return dmExtension::RESULT_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -148,6 +213,8 @@ dmExtension::Result AppFinalizeCamera(dmExtension::AppParams* params)
|
|||||||
|
|
||||||
dmExtension::Result FinalizeCamera(dmExtension::Params* params)
|
dmExtension::Result FinalizeCamera(dmExtension::Params* params)
|
||||||
{
|
{
|
||||||
|
dmMutex::Delete(g_DefoldCamera.m_Mutex);
|
||||||
|
Camera_DestroyCallback();
|
||||||
return dmExtension::RESULT_OK;
|
return dmExtension::RESULT_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -156,7 +223,7 @@ dmExtension::Result FinalizeCamera(dmExtension::Params* params)
|
|||||||
|
|
||||||
static dmExtension::Result AppInitializeCamera(dmExtension::AppParams* params)
|
static dmExtension::Result AppInitializeCamera(dmExtension::AppParams* params)
|
||||||
{
|
{
|
||||||
dmLogInfo("Registered %s (null) Extension\n", MODULE_NAME);
|
dmLogInfo("Registered %s (null) Extension", MODULE_NAME);
|
||||||
return dmExtension::RESULT_OK;
|
return dmExtension::RESULT_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -165,6 +232,12 @@ static dmExtension::Result InitializeCamera(dmExtension::Params* params)
|
|||||||
return dmExtension::RESULT_OK;
|
return dmExtension::RESULT_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static dmExtension::Result UpdateCamera(dmExtension::Params* params)
|
||||||
|
{
|
||||||
|
Camera_ProcessQueue()
|
||||||
|
return dmExtension::RESULT_OK;
|
||||||
|
}
|
||||||
|
|
||||||
static dmExtension::Result AppFinalizeCamera(dmExtension::AppParams* params)
|
static dmExtension::Result AppFinalizeCamera(dmExtension::AppParams* params)
|
||||||
{
|
{
|
||||||
return dmExtension::RESULT_OK;
|
return dmExtension::RESULT_OK;
|
||||||
@ -178,4 +251,4 @@ static dmExtension::Result FinalizeCamera(dmExtension::Params* params)
|
|||||||
#endif // platforms
|
#endif // platforms
|
||||||
|
|
||||||
|
|
||||||
DM_DECLARE_EXTENSION(EXTENSION_NAME, LIB_NAME, AppInitializeCamera, AppFinalizeCamera, InitializeCamera, 0, 0, FinalizeCamera)
|
DM_DECLARE_EXTENSION(EXTENSION_NAME, LIB_NAME, AppInitializeCamera, AppFinalizeCamera, InitializeCamera, UpdateCamera, 0, FinalizeCamera)
|
||||||
|
@ -121,11 +121,10 @@ IOSCamera g_Camera;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)captureOutput:(AVCaptureOutput *)captureOutput
|
- (void)captureOutput:(AVCaptureOutput *)captureOutput
|
||||||
didDropSampleBuffer:(CMSampleBufferRef)sampleBuffer
|
didDropSampleBuffer:(CMSampleBufferRef)sampleBuffer
|
||||||
fromConnection:(AVCaptureConnection *)connection
|
fromConnection:(AVCaptureConnection *)connection
|
||||||
{
|
{
|
||||||
|
|
||||||
//NSLog(@"DROPPING FRAME!!!");
|
//NSLog(@"DROPPING FRAME!!!");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -256,7 +255,7 @@ IOSCamera g_Camera;
|
|||||||
|
|
||||||
static CMVideoDimensions FlipCoords(AVCaptureVideoDataOutput* output, const CMVideoDimensions& in)
|
static CMVideoDimensions FlipCoords(AVCaptureVideoDataOutput* output, const CMVideoDimensions& in)
|
||||||
{
|
{
|
||||||
CMVideoDimensions out = in;
|
CMVideoDimensions out = in;
|
||||||
#if defined(DM_PLATFORM_IOS)
|
#if defined(DM_PLATFORM_IOS)
|
||||||
AVCaptureConnection* conn = [output connectionWithMediaType:AVMediaTypeVideo];
|
AVCaptureConnection* conn = [output connectionWithMediaType:AVMediaTypeVideo];
|
||||||
switch (conn.videoOrientation) {
|
switch (conn.videoOrientation) {
|
||||||
@ -274,7 +273,7 @@ static CMVideoDimensions FlipCoords(AVCaptureVideoDataOutput* output, const CMVi
|
|||||||
|
|
||||||
|
|
||||||
- ( BOOL ) startCamera: (AVCaptureDevicePosition) cameraPosition
|
- ( BOOL ) startCamera: (AVCaptureDevicePosition) cameraPosition
|
||||||
quality: (CaptureQuality)quality
|
quality: (CaptureQuality)quality
|
||||||
{
|
{
|
||||||
// 1. Find the back camera
|
// 1. Find the back camera
|
||||||
if ( ![ self findCamera: cameraPosition ] )
|
if ( ![ self findCamera: cameraPosition ] )
|
||||||
@ -352,7 +351,7 @@ static CMVideoDimensions FlipCoords(AVCaptureVideoDataOutput* output, const CMVi
|
|||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
int CameraPlatform_StartCapture(dmBuffer::HBuffer* buffer, CameraType type, CaptureQuality quality, CameraInfo& outparams)
|
void CameraPlatform_StartCaptureAuthorized(dmBuffer::HBuffer* buffer, CameraType type, CaptureQuality quality, CameraInfo& outparams)
|
||||||
{
|
{
|
||||||
if(g_Camera.m_Delegate == 0)
|
if(g_Camera.m_Delegate == 0)
|
||||||
{
|
{
|
||||||
@ -381,10 +380,65 @@ int CameraPlatform_StartCapture(dmBuffer::HBuffer* buffer, CameraType type, Capt
|
|||||||
|
|
||||||
g_Camera.m_VideoBuffer = *buffer;
|
g_Camera.m_VideoBuffer = *buffer;
|
||||||
|
|
||||||
return started ? 1 : 0;
|
if (started)
|
||||||
|
{
|
||||||
|
Camera_QueueMessage(STATUS_STARTED);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Camera_QueueMessage(STATUS_ERROR);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int CameraPlatform_StopCapture()
|
void CameraPlatform_StartCapture(dmBuffer::HBuffer* buffer, CameraType type, CaptureQuality quality, CameraInfo& outparams)
|
||||||
|
{
|
||||||
|
// 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
|
||||||
|
{
|
||||||
|
CameraPlatform_StartCaptureAuthorized(buffer, type, quality, outparams);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CameraPlatform_StopCapture()
|
||||||
{
|
{
|
||||||
if(g_Camera.m_Delegate != 0)
|
if(g_Camera.m_Delegate != 0)
|
||||||
{
|
{
|
||||||
@ -395,7 +449,6 @@ int CameraPlatform_StopCapture()
|
|||||||
dmBuffer::Destroy(g_Camera.m_VideoBuffer);
|
dmBuffer::Destroy(g_Camera.m_VideoBuffer);
|
||||||
g_Camera.m_VideoBuffer = 0;
|
g_Camera.m_VideoBuffer = 0;
|
||||||
}
|
}
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // DM_PLATFORM_IOS/DM_PLATFORM_OSX
|
#endif // DM_PLATFORM_IOS/DM_PLATFORM_OSX
|
||||||
|
@ -22,5 +22,15 @@ struct CameraInfo
|
|||||||
CameraType m_Type;
|
CameraType m_Type;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern int CameraPlatform_StartCapture(dmBuffer::HBuffer* buffer, CameraType type, CaptureQuality quality, CameraInfo& outparams);
|
enum CameraStatus
|
||||||
extern int CameraPlatform_StopCapture();
|
{
|
||||||
|
STATUS_STARTED,
|
||||||
|
STATUS_STOPPED,
|
||||||
|
STATUS_NOT_PERMITTED,
|
||||||
|
STATUS_ERROR
|
||||||
|
};
|
||||||
|
|
||||||
|
extern void CameraPlatform_StartCapture(dmBuffer::HBuffer* buffer, CameraType type, CaptureQuality quality, CameraInfo& outparams);
|
||||||
|
extern void CameraPlatform_StopCapture();
|
||||||
|
|
||||||
|
void Camera_QueueMessage(CameraStatus message);
|
||||||
|
@ -29,4 +29,3 @@ bundle_identifier = com.defold.camera
|
|||||||
|
|
||||||
[library]
|
[library]
|
||||||
include_dirs = camera
|
include_dirs = camera
|
||||||
|
|
||||||
|
@ -6,44 +6,41 @@ local function stop_capture(self)
|
|||||||
|
|
||||||
self.cameraframe = nil
|
self.cameraframe = nil
|
||||||
camera.stop_capture()
|
camera.stop_capture()
|
||||||
|
|
||||||
label.set_text("logo#status", "Capture Status: OFF")
|
label.set_text("logo#status", "Capture Status: OFF")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
local function start_capture(self)
|
local function start_capture(self)
|
||||||
if self.cameraframe ~= nil then
|
if not camera then
|
||||||
|
label.set_text("logo#status", "Capture Status: UNAVAILABLE")
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
if camera ~= nil then
|
|
||||||
|
|
||||||
local sysinfo = sys.get_sys_info()
|
local quality = camera.CAPTURE_QUALITY_HIGH
|
||||||
|
|
||||||
local quality = camera.CAPTURE_QUALITY_HIGH
|
local type = camera.CAMERA_TYPE_FRONT
|
||||||
local type = camera.CAMERA_TYPE_FRONT
|
if sys.get_sys_info().system_name == 'iPhone OS' then
|
||||||
if sysinfo.system_name == 'iPhone OS' then
|
type = camera.CAMERA_TYPE_BACK
|
||||||
type = camera.CAMERA_TYPE_BACK
|
quality = camera.CAPTURE_QUALITY_MEDIUM
|
||||||
quality = camera.CAPTURE_QUALITY_MEDIUM
|
end
|
||||||
end
|
|
||||||
|
camera.start_capture(type, quality, function(self, status)
|
||||||
if camera.start_capture(type, quality) then
|
if status == camera.STATUS_STARTED then
|
||||||
self.cameraframe = camera.get_frame()
|
self.cameraframe = camera.get_frame()
|
||||||
self.camerainfo = camera.get_info()
|
self.camerainfo = camera.get_info()
|
||||||
print("Initialized camera")
|
self.cameratextureheader = {
|
||||||
pprint(self.camerainfo)
|
width=self.camerainfo.width,
|
||||||
|
height=self.camerainfo.height,
|
||||||
self.cameratextureheader = {width=self.camerainfo.width,
|
type=resource.TEXTURE_TYPE_2D,
|
||||||
height=self.camerainfo.height,
|
format=resource.TEXTURE_FORMAT_RGB,
|
||||||
type=resource.TEXTURE_TYPE_2D,
|
num_mip_maps=1
|
||||||
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)
|
||||||
else
|
|
||||||
print("could not start camera capture")
|
|
||||||
label.set_text("logo#status", "Capture Status: UNAVAILABLE")
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function init(self)
|
function init(self)
|
||||||
@ -54,35 +51,33 @@ function init(self)
|
|||||||
local screen_height = sys.get_config("display.height", 800)
|
local screen_height = sys.get_config("display.height", 800)
|
||||||
local scale_width = screen_width / logosize
|
local scale_width = screen_width / logosize
|
||||||
local scale_height = screen_height / logosize
|
local scale_height = screen_height / logosize
|
||||||
|
|
||||||
go.set("#sprite", "scale", vmath.vector3(scale_width, scale_height, 1) )
|
|
||||||
|
|
||||||
|
go.set("#sprite", "scale", vmath.vector3(scale_width, scale_height, 1) )
|
||||||
|
|
||||||
start_capture(self)
|
start_capture(self)
|
||||||
end
|
end
|
||||||
|
|
||||||
function final(self)
|
function final(self)
|
||||||
if self.cameraframe ~= nil then
|
if self.cameraframe then
|
||||||
camera.stop_capture()
|
camera.stop_capture()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
function update(self, dt)
|
function update(self, dt)
|
||||||
if self.cameraframe ~= nil then
|
if self.cameraframe then
|
||||||
local pathmodelcamera = go.get("#sprite", "texture0")
|
local pathmodelcamera = go.get("#sprite", "texture0")
|
||||||
resource.set_texture(pathmodelcamera, self.cameratextureheader, self.cameraframe)
|
resource.set_texture(pathmodelcamera, self.cameratextureheader, self.cameraframe)
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
function on_input(self, action_id, action)
|
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
|
if self.cameraframe then
|
||||||
start_capture(self)
|
|
||||||
else
|
|
||||||
stop_capture(self)
|
stop_capture(self)
|
||||||
|
else
|
||||||
|
start_capture(self)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
Loading…
x
Reference in New Issue
Block a user