mirror of
https://github.com/defold/extension-camera
synced 2025-09-27 08:52:19 +02:00
WIP
This commit is contained in:
@@ -26,26 +26,69 @@ struct DefoldCamera
|
||||
|
||||
// Information about the currently set camera
|
||||
CameraInfo m_Params;
|
||||
|
||||
dmArray<CameraStatus> m_MessageQueue;
|
||||
dmScript::LuaCallbackInfo* m_Callback;
|
||||
dmMutex::HMutex m_Mutex;
|
||||
};
|
||||
|
||||
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];
|
||||
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)
|
||||
{
|
||||
DM_LUA_STACK_CHECK(L, 1);
|
||||
DM_LUA_STACK_CHECK(L, 0);
|
||||
|
||||
CameraType type = (CameraType) luaL_checkint(L, 1);
|
||||
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);
|
||||
if( status == 0 )
|
||||
{
|
||||
dmLogError("capture failed!\n");
|
||||
return 1;
|
||||
}
|
||||
CameraPlatform_StartCapture(&g_DefoldCamera.m_VideoBuffer, type, quality, g_DefoldCamera.m_Params);
|
||||
|
||||
// Increase ref count
|
||||
dmScript::LuaHBuffer luabuffer = {g_DefoldCamera.m_VideoBuffer, false};
|
||||
@@ -59,14 +102,9 @@ static int StopCapture(lua_State* L)
|
||||
{
|
||||
DM_LUA_STACK_CHECK(L, 0);
|
||||
|
||||
int status = CameraPlatform_StopCapture();
|
||||
if( !status )
|
||||
{
|
||||
return luaL_error(L, "Failed to stop capture. Was it started?");
|
||||
}
|
||||
CameraPlatform_StopCapture();
|
||||
|
||||
dmScript::Unref(L, LUA_REGISTRYINDEX, g_DefoldCamera.m_VideoBufferLuaRef); // We want it destroyed by the GC
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -94,7 +132,7 @@ static int GetInfo(lua_State* L)
|
||||
static int GetFrame(lua_State* L)
|
||||
{
|
||||
DM_LUA_STACK_CHECK(L, 1);
|
||||
lua_rawgeti(L,LUA_REGISTRYINDEX, g_DefoldCamera.m_VideoBufferLuaRef);
|
||||
lua_rawgeti(L,LUA_REGISTRYINDEX, g_DefoldCamera.m_VideoBufferLuaRef);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -113,9 +151,9 @@ static void LuaInit(lua_State* L)
|
||||
int top = lua_gettop(L);
|
||||
luaL_register(L, MODULE_NAME, Module_methods);
|
||||
|
||||
#define SETCONSTANT(name) \
|
||||
lua_pushnumber(L, (lua_Number) name); \
|
||||
lua_setfield(L, -2, #name);\
|
||||
#define SETCONSTANT(name) \
|
||||
lua_pushnumber(L, (lua_Number) name); \
|
||||
lua_setfield(L, -2, #name);\
|
||||
|
||||
SETCONSTANT(CAMERA_TYPE_FRONT)
|
||||
SETCONSTANT(CAMERA_TYPE_BACK)
|
||||
@@ -124,7 +162,12 @@ static void LuaInit(lua_State* L)
|
||||
SETCONSTANT(CAPTURE_QUALITY_MEDIUM)
|
||||
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);
|
||||
assert(top == lua_gettop(L));
|
||||
@@ -132,12 +175,20 @@ static void LuaInit(lua_State* L)
|
||||
|
||||
dmExtension::Result AppInitializeCamera(dmExtension::AppParams* params)
|
||||
{
|
||||
dmLogInfo("Registered %s Extension", MODULE_NAME);
|
||||
return dmExtension::RESULT_OK;
|
||||
}
|
||||
|
||||
dmExtension::Result InitializeCamera(dmExtension::Params* params)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -148,6 +199,8 @@ dmExtension::Result AppFinalizeCamera(dmExtension::AppParams* params)
|
||||
|
||||
dmExtension::Result FinalizeCamera(dmExtension::Params* params)
|
||||
{
|
||||
dmMutex::Delete(g_DefoldCamera.m_Mutex);
|
||||
Camera_DestroyCallback();
|
||||
return dmExtension::RESULT_OK;
|
||||
}
|
||||
|
||||
@@ -156,7 +209,7 @@ dmExtension::Result FinalizeCamera(dmExtension::Params* 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;
|
||||
}
|
||||
|
||||
@@ -165,6 +218,12 @@ static dmExtension::Result InitializeCamera(dmExtension::Params* params)
|
||||
return dmExtension::RESULT_OK;
|
||||
}
|
||||
|
||||
static dmExtension::Result UpdateCamera(dmExtension::Params* params)
|
||||
{
|
||||
Camera_ProcessQueue()
|
||||
return dmExtension::RESULT_OK;
|
||||
}
|
||||
|
||||
static dmExtension::Result AppFinalizeCamera(dmExtension::AppParams* params)
|
||||
{
|
||||
return dmExtension::RESULT_OK;
|
||||
@@ -178,4 +237,4 @@ static dmExtension::Result FinalizeCamera(dmExtension::Params* params)
|
||||
#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
|
||||
didDropSampleBuffer:(CMSampleBufferRef)sampleBuffer
|
||||
- (void)captureOutput:(AVCaptureOutput *)captureOutput
|
||||
didDropSampleBuffer:(CMSampleBufferRef)sampleBuffer
|
||||
fromConnection:(AVCaptureConnection *)connection
|
||||
{
|
||||
|
||||
//NSLog(@"DROPPING FRAME!!!");
|
||||
}
|
||||
|
||||
@@ -256,7 +255,7 @@ IOSCamera g_Camera;
|
||||
|
||||
static CMVideoDimensions FlipCoords(AVCaptureVideoDataOutput* output, const CMVideoDimensions& in)
|
||||
{
|
||||
CMVideoDimensions out = in;
|
||||
CMVideoDimensions out = in;
|
||||
#if defined(DM_PLATFORM_IOS)
|
||||
AVCaptureConnection* conn = [output connectionWithMediaType:AVMediaTypeVideo];
|
||||
switch (conn.videoOrientation) {
|
||||
@@ -274,7 +273,7 @@ static CMVideoDimensions FlipCoords(AVCaptureVideoDataOutput* output, const CMVi
|
||||
|
||||
|
||||
- ( BOOL ) startCamera: (AVCaptureDevicePosition) cameraPosition
|
||||
quality: (CaptureQuality)quality
|
||||
quality: (CaptureQuality)quality
|
||||
{
|
||||
// 1. Find the back camera
|
||||
if ( ![ self findCamera: cameraPosition ] )
|
||||
@@ -352,7 +351,7 @@ static CMVideoDimensions FlipCoords(AVCaptureVideoDataOutput* output, const CMVi
|
||||
|
||||
@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)
|
||||
{
|
||||
@@ -381,10 +380,57 @@ int CameraPlatform_StartCapture(dmBuffer::HBuffer* buffer, CameraType type, Capt
|
||||
|
||||
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)
|
||||
{
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
|
||||
void CameraPlatform_StopCapture()
|
||||
{
|
||||
if(g_Camera.m_Delegate != 0)
|
||||
{
|
||||
@@ -395,7 +441,6 @@ int CameraPlatform_StopCapture()
|
||||
dmBuffer::Destroy(g_Camera.m_VideoBuffer);
|
||||
g_Camera.m_VideoBuffer = 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
#endif // DM_PLATFORM_IOS/DM_PLATFORM_OSX
|
||||
|
@@ -22,5 +22,15 @@ struct CameraInfo
|
||||
CameraType m_Type;
|
||||
};
|
||||
|
||||
extern int CameraPlatform_StartCapture(dmBuffer::HBuffer* buffer, CameraType type, CaptureQuality quality, CameraInfo& outparams);
|
||||
extern int CameraPlatform_StopCapture();
|
||||
enum CameraStatus
|
||||
{
|
||||
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);
|
||||
|
Reference in New Issue
Block a user