blob: 8becfd6e58783132c9e48bd4bab047b824444d35 [file] [log] [blame]
/*
* Copyright@ Samsung Electronics Co. LTD
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*#define LOG_NDEBUG 0 */
#define LOG_TAG "ExynosCameraFactoryPlugIn"
#include <log/log.h>
#include <dlfcn.h>
#include "PlugInList.h"
#include "ExynosCameraFactoryPlugIn.h"
/* include the converter header depending on the feature */
#ifdef USES_DUAL_CAMERA_SOLUTION_FAKE
#include "ExynosCameraPlugInConverterFakeFusion.h"
#endif
#ifdef SLSI_LLS_REPROCESSING
#include "ExynosCameraPlugInConverterLowLightShot.h"
#endif
#ifdef USES_CAMERA_SOLUTION_VDIS
#include "ExynosCameraPlugInConverterVDIS.h"
#endif
namespace android {
ExynosCameraFactoryPlugIn::ExynosCameraFactoryPlugIn()
{
strncpy(m_name, "ExynosCameraFactoryPlugIn", (EXYNOS_CAMERA_NAME_STR_SIZE - 1));
m_plugInTotalCount = sizeof(g_plugInList) / sizeof(PlugInList_t);
}
int ExynosCameraFactoryPlugIn::m_findPlugInIndexByPipeId(int cameraId, int pipeId)
{
int index;
if (m_plugInTotalCount <= 0) {
CLOGE3(cameraId, "there's no plugIn to support(%d)", m_plugInTotalCount);
return -1;
}
if (pipeId < 0) {
CLOGE3(cameraId, "invalid pipeId(%d))", pipeId);
return -1;
}
for (index = 0; index < m_plugInTotalCount; index++) {
if (g_plugInList[index].pipeId == pipeId) {
CLOGD3(cameraId, "%s plugIn is found(%d)!!", g_plugInList[index].plugInLibName, pipeId);
break;
}
}
if (index == m_plugInTotalCount) {
CLOGE3(cameraId, "there's any plugIn to match with pipeId(%d)", pipeId);
index = -1;
}
return index;
}
status_t ExynosCameraFactoryPlugIn::create(int cameraId, int pipeId, ExynosCameraPlugInSP_dptr_t plugIn, ExynosCameraPlugInConverterSP_dptr_t converter, PLUGIN::MODE mode)
{
int refCount;
status_t ret = NO_ERROR;
CLOGD3(cameraId, "pipeId(%d)", pipeId);
plugIn = NULL;
converter = NULL;
Mutex::Autolock lock(m_lock);
{
void *libHandle = NULL;
PlugInSymbol_t createSymbol = NULL;
/* 1. get the lib index by pipeId */
int index = m_findPlugInIndexByPipeId(cameraId, pipeId);
if (index < 0) {
CLOGE3(cameraId, "Invalid pipeId(%d)", pipeId);
return INVALID_OPERATION;
}
/* 2. if plugIn is NULL, try to get plugIn */
if (plugIn == NULL) {
/* search lib handle */
libHandle = m_mapLibHandle[pipeId];
if (libHandle == NULL) {
libHandle = dlopen(g_plugInList[index].plugInLibName, RTLD_NOW);
if (libHandle == NULL) {
CLOGE3(cameraId, "Can't load %s library(%d, %d)",
g_plugInList[index].plugInLibName, index, pipeId);
return INVALID_OPERATION;
}
}
*(reinterpret_cast<void **>(&createSymbol)) = dlsym(libHandle, PLUGIN_SYMBOL_NAME);
if (createSymbol == NULL) {
CLOGE3(cameraId, "Can't find symbol(%s) from library(%s, %d, %d)",
PLUGIN_SYMBOL_NAME,
g_plugInList[index].plugInLibName, index, pipeId);
dlclose(libHandle);
return INVALID_OPERATION;
}
plugIn = (ExynosCameraPlugIn *)createSymbol(cameraId, pipeId, mode);
if (plugIn != NULL) {
/* 3. create the converter by pipeId */
switch (pipeId) {
#ifdef USE_DUAL_CAMERA
case PIPE_FUSION:
case PIPE_FUSION_FRONT:
case PIPE_FUSION_REPROCESSING:
#ifdef USES_DUAL_CAMERA_SOLUTION_FAKE
converter = (new ExynosCameraPlugInConverterFakeFusion(cameraId, pipeId));
#endif
break;
#endif
#ifdef SLSI_LLS_REPROCESSING
case PIPE_LLS_REPROCESSING:
converter = (new ExynosCameraPlugInConverterLowLightShot(cameraId, pipeId));
break;
#endif
case PIPE_VDIS:
#ifdef USES_CAMERA_SOLUTION_VDIS
converter = (new ExynosCameraPlugInConverterVDIS(cameraId, pipeId));
#endif
break;
default:
break;
}
}
}
/* 4. save the handle and plugIn to map */
m_mapLibHandle[pipeId] = libHandle;
refCount = m_mapPlugInRefCount[pipeId];
refCount++;
m_mapPlugInRefCount[pipeId] = refCount;
CLOGD3(cameraId, "createSymbol success!!(%d, %p, %p, %d)",
pipeId, m_mapLibHandle[pipeId], &plugIn, refCount);
}
return ret;
}
status_t ExynosCameraFactoryPlugIn::destroy(int cameraId, ExynosCameraPlugInSP_dptr_t plugIn, ExynosCameraPlugInConverterSP_dptr_t converter)
{
if (plugIn == NULL) {
CLOGE3(cameraId, "plugIn is NULL");
return INVALID_OPERATION;
}
status_t ret = NO_ERROR;
int pipeId;
void *libHandle;
int refCount = 0;
pipeId = plugIn->getPipeId();
CLOGD3(cameraId, "pipeId(%d)", pipeId);
Mutex::Autolock lock(m_lock);
{
converter = NULL;
plugIn = NULL;
/* decrease the refCount */
refCount = m_mapPlugInRefCount[pipeId];
if (refCount <= 0) {
CLOGW3(cameraId, "pipeId(%d) refCount(%d) is invalid..", pipeId, refCount);
} else {
refCount--;
m_mapPlugInRefCount[pipeId] = refCount;
}
if (!refCount) {
libHandle = m_mapLibHandle[pipeId];
if (libHandle != NULL) {
ret = dlclose(libHandle);
if (ret) {
CLOGE3(cameraId, "dlclose is failed!!(%d)", pipeId);
ret = INVALID_OPERATION;
}
}
m_mapLibHandle[pipeId] = NULL;
}
CLOGD3(cameraId, "destroy success!!(%d, %p, %p, %d)",
pipeId, m_mapLibHandle[pipeId], &plugIn, refCount);
}
return ret;
}
void ExynosCameraFactoryPlugIn::dump(__unused int cameraId)
{
/* nothing to do */
}
}