blob: 21232490891ee8e1b3ca5723e3a817cd5f72a150 [file] [log] [blame]
/*
**
** Copyright 2013, 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 "ExynosCameraPipeUVS"
#include <cutils/log.h>
#include "ExynosCameraPipeUVS.h"
namespace android {
ExynosCameraPipeUVS::~ExynosCameraPipeUVS()
{
this->destroy();
}
status_t ExynosCameraPipeUVS::create(int32_t *sensorIds)
{
if (bUVSInit == false) {
CLOGE("ERR(%s):UVS_init() fail", __FUNCTION__);
return INVALID_OPERATION;
}
m_mainThread = ExynosCameraThreadFactory::createThread(this, &ExynosCameraPipeUVS::m_mainThreadFunc, "UVSThread");
m_inputFrameQ = new frame_queue_t(m_mainThread);
CLOGI("INFO(%s[%d]):create() is succeed (%d)", __FUNCTION__, __LINE__, getPipeId());
return NO_ERROR;
}
status_t ExynosCameraPipeUVS::destroy(void)
{
int ret = 0;
if ( bUVSInit == false) {
return NO_ERROR;
}
if (end_uvs !=NULL) {
ret = (*end_uvs)();
if (ret < 0) {
CLOGE("ERR(%s):UVS End fail", __FUNCTION__);
}
else {
CLOGD("DEBUG(%s[%d]) UVS End Success!", __FUNCTION__, __LINE__);
}
end_uvs = NULL;
init_uvs = NULL;
run_uvs = NULL;
}
CLOGD("DEBUG(%s[%d])", __FUNCTION__, __LINE__);
if (uvsHandle !=NULL) {
CLOGD("DEBUG(%s[%d]) uvsHandle : %08x", __FUNCTION__, __LINE__, uvsHandle);
dlclose(uvsHandle);
uvsHandle = NULL;
}
CLOGD("DEBUG(%s[%d])", __FUNCTION__, __LINE__);
if (m_inputFrameQ != NULL) {
m_inputFrameQ->release();
delete m_inputFrameQ;
m_inputFrameQ = NULL;
}
CLOGD("DEBUG(%s[%d])", __FUNCTION__, __LINE__);
CLOGI("INFO(%s[%d]):destroy() is succeed (%d)", __FUNCTION__, __LINE__, getPipeId());
return NO_ERROR;
}
status_t ExynosCameraPipeUVS::start(void)
{
CLOGD("DEBUG(%s[%d])", __FUNCTION__, __LINE__);
return NO_ERROR;
}
status_t ExynosCameraPipeUVS::stop(void)
{
CLOGD("DEBUG(%s[%d])", __FUNCTION__, __LINE__);
int ret = 0;
m_mainThread->requestExitAndWait();
CLOGD("DEBUG(%s[%d]): thead exited", __FUNCTION__, __LINE__);
m_inputFrameQ->release();
return NO_ERROR;
}
status_t ExynosCameraPipeUVS::startThread(void)
{
CLOGV("DEBUG(%s[%d])", __FUNCTION__, __LINE__);
if (m_outputFrameQ == NULL) {
CLOGE("ERR(%s):outputFrameQ is NULL, cannot start", __FUNCTION__);
return INVALID_OPERATION;
}
m_mainThread->run();
CLOGI("INFO(%s[%d]):startThread is succeed (%d)", __FUNCTION__, __LINE__, getPipeId());
return NO_ERROR;
}
status_t ExynosCameraPipeUVS::m_run(void)
{
ExynosCameraFrame *newFrame = NULL;
ExynosCameraBuffer yuv_UVS_in_Buffer;
ExynosCameraBuffer yuv_UVS_out_Buffer;
ExynosRect pictureRect;
ExynosRect srcRect, dstRect;
int hwSensorWidth = 0;
int hwSensorHeight = 0;
long long durationTime = 0;
int ret = 0;
m_parameters->getPictureSize(&pictureRect.w, &pictureRect.h);
CLOGI("[ExynosCameraPipeUVS thread] waitFrameQ");
ret = m_inputFrameQ->waitAndPopProcessQ(&newFrame);
if (ret < 0) {
if (ret == TIMED_OUT) {
CLOGW("WARN(%s):wait timeout", __FUNCTION__);
} else {
CLOGE("ERR(%s):wait and pop fail, ret(%d)", __FUNCTION__, ret);
}
return ret;
}
if (newFrame == NULL) {
CLOGE("ERR(%s):new frame is NULL", __FUNCTION__);
CLOGI("[ExynosCameraPipeUVS thread] new frame is NULL");
return NO_ERROR;
}
ret = newFrame->getSrcBuffer(getPipeId(), &yuv_UVS_in_Buffer);
if (ret < 0) {
CLOGE("ERR(%s[%d]):frame get src buffer fail, ret(%d)", __FUNCTION__, __LINE__, ret);
return OK;
}
camera2_shot_ext shot_ext;
newFrame->getUserDynamicMeta(&shot_ext);
m_parameters->getHwSensorSize(&hwSensorWidth, &hwSensorHeight);
m_parameters->getPictureBayerCropSize(&srcRect, &dstRect);
m_uvsdynamicMeta.src_y = yuv_UVS_in_Buffer.addr[0];
m_uvsdynamicMeta.width = pictureRect.w;
m_uvsdynamicMeta.height = pictureRect.h;
/* binning_x = (cropped_width * 1024) / capture_width
* binning_y = (cropped_height * 1024) / capture_height
*/
m_uvsdynamicMeta.binning_x = (dstRect.w * 1024) / pictureRect.w;
m_uvsdynamicMeta.binning_y = (dstRect.h * 1024) / pictureRect.h;
m_uvsdynamicMeta.radial_alpha_R = shot_ext.shot.udm.as.vendorSpecific[0];
m_uvsdynamicMeta.radial_alpha_G = (shot_ext.shot.udm.as.vendorSpecific[1] + shot_ext.shot.udm.as.vendorSpecific[2])/2;
m_uvsdynamicMeta.radial_alpha_B = shot_ext.shot.udm.as.vendorSpecific[3];
CLOGD("DEBUG(%s[%d]):============= UVS Dynamic Params===================", __FUNCTION__, __LINE__);
CLOGD("DEBUG(%s[%d]):= width : %d", __FUNCTION__, __LINE__, m_uvsdynamicMeta.width);
CLOGD("DEBUG(%s[%d]):= height : %d", __FUNCTION__, __LINE__, m_uvsdynamicMeta.height);
CLOGD("DEBUG(%s[%d]):= buffersize : %d", __FUNCTION__, __LINE__, yuv_UVS_in_Buffer.size[0]);
CLOGD("DEBUG(%s[%d]):= BayerCropSize width : %d", __FUNCTION__, __LINE__, dstRect.w);
CLOGD("DEBUG(%s[%d]):= BayerCropSize height : %d", __FUNCTION__, __LINE__, dstRect.h);
CLOGD("DEBUG(%s[%d]):= binning_x : %d", __FUNCTION__, __LINE__, m_uvsdynamicMeta.binning_x);
CLOGD("DEBUG(%s[%d]):= binning_y : %d", __FUNCTION__, __LINE__, m_uvsdynamicMeta.binning_y);
CLOGD("DEBUG(%s[%d]):= radial_alpha_R : %d", __FUNCTION__, __LINE__, m_uvsdynamicMeta.radial_alpha_R);
CLOGD("DEBUG(%s[%d]):= radial_alpha_G : %d", __FUNCTION__, __LINE__, m_uvsdynamicMeta.radial_alpha_G);
CLOGD("DEBUG(%s[%d]):= radial_alpha_B : %d", __FUNCTION__, __LINE__, m_uvsdynamicMeta.radial_alpha_B);
CLOGD("DEBUG(%s[%d]):===================================================", __FUNCTION__, __LINE__);
CLOGI("DEBUG(%s[%d]): UVS Processing call", __FUNCTION__, __LINE__);
if (run_uvs !=NULL) {
m_timer.start();
ret = (*run_uvs)(&m_uvsdynamicMeta);
m_timer.stop();
durationTime = m_timer.durationMsecs();
CLOGI("UVS Execution Time : (%5d msec)", (int)durationTime);
if (ret < 0) {
CLOGE("ERR(%s[%d]):UVS run fail, ret(%d)", __FUNCTION__, __LINE__, ret);
return OK;
}
}
CLOGI("DEBUG(%s[%d]): UVS Processing done", __FUNCTION__, __LINE__);
ret = newFrame->setEntityState(getPipeId(), ENTITY_STATE_FRAME_DONE);
if (ret < 0) {
CLOGE("ERR(%s[%d]):set entity state fail, ret(%d)", __FUNCTION__, __LINE__, ret);
return OK;
}
m_outputFrameQ->pushProcessQ(&newFrame);
return NO_ERROR;
}
bool ExynosCameraPipeUVS::m_mainThreadFunc(void)
{
int ret = 0;
bool loopFlag = false;
CLOGI("[ExynosCameraPipeUVS] Enter m_mainThreadFunc");
ret = m_run();
if (ret < 0) {
if (ret != TIMED_OUT)
CLOGE("ERR(%s):m_putBuffer fail", __FUNCTION__);
}
if (m_inputFrameQ->getSizeOfProcessQ() > 0)
loopFlag = true;
return loopFlag;
}
status_t ExynosCameraPipeUVS::m_init(int32_t *nodeNums)
{
if (nodeNums == NULL)
m_uvsNum = -1;
else
m_uvsNum = nodeNums[0];
m_uvs = NULL;
/*
* Load the UVSuppression libarry
* Initialize the UVSuppression library
*/
bUVSInit = false;
hUVS_object = NULL;
uvsHandle = NULL;
init_uvs = NULL;
run_uvs = NULL;
end_uvs = NULL;
char uvs_lib_path[] = UVS_LIBRARY_PATH;
int ret = NO_ERROR;
uvsHandle = dlopen(uvs_lib_path, RTLD_NOW);
if (uvsHandle == NULL) {
ALOGE("ERR(%s[%d]): UVS so handle is NULL : %s", __FUNCTION__, __LINE__, uvs_lib_path);
return INVALID_OPERATION;
}
init_uvs = (int(*)(UVS_params *))dlsym(uvsHandle, "exn_uvs_init");
if ((dlerror()!= NULL) && (init_uvs == NULL)) {
ALOGE("ERR(%s[%d]): exn_uvs_init dlsym error", __FUNCTION__, __LINE__);
goto CLEAN;
}
run_uvs = (int(*)(UVS_params *))dlsym(uvsHandle, "exn_uvs_run");
if ((dlerror()!= NULL) && (run_uvs == NULL)) {
ALOGE("ERR(%s[%d]): exn_uvs_run dlsym error", __FUNCTION__, __LINE__);
goto CLEAN;
}
end_uvs = (int(*)())dlsym(uvsHandle, "exn_uvs_end");
if ((dlerror()!= NULL) && (end_uvs == NULL)) {
ALOGE("ERR(%s[%d]): exn_uvs_end dlsym error", __FUNCTION__, __LINE__);
goto CLEAN;
}
/*
* Call the UVSuppression library initialization function.
*
*/
ret = (*init_uvs)(&m_uvsdynamicMeta);
CLOGI(" init_uvs ret : %d", ret);
return ret;
CLEAN:
if (uvsHandle != NULL) {
dlclose(uvsHandle);
}
return INVALID_OPERATION;
}
}; /* namespace android */