blob: c9992aa0b81e7f601d90e98e2852d307e30986ae [file] [log] [blame]
/*
* Copyright 2017, 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 "ExynosCameraNodeCIP"
#include"ExynosCameraNodeCIP.h"
#include"ExynosCameraUtils.h"
namespace android {
/* HACK */
exif_attribute_t exifInfo__;
ExynosCameraNodeCIP::ExynosCameraNodeCIP()
{
memset(m_name, 0x00, sizeof(m_name));
memset(m_alias, 0x00, sizeof(m_alias));
memset(&m_v4l2Format, 0x00, sizeof(struct v4l2_format));
memset(&m_v4l2ReqBufs, 0x00, sizeof(struct v4l2_requestbuffers));
//memset(&m_exifInfo, 0x00, sizeof(exif_attribute_t));
memset(&m_debugInfo, 0x00, sizeof(debug_attribute_t));
m_fd = NODE_INIT_NEGATIVE_VALUE;
m_v4l2Format.fmt.pix_mp.width = NODE_INIT_NEGATIVE_VALUE;
m_v4l2Format.fmt.pix_mp.height = NODE_INIT_NEGATIVE_VALUE;
m_v4l2Format.fmt.pix_mp.pixelformat = NODE_INIT_NEGATIVE_VALUE;
m_v4l2Format.fmt.pix_mp.num_planes = NODE_INIT_NEGATIVE_VALUE;
m_v4l2Format.fmt.pix_mp.colorspace = (enum v4l2_colorspace)7; /* V4L2_COLORSPACE_JPEG */
/*
* 7 : Full YuvRange, 4 : Limited YuvRange
* you can refer m_YUV_RANGE_2_V4L2_COLOR_RANGE() and m_V4L2_COLOR_RANGE_2_YUV_RANGE()
*/
m_v4l2ReqBufs.count = NODE_INIT_NEGATIVE_VALUE;
m_v4l2ReqBufs.memory = (v4l2_memory)NODE_INIT_ZERO_VALUE;
m_v4l2ReqBufs.type = (v4l2_buf_type)NODE_INIT_ZERO_VALUE;
m_crop.type = (v4l2_buf_type)NODE_INIT_ZERO_VALUE;
m_crop.c.top = NODE_INIT_ZERO_VALUE;
m_crop.c.left = NODE_INIT_ZERO_VALUE;
m_crop.c.width = NODE_INIT_ZERO_VALUE;
m_crop.c.height =NODE_INIT_ZERO_VALUE;
m_flagStart = false;
m_flagCreate = false;
memset(m_flagQ, 0x00, sizeof(m_flagQ));
m_flagStreamOn = false;
m_flagDup = false;
m_paramState = 0;
m_nodeState = 0;
m_cameraId = 0;
m_sensorId = -1;
m_videoNodeNum = -1;
for (uint32_t i = 0; i < MAX_BUFFERS; i++) {
m_queueBufferList[i].index = NODE_INIT_NEGATIVE_VALUE;
}
m_nodeType = NODE_TYPE_BASE;
m_cipMode = 0;
m_cipInterface = NULL;
m_nodeLocation = NODE_LOCATION_DST;
}
ExynosCameraNodeCIP::~ExynosCameraNodeCIP()
{
EXYNOS_CAMERA_NODE_IN();
destroy();
}
status_t ExynosCameraNodeCIP::create(
const char *nodeName,
int cameraId,
enum EXYNOS_CAMERA_NODE_LOCATION location,
void *module)
{
EXYNOS_CAMERA_NODE_IN();
status_t ret = NO_ERROR;
if (nodeName == NULL) {
CLOGE("nodeName is NULL!!");
return BAD_VALUE;
}
if (cameraId >= 0) {
setCameraId(cameraId);
}
if (module == NULL) {
CLOGD("cipInterface is NULL!!");
}
/*
* Parent's function was hided, because child's function was overrode.
* So, it should call parent's function explicitly.
*/
ret = ExynosCameraNode::create(nodeName, nodeName);
if (ret != NO_ERROR) {
CLOGE("create fail [%d]", (int)ret);
return ret;
}
m_cipInterface = (cipInterface *)module;
m_nodeType = NODE_TYPE_BASE;
m_nodeLocation = location;
EXYNOS_CAMERA_NODE_OUT();
return ret;
}
status_t ExynosCameraNodeCIP::open(int videoNodeNum)
{
if (m_cipInterface == NULL) {
CLOGE("m_cipInterface is NULL, Invalid function call");
return INVALID_OPERATION;
}
return open(videoNodeNum, -1);
}
status_t ExynosCameraNodeCIP::open(int videoNodeNum, int operationMode)
{
EXYNOS_CAMERA_NODE_IN();
CLOGV("open");
status_t ret = NO_ERROR;
char node_name[30];
if (m_nodeState != NODE_STATE_CREATED) {
CLOGE("m_nodeState = [%d] is not valid",
(int)m_nodeState);
return INVALID_OPERATION;
}
memset(&node_name, 0x00, sizeof(node_name));
snprintf(node_name, sizeof(node_name), "%s%d", NODE_PREFIX, videoNodeNum);
if (m_cipInterface == NULL) {
m_cipInterface = cip_create(operataionMode);
if (m_cipInterface == NULL) {
CLOGE("Cannot create cipInterface, mode(%d)", (int)operationMode);
return INVALID_OPERATION;
}
ret = cip_open(m_cipInterface);
if (ret != NO_ERROR) {
CLOGE("CIP open fail, ret(%d)", ret);
return ret;
}
CLOGI("CIP created");
}
m_cipMode = (cipMode)operationMode;
CLOGD("Node(%d)(%s) location(%d) opened.",
videoNodeNum, node_name, m_nodeLocation);
m_videoNodeNum = videoNodeNum;
m_nodeStateLock.lock();
m_nodeState = NODE_STATE_OPENED;
m_nodeStateLock.unlock();
EXYNOS_CAMERA_NODE_OUT();
return ret;
}
status_t ExynosCameraNodeCIP::close(void)
{
EXYNOS_CAMERA_NODE_IN();
CLOGD("close");
status_t ret = NO_ERROR;
if (m_nodeState == NODE_STATE_CREATED) {
CLOGE("m_nodeState = [%d] is not valid",
(int)m_nodeState);
return INVALID_OPERATION;
}
if (m_cipInterface != NULL) {
if (m_videoNodeNum == FIMC_IS_VIDEO_CIP0S_NUM) {
ret = cip_close(m_cipInterface);
if (ret != NO_ERROR) {
CLOGE("close fail");
return ret;
}
ret = cip_destroy(&m_cipInterface);
if (ret != NO_ERROR) {
CLOGE("destory fail");
return ret;
}
delete m_cipInterface;
}
m_cipInterface = NULL;
}
m_nodeType = NODE_TYPE_BASE;
m_videoNodeNum = -1;
m_nodeStateLock.lock();
m_nodeState = NODE_STATE_CREATED;
m_nodeStateLock.unlock();
EXYNOS_CAMERA_NODE_OUT();
return ret;
}
status_t ExynosCameraNodeJpegHAL::getInternalModule(void **module)
{
*module = m_cipInterface;
if (m_cipInterface == NULL) {
return BAD_VALUE;
}
return NO_ERROR;
}
status_t ExynosCameraNodeCIP::setColorFormat(int v4l2Colorformat, __unused int planeCount, __unused int batchSize,
__unused enum YUV_RANGE yuvRange, __unused camera_pixel_size pixelSize)
{
EXYNOS_CAMERA_NODE_IN();
status_t ret = NO_ERROR;
m_nodeStateLock.lock();
if (m_nodeState != NODE_STATE_IN_PREPARE && m_nodeState != NODE_STATE_OPENED) {
CLOGE("m_nodeState = [%d] is not valid",
(int)m_nodeState);
m_nodeStateLock.unlock();
return INVALID_OPERATION;
}
CLOGD("format %d(%c %c %c %c), yuvRange %d",
v4l2Colorformat,
(char)((v4l2Colorformat >> 0) & 0xFF),
(char)((v4l2Colorformat >> 8) & 0xFF),
(char)((v4l2Colorformat >> 16) & 0xFF),
(char)((v4l2Colorformat >> 24) & 0xFF),
m_v4l2Format.fmt.pix_mp.colorspace);
if(m_nodeLocation == NODE_LOCATION_SRC) {
ret = cip_setColorFormat(m_cipInterface, v4l2Colorformat);
} else {
ret = cip_setColorFormat(m_cipInterface, v4l2Colorformat);
}
if (ret != NO_ERROR) {
CLOGE("CIP setColorFormat fail, ret(%d)", ret);
}
m_nodeState = NODE_STATE_IN_PREPARE;
m_nodeStateLock.unlock();
EXYNOS_CAMERA_NODE_OUT();
return ret;
}
status_t ExynosCameraNodeCIP::setSize(int w, int h)
{
EXYNOS_CAMERA_NODE_IN();
status_t ret = NO_ERROR;
m_nodeStateLock.lock();
if (m_nodeState != NODE_STATE_IN_PREPARE && m_nodeState != NODE_STATE_OPENED) {
CLOGE("m_nodeState = [%d] is not valid",
(int)m_nodeState);
m_nodeStateLock.unlock();
return INVALID_OPERATION;
}
CLOGD("w (%d) h (%d)", w, h);
if (m_videoNodeNum == FIMC_IS_VIDEO_CIP0S_NUM) {
ret = cip_prepare(m_cipInterface, w, h, w, h);
if (ret != NO_ERROR) {
CLOGE("CIP prepare fail, ret(%d)", ret);
}
}
m_nodeState = NODE_STATE_IN_PREPARE;
m_nodeStateLock.unlock();
EXYNOS_CAMERA_NODE_OUT();
return ret;
}
status_t ExynosCameraNodeCIP::reqBuffers(void)
{
return NO_ERROR;
}
status_t ExynosCameraNodeCIP::clrBuffers(void)
{
return NO_ERROR;
}
unsigned int ExynosCameraNodeCIP::reqBuffersCount(void)
{
return NO_ERROR;
}
status_t ExynosCameraNodeCIP::setControl(__unused unsigned int id, __unused int value)
{
return NO_ERROR;
}
status_t ExynosCameraNodeCIP::getControl(__unused unsigned int id, __unused int *value)
{
return NO_ERROR;
}
status_t ExynosCameraNodeCIP::polling(void)
{
return NO_ERROR;
}
status_t ExynosCameraNodeCIP::setInput(int sensorId)
{
m_sensorId = sensorId;
return NO_ERROR;
}
status_t ExynosCameraNodeCIP::setFormat(void)
{
return NO_ERROR;
}
status_t ExynosCameraNodeCIP::setFormat(__unused unsigned int bytesPerPlane[])
{
return NO_ERROR;
}
status_t ExynosCameraNodeCIP::setCrop(__unused enum v4l2_buf_type type,
__unused int x, __unused int y, __unused int w, __unused int h)
{
return NO_ERROR;
}
status_t ExynosCameraNodeCIP::start(void)
{
return NO_ERROR;
}
status_t ExynosCameraNodeCIP::stop(void)
{
return NO_ERROR;
}
status_t ExynosCameraNodeCIP::prepareBuffer(ExynosCameraBuffer *buf)
{
status_t ret = NO_ERROR;
return NO_ERROR;
}
status_t ExynosCameraNodeCIP::putBuffer(ExynosCameraBuffer *buf)
{
status_t ret = NO_ERROR;
if (buf == NULL) {
CLOGE("buffer is NULL");
return BAD_VALUE;
}
#if 0
if (m_nodeState != NODE_STATE_RUNNING) {
CLOGE("m_nodeState = [%d] is not valid",
(int)m_nodeState);
return INVALID_OPERATION;
}
#endif
cip_buffer_t *cipBuffer;
cip_in_buffer_t property = CIP_WIDE_YUV;
cipBuffer->planeCount = buf->planeCount;
for (int i = 0; i < buf->planeCount; i++) {
cipBuffer->fd[i] = buf->fd[i];
cipBuffer->size[i] = buf->size[i];
cipBuffer->addr[i] = buf->addr[i];
}
switch (m_videoNodeNum) {
case FIMC_IS_VIDEO_CIP0S_NUM:
if (m_cipMode == 0) {
property = CIP_WIDE_YUV;
} else {
property = CIP_TELE_YUV;
}
ret = cip_setInBuf(m_cipInterface, property, rect, cipBuffer);
if (ret != NO_ERROR) {
CLOGE("CIP setInBuffer fail, ret(%d)", ret);
return ret;
}
ret = cip_updateConfig(m_cipInterface);
if (ret != NO_ERROR) {
CLOGE("CIP updateConfig fail, ret(%d)", ret);
return ret;
}
ret = cip_execute(m_cipInterface);
if (ret != NO_ERROR) {
CLOGE("CIP execute fail, ret(%d)", ret);
return ret;
}
break;
case FIMC_IS_VIDEO_CIP1S_NUM:
property = CIP_TELE_YUV;
ret = cip_setInBuf(m_cipInterface, property, rect, cipBuffer);
if (ret != NO_ERROR) {
CLOGE("CIP setInBuffer fail, ret(%d)", ret);
return ret;
}
break;
case FIMC_IS_VIDEO_CIP2S_NUM:
property = CIP_DEPTH_MAP;
ret = cip_setInBuf(m_cipInterface, property, rect, cipBuffer);
if (ret != NO_ERROR) {
CLOGE("CIP setInBuffer fail, ret(%d)", ret);
return ret;
}
break;
case FIMC_IS_VIDEO_CIP0C_NUM:
ret = cip_setOutBuf(m_cipInterface, cipBuffer);
if (ret != NO_ERROR) {
CLOGE("CIP setInBuffer fail, ret(%d)", ret);
return ret;
}
break;
default:
CLOGE("Invalid node num(%d)", ret);
break;
}
m_buffer = *buf;
return NO_ERROR;
}
status_t ExynosCameraNodeCIP::getBuffer(ExynosCameraBuffer *buf, int *dqIndex)
{
status_t ret = NO_ERROR;
#if 0
if (m_nodeState != NODE_STATE_RUNNING) {
CLOGE("m_nodeState = [%d] is not valid",
(int)m_nodeState);
return INVALID_OPERATION;
}
#endif
if (m_videoNodeNum == FIMC_IS_VIDEO_CIP0S_NUM) {
ret = cip_waitDone(m_cipInterface);
if (ret != NO_ERROR) {
CLOGE("CIP waitDone fail, ret(%d)", ret);
return ret;
}
}
*buf = m_buffer;
*dqIndex = m_buffer.index;
return ret;
}
void ExynosCameraNodeCIP::dump(void)
{
dumpState();
dumpQueue();
return;
}
void ExynosCameraNodeCIP::dumpState(void)
{
CLOGD("");
if (strnlen(m_name, sizeof(char) * EXYNOS_CAMERA_NAME_STR_SIZE) > 0 )
CLOGD("m_name[%s]", m_name);
if (strnlen(m_alias, sizeof(char) * EXYNOS_CAMERA_NAME_STR_SIZE) > 0 )
CLOGD("m_alias[%s]", m_alias);
CLOGD("m_fd[%d], width[%d], height[%d]",
m_fd,
m_v4l2Format.fmt.pix_mp.width,
m_v4l2Format.fmt.pix_mp.height);
CLOGD("m_format[%d], m_planes[%d], m_buffers[%d], m_memory[%d]",
m_v4l2Format.fmt.pix_mp.pixelformat,
m_v4l2Format.fmt.pix_mp.num_planes,
m_v4l2ReqBufs.count,
m_v4l2ReqBufs.memory);
CLOGD("m_type[%d], m_flagStart[%d], m_flagCreate[%d]",
m_v4l2ReqBufs.type,
m_flagStart,
m_flagCreate);
CLOGD("m_crop type[%d], X : Y[%d : %d], W : H[%d : %d]",
m_crop.type,
m_crop.c.top,
m_crop.c.left,
m_crop.c.width,
m_crop.c.height);
CLOGI("Node state(%d)", m_nodeRequest.getState());
return;
}
void ExynosCameraNodeCIP::dumpQueue(void)
{
return;
}
};