blob: b6c087d29c60baa0c264aef2697db1352c6776ba [file] [log] [blame]
/*
* Copyright (C) 2015, 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_TAG "ExynosVisionContext"
#include <cutils/log.h>
#include "ExynosVisionContext.h"
const vx_char implementation[VX_MAX_IMPLEMENTATION_NAME] = "samsung.exynosvisionframework";
const vx_char extensions[] =
" ";
namespace android {
kernel_target_t default_kernel_target_preset[] = {
{VX_KERNEL_COLOR_CONVERT, VX_TARGET_VPU},
{VX_KERNEL_CHANNEL_EXTRACT, VX_TARGET_VPU},
{VX_KERNEL_CHANNEL_COMBINE, VX_TARGET_VPU},
{VX_KERNEL_SOBEL_3x3, VX_TARGET_VPU},
{VX_KERNEL_MAGNITUDE, VX_TARGET_VPU},
{VX_KERNEL_PHASE, VX_TARGET_VPU},
{VX_KERNEL_SCALE_IMAGE, VX_TARGET_VPU},
{VX_KERNEL_TABLE_LOOKUP, VX_TARGET_VPU},
{VX_KERNEL_HISTOGRAM, VX_TARGET_VPU},
{VX_KERNEL_EQUALIZE_HISTOGRAM, VX_TARGET_VPU},
{VX_KERNEL_ABSDIFF, VX_TARGET_VPU},
{VX_KERNEL_MEAN_STDDEV, VX_TARGET_VPU},
{VX_KERNEL_THRESHOLD, VX_TARGET_VPU},
{VX_KERNEL_INTEGRAL_IMAGE, VX_TARGET_VPU},
{VX_KERNEL_DILATE_3x3, VX_TARGET_VPU},
{VX_KERNEL_ERODE_3x3, VX_TARGET_VPU},
{VX_KERNEL_MEDIAN_3x3, VX_TARGET_VPU},
{VX_KERNEL_BOX_3x3, VX_TARGET_VPU},
{VX_KERNEL_GAUSSIAN_3x3, VX_TARGET_VPU},
{VX_KERNEL_CUSTOM_CONVOLUTION, VX_TARGET_VPU},
{VX_KERNEL_GAUSSIAN_PYRAMID, VX_TARGET_VPU},
{VX_KERNEL_ACCUMULATE, VX_TARGET_VPU},
{VX_KERNEL_ACCUMULATE_WEIGHTED, VX_TARGET_VPU},
{VX_KERNEL_ACCUMULATE_SQUARE, VX_TARGET_VPU},
{VX_KERNEL_MINMAXLOC, VX_TARGET_VPU},
{VX_KERNEL_CONVERTDEPTH, VX_TARGET_VPU},
{VX_KERNEL_CANNY_EDGE_DETECTOR, VX_TARGET_VPU},
{VX_KERNEL_AND, VX_TARGET_VPU},
{VX_KERNEL_OR, VX_TARGET_VPU},
{VX_KERNEL_XOR, VX_TARGET_VPU},
{VX_KERNEL_NOT, VX_TARGET_VPU},
{VX_KERNEL_MULTIPLY, VX_TARGET_VPU},
{VX_KERNEL_ADD, VX_TARGET_VPU},
{VX_KERNEL_SUBTRACT, VX_TARGET_VPU},
{VX_KERNEL_WARP_AFFINE, VX_TARGET_CPU},
{VX_KERNEL_WARP_PERSPECTIVE, VX_TARGET_CPU},
{VX_KERNEL_HARRIS_CORNERS, VX_TARGET_VPU},
{VX_KERNEL_FAST_CORNERS, VX_TARGET_VPU},
{VX_KERNEL_OPTICAL_FLOW_PYR_LK, VX_TARGET_VPU},
{VX_KERNEL_REMAP, VX_TARGET_CPU},
{VX_KERNEL_HALFSCALE_GAUSSIAN, VX_TARGET_VPU},
};
static vx_bool vxIsValidBorderMode(vx_enum mode)
{
vx_bool ret = vx_true_e;
switch (mode)
{
case VX_BORDER_MODE_UNDEFINED:
case VX_BORDER_MODE_CONSTANT:
case VX_BORDER_MODE_REPLICATE:
break;
default:
ret = vx_false_e;
break;
}
return ret;
}
vx_bool
ExynosVisionContext::isValidContext(ExynosVisionContext *context)
{
vx_bool ret = vx_false_e;
if ((context != NULL) &&
(context->m_magic == VX_MAGIC) &&
(context->getType() == VX_TYPE_CONTEXT)) {
ret = vx_true_e; /* this is the top level context */
}
return ret;
}
ExynosVisionContext::ExynosVisionContext(void) : ExynosVisionReference(this, VX_TYPE_CONTEXT, (ExynosVisionReference*)this, vx_false_e)
{
EXYNOS_VISION_SYSTEM_IN();
m_log_callback = NULL;
m_log_enabled = vx_false_e;
m_log_reentrant = vx_false_e;;
m_imm_border.mode = VX_BORDER_MODE_UNDEFINED;
m_imm_border.constant_value = 0;
m_immediate_target = NULL;
m_performance_monitor = NULL;
EXYNOS_VISION_SYSTEM_OUT();
}
ExynosVisionContext::~ExynosVisionContext(void)
{
EXYNOS_VISION_SYSTEM_IN();
EXYNOS_VISION_SYSTEM_OUT();
}
vx_status
ExynosVisionContext::init(void)
{
EXYNOS_VISION_SYSTEM_IN();
vx_status load_status = VX_SUCCESS;
if (createConstErrors() == vx_false_e) {
return VX_ERROR_NO_MEMORY;
}
#ifdef USE_OPENCL_KERNEL
/* Load opencl kernels, samsung */
VXLOGD("loading openvx-opencl kernels");
load_statu = loadKernels("openvx-opencl");
if (load_status != VX_SUCCESS)
VXLOGE("ERR(%d):loading kernel of openvx-opencl fail", load_status);
else
VXLOGD("loading kernels: openvx-opencl");
#endif
/* Load vpu kernels, samsung */
VXLOGD("loading exynosvpukernel");
load_status = loadKernels("exynosvpukernel");
if (load_status != VX_SUCCESS)
VXLOGE("ERR(%d):loading kernel of exynosvpukernel fail", load_status);
else
VXLOGD("loading kernels: exynosvpukernel");
/* Load score kernels, samsung */
VXLOGD("loading exynosscorekernel");
load_status = loadKernels("exynosscorekernel");
if (load_status != VX_SUCCESS)
VXLOGE("ERR(%d):loading kernel of exynosscorekernel fail", load_status);
else
VXLOGD("loading kernels: exynosscorekernel");
m_performance_monitor = new ExynosVisionPerfMonitor<ExynosVisionGraph*>;
if (m_performance_monitor == NULL) {
VXLOGE("performance monitor can't create");
return VX_FAILURE;
}
EXYNOS_VISION_SYSTEM_OUT();
return VX_SUCCESS;
}
vx_status
ExynosVisionContext::destroy(void)
{
vx_status status = VX_SUCCESS;
registerLogCallback(NULL, vx_false_e);
List<ExynosVisionTarget*>::iterator target_iter;
for (target_iter=m_target_list.begin(); target_iter!=m_target_list.end(); target_iter++) {
status = (*target_iter)->destroy();
if (status != VX_SUCCESS)
VXLOGE("destorying target(%d) fails, err:%d", (*target_iter)->getId(), status);
delete (*target_iter);
}
m_target_list.clear();
/* m_ref_list could be modified inside of releaseReferenceInt(), so we have to use clone of m_ref_list. */
List<ExynosVisionReference*>::iterator ref_iter;
m_internal_lock.lock();
List<ExynosVisionReference*> external_ref_list;
for (ref_iter=m_ref_list.begin(); ref_iter!=m_ref_list.end(); ref_iter++) {
if ((*ref_iter)->getExternalCnt()) {
external_ref_list.push_back(*ref_iter);
}
}
m_internal_lock.unlock();
for (ref_iter=external_ref_list.begin(); ref_iter!=external_ref_list.end(); ref_iter++) {
while((*ref_iter)->getExternalCnt()) {
/* kernel object is not released commonly, external referencing is occured at vxAddKernel API. */
if ((*ref_iter)->getType() != VX_TYPE_KERNEL)
VXLOGW("external referencing is not released, %s", (*ref_iter)->getName());
status = ExynosVisionReference::releaseReferenceInt((ExynosVisionReference**)&(*ref_iter), VX_REF_EXTERNAL);
if (status != VX_SUCCESS) {
VXLOGE("release external reference of %s fails, err:%d", (*ref_iter)->getName(), status);
}
if (*ref_iter == NULL)
break;
}
}
if (m_ref_list.size()) {
VXLOGE("some object doesn't be removed");
for (ref_iter=m_ref_list.begin(); ref_iter!=m_ref_list.end(); ref_iter++)
(*ref_iter)->displayInfo(0, vx_true_e);
}
m_internal_lock.lock();
List<ExynosVisionError*>::iterator err_iter;
for (err_iter=m_error_ref_list.begin(); err_iter!=m_error_ref_list.end(); err_iter++) {
status = (*err_iter)->destroy();
if (status != VX_SUCCESS)
VXLOGE("destorying err ref(%d) fails, err:%d", (*err_iter)->getId(), status);
delete (*err_iter);
}
vx_symbol_t sym = NULL;
vx_module_deinitializer_f deinitializer = NULL;
List<vx_module_t>::iterator module_iter;
for (module_iter=m_module_list.begin(); module_iter!=m_module_list.end(); module_iter++) {
/* Do not consider as error when Module Deinitializer is absent. */
sym = vxGetSymbol((*module_iter).handle, (vx_char*)"vxModuleDeinitializer");
deinitializer = (vx_module_deinitializer_f)sym;
if (deinitializer) {
VXLOGD2("Calling %s module deinitializer function\n", (*module_iter).name);
status = deinitializer();
if (status != VX_SUCCESS) {
VXLOGE("Failed to deinitialize module");
}
}
vxUnloadModule((*module_iter).handle);
}
m_internal_lock.unlock();
if (m_performance_monitor)
delete m_performance_monitor;
return status;
}
vx_status
ExynosVisionContext::loadKernels(const vx_char *name)
{
EXYNOS_VISION_SYSTEM_IN();
vx_status status = VX_FAILURE;
vx_char module[VX_INT_MAX_PATH];
vx_symbol_t sym = NULL;
vx_module_initializer_f initializer = NULL;
vx_publish_kernels_f publish = NULL;
vx_module_t module_str;
List<vx_module_t>::iterator module_iter;
for (module_iter=m_module_list.begin(); module_iter!=m_module_list.end(); module_iter++) {
if (strcmp((*module_iter).name, name) == 0) {
VXLOGD3("module(%s) is already loaded", name);
status = VX_SUCCESS;
goto EXIT;
}
}
sprintf(module, "lib""%s"".so", name);
module_str.handle = vxLoadModule(module);
VXLOGD("loaded a module: %s", module);
if (module_str.handle) {
/* Do not consider as error when Module Initializer is absent. */
sym = vxGetSymbol(module_str.handle, (vx_char*)"vxModuleInitializer");
initializer = (vx_module_initializer_f)sym;
if (initializer) {
VXLOGD2("Calling %s module initializer function\n", module);
status = initializer((vx_context)this);
if (status != VX_SUCCESS) {
VXLOGE("Failed to initialize module");
}
}
sym = vxGetSymbol(module_str.handle, (vx_char*)"vxPublishKernels");
publish = (vx_publish_kernels_f)sym;
if (publish == NULL) {
VXLOGE("Failed to load symbol vxPublishKernels");
status = VX_ERROR_INVALID_MODULE;
vxUnloadModule(module_str.handle);
}
else
{
VXLOGD2("Calling %s publish function\n", module);
status = publish((vx_context)this);
if (status != VX_SUCCESS) {
VXLOGE("Failed to publish kernels in module");
vxUnloadModule(module_str.handle);
}
else {
strncpy(module_str.name, name, VX_INT_MAX_PATH);
m_module_list.push_back(module_str);
}
}
} else {
VXLOGE("Failed to find module %s in libraries path", module);
}
if (status != VX_SUCCESS) {
VXLOGE("Failed to load module %s; error %d", module, status);
} else {
VXLOGD2("total module list");
for (List<vx_module_t>::iterator iterPos = m_module_list.begin(); iterPos != m_module_list.end(); iterPos++)
VXLOGD2("module: %s\n", (*iterPos).name);
}
EXIT:
EXYNOS_VISION_SYSTEM_OUT();
return status;
}
ExynosVisionKernel*
ExynosVisionContext::addKernel(const vx_char name[VX_MAX_KERNEL_NAME],
vx_enum enumeration,
vx_kernel_f func_ptr,
vx_uint32 numParams,
vx_kernel_input_validate_f input,
vx_kernel_output_validate_f output,
vx_kernel_initialize_f init,
vx_kernel_deinitialize_f deinit)
{
if (func_ptr == NULL ||
input == NULL ||
output == NULL ||
numParams > VX_INT_MAX_PARAMS ||
name == NULL ||
strncmp(name, "", VX_MAX_KERNEL_NAME) == 0) {
/* initialize and de-initialize can be NULL */
VXLOGE("invalid Parameters, func_ptr:%p, input:%p, output:%p, name:%s, numParams:%d", func_ptr, input, output, name, numParams);
addLogEntry(this, VX_ERROR_INVALID_PARAMETERS, "Invalid Parameters supplied to vxAddKernel\n");
return NULL;
}
vx_char target_name[VX_MAX_TARGET_NAME];
memset(target_name, 0x0, sizeof(target_name));
vx_char *last_char = strrchr(name, '.');
vx_int64 index = (vx_int64)last_char - (vx_int64)name;
if (index == 0)
strcpy(target_name, name);
else
strncpy(target_name, name, last_char-name);
ExynosVisionTarget *cur_target = NULL;
for (List<ExynosVisionTarget*>::iterator target_iter = m_target_list.begin(); target_iter != m_target_list.end(); target_iter++) {
if (strcmp((*target_iter)->getTargetName(), target_name) == 0) {
cur_target = *target_iter;
}
}
if (cur_target == NULL) {
VXLOGD2("making new target : %s", target_name);
cur_target = new ExynosVisionTarget(this, target_name);
addTarget(cur_target);
VXLOGD2("total target");
for (List<ExynosVisionTarget*>::iterator target_iter=m_target_list.begin(); target_iter!=m_target_list.end(); target_iter++)
VXLOGD2("target: %s", (*target_iter)->getTargetName());
}
ExynosVisionKernel *kernel = cur_target->addKernel(name, enumeration, func_ptr, numParams, input, output, init, deinit);
return kernel;
}
ExynosVisionKernel*
ExynosVisionContext::getKernelByEnum(vx_enum kernel_enum)
{
ExynosVisionKernel *kernel = NULL;
ExynosVisionTarget *target = NULL;
// priority 1: immediate target
if(m_immediate_target) {
kernel = m_immediate_target->getKernelByEnum(kernel_enum);
if (kernel)
return kernel;
}
// priority 2: default target (target any)
for (vx_uint32 k = 0; k < dimof(default_kernel_target_preset); k++) {
if (kernel_enum == default_kernel_target_preset[k].kernel_enum) {
target = getTargetByEnum(default_kernel_target_preset[k].target_enum);
if (target) {
kernel = target->getKernelByEnum(kernel_enum);
if (kernel) {
VXLOGD3("Find kernel(0x%X) at target(0x%X)", kernel_enum, default_kernel_target_preset[k].target_enum);
break;
}
}
}
}
// priority 3: first target found
if (kernel == NULL) {
VXLOGD3("defalut target for kernel(0x%x) is not found", kernel_enum);
List<ExynosVisionTarget*>::iterator target_iter;
for (target_iter = m_target_list.begin(); target_iter != m_target_list.end(); target_iter++) {
kernel = (*target_iter)->getKernelByEnum(kernel_enum);
if (kernel) {
VXLOGD3("Find kernel(0x%X) at target(%s)", kernel_enum, (*target_iter)->getTargetName());
break;
}
}
}
if (kernel == NULL)
VXLOGE("kernel enum 0x%X not found at context", kernel_enum);
return kernel;
}
ExynosVisionKernel*
ExynosVisionContext::getKernelByName(const vx_char *name)
{
ExynosVisionKernel *kernel;
List<ExynosVisionTarget*>::iterator target_iter;
for (target_iter=m_target_list.begin(); target_iter!=m_target_list.end(); target_iter++) {
kernel = (*target_iter)->getKernelByName(name);
if (kernel) {
VXLOGD3("Find kernel(%s) at target(%s)", name, (*target_iter)->getTargetName());
break;
}
}
if (kernel == NULL)
VXLOGE("kernel name %s not found at context", name);
return kernel;
}
ExynosVisionKernel*
ExynosVisionContext::getKernelByTarget(vx_enum kernel_enum, vx_enum target_enum)
{
ExynosVisionKernel *kernel = NULL;
ExynosVisionTarget *target = NULL;
List<ExynosVisionTarget*>::iterator target_iter;
for (target_iter=m_target_list.begin(); target_iter!=m_target_list.end(); target_iter++) {
if ((*target_iter)->getTargetEnum() == target_enum) {
target = *target_iter;
break;
}
}
if (target) {
kernel = target->getKernelByEnum(kernel_enum);
if (kernel)
VXLOGD3("Find kernel (0x%X) at target(%s)", kernel_enum, target->getTargetName());
else
VXLOGE("kernel 0x%X not found at target(%s)", kernel_enum, target->getTargetName());
} else {
VXLOGE("target(0x%x) is not loaded", target_enum);
}
return kernel;
}
vx_status
ExynosVisionContext::removeKernel(ExynosVisionKernel **kernel)
{
vx_status status = VX_FAILURE;
const vx_char *kernel_name = (*kernel)->getKernelName();
vx_char target_name[VX_MAX_TARGET_NAME];
memset(target_name, 0x0, sizeof(target_name));
vx_char *last_char = strrchr(kernel_name, '.');
vx_int64 index = (vx_int64)last_char - (vx_int64)kernel_name;
if (index == 0)
strcpy(target_name, kernel_name);
else
strncpy(target_name, kernel_name, last_char-kernel_name);
List<ExynosVisionTarget*>::iterator target_iter;
for (target_iter=m_target_list.begin(); target_iter!=m_target_list.end(); target_iter++) {
if (strcmp(target_name, (*target_iter)->getTargetName()) == 0)
break;
}
if (target_iter == m_target_list.end()) {
VXLOGE("can't find perfer target, expected target name is %s", target_name);
status = VX_ERROR_INVALID_PARAMETERS;
goto EXIT;
}
status = (*target_iter)->removeKernel(kernel);
if (status != VX_SUCCESS) {
VXLOGE("can't find %s in %s", (*kernel)->getKernelName(), (*target_iter)->getTargetName());
status = VX_ERROR_INVALID_PARAMETERS;
goto EXIT;
}
EXIT:
return status;
}
vx_uint32
ExynosVisionContext::getUniqueKernelsNum(void)
{
vx_uint32 kernels_num;
ExynosVisionKernel *kernel;
map<vx_enum, ExynosVisionKernel*> unique_kernels_map;
List<ExynosVisionTarget*>::iterator target_iter;
for (target_iter=m_target_list.begin(); target_iter!=m_target_list.end(); target_iter++) {
kernels_num = (*target_iter)->getKernelsNum();
for (vx_uint32 i=0; i<kernels_num; i++) {
kernel = (*target_iter)->getKernelByIndex(i);
pair <vx_enum, ExynosVisionKernel*> kernel_pair(kernel->getEnumeration(), kernel);
unique_kernels_map.insert(kernel_pair);
}
}
return unique_kernels_map.size();
}
vx_status
ExynosVisionContext::fillUniqueKernelsTable(vx_kernel_info_t *table)
{
vx_uint32 kernels_num;
ExynosVisionKernel *kernel;
map<vx_enum, ExynosVisionKernel*> unique_kernels_map;
pair< map<vx_enum, ExynosVisionKernel*>::iterator, bool > result;
vx_uint32 cnt = 0;
vx_status status = VX_SUCCESS;
List<ExynosVisionTarget*>::iterator target_iter;
for (target_iter=m_target_list.begin(); target_iter!=m_target_list.end(); target_iter++) {
kernels_num = (*target_iter)->getKernelsNum();
for (vx_uint32 i=0; i<kernels_num; i++) {
kernel = (*target_iter)->getKernelByIndex(i);
pair <vx_enum, ExynosVisionKernel*> kernel_pair(kernel->getEnumeration(), kernel);
result = unique_kernels_map.insert(kernel_pair);
if (result.second == true) {
table[cnt].enumeration = kernel->getEnumeration();
memcpy(&table[cnt++].name, kernel->getKernelName(), VX_MAX_KERNEL_NAME);
}
}
}
if (cnt != unique_kernels_map.size()) {
VXLOGE("unique kernel number is not corrent (%d, %d)", cnt, unique_kernels_map.size());
status = VX_FAILURE;
}
return VX_SUCCESS;
}
vx_status
ExynosVisionContext::queryContext(vx_enum attribute, void *ptr, vx_size size)
{
vx_status status = VX_SUCCESS;
switch (attribute) {
case VX_CONTEXT_ATTRIBUTE_VENDOR_ID:
if (VX_CHECK_PARAM(ptr, size, vx_uint16, 0x1))
*(vx_uint16 *)ptr = VX_ID_SAMSUNG;
else
status = VX_ERROR_INVALID_PARAMETERS;
break;
case VX_CONTEXT_ATTRIBUTE_VERSION:
if (VX_CHECK_PARAM(ptr, size, vx_uint16, 0x1))
*(vx_uint16 *)ptr = (vx_uint16)VX_VERSION;
else
status = VX_ERROR_INVALID_PARAMETERS;
break;
case VX_CONTEXT_ATTRIBUTE_MODULES:
if (VX_CHECK_PARAM(ptr, size, vx_uint32, 0x3))
*(vx_uint32 *)ptr = m_module_list.size();
else
status = VX_ERROR_INVALID_PARAMETERS;
break;
case VX_CONTEXT_ATTRIBUTE_REFERENCES:
if (VX_CHECK_PARAM(ptr, size, vx_uint32, 0x3)) {
vx_uint32 total_ref = m_ref_list.size() + m_error_ref_list.size();
*(vx_uint32 *)ptr = total_ref;
} else {
status = VX_ERROR_INVALID_PARAMETERS;
}
break;
case VX_CONTEXT_ATTRIBUTE_IMPLEMENTATION:
if (size <= VX_MAX_IMPLEMENTATION_NAME && ptr)
strncpy((char*)ptr, implementation, VX_MAX_IMPLEMENTATION_NAME);
else
status = VX_ERROR_INVALID_PARAMETERS;
break;
case VX_CONTEXT_ATTRIBUTE_EXTENSIONS_SIZE:
if (VX_CHECK_PARAM(ptr, size, vx_size, 0x3))
*(vx_size *)ptr = sizeof(extensions);
else
status = VX_ERROR_INVALID_PARAMETERS;
break;
case VX_CONTEXT_ATTRIBUTE_EXTENSIONS:
if (size <= sizeof(extensions) && ptr)
strncpy((char*)ptr, extensions, sizeof(extensions));
else
status = VX_ERROR_INVALID_PARAMETERS;
break;
case VX_CONTEXT_ATTRIBUTE_CONVOLUTION_MAXIMUM_DIMENSION:
if (VX_CHECK_PARAM(ptr, size, vx_size, 0x3))
*(vx_size *)ptr = VX_INT_MAX_CONVOLUTION_DIM;
else
status = VX_ERROR_INVALID_PARAMETERS;
break;
case VX_CONTEXT_ATTRIBUTE_OPTICAL_FLOW_WINDOW_MAXIMUM_DIMENSION:
if (VX_CHECK_PARAM(ptr, size, vx_size, 0x3))
*(vx_size *)ptr = VX_OPTICALFLOWPYRLK_MAX_DIM;
else
status = VX_ERROR_INVALID_PARAMETERS;
break;
case VX_CONTEXT_ATTRIBUTE_IMMEDIATE_BORDER_MODE:
if (VX_CHECK_PARAM(ptr, size, vx_border_mode_t, 0x3))
*(vx_border_mode_t *)ptr = m_imm_border;
else
status = VX_ERROR_INVALID_PARAMETERS;
break;
case VX_CONTEXT_ATTRIBUTE_UNIQUE_KERNELS:
if (VX_CHECK_PARAM(ptr, size, vx_uint32, 0x3))
*(vx_uint32 *)ptr = getUniqueKernelsNum();
else
status = VX_ERROR_INVALID_PARAMETERS;
break;
case VX_CONTEXT_ATTRIBUTE_UNIQUE_KERNEL_TABLE:
vx_uint32 unique_kernels_num;
unique_kernels_num = getUniqueKernelsNum();
if ((size == (unique_kernels_num * sizeof(vx_kernel_info_t))) && (ptr != NULL))
status = fillUniqueKernelsTable((vx_kernel_info_t*)ptr);
else
status = VX_ERROR_INVALID_PARAMETERS;
break;
default:
status = VX_ERROR_NOT_SUPPORTED;
break;
}
return status;
}
vx_status
ExynosVisionContext::setContextAttribute(vx_enum attribute, const void *ptr, vx_size size)
{
vx_status status = VX_SUCCESS;
switch (attribute) {
case VX_CONTEXT_ATTRIBUTE_IMMEDIATE_BORDER_MODE:
if (VX_CHECK_PARAM(ptr, size, vx_border_mode_t, 0x3)) {
vx_border_mode_t *config = (vx_border_mode_t *)ptr;
if (vxIsValidBorderMode(config->mode) == vx_false_e)
status = VX_ERROR_INVALID_VALUE;
else
m_imm_border = *config;
} else {
status = VX_ERROR_INVALID_PARAMETERS;
}
break;
default:
status = VX_ERROR_NOT_SUPPORTED;
break;
}
return status;
}
vx_enum
ExynosVisionContext::registerUserStruct(vx_size size)
{
if (m_user_struct_list.size() >= VX_TYPE_USER_STRUCT_END - VX_TYPE_USER_STRUCT_START) {
VXLOGE("Can't register new user struct, user struct num:%d", m_user_struct_list.size());
return VX_TYPE_INVALID;
}
vx_enum type = VX_TYPE_USER_STRUCT_START + m_user_struct_list.size();
struct user_struct user_str;
user_str.type = type;
user_str.size = size;
m_user_struct_list.push_back(user_str);
return type;
}
vx_bool
ExynosVisionContext::createConstErrors()
{
vx_bool ret = vx_true_e;
vx_enum e = 0;
/* create an error object for each status enumeration */
for (e = VX_STATUS_MIN; (e < VX_SUCCESS) && (ret == vx_true_e); e++)
{
ExynosVisionError *cError = new ExynosVisionError(this, e);
addErrorReference(cError);
}
return ret;
}
ExynosVisionReference*
ExynosVisionContext::getErrorObject(vx_status status)
{
EXYNOS_VISION_SYSTEM_IN();
ExynosVisionError *error = NULL;
vx_size i = 0ul;
Mutex::Autolock lock(m_internal_lock);
for (List<ExynosVisionError*>::iterator iterPos = m_error_ref_list.begin(); iterPos != m_error_ref_list.end(); iterPos++) {
if ((*iterPos)->getStatus() == status) {
error = *iterPos;
break;
}
}
if (error == NULL)
VXLOGE("error object is not found");
EXYNOS_VISION_SYSTEM_OUT();
return error;
}
vx_bool
ExynosVisionContext::addErrorReference(ExynosVisionError *error_ref)
{
EXYNOS_VISION_SYSTEM_IN();
Mutex::Autolock lock(m_internal_lock);
m_error_ref_list.push_back(error_ref);
error_ref->incrementReference(VX_REF_INTERNAL, this);
EXYNOS_VISION_SYSTEM_OUT();
return vx_true_e;
}
vx_bool
ExynosVisionContext::addReference(ExynosVisionReference *ref)
{
EXYNOS_VISION_SYSTEM_IN();
Mutex::Autolock lock(m_internal_lock);
m_ref_list.push_back(ref);
EXYNOS_VISION_SYSTEM_OUT();
return vx_true_e;
}
vx_bool
ExynosVisionContext::addTarget(ExynosVisionTarget *target)
{
Mutex::Autolock lock(m_internal_lock);
m_target_list.push_back(target);
target->incrementReference(VX_REF_INTERNAL, this);
return vx_true_e;
}
ExynosVisionTarget*
ExynosVisionContext::getTargetByEnum(vx_enum target_enum)
{
List<ExynosVisionTarget*>::iterator target_iter;
for (target_iter=m_target_list.begin(); target_iter!=m_target_list.end(); target_iter++) {
if(target_enum == (*target_iter)->getTargetEnum()) {
VXLOGD3("found target (%s) by enum(0x%X)", (*target_iter)->getTargetName(), target_enum);
return *target_iter;
}
}
VXLOGE("Failed to find target by enum(0x%X)", target_enum);
return NULL;
}
vx_status
ExynosVisionContext::setImmediateModeTarget(vx_enum target_enum)
{
EXYNOS_VISION_SYSTEM_IN();
vx_status status = VX_SUCCESS;
if (target_enum == VX_TARGET_ANY) {
status = VX_SUCCESS;
goto EXIT;
}
m_immediate_target = getTargetByEnum(target_enum);
if(m_immediate_target == NULL)
status = VX_FAILURE;
EXIT:
EXYNOS_VISION_SYSTEM_OUT();
return status;
}
vx_status
ExynosVisionContext::removeReference(ExynosVisionReference *ref)
{
EXYNOS_VISION_SYSTEM_IN();
Mutex::Autolock lock(m_internal_lock);
vx_status status = VX_FAILURE;
if (ref->getType() == VX_TYPE_ERROR) {
List<ExynosVisionError*>::iterator iterPos;
for (iterPos = m_error_ref_list.begin(); iterPos != m_error_ref_list.end(); iterPos++) {
if ((*iterPos) == ref) {
m_error_ref_list.erase(iterPos);
status = VX_SUCCESS;
}
}
if (iterPos == m_error_ref_list.end()) {
VXLOGE("error ref %d is not found", ref->getId());
status = VX_ERROR_INVALID_REFERENCE;
}
} else if (ref->getType() == VX_TYPE_TARGET) {
VXLOGE("removing target is not defined yet");
status = VX_ERROR_INVALID_REFERENCE;
} else {
List<ExynosVisionReference*>::iterator iterPos;
for (iterPos = m_ref_list.begin(); iterPos != m_ref_list.end(); iterPos++) {
if ((*iterPos) == ref) {
m_ref_list.erase(iterPos);
status = VX_SUCCESS;
break;
}
}
if (iterPos == m_ref_list.end()) {
VXLOGE("ref %d is not found", ref->getId());
ref->displayInfo(0, vx_true_e);
status = VX_ERROR_INVALID_REFERENCE;
}
}
EXYNOS_VISION_SYSTEM_OUT();
return status;
}
void
ExynosVisionContext::displayInfo(vx_uint32 tab_num, vx_bool detail_info)
{
EXYNOS_VISION_SYSTEM_IN();
vx_char tap[MAX_TAB_NUM];
VXLOGI("%s[CONTEXT][%d] =====[Context Information]======", MAKE_TAB(tap, tab_num), detail_info);
VXLOGI("%s[CONTEXT] module number : %d", MAKE_TAB(tap, tab_num), m_module_list.size());
for (List<vx_module_t>::iterator iterPos = m_module_list.begin(); iterPos != m_module_list.end(); iterPos++) {
VXLOGI("%s[MODULE ] name : %s", MAKE_TAB(tap, tab_num), (*iterPos).name);
}
VXLOGI("%s[CONTEXT] ================================", MAKE_TAB(tap, tab_num));
VXLOGI("%s[CONTEXT] target number : %d", MAKE_TAB(tap, tab_num), m_target_list.size());
for (List<ExynosVisionTarget*>::iterator iterPos = m_target_list.begin(); iterPos != m_target_list.end(); iterPos++) {
(*iterPos)->displayInfo(0, vx_true_e);
}
VXLOGI("%s[CONTEXT] ================================", MAKE_TAB(tap, tab_num));
VXLOGI("%s[CONTEXT] ref number : %d", MAKE_TAB(tap, tab_num), m_ref_list.size());
for (List<ExynosVisionReference*>::iterator iterPos = m_ref_list.begin(); iterPos != m_ref_list.end(); iterPos++) {
(*iterPos)->displayInfo(0, vx_true_e);
}
VXLOGI("%s[CONTEXT] ================================", MAKE_TAB(tap, tab_num));
EXYNOS_VISION_SYSTEM_OUT();
}
vx_status
ExynosVisionContext::setDirective(vx_enum directive)
{
vx_status status = VX_SUCCESS;
switch (directive) {
/*! \todo add directive to the sample implementation */
case VX_DIRECTIVE_DISABLE_LOGGING:
m_log_enabled = vx_false_e;
break;
case VX_DIRECTIVE_ENABLE_LOGGING:
m_log_enabled = vx_true_e;
break;
default:
status = VX_ERROR_NOT_SUPPORTED;
break;
}
return status;
}
void
ExynosVisionContext::registerLogCallback(vx_log_callback_f callback, vx_bool reentrant)
{
EXYNOS_VISION_SYSTEM_IN();
if (callback == NULL)
m_log_enabled = vx_false_e;
else
m_log_enabled = vx_true_e;
m_log_callback = callback;
m_log_reentrant = reentrant;
EXYNOS_VISION_SYSTEM_OUT();
}
void
ExynosVisionContext::addLogEntry(ExynosVisionReference *ref, vx_status status, const char *message, ...)
{
va_list ap;
vx_char string[VX_MAX_LOG_MESSAGE_LEN];
if (m_log_enabled == vx_false_e)
return;
if (m_log_callback == NULL) {
VXLOGE("no callback is registered");
return;
}
va_start(ap, message);
vsnprintf(string, VX_MAX_LOG_MESSAGE_LEN, message, ap);
string[VX_MAX_LOG_MESSAGE_LEN-1] = 0; // for MSVC which is not C99 compliant
va_end(ap);
if (m_log_reentrant == vx_false_e)
m_log_mutex.lock();
m_log_callback((vx_context)this, (vx_reference)ref, status, string);
if (m_log_reentrant == vx_false_e)
m_log_mutex.unlock();
return;
}
vx_size
ExynosVisionContext::getUserStructsSize(vx_enum item_type)
{
vx_size res = 0;
List<struct user_struct>::iterator str_iter;
for (str_iter=m_user_struct_list.begin(); str_iter!=m_user_struct_list.end(); str_iter++) {
if ((*str_iter).type == item_type) {
res = (*str_iter).size;
break;
}
}
return res;
}
}; /* namespace android */