| /* |
| ** |
| ** 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 "ExynosCameraMCPipe" |
| #include <cutils/log.h> |
| |
| #include "ExynosCameraMCPipe.h" |
| |
| namespace android { |
| |
| ExynosCameraMCPipe::~ExynosCameraMCPipe() |
| { |
| this->destroy(); |
| } |
| |
| status_t ExynosCameraMCPipe::create(int32_t *sensorIds) |
| { |
| CLOGD("DEBUG(%s[%d])", __FUNCTION__, __LINE__); |
| status_t ret = NO_ERROR; |
| |
| ret = m_preCreate(); |
| if (ret != NO_ERROR) { |
| CLOGE("ERR(%s[%d]):m_preCreate() fail, ret(%d)", __FUNCTION__, __LINE__, ret); |
| return ret; |
| } |
| |
| ret = m_postCreate(sensorIds); |
| if (ret != NO_ERROR) { |
| CLOGE("ERR(%s[%d]):m_postCreate() fail, ret(%d)", __FUNCTION__, __LINE__, ret); |
| return ret; |
| } |
| |
| return ret; |
| } |
| |
| #ifdef SAMSUNG_COMPANION |
| status_t ExynosCameraMCPipe::precreate(int32_t *sensorIds) |
| { |
| CLOGD("DEBUG(%s[%d])", __FUNCTION__, __LINE__); |
| status_t ret = NO_ERROR; |
| |
| ret = m_preCreate(); |
| if (ret != NO_ERROR) { |
| CLOGE("ERR(%s[%d]):m_preCreate() fail, ret(%d)", __FUNCTION__, __LINE__, ret); |
| return ret; |
| } |
| |
| return ret; |
| } |
| |
| status_t ExynosCameraMCPipe::postcreate(int32_t *sensorIds) |
| { |
| CLOGD("DEBUG(%s[%d])", __FUNCTION__, __LINE__); |
| status_t ret = NO_ERROR; |
| |
| ret = m_postCreate(sensorIds); |
| if (ret != NO_ERROR) { |
| CLOGE("ERR(%s[%d]):m_postCreate() fail, ret(%d)", __FUNCTION__, __LINE__, ret); |
| return ret; |
| } |
| |
| CLOGI("INFO(%s[%d]):postcreate() is succeed, Pipe(%d)", __FUNCTION__, __LINE__, getPipeId()); |
| |
| return ret; |
| } |
| #endif |
| |
| status_t ExynosCameraMCPipe::destroy(void) |
| { |
| CLOGD("DEBUG(%s[%d])", __FUNCTION__, __LINE__); |
| status_t ret = NO_ERROR; |
| |
| for (int i = (MAX_NODE - 1); i >= OUTPUT_NODE; i--) { |
| if (m_node[i] != NULL) { |
| if (OUTPUT_NODE < i |
| && m_node[OUTPUT_NODE] != NULL |
| && m_deviceInfo->nodeNum[OUTPUT_NODE] == m_deviceInfo->nodeNum[i]) { |
| /* In this case(3AA of 54xx), 3AA, 3AP node is same. |
| * So, should close one node. Skip 3AP node. |
| */ |
| } else { |
| ret = m_node[i]->close(); |
| if (ret != NO_ERROR) { |
| CLOGE("ERR(%s[%d]):Main node(%s) close fail, ret(%d)", |
| __FUNCTION__, __LINE__, m_deviceInfo->nodeName[i], ret); |
| return ret; |
| } |
| } |
| |
| SAFE_DELETE(m_node[i]); |
| CLOGD("DEBUG(%s[%d]):Main node(%s, sensorIds:%d) closed", |
| __FUNCTION__, __LINE__, m_deviceInfo->nodeName[i], m_sensorIds[i]); |
| } |
| } |
| |
| for (int i = (MAX_NODE - 1); i >= OUTPUT_NODE; i--) { |
| if (m_secondaryNode[i] != NULL) { |
| ret = m_secondaryNode[i]->close(); |
| if (ret != NO_ERROR) { |
| CLOGE("ERR(%s[%d]):secondary node(%s) close fail, ret(%d)", |
| __FUNCTION__, __LINE__, m_deviceInfo->secondaryNodeName[i], ret); |
| return ret; |
| } |
| SAFE_DELETE(m_secondaryNode[i]); |
| CLOGD("DEBUG(%s[%d]):secondary node(%s, sensorIds:%d) closed", |
| __FUNCTION__, __LINE__, m_deviceInfo->secondaryNodeName[i], m_secondarySensorIds[i]); |
| } |
| } |
| |
| CLOGD("DEBUG(%s[%d]):Node destroyed", __FUNCTION__, __LINE__); |
| |
| if (m_inputFrameQ != NULL) { |
| m_inputFrameQ->release(); |
| SAFE_DELETE(m_inputFrameQ); |
| } |
| |
| if (m_requestFrameQ != NULL) { |
| m_requestFrameQ->release(); |
| SAFE_DELETE(m_requestFrameQ); |
| } |
| |
| CLOGI("INFO(%s[%d]):destroy() is succeed, Pipe(%d)", __FUNCTION__, __LINE__, getPipeId()); |
| |
| return ret; |
| } |
| |
| status_t ExynosCameraMCPipe::setupPipe(camera_pipe_info_t *pipeInfos, int32_t *sensorIds) |
| { |
| status_t ret = NO_ERROR; |
| |
| ret = this->setupPipe(pipeInfos, sensorIds, NULL); |
| |
| return ret; |
| } |
| |
| status_t ExynosCameraMCPipe::setupPipe(camera_pipe_info_t *pipeInfos, int32_t *sensorIds, int32_t *secondarySensorIds) |
| { |
| CLOGD("DEBUG(%s[%d])", __FUNCTION__, __LINE__); |
| status_t ret = NO_ERROR; |
| uint32_t pipeId = 0; |
| int result = 0; |
| ExynosCameraNode *setFileSettingNode = NULL; |
| |
| /* TODO: check node state */ |
| |
| /* set new sensorId to m_sensorIds */ |
| if (sensorIds != NULL) { |
| CLOGD("DEBUG(%s[%d]):set new sensorIds", __FUNCTION__, __LINE__); |
| for (int i = OUTPUT_NODE; i < MAX_NODE; i++) |
| m_sensorIds[i] = sensorIds[i]; |
| } |
| |
| if (secondarySensorIds != NULL) { |
| CLOGD("DEBUG(%s[%d]):set new ispSensorIds", __FUNCTION__, __LINE__); |
| for (int i = OUTPUT_NODE; i < MAX_NODE; i++) |
| m_secondarySensorIds[i] = secondarySensorIds[i]; |
| } |
| |
| ret = m_setInput(m_node, m_deviceInfo->nodeNum, m_sensorIds); |
| if (ret != NO_ERROR) { |
| CLOGE("ERR(%s[%d]):m_setInput(Main) fail, ret(%d)", __FUNCTION__, __LINE__, ret); |
| return ret; |
| } |
| |
| ret = m_setInput(m_secondaryNode, m_deviceInfo->secondaryNodeNum, m_secondarySensorIds); |
| if (ret != NO_ERROR) { |
| CLOGE("ERR(%s[%d]):m_setInput(secondary) fail, ret(%d)", __FUNCTION__, __LINE__, ret); |
| return ret; |
| } |
| |
| if (pipeInfos != NULL) { |
| ret = m_setPipeInfo(pipeInfos); |
| if (ret != NO_ERROR) { |
| CLOGE("ERR(%s[%d]):m_setPipeInfo() fail, ret(%d)", __FUNCTION__, __LINE__, ret); |
| return ret; |
| } |
| } else { |
| CLOGE("ERR(%s[%d]):pipeInfos is NULL", __FUNCTION__, __LINE__); |
| return BAD_VALUE; |
| } |
| |
| for (int i = OUTPUT_NODE; i < MAX_NODE; i++) { |
| result = getPipeId((enum NODE_TYPE)i); |
| if (0 <= result) { |
| if (m_node[i] != NULL) |
| setFileSettingNode = m_node[i]; |
| else if (m_secondaryNode[i] != NULL) |
| setFileSettingNode = m_secondaryNode[i]; |
| else |
| continue; |
| |
| pipeId = (uint32_t)result; |
| |
| ret = m_setSetfile(setFileSettingNode, pipeId); |
| if (ret != NO_ERROR) { |
| CLOGE("ERR(%s[%d]):m_setSetfile() fail, ret(%d)", __FUNCTION__, __LINE__, ret); |
| return ret; |
| } |
| } |
| |
| for (uint32_t j = 0; j < m_numBuffers[i]; j++) { |
| m_runningFrameList[i][j] = NULL; |
| } |
| m_numOfRunningFrame[i] = 0; |
| } |
| |
| m_prepareBufferCount = m_exynosconfig->current->pipeInfo.prepare[getPipeId()]; |
| |
| CLOGI("INFO(%s[%d]):setupPipe() is succeed, Pipe(%d), prepare(%d)", __FUNCTION__, __LINE__, getPipeId(), m_prepareBufferCount); |
| |
| return ret; |
| } |
| |
| status_t ExynosCameraMCPipe::prepare(void) |
| { |
| /* need modify */ |
| CLOGD("DEBUG(%s[%d])", __FUNCTION__, __LINE__); |
| status_t ret = NO_ERROR; |
| uint32_t nodeCount = 0; |
| |
| /* |
| * prepare on only capture node |
| * output node doesn't need prepare |
| */ |
| for (uint32_t i = 0; i < m_prepareBufferCount; i++) { |
| ret = m_putBufferThreadFunc(); |
| if (ret == false) { |
| CLOGE("WRN(%s):m_putBufferThreadFunc no Frame(count = %d)", __FUNCTION__, m_inputFrameQ->getSizeOfProcessQ()); |
| } |
| } |
| |
| CLOGI("INFO(%s[%d]):prepare() is succeed, Pipe(%d), prepare(%d)", |
| __FUNCTION__, __LINE__, getPipeId(), m_prepareBufferCount); |
| |
| return ret; |
| } |
| |
| status_t ExynosCameraMCPipe::start(void) |
| { |
| CLOGD("DEBUG(%s[%d])", __FUNCTION__, __LINE__); |
| status_t ret = NO_ERROR; |
| |
| /* TODO: check state ready for start */ |
| ret = m_startNode(); |
| if (ret != NO_ERROR) { |
| CLOGE("ERR(%s[%d]):m_startNode() fail, ret(%d)", __FUNCTION__, __LINE__, ret); |
| return ret; |
| } |
| |
| m_threadState = 0; |
| m_threadRenew = 0; |
| |
| m_flagStartPipe = true; |
| m_flagTryStop = false; |
| |
| CLOGI("INFO(%s[%d]):start() is succeed, Pipe(%d)", __FUNCTION__, __LINE__, getPipeId()); |
| |
| return ret; |
| } |
| |
| status_t ExynosCameraMCPipe::stop(void) |
| { |
| CLOGD("DEBUG(%s[%d])", __FUNCTION__, __LINE__); |
| status_t ret = NO_ERROR; |
| |
| ret = m_stopNode(); |
| if (ret != NO_ERROR) { |
| CLOGE("ERR(%s[%d]):m_stopNode() fail, ret(%d)", __FUNCTION__, __LINE__, ret); |
| return ret; |
| } |
| |
| m_putBufferThread->requestExitAndWait(); |
| m_getBufferThread->requestExitAndWait(); |
| |
| CLOGD("DEBUG(%s[%d]):Thread exited", __FUNCTION__, __LINE__); |
| |
| m_inputFrameQ->release(); |
| m_requestFrameQ->release(); |
| |
| for (int i = OUTPUT_NODE; i < MAX_NODE; i++) { |
| for (uint32_t j = 0; j < m_numBuffers[i]; j++) { |
| m_runningFrameList[i][j] = NULL; |
| } |
| m_numOfRunningFrame[i] = 0; |
| m_skipBuffer[i].index = -2; |
| m_skipPutBuffer[i] = false; |
| |
| if (m_node[i] != NULL) |
| m_node[i]->removeItemBufferQ(); |
| |
| } |
| |
| m_flagStartPipe = false; |
| m_flagTryStop = false; |
| |
| CLOGI("INFO(%s[%d]):stop() is succeed, Pipe(%d)", __FUNCTION__, __LINE__, getPipeId()); |
| |
| return ret; |
| } |
| |
| bool ExynosCameraMCPipe::flagStart(void) |
| { |
| return m_flagStartPipe; |
| } |
| |
| status_t ExynosCameraMCPipe::startThread(void) |
| { |
| CLOGD("DEBUG(%s[%d])", __FUNCTION__, __LINE__); |
| status_t ret = NO_ERROR; |
| |
| if (m_outputFrameQ == NULL) { |
| CLOGE("ERR(%s[%d]):outputFrameQ is NULL, cannot start", __FUNCTION__, __LINE__); |
| return INVALID_OPERATION; |
| } |
| |
| m_putBufferThread->run(PRIORITY_URGENT_DISPLAY); |
| m_getBufferThread->run(PRIORITY_URGENT_DISPLAY); |
| |
| CLOGI("INFO(%s[%d]):startThread is succeed, Pipe(%d)", __FUNCTION__, __LINE__, getPipeId()); |
| |
| return ret; |
| } |
| |
| status_t ExynosCameraMCPipe::stopThread(void) |
| { |
| CLOGD("DEBUG(%s[%d])", __FUNCTION__, __LINE__); |
| status_t ret = NO_ERROR; |
| |
| m_putBufferThread->requestExit(); |
| m_getBufferThread->requestExit(); |
| |
| m_inputFrameQ->sendCmd(WAKE_UP); |
| m_requestFrameQ->sendCmd(WAKE_UP); |
| |
| m_dumpRunningFrameList(); |
| |
| CLOGI("INFO(%s[%d]):stopThread is succeed, Pipe(%d)", __FUNCTION__, __LINE__, getPipeId()); |
| |
| return ret; |
| } |
| |
| status_t ExynosCameraMCPipe::stopThreadAndWait(int sleep, int times) |
| { |
| CLOGD("DEBUG(%s[%d]) IN", __FUNCTION__, __LINE__); |
| status_t status = NO_ERROR; |
| int i = 0; |
| |
| for (i = 0; i < times ; i++) { |
| if (m_putBufferThread->isRunning() == false && m_getBufferThread->isRunning() == false) { |
| break; |
| } |
| usleep(sleep * 1000); |
| } |
| |
| if (i >= times) { |
| status = TIMED_OUT; |
| CLOGE("ERR(%s[%d]): stopThreadAndWait failed, waitTime(%d)ms", __FUNCTION__, __LINE__, sleep*times); |
| } |
| |
| CLOGD("DEBUG(%s[%d]) OUT", __FUNCTION__, __LINE__); |
| return status; |
| } |
| |
| bool ExynosCameraMCPipe::flagStartThread(void) |
| { |
| return m_putBufferThread->isRunning(); |
| } |
| |
| status_t ExynosCameraMCPipe::sensorStream(bool on) |
| { |
| CLOGD("DEBUG(%s[%d])", __FUNCTION__, __LINE__); |
| status_t ret = NO_ERROR; |
| |
| int value = on ? IS_ENABLE_STREAM : IS_DISABLE_STREAM; |
| |
| for (int i = OUTPUT_NODE; i < MAX_NODE; i++) { |
| if (m_node[i] != NULL) { |
| ret = m_node[i]->setControl(V4L2_CID_IS_S_STREAM, value); |
| if (ret != NO_ERROR) |
| CLOGE("ERR(%s[%d]):sensorStream failed, %s node, ret(%d)", |
| __FUNCTION__, __LINE__, m_deviceInfo->nodeName[i], ret); |
| |
| return ret; |
| } |
| } |
| |
| CLOGE("ERR(%s[%d]):All Nodes is NULL", __FUNCTION__, __LINE__); |
| |
| return INVALID_OPERATION; |
| } |
| |
| status_t ExynosCameraMCPipe::forceDone(unsigned int cid, int value) |
| { |
| CLOGD("DEBUG(%s[%d])", __FUNCTION__, __LINE__); |
| status_t ret = NO_ERROR; |
| |
| if (m_node[OUTPUT_NODE] == NULL) { |
| CLOGD("DEBUG(%s[%d]):m_node[OUTPUT_NODE] is NULL. just ignore", __FUNCTION__, __LINE__); |
| return ret; |
| } |
| |
| ret = m_forceDone(m_node[OUTPUT_NODE], cid, value); |
| if (ret != NO_ERROR) { |
| CLOGE("ERR(%s):m_forceDone() is failed, ret", __FUNCTION__); |
| return ret; |
| } |
| |
| CLOGI("INFO(%s[%d]):forceDone() is succeed, Pipe(%d)", __FUNCTION__, __LINE__, getPipeId()); |
| |
| return ret; |
| } |
| |
| status_t ExynosCameraMCPipe::setControl(int cid, int value) |
| { |
| CLOGD("DEBUG(%s[%d])", __FUNCTION__, __LINE__); |
| status_t ret = NO_ERROR; |
| |
| for (int i = OUTPUT_NODE; i < MAX_NODE; i++) { |
| if (m_node[i] != NULL) { |
| ret = m_node[i]->setControl(cid, value); |
| if (ret != NO_ERROR) { |
| CLOGE("ERR(%s[%d]):m_node(%s)->setControl failed, ret(%d)", |
| __FUNCTION__, __LINE__, m_deviceInfo->nodeName[i], ret); |
| return ret; |
| } |
| CLOGI("INFO(%s[%d]):setControl() is succeed, Pipe(%d)", __FUNCTION__, __LINE__, getPipeId((enum NODE_TYPE)i)); |
| return ret; |
| } |
| } |
| |
| CLOGE("ERR(%s[%d]):All nodes is NULL", __FUNCTION__, __LINE__); |
| |
| return INVALID_OPERATION; |
| } |
| |
| status_t ExynosCameraMCPipe::setControl(int cid, int value, enum NODE_TYPE nodeType) |
| { |
| CLOGD("DEBUG(%s[%d])", __FUNCTION__, __LINE__); |
| status_t ret = NO_ERROR; |
| |
| if (m_node[nodeType] == NULL) { |
| CLOGE("ERR(%s[%d]):m_node[%d] == NULL. so, fail", __FUNCTION__, __LINE__, nodeType); |
| return INVALID_OPERATION; |
| } |
| |
| ret = m_node[nodeType]->setControl(cid, value); |
| if (ret != NO_ERROR) { |
| CLOGE("ERR(%s[%d]):m_node(%s)->setControl failed, ret(%d)", |
| __FUNCTION__, __LINE__, m_deviceInfo->nodeName[nodeType], ret); |
| return ret; |
| } |
| CLOGI("INFO(%s[%d]):setControl() is succeed, Pipe(%d)", __FUNCTION__, __LINE__, getPipeId()); |
| return ret; |
| } |
| |
| status_t ExynosCameraMCPipe::getControl(int cid, int *value) |
| { |
| CLOGV("DEBUG(%s[%d])", __FUNCTION__, __LINE__); |
| status_t ret = NO_ERROR; |
| uint32_t nodeCount = 0; |
| |
| for (int i = OUTPUT_NODE; i < MAX_NODE; i++) { |
| if (m_node[i] != NULL) { |
| ret = m_node[i]->getControl(cid, value); |
| if (ret != NO_ERROR) { |
| CLOGE("ERR(%s[%d]):m_node(%s)->getControl failed, ret(%d)", |
| __FUNCTION__, __LINE__, m_deviceInfo->nodeName[i], ret); |
| return ret; |
| } |
| CLOGI("INFO(%s[%d]):getControl() is succeed, Pipe(%d)", __FUNCTION__, __LINE__, getPipeId((enum NODE_TYPE)i)); |
| return ret; |
| } |
| } |
| |
| CLOGE("ERR(%s[%d]):All nodes is NULL", __FUNCTION__, __LINE__); |
| |
| return INVALID_OPERATION; |
| } |
| |
| status_t ExynosCameraMCPipe::getControl(int cid, int *value, enum NODE_TYPE nodeType) |
| { |
| CLOGD("DEBUG(%s[%d])", __FUNCTION__, __LINE__); |
| status_t ret = NO_ERROR; |
| |
| if (m_node[nodeType] == NULL) { |
| CLOGE("ERR(%s[%d]):m_node[%d] == NULL. so, fail", __FUNCTION__, __LINE__, nodeType); |
| return INVALID_OPERATION; |
| } |
| |
| ret = m_node[nodeType]->getControl(cid, value); |
| if (ret != NO_ERROR) { |
| CLOGE("ERR(%s[%d]):m_node(%s)->getControl failed, ret(%d)", |
| __FUNCTION__, __LINE__, m_deviceInfo->nodeName[nodeType], ret); |
| return ret; |
| } |
| CLOGI("INFO(%s[%d]):getControl() is succeed, Pipe(%d)", __FUNCTION__, __LINE__, getPipeId()); |
| return ret; |
| } |
| |
| status_t ExynosCameraMCPipe::setParam(struct v4l2_streamparm streamParam) |
| { |
| CLOGD("DEBUG(%s[%d])", __FUNCTION__, __LINE__); |
| status_t ret = NO_ERROR; |
| uint32_t nodeCount = 0; |
| |
| for (int i = OUTPUT_NODE; i < MAX_NODE; i++) { |
| if (m_node[i] != NULL) { |
| ret = m_node[i]->setParam(&streamParam); |
| if (ret != NO_ERROR) { |
| CLOGE("ERR(%s[%d]):m_node(%s)->setParam failed, ret(%d)", |
| __FUNCTION__, __LINE__, m_deviceInfo->nodeName[i], ret); |
| return ret; |
| } |
| CLOGI("INFO(%s[%d]):setParam() is succeed, Pipe(%d)", __FUNCTION__, __LINE__, getPipeId((enum NODE_TYPE)i)); |
| return ret; |
| } |
| } |
| |
| CLOGE("ERR(%s[%d]):All nodes is NULL", __FUNCTION__, __LINE__); |
| |
| return INVALID_OPERATION; |
| } |
| |
| status_t ExynosCameraMCPipe::pushFrame(ExynosCameraFrame **newFrame) |
| { |
| Mutex::Autolock lock(m_pipeframeLock); |
| if (newFrame == NULL) { |
| CLOGE("ERR(%s):newFrame is NULL", __FUNCTION__); |
| return BAD_VALUE; |
| } |
| |
| m_inputFrameQ->pushProcessQ(newFrame); |
| |
| return NO_ERROR; |
| } |
| |
| status_t ExynosCameraMCPipe::instantOn(int32_t numFrames) |
| { |
| CLOGD("DEBUG(%s[%d])", __FUNCTION__, __LINE__); |
| status_t ret = NO_ERROR; |
| uint32_t nodeCount = 0; |
| ExynosCameraFrame *newFrame = NULL; |
| ExynosCameraBuffer newBuffer; |
| |
| if (m_inputFrameQ->getSizeOfProcessQ() != numFrames) { |
| CLOGE("ERR(%s[%d]):instantOn need %d Frames, but %d Frames are queued", |
| __FUNCTION__, __LINE__, numFrames, m_inputFrameQ->getSizeOfProcessQ()); |
| return BAD_VALUE; |
| } |
| |
| for (int i = (MAX_NODE - 1); i >= OUTPUT_NODE; i--) { |
| if (m_node[i] != NULL) { |
| ret = m_node[i]->start(); |
| if (ret != NO_ERROR) { |
| CLOGE("ERR(%s[%d]):node(%s) instantOn fail, ret(%d)", |
| __FUNCTION__, __LINE__, m_deviceInfo->nodeName[i], ret); |
| return ret; |
| } |
| nodeCount++; |
| } |
| } |
| |
| if (nodeCount == 0) { |
| CLOGE("ERR(%s[%d]):All nodes is NULL", __FUNCTION__, __LINE__); |
| return INVALID_OPERATION; |
| } |
| |
| for (int i = 0; i < numFrames; i++) { |
| ret = m_inputFrameQ->popProcessQ(&newFrame); |
| if (ret != NO_ERROR) { |
| CLOGE("ERR(%s[%d]):Wait and pop fail, ret(%d)", __FUNCTION__, __LINE__, ret); |
| return ret; |
| } |
| |
| if (newFrame == NULL) { |
| CLOGE("ERR(%s[%d]):newFrame is NULL", __FUNCTION__, __LINE__); |
| return INVALID_OPERATION; |
| } |
| |
| ret = newFrame->getSrcBuffer(getPipeId(), &newBuffer); |
| if (ret != NO_ERROR) { |
| CLOGE("ERR(%s[%d]):Frame get buffer fail, ret(%d)", __FUNCTION__, __LINE__, ret); |
| return ret; |
| } |
| |
| if (m_node[OUTPUT_NODE] != NULL) { |
| CLOGD("DEBUG(%s[%d]):Put instantOn Buffer (index %d)", __FUNCTION__, __LINE__, newBuffer.index); |
| |
| ret = m_node[OUTPUT_NODE]->putBuffer(&newBuffer); |
| if (ret != NO_ERROR) { |
| CLOGE("ERR(%s[%d]):putBuffer() fail, ret(%d)", __FUNCTION__, __LINE__, ret); |
| return ret; |
| /* TODO: doing exception handling */ |
| } |
| } else { |
| CLOGE("ERR(%s[%d]):m_node[OUTPUT_NODE] is NULL", __FUNCTION__, __LINE__); |
| return INVALID_OPERATION; |
| } |
| } |
| |
| CLOGI("INFO(%s[%d]):instantOn() is succeed, Pipe(%d), Frames(%d)", |
| __FUNCTION__, __LINE__, getPipeId(), numFrames); |
| |
| return ret; |
| } |
| |
| /* Don't use this function, this is regacy code */ |
| status_t ExynosCameraMCPipe::instantOnQbuf(ExynosCameraFrame **frame, BUFFER_POS::POS pos) |
| { |
| if (m_node[OUTPUT_NODE] == NULL) { |
| CLOGE("ERR(%s): m_mainNode == NULL. so, fail", __FUNCTION__); |
| return INVALID_OPERATION; |
| } |
| |
| ExynosCameraFrame *newFrame = NULL; |
| ExynosCameraBuffer newBuffer; |
| int ret = 0; |
| ret = m_inputFrameQ->waitAndPopProcessQ(&newFrame); |
| if (ret < 0) { |
| /* TODO: We need to make timeout duration depends on FPS */ |
| if (ret == TIMED_OUT) { |
| CLOGW("WARN(%s):wait timeout", __FUNCTION__); |
| m_mainNode->dumpState(); |
| } else { |
| CLOGE("ERR(%s):wait and pop fail, ret(%d)", __FUNCTION__, ret); |
| /* TODO: doing exception handling */ |
| } |
| return ret; |
| } |
| |
| if (newFrame == NULL) { |
| CLOGE("ERR(%s):newFrame is NULL", __FUNCTION__); |
| return INVALID_OPERATION; |
| } |
| |
| if(pos == BUFFER_POS::DST) |
| ret = newFrame->getDstBuffer(getPipeId(), &newBuffer); |
| else if(pos == BUFFER_POS::SRC) |
| ret = newFrame->getSrcBuffer(getPipeId(), &newBuffer); |
| |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]):frame get buffer fail, ret(%d)", __FUNCTION__, __LINE__, ret); |
| /* TODO: doing exception handling */ |
| return OK; |
| } |
| |
| if (m_runningFrameList[OUTPUT_NODE][newBuffer.index] != NULL) { |
| CLOGE("ERR(%s):new buffer is invalid, we already get buffer index(%d), newFrame->frameCount(%d)", |
| __FUNCTION__, newBuffer.index, newFrame->getFrameCount()); |
| return BAD_VALUE; |
| } |
| |
| camera2_shot_ext *shot_ext = (struct camera2_shot_ext *)(newBuffer.addr[1]); |
| |
| if (shot_ext != NULL) { |
| newFrame->getMetaData(shot_ext); |
| m_parameters->duplicateCtrlMetadata((void *)shot_ext); |
| m_activityControl->activityBeforeExecFunc(getPipeId(), (void *)&newBuffer); |
| |
| /* set metadata for instant on */ |
| shot_ext->shot.ctl.scaler.cropRegion[0] = 0; |
| shot_ext->shot.ctl.scaler.cropRegion[1] = 0; |
| #if defined(FASTEN_AE_WIDTH) && defined(FASTEN_AE_HEIGHT) |
| shot_ext->shot.ctl.scaler.cropRegion[2] = FASTEN_AE_WIDTH; |
| shot_ext->shot.ctl.scaler.cropRegion[3] = FASTEN_AE_HEIGHT; |
| #else |
| int bcropW = 0; |
| int bcropH = 0; |
| |
| ret = m_parameters->getFastenAeStableBcropSize(&bcropW, &bcropH); |
| if (ret != NO_ERROR) { |
| CLOGE("ERR(%s[%d]):m_parameters->getFastenAeStableBcropSize() fail on fastAE", |
| __FUNCTION__, __LINE__); |
| return INVALID_OPERATION; |
| } |
| |
| shot_ext->shot.ctl.scaler.cropRegion[2] = bcropW; |
| shot_ext->shot.ctl.scaler.cropRegion[3] = bcropH; |
| #endif |
| uint32_t frameRate = 0; |
| if (m_parameters->getCameraId() == CAMERA_ID_FRONT) { |
| frameRate = FASTEN_AE_FPS_FRONT; |
| } else { |
| frameRate = FASTEN_AE_FPS; |
| } |
| setMetaCtlAeTargetFpsRange(shot_ext, frameRate, frameRate); |
| setMetaCtlSensorFrameDuration(shot_ext, (uint64_t)((1000 * 1000 * 1000) / (uint64_t)frameRate)); |
| |
| #if defined(USE_HAL3_2_METADATA_INTERFACE) |
| /* set afMode into INFINITY */ |
| shot_ext->shot.ctl.aa.afTrigger = AA_AF_TRIGGER_CANCEL; |
| shot_ext->shot.ctl.aa.vendor_afmode_option &= (0 << AA_AFMODE_OPTION_BIT_MACRO); |
| #else |
| shot_ext->shot.ctl.aa.afMode = AA_AFMODE_INFINITY; |
| #endif |
| |
| if (m_perframeMainNodeGroupInfo[OUTPUT_NODE].perFrameLeaderInfo.perFrameNodeType == PERFRAME_NODE_TYPE_LEADER) { |
| camera2_node_group node_group_info; |
| memset(&shot_ext->node_group, 0x0, sizeof(camera2_node_group)); |
| newFrame->getNodeGroupInfo(&node_group_info, m_perframeMainNodeGroupInfo[OUTPUT_NODE].perFrameLeaderInfo.perframeInfoIndex); |
| |
| /* Per - Leader */ |
| if (node_group_info.leader.request == 1) { |
| |
| if (m_checkNodeGroupInfo(m_mainNode->getName(), &m_curNodeGroupInfo.leader, &node_group_info.leader) != NO_ERROR) |
| CLOGW("WARN(%s[%d]): m_checkNodeGroupInfo(%s) fail", __FUNCTION__, __LINE__, m_mainNode->getName()); |
| |
| setMetaNodeLeaderInputSize(shot_ext, |
| node_group_info.leader.input.cropRegion[0], |
| node_group_info.leader.input.cropRegion[1], |
| node_group_info.leader.input.cropRegion[2], |
| node_group_info.leader.input.cropRegion[3]); |
| setMetaNodeLeaderOutputSize(shot_ext, |
| node_group_info.leader.output.cropRegion[0], |
| node_group_info.leader.output.cropRegion[1], |
| node_group_info.leader.output.cropRegion[2], |
| node_group_info.leader.output.cropRegion[3]); |
| setMetaNodeLeaderRequest(shot_ext, |
| node_group_info.leader.request); |
| setMetaNodeLeaderVideoID(shot_ext, |
| m_perframeMainNodeGroupInfo[OUTPUT_NODE].perFrameLeaderInfo.perFrameVideoID); |
| } |
| |
| /* Per - Captures */ |
| if (CAPTURE_NODE_MAX < m_perframeMainNodeGroupInfo[OUTPUT_NODE].perframeSupportNodeNum) { |
| android_printAssert(NULL, LOG_TAG, "ASSERT(%s[%d]):PipeId(%d) has Invalid perframeSupportNodeNum:CAPTURE_NODE_MAX(%d) < m_perframeMainNodeGroupInfo[OUTPUT_NODE].perframeSupportNodeNum(%d), assert!!!!", |
| __FUNCTION__, __LINE__, getPipeId(), CAPTURE_NODE_MAX, m_perframeMainNodeGroupInfo[OUTPUT_NODE].perframeSupportNodeNum); |
| } |
| |
| for (int i = 0; i < m_perframeMainNodeGroupInfo[OUTPUT_NODE].perframeSupportNodeNum; i ++) { |
| if (node_group_info.capture[i].request == 1) { |
| |
| if (m_checkNodeGroupInfo(i, &m_curNodeGroupInfo.capture[i], &node_group_info.capture[i]) != NO_ERROR) |
| CLOGW("WARN(%s[%d]): m_checkNodeGroupInfo(%d) fail", __FUNCTION__, __LINE__, i); |
| |
| setMetaNodeCaptureInputSize(shot_ext, i, |
| node_group_info.capture[i].input.cropRegion[0], |
| node_group_info.capture[i].input.cropRegion[1], |
| node_group_info.capture[i].input.cropRegion[2], |
| node_group_info.capture[i].input.cropRegion[3]); |
| setMetaNodeCaptureOutputSize(shot_ext, i, |
| node_group_info.capture[i].output.cropRegion[0], |
| node_group_info.capture[i].output.cropRegion[1], |
| node_group_info.capture[i].output.cropRegion[2], |
| node_group_info.capture[i].output.cropRegion[3]); |
| setMetaNodeCaptureRequest(shot_ext, i, node_group_info.capture[i].request); |
| setMetaNodeCaptureVideoID(shot_ext, i, m_perframeMainNodeGroupInfo[OUTPUT_NODE].perFrameCaptureInfo[i].perFrameVideoID); |
| } |
| } |
| } |
| } |
| ret = m_mainNode->putBuffer(&newBuffer); |
| if (ret < 0) { |
| CLOGE("ERR(%s):putBuffer fail", __FUNCTION__); |
| return ret; |
| /* TODO: doing exception handling */ |
| } |
| |
| ret = newFrame->setDstBufferState(getPipeId(), ENTITY_BUFFER_STATE_PROCESSING); |
| if (ret < 0) { |
| CLOGE("ERR(%s): setDstBuffer state fail", __FUNCTION__); |
| return ret; |
| } |
| |
| m_runningFrameList[OUTPUT_NODE][newBuffer.index] = newFrame; |
| |
| m_numOfRunningFrame[OUTPUT_NODE]++; |
| |
| *frame = newFrame; |
| |
| return NO_ERROR; |
| } |
| |
| /* Don't use this function, this is regacy code */ |
| status_t ExynosCameraMCPipe::instantOnDQbuf(ExynosCameraFrame **frame, __unused BUFFER_POS::POS pos) |
| { |
| if (m_mainNode == NULL) { |
| CLOGE("ERR(%s): m_mainNode == NULL. so, fail", __FUNCTION__); |
| return INVALID_OPERATION; |
| } |
| |
| ExynosCameraFrame *curFrame = NULL; |
| ExynosCameraBuffer curBuffer; |
| int index = -1; |
| int ret = 0; |
| |
| if (m_numOfRunningFrame[OUTPUT_NODE] <= 0 ) { |
| CLOGD("DEBUG(%s[%d]): skip getBuffer, numOfRunningFrame = %d", __FUNCTION__, __LINE__, m_numOfRunningFrame[OUTPUT_NODE]); |
| return NO_ERROR; |
| } |
| |
| ret = m_mainNode->getBuffer(&curBuffer, &index); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]):getBuffer fail", __FUNCTION__, __LINE__); |
| /* TODO: doing exception handling */ |
| return ret; |
| } |
| |
| if (index < 0) { |
| CLOGE("ERR(%s[%d]):Invalid index(%d) fail", __FUNCTION__, __LINE__, index); |
| return INVALID_OPERATION; |
| } |
| |
| m_activityControl->activityAfterExecFunc(getPipeId(), (void *)&curBuffer); |
| |
| ret = m_updateMetadataToFrame(curBuffer.addr[1], curBuffer.index); |
| if (ret < 0) |
| CLOGE("ERR(%s[%d]): updateMetadataToFrame fail, ret(%d)", __FUNCTION__, __LINE__, ret); |
| |
| if (curBuffer.index < 0) { |
| CLOGE("ERR(%s):index(%d) is invalid", __FUNCTION__, curBuffer.index); |
| return BAD_VALUE; |
| } |
| |
| curFrame = m_runningFrameList[OUTPUT_NODE][curBuffer.index]; |
| |
| if (curFrame == NULL) { |
| CLOGE("ERR(%s):Unknown buffer, frame is NULL", __FUNCTION__); |
| dump(); |
| return BAD_VALUE; |
| } |
| |
| *frame = curFrame; |
| |
| return NO_ERROR; |
| } |
| |
| status_t ExynosCameraMCPipe::instantOff(void) |
| { |
| CLOGD("DEBUG(%s[%d])", __FUNCTION__, __LINE__); |
| status_t ret = NO_ERROR; |
| |
| for (int i = OUTPUT_NODE; i < MAX_NODE; i++) { |
| if (m_node[i] != NULL) { |
| ret = m_node[i]->stop(); |
| if (ret != NO_ERROR) { |
| CLOGE("ERR(%s[%d]):node(%s) stop fail, ret(%d)", |
| __FUNCTION__, __LINE__, m_deviceInfo->nodeName[i], ret); |
| return ret; |
| } |
| |
| ret = m_node[i]->clrBuffers(); |
| if (ret != NO_ERROR) { |
| CLOGE("ERR(%s[%d]):node(%s) clrBuffers fail, ret(%d)", |
| __FUNCTION__, __LINE__, m_deviceInfo->nodeName[i], ret); |
| return ret; |
| } |
| } |
| } |
| |
| CLOGI("INFO(%s[%d]):instantOff() is succeed, Pipe(%d)", __FUNCTION__, __LINE__, getPipeId()); |
| |
| return ret; |
| } |
| |
| /* Don't use this function, this is regacy code */ |
| status_t ExynosCameraMCPipe::instantOnPushFrameQ(BUFFERQ_TYPE::TYPE type, ExynosCameraFrame **frame) |
| { |
| if( type == BUFFERQ_TYPE::OUTPUT ) |
| m_outputFrameQ->pushProcessQ(frame); |
| else |
| m_inputFrameQ->pushProcessQ(frame); |
| |
| return NO_ERROR; |
| } |
| |
| status_t ExynosCameraMCPipe::getPipeInfo(int *fullW, int *fullH, int *colorFormat, int pipePosition) |
| { |
| CLOGV("DEBUG(%s[%d])", __FUNCTION__, __LINE__); |
| status_t ret = NO_ERROR; |
| int planeCount = 0; |
| |
| if (pipePosition == DST_PIPE) { |
| if (m_node[OUTPUT_NODE] == NULL) { |
| CLOGE("ERR(%s[%d]):m_node[OUTPUT_NODE] is NULL", __FUNCTION__, __LINE__); |
| return INVALID_OPERATION; |
| } |
| |
| ret = m_node[OUTPUT_NODE]->getSize(fullW, fullH); |
| if (ret != NO_ERROR) { |
| CLOGE("ERR(%s[%d]):node(%s) getSize fail, ret(%d)", |
| __FUNCTION__, __LINE__, m_deviceInfo->nodeName[OUTPUT_NODE], ret); |
| return ret; |
| } |
| |
| ret = m_node[OUTPUT_NODE]->getColorFormat(colorFormat, &planeCount); |
| if (ret != NO_ERROR) { |
| CLOGE("ERR(%s[%d]):node(%s) getColorFormat fail, ret(%d)", |
| __FUNCTION__, __LINE__, m_deviceInfo->nodeName[OUTPUT_NODE], ret); |
| return ret; |
| } |
| } else if (pipePosition == SRC_PIPE) { |
| for (int i = (MAX_NODE - 1); i > OUTPUT_NODE; i--) { |
| if (m_node[i] != NULL) { |
| ret = m_node[i]->getSize(fullW, fullH); |
| if (ret != NO_ERROR) { |
| CLOGE("ERR(%s[%d]):node(%s) getSize fail, ret(%d)", |
| __FUNCTION__, __LINE__, m_deviceInfo->nodeName[i], ret); |
| return ret; |
| } |
| |
| ret = m_node[i]->getColorFormat(colorFormat, &planeCount); |
| if (ret != NO_ERROR) { |
| CLOGE("ERR(%s[%d]):node(%s) getColorFormat fail, ret(%d)", |
| __FUNCTION__, __LINE__, m_deviceInfo->nodeName[i], ret); |
| return ret; |
| } |
| |
| CLOGV("INFO(%s[%d]):getPipeInfo() is succeed, Pipe(%d)", __FUNCTION__, __LINE__, getPipeId((enum NODE_TYPE)i)); |
| return ret; |
| } |
| } |
| CLOGE("ERR(%s[%d]):all capture m_node is NULL", __FUNCTION__, __LINE__); |
| return INVALID_OPERATION; |
| } else { |
| CLOGE("ERR(%s[%d]):Pipe position is Invalid, position(%d)", __FUNCTION__, __LINE__, pipePosition); |
| return BAD_VALUE; |
| } |
| |
| CLOGV("INFO(%s[%d]):getPipeInfo() is succeed, Pipe(%d)", __FUNCTION__, __LINE__, getPipeId()); |
| return ret; |
| } |
| |
| int ExynosCameraMCPipe::getCameraId(void) |
| { |
| return this->m_cameraId; |
| } |
| |
| status_t ExynosCameraMCPipe::setPipeId(uint32_t id) |
| { |
| return this->setPipeId(OUTPUT_NODE, id); |
| } |
| |
| uint32_t ExynosCameraMCPipe::getPipeId(void) |
| { |
| return (uint32_t)this->getPipeId(OUTPUT_NODE); |
| } |
| |
| status_t ExynosCameraMCPipe::setPipeId(enum NODE_TYPE nodeType, uint32_t id) |
| { |
| if (nodeType < OUTPUT_NODE || MAX_NODE <= nodeType) { |
| CLOGE("ERR(%s[%d]):Invalid nodeType(%d). so, fail", __FUNCTION__, __LINE__, nodeType); |
| return BAD_VALUE; |
| } |
| |
| CLOGD("DEBUG(%s[%d]):nodeType(%d), id(%d)", __FUNCTION__, __LINE__, nodeType, id); |
| |
| m_pipeIdArr[nodeType] = id; |
| |
| if (nodeType == OUTPUT_NODE) |
| m_pipeId = id; |
| |
| return NO_ERROR; |
| } |
| |
| int ExynosCameraMCPipe::getPipeId(enum NODE_TYPE nodeType) |
| { |
| if (nodeType < OUTPUT_NODE || MAX_NODE <= nodeType) { |
| CLOGE("ERR(%s[%d]):Invalid nodeType(%d). so, fail", __FUNCTION__, __LINE__, nodeType); |
| return -1; |
| } |
| |
| return m_pipeIdArr[nodeType]; |
| } |
| |
| |
| status_t ExynosCameraMCPipe::setPipeName(const char *pipeName) |
| { |
| CLOGD("DEBUG(%s[%d])", __FUNCTION__, __LINE__); |
| |
| strncpy(m_name, pipeName, (EXYNOS_CAMERA_NAME_STR_SIZE - 1)); |
| |
| return NO_ERROR; |
| } |
| |
| char *ExynosCameraMCPipe::getPipeName(void) |
| { |
| return m_name; |
| } |
| |
| status_t ExynosCameraMCPipe::setBufferManager(ExynosCameraBufferManager **bufferManager) |
| { |
| CLOGD("DEBUG(%s[%d])", __FUNCTION__, __LINE__); |
| |
| for (int i = OUTPUT_NODE; i < MAX_NODE; i++) |
| m_bufferManager[i] = bufferManager[i]; |
| |
| return NO_ERROR; |
| } |
| |
| status_t ExynosCameraMCPipe::clearInputFrameQ(void) |
| { |
| CLOGD("DEBUG(%s[%d])", __FUNCTION__, __LINE__); |
| |
| if (m_inputFrameQ != NULL) |
| m_inputFrameQ->release(); |
| |
| return NO_ERROR; |
| } |
| |
| status_t ExynosCameraMCPipe::getInputFrameQ(frame_queue_t **inputFrameQ) |
| { |
| *inputFrameQ = m_inputFrameQ; |
| |
| if (*inputFrameQ == NULL) |
| CLOGE("ERR(%s[%d])inputFrameQ is NULL", __FUNCTION__, __LINE__); |
| |
| return NO_ERROR; |
| } |
| |
| status_t ExynosCameraMCPipe::setOutputFrameQ(frame_queue_t *outputFrameQ) |
| { |
| CLOGV("DEBUG(%s[%d])", __FUNCTION__, __LINE__); |
| |
| m_outputFrameQ = outputFrameQ; |
| |
| return NO_ERROR; |
| } |
| |
| status_t ExynosCameraMCPipe::getOutputFrameQ(frame_queue_t **outputFrameQ) |
| { |
| *outputFrameQ = m_outputFrameQ; |
| |
| if (*outputFrameQ == NULL) |
| CLOGE("ERR(%s[%d]):outputFrameQ is NULL", __FUNCTION__, __LINE__); |
| |
| return NO_ERROR; |
| } |
| |
| status_t ExynosCameraMCPipe::setFrameDoneQ(frame_queue_t *frameDoneQ) |
| { |
| CLOGV("DEBUG(%s[%d])", __FUNCTION__, __LINE__); |
| |
| m_frameDoneQ = frameDoneQ; |
| |
| return NO_ERROR; |
| } |
| |
| status_t ExynosCameraMCPipe::getFrameDoneQ(frame_queue_t **frameDoneQ) |
| { |
| *frameDoneQ = m_frameDoneQ; |
| |
| if (*frameDoneQ == NULL) |
| CLOGE("ERR(%s[%d]):frameDoneQ is NULL", __FUNCTION__, __LINE__); |
| |
| return NO_ERROR; |
| } |
| |
| #ifdef SUPPORT_GROUP_MIGRATION |
| status_t ExynosCameraMCPipe::setNodeInfos(struct nodeInfos* nodeinfos, bool flagReset) |
| { |
| CLOGD("DEBUG(%s[%d]):setNodeInfos flagReset(%s)", __FUNCTION__, __LINE__, (flagReset)?"true":"false"); |
| for (int i = OUTPUT_NODE; i < MAX_NODE; i++) { |
| m_node[i] = nodeinfos->node[i]; |
| if(flagReset == true && m_node[i] != NULL) { |
| m_node[i]->resetInput(); |
| } |
| |
| m_secondaryNode[i] = nodeinfos->secondaryNode[i]; |
| if(flagReset == true && m_secondaryNode[i] != NULL) { |
| m_secondaryNode[i]->resetInput(); |
| } |
| } |
| m_mainNode = nodeinfos->mainNode; |
| |
| if(flagReset == true) { |
| m_frameDoneQ = NULL; |
| m_outputFrameQ = NULL; |
| } |
| |
| return NO_ERROR; |
| } |
| |
| status_t ExynosCameraMCPipe::getNodeInfos(struct nodeInfos* nodeinfos) |
| { |
| CLOGD("DEBUG(%s[%d]):getNodeInfos", __FUNCTION__, __LINE__); |
| for (int i = OUTPUT_NODE; i < MAX_NODE; i++) { |
| nodeinfos->node[i] = m_node[i]; |
| nodeinfos->secondaryNode[i] = m_secondaryNode[i]; |
| } |
| nodeinfos->mainNode = m_mainNode; |
| |
| return NO_ERROR; |
| } |
| #endif |
| |
| status_t ExynosCameraMCPipe::setMapBuffer(ExynosCameraBuffer *srcBuf, __unused ExynosCameraBuffer *dstBuf) |
| { |
| for (int i = OUTPUT_NODE; i < MAX_NODE; i++) { |
| if (m_node[i] != NULL) |
| return m_setMapBuffer(m_node[i], srcBuf); |
| } |
| |
| return INVALID_OPERATION; |
| } |
| |
| status_t ExynosCameraMCPipe::setBoosting(bool isBoosting) |
| { |
| CLOGD("DEBUG(%s[%d])", __FUNCTION__, __LINE__); |
| |
| m_isBoosting = isBoosting; |
| |
| return NO_ERROR; |
| } |
| |
| bool ExynosCameraMCPipe::isThreadRunning(void) |
| { |
| if (m_putBufferThread->isRunning() || m_getBufferThread->isRunning()) |
| return true; |
| |
| return false; |
| } |
| |
| status_t ExynosCameraMCPipe::getThreadState(int **threadState) |
| { |
| *threadState = &m_threadState; |
| |
| return NO_ERROR; |
| } |
| |
| status_t ExynosCameraMCPipe::getThreadInterval(uint64_t **timeInterval) |
| { |
| *timeInterval = &m_timeInterval; |
| |
| return NO_ERROR; |
| } |
| |
| status_t ExynosCameraMCPipe::getThreadRenew(int **timeRenew) |
| { |
| *timeRenew = &m_threadRenew; |
| |
| return NO_ERROR; |
| } |
| |
| status_t ExynosCameraMCPipe::incThreadRenew(void) |
| { |
| m_threadRenew ++; |
| |
| return NO_ERROR; |
| } |
| |
| status_t ExynosCameraMCPipe::setStopFlag(void) |
| { |
| CLOGD("DEBUG(%s[%d])", __FUNCTION__, __LINE__); |
| |
| m_flagTryStop = true; |
| |
| return NO_ERROR; |
| } |
| |
| void ExynosCameraMCPipe::dump(void) |
| { |
| CLOGI("INFO(%s[%d])", __FUNCTION__, __LINE__); |
| |
| m_dumpRunningFrameList(); |
| |
| for (int i = OUTPUT_NODE; i < MAX_NODE; i++) { |
| if (m_node[i] != NULL) { |
| m_node[i]->dump(); |
| } |
| } |
| |
| return; |
| } |
| |
| status_t ExynosCameraMCPipe::dumpFimcIsInfo(bool bugOn) |
| { |
| CLOGD("DEBUG(%s[%d])", __FUNCTION__, __LINE__); |
| status_t ret = NO_ERROR; |
| |
| ret = m_node[OUTPUT_NODE]->setControl(V4L2_CID_IS_DEBUG_DUMP, bugOn); |
| if (ret != NO_ERROR) |
| CLOGE("ERR(%s[%d]):m_node[OUTPUT_NODE]->setControl failed", __FUNCTION__, __LINE__); |
| |
| return ret; |
| } |
| |
| #ifdef MONITOR_LOG_SYNC |
| status_t ExynosCameraMCPipe::syncLog(uint32_t syncId) |
| { |
| CLOGD("DEBUG(%s[%d])", __FUNCTION__, __LINE__); |
| status_t ret = NO_ERROR; |
| |
| ret = m_node[OUTPUT_NODE]->setControl(V4L2_CID_IS_DEBUG_SYNC_LOG, syncId); |
| if (ret != NO_ERROR) |
| CLOGE("ERR(%s[%d]):m_node[OUTPUT_NODE]->setControl failed", __FUNCTION__, __LINE__); |
| |
| return ret; |
| } |
| #endif |
| |
| status_t ExynosCameraMCPipe::m_preCreate(void) |
| { |
| CLOGD("DEBUG(%s[%d])", __FUNCTION__, __LINE__); |
| status_t ret = NO_ERROR; |
| |
| /* Create & open output/capture nodes */ |
| for (int i = OUTPUT_NODE; i < MAX_NODE; i++) { |
| if (OUTPUT_NODE < i |
| && m_node[OUTPUT_NODE] != NULL |
| && m_deviceInfo->nodeNum[OUTPUT_NODE] == m_deviceInfo->nodeNum[i]) { |
| /* W/A for under Helsinki Prime */ |
| m_node[i] = new ExynosCameraNode(); |
| |
| int fd = -1; |
| ret = m_node[OUTPUT_NODE]->getFd(&fd); |
| if (ret != NO_ERROR || m_flagValidInt(fd) == false) { |
| CLOGE("ERR(%s):OUTPUT_NODE->getFd failed", __FUNCTION__); |
| return ret; |
| } |
| |
| ret = m_node[i]->create(m_deviceInfo->nodeName[i], m_cameraId, fd); |
| if (ret != NO_ERROR) { |
| CLOGE("ERR(%s[%d]):Create node fail(Node:%s), ret(%d)", |
| __FUNCTION__, __LINE__, m_deviceInfo->nodeName[i], ret); |
| return ret; |
| } |
| |
| CLOGD("DEBUG(%s[%d]):Node(%d) opened, fd(%d)", __FUNCTION__, __LINE__, m_deviceInfo->nodeNum[i], fd); |
| } else if (m_flagValidInt(m_deviceInfo->nodeNum[i]) == true) { |
| m_node[i] = new ExynosCameraNode(); |
| |
| ret = m_node[i]->create(m_deviceInfo->nodeName[i], m_cameraId); |
| if (ret != NO_ERROR) { |
| CLOGE("ERR(%s[%d]):Create node fail(Node:%s), ret(%d)", |
| __FUNCTION__, __LINE__, m_deviceInfo->nodeName[i], ret); |
| return ret; |
| } |
| |
| ret = m_node[i]->open(m_deviceInfo->nodeNum[i]); |
| if (ret != NO_ERROR) { |
| CLOGE("ERR(%s[%d]):Open node fail(Node:%s), ret(%d)", |
| __FUNCTION__, __LINE__, m_deviceInfo->nodeName[i], ret); |
| return ret; |
| } |
| |
| CLOGD("DEBUG(%s[%d]):Node(%d) opened", __FUNCTION__, __LINE__, m_deviceInfo->nodeNum[i]); |
| } |
| } |
| |
| /* Create & open OTF nodes */ |
| for (int i = OUTPUT_NODE; i < MAX_NODE; i++) { |
| if (m_flagValidInt(m_deviceInfo->secondaryNodeNum[i]) == true) { |
| m_secondaryNode[i] = new ExynosCameraNode(); |
| |
| ret = m_secondaryNode[i]->create(m_deviceInfo->secondaryNodeName[i], m_cameraId); |
| if (ret != NO_ERROR) { |
| CLOGE("ERR(%s[%d]):Create node fail(Node:%s), ret(%d)", |
| __FUNCTION__, __LINE__, m_deviceInfo->secondaryNodeName[i], ret); |
| return ret; |
| } |
| |
| ret = m_secondaryNode[i]->open(m_deviceInfo->secondaryNodeNum[i]); |
| if (ret != NO_ERROR) { |
| CLOGE("ERR(%s[%d]):Open node fail(Node:%s), ret(%d)", |
| __FUNCTION__, __LINE__, m_deviceInfo->secondaryNodeName[i], ret); |
| return ret; |
| } |
| |
| CLOGD("DEBUG(%s[%d]):Node(%s) opened", __FUNCTION__, __LINE__, m_deviceInfo->secondaryNodeName[i]); |
| } |
| } |
| |
| m_putBufferThread = new MCPipeThread(this, |
| &ExynosCameraMCPipe::m_putBufferThreadFunc, "putBufferThread", PRIORITY_URGENT_DISPLAY); |
| m_getBufferThread = new MCPipeThread(this, |
| &ExynosCameraMCPipe::m_getBufferThreadFunc, "getBufferThread", PRIORITY_URGENT_DISPLAY); |
| |
| if (m_reprocessing == true) { |
| m_inputFrameQ = new frame_queue_t(m_putBufferThread); |
| m_requestFrameQ = new frame_queue_t(m_getBufferThread); |
| } else { |
| m_inputFrameQ = new frame_queue_t; |
| m_requestFrameQ = new frame_queue_t; |
| } |
| m_inputFrameQ->setWaitTime(550000000); /* .55 sec */ |
| m_requestFrameQ->setWaitTime(550000000); /* .55 sec */ |
| |
| CLOGI("INFO(%s[%d]):m_preCreate() is succeed, Pipe(%d), prepare(%d)", |
| __FUNCTION__, __LINE__, getPipeId(), m_prepareBufferCount); |
| |
| return ret; |
| } |
| |
| status_t ExynosCameraMCPipe::m_postCreate(int32_t *sensorIds) |
| { |
| CLOGD("DEBUG(%s[%d])", __FUNCTION__, __LINE__); |
| status_t ret = NO_ERROR; |
| |
| for (int i = OUTPUT_NODE; i < MAX_NODE; i++) { |
| if (sensorIds != NULL) { |
| CLOGD("DEBUG(%s[%d]):Set new sensorIds[%d] : %d", __FUNCTION__, __LINE__, i, sensorIds[i]); |
| m_sensorIds[i] = sensorIds[i]; |
| } else { |
| m_sensorIds[i] = -1; |
| } |
| } |
| |
| ret = m_setInput(m_node, m_deviceInfo->nodeNum, m_sensorIds); |
| if (ret != NO_ERROR) { |
| CLOGE("ERR(%s[%d]):m_setInput(Main) fail, ret(%d)", __FUNCTION__, __LINE__, ret); |
| return ret; |
| } |
| |
| ret = m_setInput(m_secondaryNode, m_deviceInfo->secondaryNodeNum, m_secondarySensorIds); |
| if (ret != NO_ERROR) { |
| CLOGE("ERR(%s[%d]):m_setInput(secondary) fail, ret(%d)", __FUNCTION__, __LINE__, ret); |
| return ret; |
| } |
| |
| CLOGI("INFO(%s[%d]):m_postCreate() is succeed, Pipe(%d)", __FUNCTION__, __LINE__, getPipeId()); |
| |
| return ret; |
| } |
| |
| bool ExynosCameraMCPipe::m_putBufferThreadFunc(void) |
| { |
| status_t ret = NO_ERROR; |
| |
| #ifdef TEST_WATCHDOG_THREAD |
| testErrorDetect++; |
| if (testErrorDetect == 100) |
| m_threadState = ERROR_POLLING_DETECTED; |
| #endif |
| |
| if (m_flagTryStop == true) { |
| usleep(5000); |
| return true; |
| } |
| |
| ret = m_putBuffer(); |
| if (ret != NO_ERROR) |
| CLOGW("WARN(%s[%d]):m_putbuffer fail, ret(%d)", __FUNCTION__, __LINE__, ret); |
| |
| return m_checkThreadLoop(m_inputFrameQ); |
| } |
| |
| bool ExynosCameraMCPipe::m_getBufferThreadFunc(void) |
| { |
| status_t ret = NO_ERROR; |
| |
| if (m_flagTryStop == true) { |
| usleep(5000); |
| return true; |
| } |
| |
| ret = m_getBuffer(); |
| if (ret != NO_ERROR) |
| CLOGW("WARN(%s[%d]):m_getBuffer fail, ret(%d)", __FUNCTION__, __LINE__, ret); |
| |
| m_timer.stop(); |
| m_timeInterval = m_timer.durationMsecs(); |
| m_timer.start(); |
| |
| /* update renew count */ |
| if (ret >= 0) |
| m_threadRenew = 0; |
| |
| return m_checkThreadLoop(m_requestFrameQ); |
| } |
| |
| status_t ExynosCameraMCPipe::m_putBuffer(void) |
| { |
| CLOGV("DEBUG(%s[%d]):-IN-", __FUNCTION__, __LINE__); |
| status_t ret = NO_ERROR; |
| ExynosCameraFrame *newFrame = NULL; |
| ExynosCameraBuffer buffer[MAX_NODE]; |
| int pipeId = 0; |
| int bufferIndex[MAX_NODE]; |
| for (int i = OUTPUT_NODE; i < MAX_NODE; i++) |
| bufferIndex[i] = -2; |
| uint32_t captureNodeCount = 0; |
| |
| /* 1. Pop from input frame queue */ |
| ret = m_inputFrameQ->waitAndPopProcessQ(&newFrame); |
| if (ret == TIMED_OUT) { |
| CLOGW("WARN(%s[%d]):inputFrameQ wait timeout", __FUNCTION__, __LINE__); |
| return ret; |
| } else if (ret != NO_ERROR) { |
| CLOGE("ERR(%s[%d]):inputFrameQ wait and pop fail, ret(%d)", __FUNCTION__, __LINE__, ret); |
| /* TODO: doing exception handling */ |
| return ret; |
| } |
| |
| if (newFrame == NULL) { |
| CLOGE("ERR(%s[%d]):New frame is NULL", __FUNCTION__, __LINE__); |
| return BAD_VALUE; |
| } |
| |
| if (newFrame->getFrameState() == FRAME_STATE_SKIPPED |
| || newFrame->getFrameState() == FRAME_STATE_INVALID) { |
| CLOGE("ERR(%s[%d]):New frame is INVALID, frameCount(%d)", |
| __FUNCTION__, __LINE__, newFrame->getFrameCount()); |
| goto CLEAN_FRAME; |
| } |
| |
| if (m_reprocessing == false |
| /* HACK: MC Pipe is common pipe, but it is only for ISP node */ |
| /* TODO: Make generally */ |
| && getPipeId() == PIPE_ISP |
| && m_bufferManager[OUTPUT_NODE]->getNumOfAvailableBuffer() <= 0) { |
| CLOGE("ERR(%s[%d]):Pipe is Busy, Skip frame, frameCount(%d)", |
| __FUNCTION__, __LINE__, newFrame->getFrameCount()); |
| goto CLEAN_FRAME; |
| } |
| |
| for (int i = (MAX_NODE - 1); i > OUTPUT_NODE; i--) { |
| if (m_node[i] == NULL) |
| continue; |
| |
| pipeId = getPipeId((enum NODE_TYPE)i); |
| if (pipeId < 0) { |
| CLOGE("ERR(%s[%d]):getPipeId(%d) fail", __FUNCTION__, __LINE__, i); |
| return BAD_VALUE; |
| } |
| |
| /* 2. Get capture node buffer(DstBuffer) from buffer manager */ |
| if (m_node[i] != NULL |
| && newFrame->getRequest(pipeId) == true |
| && m_skipPutBuffer[i] == false) { |
| if (m_bufferManager[i] == NULL) { |
| CLOGE("ERR(%s[%d]):Buffer manager is NULL, i(%d), piepId(%d), frameCount(%d)", |
| __FUNCTION__, __LINE__, i, pipeId, newFrame->getFrameCount()); |
| continue; |
| } |
| |
| ret = m_bufferManager[i]->getBuffer(&(bufferIndex[i]), EXYNOS_CAMERA_BUFFER_POSITION_IN_HAL, &(buffer[i])); |
| if (ret != NO_ERROR) { |
| CLOGE("ERR(%s[%d]):Buffer manager getBuffer fail, manager(%d), frameCount(%d), ret(%d)", |
| __FUNCTION__, __LINE__, i, newFrame->getFrameCount(), ret); |
| newFrame->setRequest(pipeId, false); |
| /* m_bufferManager[i]->dump(); */ |
| continue; |
| } |
| |
| if (m_runningFrameList[i][(bufferIndex[i])] != NULL) { |
| CLOGE("ERR(%s[%d]):New buffer is invalid, we already get buffer, index(%d), frameCount(%d)", |
| __FUNCTION__, __LINE__, bufferIndex[i], newFrame->getFrameCount()); |
| newFrame->setRequest(pipeId, false); |
| /* dump(); */ |
| continue; |
| } |
| |
| /* 3. Put capture buffer(DstBuffer) to node */ |
| if (bufferIndex[i] >= 0 |
| && newFrame->getRequest(pipeId) == true) { |
| ret = m_node[i]->putBuffer(&(buffer[i])); |
| if (ret != NO_ERROR) { |
| CLOGE("ERR(%s[%d]):node(%s)->putBuffer() fail, frameCount(%d), ret(%d)", |
| __FUNCTION__, __LINE__, m_deviceInfo->nodeName[i], newFrame->getFrameCount(), ret); |
| |
| /* TODO: doing exception handling */ |
| ret = m_bufferManager[i]->putBuffer(bufferIndex[i], EXYNOS_CAMERA_BUFFER_POSITION_NONE); |
| if (ret != NO_ERROR) { |
| CLOGE("ERR(%s[%d]):Buffer manager putBuffer fail, manager(%d), frameCount(%d), ret(%d)", |
| __FUNCTION__, __LINE__, i, newFrame->getFrameCount(), ret); |
| } |
| |
| newFrame->setRequest(pipeId, false); |
| } else { |
| m_skipPutBuffer[i] = true; |
| m_skipBuffer[i].index = buffer[i].index; |
| } |
| } |
| } |
| |
| if (m_skipPutBuffer[i] == true) |
| captureNodeCount++; |
| } |
| |
| if (captureNodeCount == 0) { |
| CLOGW("WRN(%s[%d]):Capture node putbuffer is Zero, frameCount(%d)", |
| __FUNCTION__, __LINE__, newFrame->getFrameCount()); |
| /* Comment out: 3AA and ISP must running, because it save stat and refered next frame. |
| * So, put SRC buffer to output node when DST buffers all empty(zero). |
| */ |
| /* goto CLEAN_FRAME; */ |
| } |
| |
| /* 4. Get output node(SrcBuffer) buffer from frame */ |
| if (m_node[OUTPUT_NODE] != NULL) { |
| ret = newFrame->getSrcBuffer(getPipeId(OUTPUT_NODE), &(buffer[OUTPUT_NODE])); |
| if (ret != NO_ERROR) { |
| CLOGE("ERR(%s[%d]):Frame get src buffer fail, frameCount(%d), ret(%d)", |
| __FUNCTION__, __LINE__, newFrame->getFrameCount(), ret); |
| /* TODO: doing exception handling */ |
| goto CLEAN_FRAME; |
| } |
| |
| if (m_runningFrameList[OUTPUT_NODE][(buffer[OUTPUT_NODE].index)] != NULL) { |
| CLOGE("ERR(%s[%d]):New buffer is invalid, we already get buffer, index(%d), frameCount(%d)", |
| __FUNCTION__, __LINE__, buffer[OUTPUT_NODE].index, newFrame->getFrameCount()); |
| /* dump(); */ |
| goto CLEAN_FRAME; |
| } |
| |
| /* 5. Update control metadata for request, Zoom, ... */ |
| ret = m_updateMetadataFromFrame(newFrame, &(buffer[OUTPUT_NODE])); |
| if (ret != NO_ERROR) { |
| CLOGW("WARN(%s[%d]):Update metadata fail, frameCount(%d), ret(%d)", |
| __FUNCTION__, __LINE__, newFrame->getFrameCount(), ret); |
| } |
| |
| /* 6. Put output buffer(SrcBuffer) to node */ |
| ret = m_node[OUTPUT_NODE]->putBuffer(&(buffer[OUTPUT_NODE])); |
| if (ret != NO_ERROR) { |
| CLOGE("ERR(%s[%d]):node(%s)->putBuffer() fail, frameCount(%d), ret(%d)", |
| __FUNCTION__, __LINE__, m_deviceInfo->nodeName[OUTPUT_NODE], newFrame->getFrameCount(), ret); |
| /* TODO: doing exception handling */ |
| goto CLEAN_FRAME; |
| } |
| |
| ret = newFrame->setSrcBufferState(getPipeId(OUTPUT_NODE), ENTITY_BUFFER_STATE_PROCESSING); |
| if (ret != NO_ERROR) { |
| CLOGE("ERR(%s[%d]):setSrcBuffer state fail, frameCount(%d), ret(%d)", |
| __FUNCTION__, __LINE__, newFrame->getFrameCount(), ret); |
| } |
| |
| m_runningFrameList[OUTPUT_NODE][(buffer[OUTPUT_NODE].index)] = newFrame; |
| m_numOfRunningFrame[OUTPUT_NODE]++; |
| |
| /* 7. Link capture node buffer(DstBuffer) to frame */ |
| for (int i = (MAX_NODE - 1); i > OUTPUT_NODE; i--) { |
| if (m_node[i] == NULL) |
| continue; |
| |
| pipeId = getPipeId((enum NODE_TYPE)i); |
| if (pipeId < 0) { |
| CLOGE("ERR(%s[%d]):getPipeId(%d) fail", __FUNCTION__, __LINE__, i); |
| return BAD_VALUE; |
| } |
| |
| |
| if (m_node[i] != NULL |
| && newFrame->getRequest(pipeId) == true) { |
| /* HACK: Should change ExynosCamera, Frame */ |
| ret = newFrame->setDstBufferState(getPipeId(), ENTITY_BUFFER_STATE_REQUESTED, i); |
| if (ret != NO_ERROR) { |
| CLOGE("ERR(%s[%d]):setDstBuffer state fail, pipeID(%d), frameCount(%d), ret(%d)", |
| __FUNCTION__, __LINE__, pipeId, newFrame->getFrameCount(), ret); |
| } |
| |
| if (m_skipPutBuffer[i] == true) |
| buffer[i].index = m_skipBuffer[i].index; |
| |
| ret = newFrame->setDstBuffer(getPipeId(), buffer[i], i, INDEX(pipeId)); |
| if (ret != NO_ERROR) { |
| CLOGE("ERR(%s[%d]):Frame set dst buffer fail, frameCount(%d), ret(%d)", |
| __FUNCTION__, __LINE__, newFrame->getFrameCount(), ret); |
| /* TODO: doing exception handling */ |
| if (m_bufferManager[i] != NULL) |
| ret = m_bufferManager[i]->putBuffer(buffer[i].index, EXYNOS_CAMERA_BUFFER_POSITION_NONE); |
| |
| if (ret != NO_ERROR) { |
| CLOGE("ERR(%s[%d]):Buffer manager putBuffer fail, manager(%d), frameCount(%d), ret(%d)", |
| __FUNCTION__, __LINE__, i, newFrame->getFrameCount(), ret); |
| } |
| |
| newFrame->setRequest(pipeId, false); |
| } |
| |
| ret = newFrame->setDstBufferState(getPipeId(), ENTITY_BUFFER_STATE_PROCESSING, i); |
| if (ret != NO_ERROR) { |
| CLOGE("ERR(%s[%d]):setDstBuffer state fail, pipeID(%d), frameCount(%d), ret(%d)", |
| __FUNCTION__, __LINE__, getPipeId(), newFrame->getFrameCount(), ret); |
| } |
| |
| m_runningFrameList[i][(bufferIndex[i])] = newFrame; |
| m_numOfRunningFrame[i]++; |
| m_skipPutBuffer[i] = false; |
| m_skipBuffer[i].index = -2; |
| } |
| } |
| } |
| |
| /* 8. Push frame to getBufferThread */ |
| m_requestFrameQ->pushProcessQ(&newFrame); |
| |
| CLOGV("DEBUG(%s[%d]):OUT-", __FUNCTION__, __LINE__); |
| return NO_ERROR; |
| |
| /* Error handling for SrcBuffer and Frame */ |
| CLEAN_FRAME: |
| CLOGD("DEBUG(%s[%d]):clean frame, frameCount(%d)", |
| __FUNCTION__, __LINE__, newFrame->getFrameCount()); |
| |
| if (m_parameters->getHalVersion() == IS_HAL_VER_3_2) { |
| for (int i = (MAX_NODE - 1); i > OUTPUT_NODE; i--) { |
| if (m_node[i] == NULL) |
| continue; |
| |
| pipeId = getPipeId((enum NODE_TYPE)i); |
| if (pipeId < 0) { |
| CLOGE("ERR(%s[%d]):getPipeId(%d) fail", __FUNCTION__, __LINE__, i); |
| return BAD_VALUE; |
| } |
| |
| if (pipeId == PIPE_SCP |
| && m_node[i] != NULL |
| && m_bufferManager[i] != NULL |
| && newFrame->getRequest(pipeId) == true) { |
| ret = m_bufferManager[i]->getBuffer(&(bufferIndex[i]), EXYNOS_CAMERA_BUFFER_POSITION_IN_HAL, &(buffer[i])); |
| if (ret != NO_ERROR) { |
| CLOGE("ERR(%s[%d]):Buffer manager getBuffer fail, manager(%d), frameCount(%d), ret(%d)", |
| __FUNCTION__, __LINE__, i, newFrame->getFrameCount(), ret); |
| } |
| |
| ret = newFrame->setDstBufferState(getPipeId(), ENTITY_BUFFER_STATE_REQUESTED, i); |
| if (ret != NO_ERROR) { |
| CLOGE("ERR(%s[%d]):setDstBuffer state fail, pipeID(%d), frameCount(%d), ret(%d)", |
| __FUNCTION__, __LINE__, getPipeId(), newFrame->getFrameCount(), ret); |
| } |
| |
| ret = newFrame->setDstBuffer(getPipeId(), buffer[i], i); |
| if (ret != NO_ERROR) { |
| CLOGE("ERR(%s[%d]):Frame set dst buffer fail, frameCount(%d), ret(%d)", |
| __FUNCTION__, __LINE__, newFrame->getFrameCount(), ret); |
| } |
| break; |
| } |
| } |
| } |
| |
| ret = newFrame->setSrcBufferState(getPipeId(), ENTITY_BUFFER_STATE_ERROR); |
| if (ret != NO_ERROR) { |
| CLOGE("ERR(%s[%d]):setSrcBuffer state fail, frameCount(%d), ret(%d)", |
| __FUNCTION__, __LINE__, newFrame->getFrameCount(), ret); |
| } |
| |
| ret = newFrame->setDstBufferState(getPipeId(), ENTITY_BUFFER_STATE_ERROR); |
| if (ret != NO_ERROR) { |
| CLOGE("ERR(%s[%d]):setDstBuffer state fail, pipeID(%d), frameCount(%d), ret(%d)", |
| __FUNCTION__, __LINE__, getPipeId(), newFrame->getFrameCount(), ret); |
| } |
| |
| if (newFrame->getFrameState() != FRAME_STATE_SKIPPED |
| && newFrame->getFrameState() != FRAME_STATE_INVALID) { |
| newFrame->setFrameState(FRAME_STATE_SKIPPED); |
| if (ret != NO_ERROR) { |
| CLOGE("ERR(%s[%d]):setFrameState fail, frameCount(%d), ret(%d)", |
| __FUNCTION__, __LINE__, newFrame->getFrameCount(), ret); |
| } |
| } |
| |
| ret = m_completeFrame(newFrame, false); |
| if (ret != NO_ERROR) { |
| CLOGE("ERR(%s[%d]):Complete frame fail, frameCount(%d), ret(%d)", __FUNCTION__, __LINE__, newFrame->getFrameCount(), ret); |
| /* TODO: doing exception handling */ |
| } |
| |
| if (m_frameDoneQ != NULL) |
| m_frameDoneQ->pushProcessQ(&newFrame); |
| |
| m_outputFrameQ->pushProcessQ(&newFrame); |
| |
| return INVALID_OPERATION; |
| } |
| |
| status_t ExynosCameraMCPipe::m_getBuffer(void) |
| { |
| CLOGV("DEBUG(%s[%d]):-IN-", __FUNCTION__, __LINE__); |
| status_t ret = NO_ERROR; |
| status_t nodeDqRet[MAX_NODE]; |
| |
| ExynosCameraFrame *newFrame = NULL; |
| ExynosCameraBuffer buffer[MAX_NODE]; |
| int pipeId = 0; |
| int v4l2Colorformat = 0; |
| int planeCount[MAX_NODE] = {0}; |
| int bufferIndex[MAX_NODE]; |
| for (int i = OUTPUT_NODE; i < MAX_NODE; i++) { |
| bufferIndex[i] = -2; |
| nodeDqRet[i] = NO_ERROR; |
| } |
| uint32_t captureNodeCount = 0; |
| uint32_t checkPollingCount = 0; |
| |
| /* 1. Pop from request frame queue */ |
| ret = m_requestFrameQ->waitAndPopProcessQ(&newFrame); |
| if (ret == TIMED_OUT) { |
| CLOGW("WARN(%s[%d]):requestFrameQ wait timeout", __FUNCTION__, __LINE__); |
| return ret; |
| } else if (ret != NO_ERROR) { |
| CLOGE("ERR(%s[%d]):requestFrameQ wait and pop fail, ret(%d)", __FUNCTION__, __LINE__, ret); |
| /* TODO: doing exception handling */ |
| return ret; |
| } |
| |
| if (newFrame == NULL) { |
| CLOGE("ERR(%s[%d]):New frame is NULL", __FUNCTION__, __LINE__); |
| return BAD_VALUE; |
| } |
| |
| /* 2. Get output buffer(SrcBuffer) from node */ |
| if (m_node[OUTPUT_NODE] != NULL) { |
| ret = m_node[OUTPUT_NODE]->getBuffer(&(buffer[OUTPUT_NODE]), &(bufferIndex[OUTPUT_NODE])); |
| nodeDqRet[OUTPUT_NODE] = ret; |
| if (ret != NO_ERROR) { |
| CLOGE("ERR(%s[%d]):node(%s)->getBuffer() fail, index(%d), frameCount(%d), ret(%d)", |
| __FUNCTION__, __LINE__, m_deviceInfo->nodeName[OUTPUT_NODE], |
| bufferIndex[OUTPUT_NODE], newFrame->getFrameCount(), ret); |
| /* TODO: doing exception handling */ |
| /* Comment out : dqblock case was disappeared */ |
| /* |
| for (int i = (MAX_NODE - 1); i > OUTPUT_NODE; i--) { |
| if (newFrame->getRequest(getPipeId() + i) == true) |
| m_skipPutBuffer[i] = true; |
| } |
| |
| ret = m_completeFrame(newFrame, false); |
| if (ret != NO_ERROR) { |
| CLOGE("ERR(%s[%d]):Complete frame fail, ret(%d)", __FUNCTION__, __LINE__, ret); |
| } |
| |
| goto CLEAN; |
| */ |
| |
| if (bufferIndex[OUTPUT_NODE] >= 0) { |
| newFrame = m_runningFrameList[OUTPUT_NODE][bufferIndex[OUTPUT_NODE]]; |
| } else { |
| ret = newFrame->getSrcBuffer(getPipeId(), &buffer[OUTPUT_NODE]); |
| if (ret != NO_ERROR) { |
| CLOGE("ERR(%s[%d]):Frame get buffer fail, frameCount(%d), ret(%d)", |
| __FUNCTION__, __LINE__, newFrame->getFrameCount(), ret); |
| } else { |
| buffer[OUTPUT_NODE].index = -2; |
| } |
| } |
| |
| if (newFrame == NULL) { |
| CLOGE("ERR(%s[%d]):Invalid DQ buffer index(%d)", __FUNCTION__, __LINE__, bufferIndex[OUTPUT_NODE]); |
| return BAD_VALUE; |
| } |
| |
| ret = newFrame->setSrcBufferState(getPipeId(), ENTITY_BUFFER_STATE_ERROR); |
| if (ret != NO_ERROR) { |
| CLOGE("ERR(%s[%d]):setSrcBuffer state fail, frameCount(%d), ret(%d)", |
| __FUNCTION__, __LINE__, newFrame->getFrameCount(), ret); |
| } |
| } else { |
| /* |
| prevent the frame null pointer exception, get the frame from m_runningFrameList |
| 1. in case of NDONE, dq order was reversed. |
| 2. always use the m_runningFrameList instead of m_requestFrameQ |
| */ |
| newFrame = m_runningFrameList[OUTPUT_NODE][bufferIndex[OUTPUT_NODE]]; |
| ret = newFrame->getSrcBuffer(getPipeId(), &buffer[OUTPUT_NODE]); |
| if (ret != NO_ERROR) { |
| CLOGE("ERR(%s[%d]):Frame get buffer fail, frameCount(%d), ret(%d)", |
| __FUNCTION__, __LINE__, newFrame->getFrameCount(), ret); |
| } else { |
| if (bufferIndex[OUTPUT_NODE] != buffer[OUTPUT_NODE].index) { |
| ret = newFrame->getSrcBuffer(getPipeId(), &buffer[OUTPUT_NODE]); |
| if (ret != NO_ERROR) { |
| CLOGE("ERR(%s[%d]):Frame get buffer fail, frameCount(%d), ret(%d)", |
| __FUNCTION__, __LINE__, newFrame->getFrameCount(), ret); |
| } |
| } |
| |
| ret = newFrame->setSrcBufferState(getPipeId(), ENTITY_BUFFER_STATE_COMPLETE); |
| if (ret != NO_ERROR) { |
| CLOGE("ERR(%s[%d]):setSrcBuffer state fail, frameCount(%d), ret(%d)", |
| __FUNCTION__, __LINE__, newFrame->getFrameCount(), ret); |
| } |
| |
| if (m_reprocessing == false) |
| m_activityControl->activityAfterExecFunc(getPipeId(), (void *)&buffer[OUTPUT_NODE]); |
| } |
| } |
| |
| if (bufferIndex[OUTPUT_NODE] >= 0) { |
| /* 3. Update frame from dynamic metadata of output node buffer(SrcBuffer) for request, ... */ |
| ret = m_updateMetadataToFrame(buffer[OUTPUT_NODE].addr[1], buffer[OUTPUT_NODE].index, newFrame, OUTPUT_NODE); |
| if (ret != NO_ERROR) { |
| CLOGE("ERR(%s[%d]):Update metadata fail, frameCount(%d), ret(%d)", |
| __FUNCTION__, __LINE__, newFrame->getFrameCount(), ret); |
| } |
| |
| m_runningFrameList[OUTPUT_NODE][bufferIndex[OUTPUT_NODE]] = NULL; |
| m_numOfRunningFrame[OUTPUT_NODE]--; |
| } |
| } |
| |
| /* 4. Get capture buffer(DstBuffer) from node */ |
| for (int i = (MAX_NODE - 1); i > OUTPUT_NODE; i--) { |
| ret = NO_ERROR; |
| |
| if (m_node[i] == NULL) |
| continue; |
| |
| pipeId = getPipeId((enum NODE_TYPE)i); |
| if (pipeId < 0) { |
| CLOGE("ERR(%s[%d]):getPipeId(%d) fail", __FUNCTION__, __LINE__, i); |
| return BAD_VALUE; |
| } |
| |
| if (m_node[i] != NULL |
| && newFrame->getRequest(pipeId) == true) { |
| #ifndef SKIP_SCHECK_POLLING |
| if (pipeId == PIPE_SCP && checkPollingCount == 0) |
| ret = m_checkPolling(m_node[i]); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]):m_checkPolling fail, frameCount(%d), ret(%d)", |
| __FUNCTION__, __LINE__, newFrame->getFrameCount(), ret); |
| /* TODO: doing exception handling */ |
| // HACK: for panorama shot |
| //return false; |
| } |
| checkPollingCount++; |
| #endif |
| ret = m_node[i]->getBuffer(&(buffer[i]), &(bufferIndex[i])); |
| nodeDqRet[i] = ret; |
| if (ret != NO_ERROR) { |
| CLOGE("ERR(%s[%d]):node(%s)->getBuffer() fail, index(%d), frameCount(%d), ret(%d)", |
| __FUNCTION__, __LINE__, m_deviceInfo->nodeName[i], |
| bufferIndex[i], newFrame->getFrameCount(), ret); |
| /* TODO: doing exception handling */ |
| |
| if (bufferIndex[i] >= 0) { |
| newFrame = m_runningFrameList[i][bufferIndex[i]]; |
| } else { |
| ret = newFrame->getDstBuffer(getPipeId(), &buffer[i], i); |
| if (ret != NO_ERROR) { |
| CLOGE("ERR(%s[%d]):Frame get buffer fail, frameCount(%d), ret(%d)", |
| __FUNCTION__, __LINE__, newFrame->getFrameCount(), ret); |
| } else { |
| bufferIndex[i] = buffer[i].index = -2; |
| } |
| newFrame->setRequest(pipeId, false); |
| } |
| |
| if (newFrame == NULL) { |
| CLOGE("ERR(%s[%d]):Invalid DQ buffer bufferIndex[%d](%d)", __FUNCTION__, __LINE__, i, bufferIndex[i]); |
| return BAD_VALUE; |
| } |
| |
| ret = newFrame->setDstBufferState(getPipeId(), ENTITY_BUFFER_STATE_ERROR, i); |
| if (ret != NO_ERROR) { |
| CLOGE("ERR(%s[%d]):setDstBuffer state fail, pipeID(%d), frameCount(%d), ret(%d)", |
| __FUNCTION__, __LINE__, getPipeId(), newFrame->getFrameCount(), ret); |
| } |
| } |
| |
| if (bufferIndex[i] >= 0) { |
| m_runningFrameList[i][bufferIndex[i]] = NULL; |
| m_numOfRunningFrame[i]--; |
| } |
| |
| /* 5. Link capture node buffer(DstBuffer) to frame */ |
| if (bufferIndex[i] >= 0 && nodeDqRet[i] == NO_ERROR) { |
| if (bufferIndex[i] != buffer[i].index) |
| newFrame = m_runningFrameList[i][bufferIndex[i]]; |
| |
| /* HACK: Should change ExynosCamera, Frame */ |
| ret = newFrame->setDstBufferState(getPipeId(), ENTITY_BUFFER_STATE_REQUESTED, i); |
| if (ret != NO_ERROR) { |
| CLOGE("ERR(%s[%d]):setDstBuffer state fail, pipeID(%d), frameCount(%d), ret(%d)", |
| __FUNCTION__, __LINE__, pipeId, newFrame->getFrameCount(), ret); |
| } |
| |
| ret = newFrame->setDstBuffer(getPipeId(), buffer[i], i, INDEX(pipeId)); |
| if (ret != NO_ERROR) { |
| CLOGE("ERR(%s[%d]):Frame set dst buffer fail, frameCount(%d), ret(%d)", |
| __FUNCTION__, __LINE__, newFrame->getFrameCount(), ret); |
| /* TODO: doing exception handling */ |
| if (m_bufferManager[i] != NULL) |
| ret = m_bufferManager[i]->putBuffer(buffer[i].index, EXYNOS_CAMERA_BUFFER_POSITION_NONE); |
| |
| if (ret != NO_ERROR) { |
| CLOGE("ERR(%s[%d]):Buffer manager putBuffer fail, manager(%d), frameCount(%d), ret(%d)", |
| __FUNCTION__, __LINE__, i, newFrame->getFrameCount(), ret); |
| } |
| |
| newFrame->setRequest(pipeId, false); |
| } |
| |
| ret = newFrame->setDstBufferState(getPipeId(), ENTITY_BUFFER_STATE_COMPLETE, i); |
| if (ret != NO_ERROR) { |
| CLOGE("ERR(%s[%d]):setDstBuffer state fail, pipeID(%d), frameCount(%d), ret(%d)", |
| __FUNCTION__, __LINE__, getPipeId(), newFrame->getFrameCount(), ret); |
| } |
| |
| captureNodeCount++; |
| } |
| |
| /* 6. Update metadata of capture node buffer(DstBuffer) from output node buffer(SrcBuffer) */ |
| if (m_node[OUTPUT_NODE] != NULL) { |
| m_node[OUTPUT_NODE]->getColorFormat(&v4l2Colorformat, &planeCount[OUTPUT_NODE]); |
| m_node[i]->getColorFormat(&v4l2Colorformat, &planeCount[i]); |
| |
| camera2_shot_ext *shot_ext_src = (struct camera2_shot_ext *)(buffer[OUTPUT_NODE].addr[(planeCount[OUTPUT_NODE] - 1)]); |
| camera2_shot_ext *shot_ext_dst = (struct camera2_shot_ext *)(buffer[i].addr[(planeCount[i] - 1)]); |
| if (shot_ext_src != NULL && shot_ext_dst != NULL) { |
| memcpy(&shot_ext_dst->shot.ctl, &shot_ext_src->shot.ctl, sizeof(struct camera2_ctl) - sizeof(struct camera2_entry_ctl)); |
| memcpy(&shot_ext_dst->shot.udm, &shot_ext_src->shot.udm, sizeof(struct camera2_udm)); |
| memcpy(&shot_ext_dst->shot.dm, &shot_ext_src->shot.dm, sizeof(struct camera2_dm)); |
| |
| shot_ext_dst->setfile = shot_ext_src->setfile; |
| shot_ext_dst->drc_bypass = shot_ext_src->drc_bypass; |
| shot_ext_dst->dis_bypass = shot_ext_src->dis_bypass; |
| shot_ext_dst->dnr_bypass = shot_ext_src->dnr_bypass; |
| shot_ext_dst->fd_bypass = shot_ext_src->fd_bypass; |
| shot_ext_dst->shot.dm.request.frameCount = shot_ext_src->shot.dm.request.frameCount; |
| shot_ext_dst->shot.magicNumber= shot_ext_src->shot.magicNumber; |
| #ifdef SAMSUNG_COMPANION |
| shot_ext_dst->shot.uctl.companionUd.wdr_mode = shot_ext_src->shot.uctl.companionUd.wdr_mode; |
| #endif |
| } else { |
| CLOGE("ERR(%s[%d]):metadata address fail, frameCount(%d) shot_ext src(%p) dst(%p) ", |
| __FUNCTION__, __LINE__, newFrame->getFrameCount(), shot_ext_src, shot_ext_dst); |
| } |
| /* Comment out : It was not useful for metadate fully update, I want know reasons for the existence. */ |
| /* memcpy(buffer[i].addr[(planeCount[i] - 1)], buffer[OUTPUT_NODE].addr[(planeCount[OUTPUT_NODE] - 1)], sizeof(struct camera2_shot_ext)); */ |
| } |
| } |
| } |
| |
| /* |
| * skip condition : |
| * 1 : all capture nodes are not valid. |
| * 2 : one of capture nodes is not valid. |
| */ |
| int checkRet = NO_ERROR; |
| |
| for (int i = OUTPUT_NODE; i < MAX_NODE; i++) { |
| checkRet |= nodeDqRet[i]; |
| } |
| |
| if (captureNodeCount == 0 || checkRet != NO_ERROR) { |
| CLOGE("ERR(%s[%d]):frameCount(%d) : captureNodeCount == %d || checkRet(%d) != NO_ERROR. so, setFrameState(FRAME_STATE_SKIPPED)", |
| __FUNCTION__, __LINE__, newFrame->getFrameCount(), captureNodeCount, checkRet); |
| |
| /* set err on frame */ |
| newFrame->setFrameState(FRAME_STATE_SKIPPED); |
| |
| /* set err on src */ |
| ret = newFrame->setSrcBufferState(getPipeId(), ENTITY_BUFFER_STATE_ERROR); |
| if (ret != NO_ERROR) { |
| CLOGE("ERR(%s[%d]):setSrcBufferState(%d, ENTITY_BUFFER_STATE_ERROR) fail, frameCount(%d), ret(%d)", |
| __FUNCTION__, __LINE__, getPipeId(), newFrame->getFrameCount(), ret); |
| } |
| |
| /* set err on dst */ |
| for (int i = OUTPUT_NODE + 1; i < MAX_NODE; i++) { |
| int dstPipeId = getPipeId((enum NODE_TYPE)i); |
| |
| if (dstPipeId < 0) |
| continue; |
| |
| if (newFrame->getRequest(dstPipeId) == true) { |
| ret = newFrame->setDstBufferState(getPipeId(), ENTITY_BUFFER_STATE_ERROR, i); |
| if (ret != NO_ERROR) { |
| CLOGE("ERR(%s[%d]):setDstBufferState(%d, ENTITY_BUFFER_STATE_ERROR, %d) fail, frameCount(%d), ret(%d)", |
| __FUNCTION__, __LINE__, getPipeId(), i, newFrame->getFrameCount(), ret); |
| } |
| } |
| } |
| } |
| |
| /* 7. Complete frame */ |
| ret = m_completeFrame(newFrame); |
| if (ret != NO_ERROR) { |
| CLOGE("ERR(%s[%d]):Complete frame fail, frameCount(%d), ret(%d)", |
| __FUNCTION__, __LINE__, newFrame->getFrameCount(), ret); |
| /* TODO: doing exception handling */ |
| } |
| |
| /* 8. Push frame to out of Pipe */ |
| CLEAN: |
| m_outputFrameQ->pushProcessQ(&newFrame); |
| if (m_frameDoneQ != NULL) |
| m_frameDoneQ->pushProcessQ(&newFrame); |
| |
| for (int i = OUTPUT_NODE; i < MAX_NODE; i++) |
| ret |= nodeDqRet[i]; |
| |
| CLOGV("DEBUG(%s[%d]):OUT-", __FUNCTION__, __LINE__); |
| |
| return ret; |
| } |
| |
| status_t ExynosCameraMCPipe::m_checkShotDone(struct camera2_shot_ext *shot_ext) |
| { |
| CLOGD("DEBUG(%s[%d])", __FUNCTION__, __LINE__); |
| |
| if (shot_ext == NULL) { |
| CLOGE("ERR(%s[%d]):shot_ext is NULL", __FUNCTION__, __LINE__); |
| return BAD_VALUE; |
| } |
| |
| if (shot_ext->node_group.leader.request != 1) { |
| CLOGW("WARN(%s[%d]):3a1 NOT DONE, frameCount(%d)", __FUNCTION__, __LINE__, |
| getMetaDmRequestFrameCount(shot_ext)); |
| /* TODO: doing exception handling */ |
| return INVALID_OPERATION; |
| } |
| |
| return OK; |
| } |
| |
| status_t ExynosCameraMCPipe::m_updateMetadataFromFrame(ExynosCameraFrame *frame, ExynosCameraBuffer *buffer) |
| { |
| CLOGV("DEBUG(%s[%d])", __FUNCTION__, __LINE__); |
| status_t ret = NO_ERROR; |
| |
| int pictureW = 0, pictureH = 0; |
| int cropW = 0, cropH = 0, cropX = 0, cropY = 0; |
| |
| camera2_shot_ext *shot_ext = (struct camera2_shot_ext *)(buffer->addr[1]); |
| |
| if (shot_ext != NULL) { |
| m_parameters->getPictureSize(&pictureW, &pictureH); |
| m_parameters->getHwBayerCropRegion(&cropW, &cropH, &cropX, &cropY); |
| |
| if (INDEX(getPipeId()) == PERFRAME_CONTROL_PIPE |
| || getPipeId() == PERFRAME_CONTROL_REPROCESSING_PIPE) { |
| frame->getMetaData(shot_ext); |
| |
| if (m_parameters->getHalVersion() != IS_HAL_VER_3_2) { |
| ret = m_parameters->duplicateCtrlMetadata((void *)shot_ext); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]):duplicate Ctrl metadata fail", __FUNCTION__, __LINE__); |
| return INVALID_OPERATION; |
| } |
| } |
| |
| setMetaSetfile(shot_ext, m_setfile); |
| } |
| |
| if (m_reprocessing == false) |
| m_activityControl->activityBeforeExecFunc(getPipeId(), (void *)buffer); |
| |
| #ifdef ENABLE_SETFILE |
| /* setfile setting */ |
| if (m_reprocessing == true) { |
| int yuvRange = 0; |
| int setfile = 0; |
| m_parameters->getSetfileYuvRange(m_reprocessing, &setfile, &yuvRange); |
| ALOGD("INFO(%s[%d]):setfile(%d),m_reprocessing(%d)", __FUNCTION__, __LINE__, setfile, m_reprocessing); |
| setMetaSetfile(shot_ext, setfile); |
| } |
| #endif |
| |
| CLOGV("DEBUG(%s[%d]):frameCount(%d), rCount(%d)", |
| __FUNCTION__, __LINE__, |
| frame->getFrameCount(), getMetaDmRequestFrameCount(shot_ext)); |
| |
| if (m_perframeMainNodeGroupInfo[OUTPUT_NODE].perFrameLeaderInfo.perFrameNodeType == PERFRAME_NODE_TYPE_LEADER) { |
| int perframePosition = 0; |
| int zoomParamInfo = m_parameters->getZoomLevel(); |
| int zoomFrameInfo = 0; |
| int previewW = 0, previewH = 0; |
| int pictureW = 0, pictureH = 0; |
| ExynosRect sensorSize; |
| ExynosRect bnsSize; |
| ExynosRect bayerCropSize; |
| ExynosRect bdsSize; |
| camera2_node_group node_group_info; |
| camera2_node_group node_group_info_isp; |
| camera2_node_group node_group_info_dis; |
| |
| frame->getNodeGroupInfo(&node_group_info, m_perframeMainNodeGroupInfo[OUTPUT_NODE].perFrameLeaderInfo.perframeInfoIndex, &zoomFrameInfo); |
| frame->getNodeGroupInfo(&node_group_info_isp, PERFRAME_INFO_ISP, &zoomFrameInfo); |
| frame->getNodeGroupInfo(&node_group_info_dis, PERFRAME_INFO_DIS, &zoomFrameInfo); |
| |
| /* HACK: To speed up DZOOM */ |
| if ((INDEX(getPipeId()) == PERFRAME_CONTROL_PIPE |
| || getPipeId() == PERFRAME_CONTROL_REPROCESSING_PIPE) |
| && zoomFrameInfo != zoomParamInfo) { |
| CLOGI("INFO(%s[%d]):zoomFrameInfo(%d), zoomParamInfo(%d)", |
| __FUNCTION__, __LINE__, zoomFrameInfo, zoomParamInfo); |
| |
| m_parameters->getHwPreviewSize(&previewW, &previewH); |
| m_parameters->getPictureSize(&pictureW, &pictureH); |
| |
| if (m_reprocessing == false) { |
| m_parameters->getPreviewBayerCropSize(&sensorSize, &bayerCropSize); |
| m_parameters->getPreviewBdsSize(&bdsSize); |
| |
| ExynosCameraNodeGroup3AA::updateNodeGroupInfo( |
| m_cameraId, |
| &node_group_info, |
| bayerCropSize, |
| bdsSize, |
| previewW, previewH, |
| pictureW, pictureH); |
| |
| ExynosCameraNodeGroupISP::updateNodeGroupInfo( |
| m_cameraId, |
| &node_group_info_isp, |
| bayerCropSize, |
| bdsSize, |
| previewW, previewH, |
| pictureW, pictureH, |
| m_parameters->getHWVdisMode()); |
| |
| ExynosCameraNodeGroupDIS::updateNodeGroupInfo( |
| m_cameraId, |
| &node_group_info_dis, |
| bayerCropSize, |
| bdsSize, |
| previewW, previewH, |
| pictureW, pictureH, |
| m_parameters->getHWVdisMode()); |
| |
| frame->storeNodeGroupInfo(&node_group_info, PERFRAME_INFO_3AA, zoomParamInfo); |
| frame->storeNodeGroupInfo(&node_group_info_isp, PERFRAME_INFO_ISP, zoomParamInfo); |
| frame->storeNodeGroupInfo(&node_group_info_dis, PERFRAME_INFO_DIS, zoomParamInfo); |
| } else { |
| m_parameters->getPictureBayerCropSize(&bnsSize, &bayerCropSize); |
| m_parameters->getPictureBdsSize(&bdsSize); |
| |
| ExynosCameraNodeGroup::updateNodeGroupInfo( |
| m_cameraId, |
| &node_group_info, |
| &node_group_info_isp, |
| bayerCropSize, |
| bayerCropSize, |
| bdsSize, |
| pictureW, pictureH, |
| m_parameters->getUsePureBayerReprocessing(), |
| m_parameters->isReprocessing3aaIspOTF()); |
| |
| frame->storeNodeGroupInfo(&node_group_info, PERFRAME_INFO_PURE_REPROCESSING_3AA, zoomParamInfo); |
| frame->storeNodeGroupInfo(&node_group_info_isp, PERFRAME_INFO_PURE_REPROCESSING_ISP, zoomParamInfo); |
| } |
| } |
| |
| memset(&shot_ext->node_group, 0x0, sizeof(camera2_node_group)); |
| |
| if (node_group_info.leader.request == 1) { |
| if (m_checkNodeGroupInfo(m_deviceInfo->nodeName[OUTPUT_NODE], &m_curNodeGroupInfo.leader, &node_group_info.leader) != NO_ERROR) |
| CLOGW("WARN(%s[%d]): m_checkNodeGroupInfo(leader) fail", __FUNCTION__, __LINE__); |
| |
| setMetaNodeLeaderInputSize(shot_ext, |
| node_group_info.leader.input.cropRegion[0], |
| node_group_info.leader.input.cropRegion[1], |
| node_group_info.leader.input.cropRegion[2], |
| node_group_info.leader.input.cropRegion[3]); |
| |
| setMetaNodeLeaderOutputSize(shot_ext, |
| node_group_info.leader.output.cropRegion[0], |
| node_group_info.leader.output.cropRegion[1], |
| node_group_info.leader.output.cropRegion[2], |
| node_group_info.leader.output.cropRegion[3]); |
| |
| setMetaNodeLeaderRequest(shot_ext, node_group_info.leader.request); |
| setMetaNodeLeaderVideoID(shot_ext, |
| m_perframeMainNodeGroupInfo[OUTPUT_NODE].perFrameLeaderInfo.perFrameVideoID); |
| } |
| |
| if (CAPTURE_NODE_MAX < m_perframeMainNodeGroupInfo[OUTPUT_NODE].perframeSupportNodeNum) { |
| android_printAssert(NULL, LOG_TAG, "ASSERT(%s[%d]):PipeId(%d) has Invalid perframeSupportNodeNum:CAPTURE_NODE_MAX(%d) < m_perframeMainNodeGroupInfo[OUTPUT_NODE].perframeSupportNodeNum(%d), assert!!!!", |
| __FUNCTION__, __LINE__, getPipeId(), CAPTURE_NODE_MAX, m_perframeMainNodeGroupInfo[OUTPUT_NODE].perframeSupportNodeNum); |
| } |
| |
| /* Update capture node request from Frame */ |
| for (int i = CAPTURE_NODE; i < MAX_NODE; i++) { |
| int funcRet = NO_ERROR; |
| if (m_node[i] != NULL) { |
| funcRet = m_getPerframePosition(&perframePosition, getPipeId((enum NODE_TYPE)i)); |
| if (funcRet != NO_ERROR) { |
| CLOGE("ERR(%s[%d]):m_getPerframePosition fail, ret(%d)", |
| __FUNCTION__, __LINE__, funcRet); |
| ret = funcRet; |
| continue; |
| } |
| node_group_info.capture[perframePosition].request = frame->getRequest(getPipeId((enum NODE_TYPE)i)); |
| } |
| } |
| |
| for (int i = 0; i < m_perframeMainNodeGroupInfo[OUTPUT_NODE].perframeSupportNodeNum; i ++) { |
| /* |
| * To set 3AP BDS size on full OTF, |
| * We need to set perframeSize. |
| * request is 0. so, no side effect. |
| */ |
| //if (node_group_info.capture[i].request == 1) { |
| if (m_checkNodeGroupInfo(i, &m_curNodeGroupInfo.capture[i], &node_group_info.capture[i]) != NO_ERROR) |
| CLOGW("WARN(%s[%d]): m_checkNodeGroupInfo(%d) fail", __FUNCTION__, __LINE__, i); |
| |
| setMetaNodeCaptureInputSize(shot_ext, i, |
| node_group_info.capture[i].input.cropRegion[0], |
| node_group_info.capture[i].input.cropRegion[1], |
| node_group_info.capture[i].input.cropRegion[2], |
| node_group_info.capture[i].input.cropRegion[3]); |
| |
| setMetaNodeCaptureOutputSize(shot_ext, i, |
| node_group_info.capture[i].output.cropRegion[0], |
| node_group_info.capture[i].output.cropRegion[1], |
| node_group_info.capture[i].output.cropRegion[2], |
| node_group_info.capture[i].output.cropRegion[3]); |
| |
| setMetaNodeCaptureRequest(shot_ext, i, node_group_info.capture[i].request); |
| setMetaNodeCaptureVideoID(shot_ext, i, |
| m_perframeMainNodeGroupInfo[OUTPUT_NODE].perFrameCaptureInfo[i].perFrameVideoID); |
| //} |
| } |
| |
| /* |
| CLOGI("INFO(%s[%d]):frameCount(%d)", __FUNCTION__, __LINE__, shot_ext->shot.dm.request.frameCount); |
| frame->dumpNodeGroupInfo(m_deviceInfo->nodeName[OUTPUT_NODE]); |
| m_dumpPerframeNodeGroupInfo("m_perframeMainNodeGroupInfo", m_perframeMainNodeGroupInfo[OUTPUT_NODE]); |
| |
| for (int i = (OUTPUT_NODE + 1); i < m_perframeMainNodeGroupInfo[OUTPUT_NODE].perframeSupportNodeNum; i++) |
| m_dumpPerframeNodeGroupInfo("m_perframeCaptureNodeGroupInfo", m_perframeMainNodeGroupInfo[i]); |
| */ |
| |
| /* dump info on shot_ext, just before qbuf */ |
| //m_dumpPerframeShotInfo(m_deviceInfo->nodeName[OUTPUT_NODE], frame->getFrameCount(), shot_ext); |
| } |
| } |
| |
| return ret; |
| } |
| |
| status_t ExynosCameraMCPipe::m_updateMetadataToFrame(void *metadata, int index, ExynosCameraFrame *frame, enum NODE_TYPE nodeLocation) |
| { |
| CLOGV("DEBUG(%s[%d])", __FUNCTION__, __LINE__); |
| status_t ret = NO_ERROR; |
| ExynosCameraFrame *curFrame = NULL; |
| camera2_shot_ext *shot_ext; |
| shot_ext = (struct camera2_shot_ext *)metadata; |
| |
| if (shot_ext == NULL) { |
| CLOGE("ERR(%s[%d]):Meta buffer is null", __FUNCTION__, __LINE__); |
| return BAD_VALUE; |
| } |
| if (index < 0) { |
| CLOGE("ERR(%s[%d]):Invalid index(%d)", __FUNCTION__, __LINE__, index); |
| return BAD_VALUE; |
| } |
| if (frame == NULL) { |
| CLOGE("ERR(%s[%d]):frame is Null", __FUNCTION__, __LINE__); |
| return BAD_VALUE; |
| } |
| if (nodeLocation < OUTPUT_NODE) { |
| CLOGE("ERR(%s[%d]):Invalid node location(%d)", __FUNCTION__, __LINE__, nodeLocation); |
| return BAD_VALUE; |
| } |
| |
| if (m_metadataTypeShot == false) { |
| CLOGV("DEBUG(%s[%d]):Stream type do not need update metadata", __FUNCTION__, __LINE__); |
| return NO_ERROR; |
| } |
| |
| /* |
| ret = m_getFrameByIndex(&curFrame, index, nodeLocation); |
| if (ret != NO_ERROR) { |
| CLOGE("ERR(%s[%d]):m_getFrameByIndex() fail, node(%s), index(%d), ret(%d)", |
| __FUNCTION__, __LINE__, m_deviceInfo->nodeName[nodeLocation], index, ret); |
| return ret; |
| } |
| */ |
| |
| ret = frame->storeDynamicMeta(shot_ext); |
| if (ret != NO_ERROR) { |
| CLOGE("ERR(%s[%d]):storeDynamicMeta() fail, ret(%d)", __FUNCTION__, __LINE__, ret); |
| return ret; |
| } |
| |
| ret = frame->storeUserDynamicMeta(shot_ext); |
| if (ret != NO_ERROR) { |
| CLOGE("ERR(%s[%d]):storeUserDynamicMeta() fail, ret(%d)", __FUNCTION__, __LINE__, ret); |
| return ret; |
| } |
| |
| return ret; |
| } |
| |
| status_t ExynosCameraMCPipe::m_getFrameByIndex(ExynosCameraFrame **frame, int index, enum NODE_TYPE nodeLocation) |
| { |
| CLOGV("DEBUG(%s[%d])", __FUNCTION__, __LINE__); |
| |
| if (nodeLocation < OUTPUT_NODE) { |
| CLOGE("ERR(%s[%d]):Invalid node location(%d)", __FUNCTION__, __LINE__, nodeLocation); |
| return BAD_VALUE; |
| } |
| if (index < 0) { |
| CLOGE("ERR(%s[%d]):Invalid index(%d)", __FUNCTION__, __LINE__, index); |
| return BAD_VALUE; |
| } |
| |
| *frame = m_runningFrameList[nodeLocation][index]; |
| if (*frame == NULL) { |
| CLOGE("ERR(%s[%d]):Unknown buffer, index %d frame is NULL", __FUNCTION__, __LINE__, index); |
| dump(); |
| return BAD_VALUE; |
| } |
| |
| return NO_ERROR; |
| } |
| |
| status_t ExynosCameraMCPipe::m_completeFrame( |
| ExynosCameraFrame *frame, |
| bool isValid) |
| { |
| CLOGV("DEBUG(%s[%d])", __FUNCTION__, __LINE__); |
| status_t ret = NO_ERROR; |
| |
| if (frame == NULL) { |
| CLOGE("ERR(%s[%d]):Frame is NULL", __FUNCTION__, __LINE__); |
| dump(); |
| return BAD_VALUE; |
| } |
| |
| if (isValid == false) { |
| CLOGD("DEBUG(%s[%d]):NOT DONE frameCount(%d)", __FUNCTION__, __LINE__, |
| frame->getFrameCount()); |
| } |
| |
| ret = frame->setEntityState(getPipeId(), ENTITY_STATE_FRAME_DONE); |
| if (ret != NO_ERROR) { |
| CLOGE("ERR(%s[%d]):Set entity state fail, ret(%d)", __FUNCTION__, __LINE__, ret); |
| /* TODO: doing exception handling */ |
| return ret; |
| } |
| |
| CLOGV("DEBUG(%s[%d]):Entity pipeId(%d), frameCount(%d)", |
| __FUNCTION__, __LINE__, getPipeId(), frame->getFrameCount()); |
| |
| return ret; |
| } |
| |
| status_t ExynosCameraMCPipe::m_setInput(ExynosCameraNode *nodes[], int32_t *nodeNums, int32_t *sensorIds) |
| { |
| status_t ret = NO_ERROR; |
| int currentSensorId[MAX_NODE] = {0}; |
| |
| if (nodes == NULL || nodeNums == NULL || sensorIds == NULL) { |
| CLOGE("ERR(%s[%d]): nodes == %p || nodeNum == %p || sensorId == %p", |
| __FUNCTION__, __LINE__, nodes, nodeNums, sensorIds); |
| return INVALID_OPERATION; |
| } |
| |
| for (int i = OUTPUT_NODE; i < MAX_NODE; i++) { |
| if (m_flagValidInt(nodeNums[i]) == false) |
| continue; |
| |
| if (m_flagValidInt(sensorIds[i]) == false) |
| continue; |
| |
| if (nodes[i] == NULL) |
| continue; |
| |
| currentSensorId[i] = nodes[i]->getInput(); |
| |
| if (m_flagValidInt(currentSensorId[i]) == false || |
| currentSensorId[i] != sensorIds[i]) { |
| |
| #ifdef INPUT_STREAM_MASK |
| CLOGD("DEBUG(%s[%d]): setInput(sensorIds : %d) [src nodeNum : %d][nodeNums : %d][otf : %d][leader : %d][reprocessing : %d][unique sensorId : %d]", |
| __FUNCTION__, __LINE__, |
| sensorIds[i], |
| ((sensorIds[i] & INPUT_VINDEX_MASK) >> INPUT_VINDEX_SHIFT) + FIMC_IS_VIDEO_BAS_NUM, |
| nodeNums[i], |
| ((sensorIds[i] & INPUT_MEMORY_MASK) >> INPUT_MEMORY_SHIFT), |
| ((sensorIds[i] & INPUT_LEADER_MASK) >> INPUT_LEADER_SHIFT), |
| ((sensorIds[i] & INPUT_STREAM_MASK) >> INPUT_STREAM_SHIFT), |
| ((sensorIds[i] & INPUT_MODULE_MASK) >> INPUT_MODULE_SHIFT)); |
| #else |
| CLOGD("DEBUG(%s[%d]): setInput(sensorIds : %d)", |
| __FUNCTION__, __LINE__, sensorIds[i]); |
| #endif |
| ret = nodes[i]->setInput(sensorIds[i]); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]): nodeNums[%d] : %d, setInput(sensorIds : %d fail, ret(%d)", |
| __FUNCTION__, __LINE__, i, nodeNums[i], sensorIds[i], |
| ret); |
| |
| return ret; |
| } |
| } |
| } |
| |
| return ret; |
| } |
| |
| status_t ExynosCameraMCPipe::m_setPipeInfo(camera_pipe_info_t *pipeInfos) |
| { |
| CLOGD("DEBUG(%s[%d])", __FUNCTION__, __LINE__); |
| status_t ret = NO_ERROR; |
| uint32_t planeCount = 2; |
| |
| if (pipeInfos == NULL) { |
| CLOGE("ERR(%s[%d]):pipeInfos is NULL", __FUNCTION__, __LINE__); |
| return BAD_VALUE; |
| } |
| |
| for (int i = OUTPUT_NODE; i < MAX_NODE; i++) { |
| if (m_node[i] != NULL && |
| 0 < pipeInfos[i].rectInfo.fullW && |
| 0 < pipeInfos[i].rectInfo.fullH) { |
| /* check about OUTPUT_NODE */ |
| if (i == OUTPUT_NODE && pipeInfos[i].bufInfo.type != V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { |
| CLOGE("ERR(%s[%d]):pipeInfos[%d].bufInfo.type is not Valid(type:%d)", |
| __FUNCTION__, __LINE__, i, pipeInfos[i].bufInfo.type); |
| return BAD_VALUE; |
| } |
| |
| /* check about CAPTURE_NODE */ |
| if ((OUTPUT_NODE < i && i < OTF_NODE_BASE) && |
| (pipeInfos[i].bufInfo.type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)) { |
| CLOGE("ERR(%s[%d]):pipeInfos[%d].bufInfo.type is not Valid(type:%d)", |
| __FUNCTION__, __LINE__, i, pipeInfos[i].bufInfo.type); |
| return BAD_VALUE; |
| } |
| |
| if (m_deviceInfo->nodeNum[i] == FIMC_IS_VIDEO_SCP_NUM) { |
| int setfile = 0; |
| int yuvRange = 0; |
| uint32_t bytePerPlane = 0; |
| int colorFormat = m_parameters->getHwPreviewFormat(); |
| |
| if (colorFormat != pipeInfos[i].rectInfo.colorFormat) { |
| CLOGE("ERR(%s[%d]):SCP colorformat is not Valid(%d)", |
| __FUNCTION__, __LINE__, pipeInfos[i].rectInfo.colorFormat); |
| return BAD_VALUE; |
| } |
| |
| getYuvFormatInfo(colorFormat, &bytePerPlane, &planeCount); |
| /* Add medadata plane count */ |
| planeCount++; |
| |
| m_parameters->getSetfileYuvRange(m_reprocessing, &setfile, &yuvRange); |
| |
| ret = m_setNodeInfo(m_node[i], &pipeInfos[i], |
| planeCount, (enum YUV_RANGE)yuvRange); |
| } else { |
| ret = m_setNodeInfo(m_node[i], &pipeInfos[i], |
| planeCount, YUV_FULL_RANGE); |
| } |
| |
| if (ret != NO_ERROR) { |
| CLOGE("ERR(%s[%d]):m_setNodeInfo(W:%d, H:%d, buffer count:%d) fail(Node:%s), ret(%d)", |
| __FUNCTION__, __LINE__, |
| pipeInfos[i].rectInfo.fullW, pipeInfos[i].rectInfo.fullH, |
| pipeInfos[i].bufInfo.count, m_deviceInfo->nodeName[i], ret); |
| return ret; |
| } |
| |
| m_numBuffers[i] = pipeInfos[i].bufInfo.count; |
| m_perframeMainNodeGroupInfo[i] = pipeInfos[i].perFrameNodeGroupInfo; |
| } |
| } |
| |
| return ret; |
| } |
| |
| status_t ExynosCameraMCPipe::m_setNodeInfo(ExynosCameraNode *node, camera_pipe_info_t *pipeInfos, |
| uint32_t planeCount, enum YUV_RANGE yuvRange, |
| __unused bool flagBayer) |
| { |
| CLOGD("DEBUG(%s[%d])", __FUNCTION__, __LINE__); |
| status_t ret = NO_ERROR; |
| |
| bool flagSetRequest = false; |
| unsigned int requestBufCount = 0; |
| |
| int currentW = 0; |
| int currentH = 0; |
| int currentV4l2Colorformat = 0; |
| int currentPlanesCount = 0; |
| enum YUV_RANGE currentYuvRange = YUV_FULL_RANGE; |
| int currentBufferCount = 0; |
| enum v4l2_buf_type currentBufType; |
| enum v4l2_memory currentMemType; |
| |
| if (node == NULL) { |
| CLOGE("ERR(%s[%d]):node is NULL", __FUNCTION__, __LINE__); |
| return BAD_VALUE; |
| } |
| |
| if (pipeInfos == NULL) { |
| CLOGE("ERR(%s[%d]):pipeInfos is NULL", __FUNCTION__, __LINE__); |
| return BAD_VALUE; |
| } |
| |
| requestBufCount = node->reqBuffersCount(); |
| |
| /* If it already set */ |
| if (0 < requestBufCount) { |
| node->getSize(¤tW, ¤tH); |
| node->getColorFormat(¤tV4l2Colorformat, ¤tPlanesCount, ¤tYuvRange); |
| node->getBufferType(¤tBufferCount, ¤tBufType, ¤tMemType); |
| |
| if (/* setSize */ |
| currentW != pipeInfos->rectInfo.fullW || |
| currentH != pipeInfos->rectInfo.fullH || |
| /* setColorFormat */ |
| currentV4l2Colorformat != pipeInfos->rectInfo.colorFormat || |
| currentPlanesCount != (int)planeCount || |
| currentYuvRange != yuvRange || |
| /* setBufferType */ |
| currentBufferCount != (int)pipeInfos->bufInfo.count || |
| currentBufType != (enum v4l2_buf_type)pipeInfos->bufInfo.type || |
| currentMemType != (enum v4l2_memory)pipeInfos->bufInfo.memory) { |
| |
| flagSetRequest = true; |
| |
| CLOGW("WARN(%s[%d]):Node is already requested. call clrBuffers()", __FUNCTION__, __LINE__); |
| |
| CLOGW("WARN(%s[%d]):W(%d -> %d), H(%d -> %d)", |
| __FUNCTION__, __LINE__, |
| currentW, pipeInfos->rectInfo.fullW, |
| currentH, pipeInfos->rectInfo.fullH); |
| |
| CLOGW("WARN(%s[%d]):colorFormat(%d -> %d), planeCount(%d -> %d), yuvRange(%d -> %d)", |
| __FUNCTION__, __LINE__, |
| currentV4l2Colorformat, pipeInfos->rectInfo.colorFormat, |
| currentPlanesCount, planeCount, |
| currentYuvRange, yuvRange); |
| |
| CLOGW("WARN(%s[%d]):bufferCount(%d -> %d), bufType(%d -> %d), memType(%d -> %d)", |
| __FUNCTION__, __LINE__, |
| currentBufferCount, pipeInfos->bufInfo.count, |
| currentBufType, pipeInfos->bufInfo.type, |
| currentMemType, pipeInfos->bufInfo.memory); |
| |
| ret = node->clrBuffers(); |
| if (ret != NO_ERROR) { |
| CLOGE("ERR(%s[%d]): node->clrBuffers() fail", __FUNCTION__, __LINE__); |
| return ret; |
| } |
| } |
| } else { |
| flagSetRequest = true; |
| } |
| |
| if (flagSetRequest == true) { |
| CLOGD("DEBUG(%s[%d]):set pipeInfos on %s, setFormat(%d, %d) and reqBuffers(%d)", |
| __FUNCTION__, __LINE__, |
| node->getName(), pipeInfos->rectInfo.fullW, |
| pipeInfos->rectInfo.fullH, pipeInfos->bufInfo.count); |
| |
| bool flagValidSetFormatInfo = true; |
| |
| if (pipeInfos->rectInfo.fullW == 0 || pipeInfos->rectInfo.fullH == 0) { |
| CLOGW("WARN(%s[%d]):Invalid size(%d x %d), skip setSize()", |
| __FUNCTION__, __LINE__, |
| pipeInfos->rectInfo.fullW, pipeInfos->rectInfo.fullH); |
| |
| flagValidSetFormatInfo = false; |
| } |
| node->setSize(pipeInfos->rectInfo.fullW, pipeInfos->rectInfo.fullH); |
| |
| if (pipeInfos->rectInfo.colorFormat == 0 || planeCount == 0) { |
| CLOGW("WARN(%s[%d]):invalid colorFormat(%d), planeCount(%d), skip setColorFormat()", |
| __FUNCTION__, __LINE__, |
| pipeInfos->rectInfo.colorFormat, planeCount); |
| |
| flagValidSetFormatInfo = false; |
| } |
| node->setColorFormat(pipeInfos->rectInfo.colorFormat, planeCount, yuvRange); |
| |
| if ((int)pipeInfos->bufInfo.type == 0 || pipeInfos->bufInfo.memory == 0) { |
| CLOGW("WARN(%s[%d]):Invalid bufInfo.type(%d), bufInfo.memory(%d), skip setBufferType()", |
| __FUNCTION__, __LINE__, |
| (int)pipeInfos->bufInfo.type, (int)pipeInfos->bufInfo.memory); |
| |
| flagValidSetFormatInfo = false; |
| } |
| node->setBufferType(pipeInfos->bufInfo.count, |
| (enum v4l2_buf_type)pipeInfos->bufInfo.type, |
| (enum v4l2_memory)pipeInfos->bufInfo.memory); |
| |
| if (flagValidSetFormatInfo == true) { |
| ret = node->setFormat(pipeInfos->bytesPerPlane); |
| if (ret != NO_ERROR) { |
| CLOGE("ERR(%s[%d]):node->setFormat() fail", __FUNCTION__, __LINE__); |
| return ret; |
| } |
| } |
| |
| node->getBufferType(¤tBufferCount, ¤tBufType, ¤tMemType); |
| |
| } else { |
| CLOGD("DEBUG(%s[%d]):Skip set pipeInfos setFormat(%d, %d) and reqBuffers(%d).", |
| __FUNCTION__, __LINE__, |
| pipeInfos->rectInfo.fullW, pipeInfos->rectInfo.fullH, pipeInfos->bufInfo.count); |
| } |
| |
| if (currentBufferCount <= 0) { |
| CLOGW("WARN(%s[%d]):Invalid currentBufferCount(%d), skip reqBuffers()", |
| __FUNCTION__, __LINE__, currentBufferCount); |
| } else { |
| ret = node->reqBuffers(); |
| if (ret != NO_ERROR) { |
| CLOGE("ERR(%s[%d]):node->reqBuffers() fail", __FUNCTION__, __LINE__); |
| return ret; |
| } |
| } |
| |
| return ret; |
| } |
| |
| status_t ExynosCameraMCPipe::m_getPerframePosition(int *perframePosition, uint32_t pipeId) |
| { |
| status_t ret = NO_ERROR; |
| |
| if (perframePosition == NULL) { |
| CLOGE("ERR(%s[%d]):perframePosition is NULL", __FUNCTION__, __LINE__); |
| return BAD_VALUE; |
| } |
| |
| switch(INDEX(pipeId)) { |
| case PIPE_3AC: |
| *perframePosition = (m_cameraId == CAMERA_ID_BACK) ? PERFRAME_BACK_3AC_POS : PERFRAME_FRONT_3AC_POS; |
| break; |
| case PIPE_3AP: |
| *perframePosition = (m_cameraId == CAMERA_ID_BACK) ? PERFRAME_BACK_3AP_POS : PERFRAME_FRONT_3AP_POS; |
| break; |
| case PIPE_ISPC: |
| *perframePosition = (m_cameraId == CAMERA_ID_BACK) ? PERFRAME_BACK_ISPC_POS : PERFRAME_FRONT_ISPC_POS; |
| break; |
| case PIPE_ISPP: |
| *perframePosition = (m_cameraId == CAMERA_ID_BACK) ? PERFRAME_BACK_ISPP_POS : PERFRAME_FRONT_ISPP_POS; |
| break; |
| case PIPE_SCC: |
| *perframePosition = (m_cameraId == CAMERA_ID_BACK) ? PERFRAME_BACK_SCC_POS : PERFRAME_FRONT_SCC_POS; |
| break; |
| case PIPE_SCP: |
| *perframePosition = (m_cameraId == CAMERA_ID_BACK) ? PERFRAME_BACK_SCC_POS : PERFRAME_FRONT_SCC_POS; |
| break; |
| default: |
| CLOGV("ERR(%s[%d]):Invalid pipeID(%d)", __FUNCTION__, __LINE__, pipeId); |
| ret = BAD_VALUE; |
| break; |
| } |
| |
| return ret; |
| } |
| |
| status_t ExynosCameraMCPipe::m_setSetfile(ExynosCameraNode *node, uint32_t pipeId) |
| { |
| CLOGD("DEBUG(%s[%d])", __FUNCTION__, __LINE__); |
| status_t ret = NO_ERROR; |
| int yuvRange = 0; |
| |
| m_parameters->getSetfileYuvRange(m_reprocessing, &m_setfile, &yuvRange); |
| |
| #ifdef SET_SETFILE_BY_SHOT |
| m_setfile = mergeSetfileYuvRange(m_setfile, yuvRange); |
| #else |
| #ifdef SET_SETFILE_BY_SET_CTRL |
| #ifdef SET_SETFILE_BY_SET_CTRL_3AA |
| if (SET_SETFILE_BY_SET_CTRL_3AA == true && INDEX(pipeId) == INDEX(PIPE_3AA)) { |
| ret = node->setControl(V4L2_CID_IS_SET_SETFILE, m_setfile); |
| if (ret != NO_ERROR) { |
| CLOGE("ERR(%s[%d]):setControl(%d) fail(ret = %d)", __FUNCTION__, __LINE__, m_setfile, ret); |
| return ret; |
| } |
| } else |
| #endif |
| if (SET_SETFILE_BY_SET_CTRL_ISP == true && INDEX(pipeId) == INDEX(PIPE_ISP)) { |
| ret = node->setControl(V4L2_CID_IS_SET_SETFILE, m_setfile); |
| if (ret != NO_ERROR) { |
| CLOGE("ERR(%s[%d]):setControl(%d) fail(ret = %d)", __FUNCTION__, __LINE__, m_setfile, ret); |
| return ret; |
| } |
| } else if (SET_SETFILE_BY_SET_CTRL_SCP == true && INDEX(pipeId) == INDEX(PIPE_SCP)) { |
| ret = node->setControl(V4L2_CID_IS_COLOR_RANGE, yuvRange); |
| if (ret != NO_ERROR) { |
| CLOGE("ERR(%s[%d]):setControl(%d) fail(ret = %d)", __FUNCTION__, __LINE__, m_setfile, ret); |
| return ret; |
| } |
| } |
| #endif |
| #endif |
| |
| return ret; |
| } |
| |
| status_t ExynosCameraMCPipe::m_forceDone(ExynosCameraNode *node, unsigned int cid, int value) |
| { |
| CLOGD("DEBUG(%s[%d])", __FUNCTION__, __LINE__); |
| status_t ret = NO_ERROR; |
| |
| if (node == NULL) { |
| CLOGE("ERR(%s[%d]):node is NULL", __FUNCTION__, __LINE__); |
| return BAD_VALUE; |
| } |
| |
| if (cid != V4L2_CID_IS_FORCE_DONE) { |
| CLOGW("ERR(%s[%d]):cid != V4L2_CID_IS_FORCE_DONE", __FUNCTION__, __LINE__); |
| } |
| |
| /* "value" is not meaningful */ |
| ret = node->setControl(V4L2_CID_IS_FORCE_DONE, value); |
| if (ret != NO_ERROR) { |
| ALOGE("ERR(%s[%d]):node V4L2_CID_IS_FORCE_DONE failed", __FUNCTION__, __LINE__); |
| node->dump(); |
| return ret; |
| } |
| |
| return ret; |
| } |
| |
| status_t ExynosCameraMCPipe::m_setMapBuffer(ExynosCameraNode *node, ExynosCameraBuffer *buffer) |
| { |
| status_t ret = NO_ERROR; |
| |
| if (buffer == NULL) { |
| CLOGE("ERR(%s[%d]):Buffer is NULL", __FUNCTION__, __LINE__); |
| return BAD_VALUE; |
| } |
| if (node == NULL) { |
| CLOGE("ERR(%s[%d]):Node is NULL", __FUNCTION__, __LINE__); |
| return BAD_VALUE; |
| } |
| |
| /* Require code sync release-git to Repo */ |
| /* ret = node->mapBuffer(buffer); */ |
| if (ret != NO_ERROR) |
| CLOGE("ERR(%s[%d]):mapBuffer() fail, ret(%d)", __FUNCTION__, __LINE__, ret); |
| |
| return ret; |
| } |
| |
| status_t ExynosCameraMCPipe::m_startNode(void) |
| { |
| CLOGD("DEBUG(%s[%d])", __FUNCTION__, __LINE__); |
| status_t ret = NO_ERROR; |
| |
| for (int i = (MAX_NODE - 1); i >= OUTPUT_NODE; i--) { |
| /* only M2M mode need stream on/off */ |
| /* TODO : flite has different sensorId bit */ |
| if (m_node[i] != NULL) { |
| ret = m_node[i]->start(); |
| if (ret != NO_ERROR) { |
| CLOGE("ERR(%s[%d]):node(%s)->start fail, ret(%d)", |
| __FUNCTION__, __LINE__, m_deviceInfo->nodeName[i], ret); |
| return ret; |
| } |
| } |
| } |
| |
| return ret; |
| } |
| |
| status_t ExynosCameraMCPipe::m_stopNode(void) |
| { |
| CLOGD("DEBUG(%s[%d])", __FUNCTION__, __LINE__); |
| status_t ret = NO_ERROR; |
| |
| for (int i = OUTPUT_NODE; i < MAX_NODE; i++) { |
| /* only M2M mode need stream on/off */ |
| /* TODO : flite has different sensorId bit */ |
| if (m_node[i] != NULL) { |
| ret = m_node[i]->stop(); |
| if (ret != NO_ERROR) { |
| CLOGE("ERR(%s[%d]):node(%s)->stop fail, ret(%d)", |
| __FUNCTION__, __LINE__, m_deviceInfo->nodeName[i], ret); |
| return ret; |
| } |
| |
| ret = m_node[i]->clrBuffers(); |
| if (ret != NO_ERROR) { |
| CLOGE("ERR(%s[%d]):node(%s)->clrBuffers fail, ret(%d)", |
| __FUNCTION__, __LINE__, m_deviceInfo->nodeName[i], ret); |
| return ret; |
| } |
| |
| m_node[i]->removeItemBufferQ(); |
| } |
| } |
| |
| return ret; |
| } |
| |
| status_t ExynosCameraMCPipe::m_clearNode(void) |
| { |
| CLOGD("DEBUG(%s[%d])", __FUNCTION__, __LINE__); |
| status_t ret = NO_ERROR; |
| |
| for (int i = OUTPUT_NODE; i < MAX_NODE; i++) { |
| if (m_node[i] != NULL) { |
| ret = m_node[i]->clrBuffers(); |
| if (ret != NO_ERROR) { |
| CLOGE("ERR(%s[%d]):node(%s)->clrBuffers fail, ret(%d)", |
| __FUNCTION__, __LINE__, m_deviceInfo->nodeName[i], ret); |
| return ret; |
| } |
| } |
| } |
| |
| return ret; |
| } |
| |
| status_t ExynosCameraMCPipe::m_checkNodeGroupInfo(char *name, camera2_node *oldNode, camera2_node *newNode) |
| { |
| if (oldNode == NULL || newNode == NULL) { |
| CLOGE("ERR(%s[%d]): oldNode(%p) == NULL || newNode(%p) == NULL", __FUNCTION__, __LINE__, oldNode, newNode); |
| return INVALID_OPERATION; |
| } |
| |
| bool flagCropRegionChanged = false; |
| |
| for (int i = 0; i < 4; i++) { |
| if (oldNode->input.cropRegion[i] != newNode->input.cropRegion[i] || |
| oldNode->output.cropRegion[i] != newNode->output.cropRegion[i]) { |
| |
| CLOGD("DEBUG(%s[%d]):(%s):oldCropSize(%d, %d, %d, %d / %d, %d, %d, %d) -> newCropSize(%d, %d, %d, %d / %d, %d, %d, %d)", |
| __FUNCTION__, __LINE__, |
| name, |
| oldNode->input. cropRegion[0], oldNode->input. cropRegion[1], oldNode->input. cropRegion[2], oldNode->input. cropRegion[3], |
| oldNode->output.cropRegion[0], oldNode->output.cropRegion[1], oldNode->output.cropRegion[2], oldNode->output.cropRegion[3], |
| newNode->input. cropRegion[0], newNode->input. cropRegion[1], newNode->input. cropRegion[2], newNode->input. cropRegion[3], |
| newNode->output.cropRegion[0], newNode->output.cropRegion[1], newNode->output.cropRegion[2], newNode->output.cropRegion[3]); |
| |
| break; |
| } |
| } |
| |
| for (int i = 0; i < 4; i++) { |
| oldNode->input. cropRegion[i] = newNode->input. cropRegion[i]; |
| oldNode->output.cropRegion[i] = newNode->output.cropRegion[i]; |
| } |
| |
| return NO_ERROR; |
| } |
| |
| status_t ExynosCameraMCPipe::m_checkNodeGroupInfo(char *name, int index, camera2_node *oldNode, camera2_node *newNode) |
| { |
| if (oldNode == NULL || newNode == NULL) { |
| CLOGE("ERR(%s[%d]): oldNode(%p) == NULL || newNode(%p) == NULL", __FUNCTION__, __LINE__, oldNode, newNode); |
| return INVALID_OPERATION; |
| } |
| |
| bool flagCropRegionChanged = false; |
| |
| for (int i = 0; i < 4; i++) { |
| if (oldNode->input.cropRegion[i] != newNode->input.cropRegion[i] || |
| oldNode->output.cropRegion[i] != newNode->output.cropRegion[i]) { |
| |
| CLOGD("DEBUG(%s[%d]): name %s : index %d: PerFrame oldCropSize (%d, %d, %d, %d / %d, %d, %d, %d) -> newCropSize (%d, %d, %d, %d / %d, %d, %d, %d)", |
| __FUNCTION__, __LINE__, |
| name, |
| index, |
| oldNode->input. cropRegion[0], oldNode->input. cropRegion[1], oldNode->input. cropRegion[2], oldNode->input. cropRegion[3], |
| oldNode->output.cropRegion[0], oldNode->output.cropRegion[1], oldNode->output.cropRegion[2], oldNode->output.cropRegion[3], |
| newNode->input. cropRegion[0], newNode->input. cropRegion[1], newNode->input. cropRegion[2], newNode->input. cropRegion[3], |
| newNode->output.cropRegion[0], newNode->output.cropRegion[1], newNode->output.cropRegion[2], newNode->output.cropRegion[3]); |
| |
| break; |
| } |
| } |
| |
| for (int i = 0; i < 4; i++) { |
| oldNode->input. cropRegion[i] = newNode->input. cropRegion[i]; |
| oldNode->output.cropRegion[i] = newNode->output.cropRegion[i]; |
| } |
| |
| return NO_ERROR; |
| } |
| |
| status_t ExynosCameraMCPipe::m_checkNodeGroupInfo(int index, camera2_node *oldNode, camera2_node *newNode) |
| { |
| return m_checkNodeGroupInfo(m_deviceInfo->nodeName[index], oldNode, newNode); |
| } |
| |
| void ExynosCameraMCPipe::m_dumpRunningFrameList(void) |
| { |
| CLOGI("INFO(%s[%d]):*********runningFrameList dump***********", __FUNCTION__, __LINE__); |
| for (int i = OUTPUT_NODE; i < MAX_NODE; i++) { |
| CLOGI("INFO(%s[%d]):m_numBuffers[%d] : %d", __FUNCTION__, __LINE__, i, m_numBuffers[i]); |
| for (uint32_t j = 0; j < m_numBuffers[i]; j++) { |
| if (m_runningFrameList[i][j] == NULL) { |
| CLOGI("runningFrameList[%d][%d] is NULL", i, j); |
| } else { |
| CLOGI("runningFrameList[%d][%d]: fcount = %d", |
| i, j, m_runningFrameList[i][j]->getFrameCount()); |
| } |
| } |
| } |
| |
| return; |
| } |
| |
| void ExynosCameraMCPipe::m_dumpPerframeNodeGroupInfo(const char *name, camera_pipe_perframe_node_group_info_t nodeInfo) |
| { |
| if (name != NULL) |
| CLOGI("DEBUG(%s[%d]):(%s) ++++++++++++++++++++", __FUNCTION__, __LINE__, name); |
| |
| CLOGI("\t\t perframeSupportNodeNum : %d", nodeInfo.perframeSupportNodeNum); |
| CLOGI("\t\t perFrameLeaderInfo.perframeInfoIndex : %d", nodeInfo.perFrameLeaderInfo.perframeInfoIndex); |
| CLOGI("\t\t perFrameLeaderInfo.perFrameVideoID : %d", nodeInfo.perFrameLeaderInfo.perFrameVideoID); |
| |
| for (int i = 0; i < CAPTURE_NODE_MAX; i++) |
| CLOGI("\t\t perFrameCaptureInfo[%d].perFrameVideoID : %d", i, nodeInfo.perFrameCaptureInfo[i].perFrameVideoID); |
| |
| if (name != NULL) |
| CLOGI("DEBUG(%s[%d]):(%s) ------------------------------", __FUNCTION__, __LINE__, name); |
| |
| return; |
| } |
| |
| void ExynosCameraMCPipe::m_dumpPerframeShotInfo(const char *name, int frameCount, camera2_shot_ext *shot_ext) |
| { |
| if (name != NULL) |
| CLOGI("DEBUG(%s[%d]):(%s) frameCount(%d) ++++++++++++++++++++", __FUNCTION__, __LINE__, name, frameCount); |
| |
| if (shot_ext != NULL) { |
| for (int i = 0; i < CAPTURE_NODE_MAX; i++) { |
| CLOGI("DEBUG(%s[%d]):\t\t index(%d), vid(%d) request(%d) input (%d, %d, %d, %d) output (%d, %d, %d, %d)", |
| __FUNCTION__, __LINE__, |
| i, |
| shot_ext->node_group.capture[i].vid, |
| shot_ext->node_group.capture[i].request, |
| shot_ext->node_group.capture[i].input.cropRegion[0], |
| shot_ext->node_group.capture[i].input.cropRegion[1], |
| shot_ext->node_group.capture[i].input.cropRegion[2], |
| shot_ext->node_group.capture[i].input.cropRegion[3], |
| shot_ext->node_group.capture[i].output.cropRegion[0], |
| shot_ext->node_group.capture[i].output.cropRegion[1], |
| shot_ext->node_group.capture[i].output.cropRegion[2], |
| shot_ext->node_group.capture[i].output.cropRegion[3]); |
| } |
| } else { |
| CLOGI("DEBUG(%s[%d]):\t\t shot_ext == NULL", __FUNCTION__, __LINE__); |
| } |
| |
| if (name != NULL) |
| CLOGI("DEBUG(%s[%d]):(%s) ------------------------------", __FUNCTION__, __LINE__, name); |
| } |
| |
| void ExynosCameraMCPipe::m_configDvfs(void) |
| { |
| CLOGD("DEBUG(%s[%d])", __FUNCTION__, __LINE__); |
| |
| bool newDvfs = m_parameters->getDvfsLock(); |
| |
| if (newDvfs != m_dvfsLocked) { |
| setControl(V4L2_CID_IS_DVFS_LOCK, 533000); |
| m_dvfsLocked = newDvfs; |
| } |
| } |
| |
| bool ExynosCameraMCPipe::m_flagValidInt(int num) |
| { |
| bool ret = false; |
| |
| if (num == -1 || num == 0) |
| ret = false; |
| else |
| ret = true; |
| |
| return ret; |
| } |
| |
| bool ExynosCameraMCPipe::m_checkThreadLoop(frame_queue_t *frameQ) |
| { |
| Mutex::Autolock lock(m_pipeframeLock); |
| bool loop = false; |
| |
| if (m_reprocessing == false) |
| loop = true; |
| |
| if (frameQ->getSizeOfProcessQ() > 0) |
| loop = true; |
| |
| if (m_flagTryStop == true) |
| loop = false; |
| |
| return loop; |
| } |
| |
| status_t ExynosCameraMCPipe::m_checkPolling(ExynosCameraNode *node) |
| { |
| int ret = 0; |
| |
| ret = node->polling(); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]):polling fail, ret(%d)", __FUNCTION__, __LINE__, ret); |
| /* TODO: doing exception handling */ |
| |
| m_threadState = ERROR_POLLING_DETECTED; |
| return ERROR_POLLING_DETECTED; |
| } |
| |
| return NO_ERROR; |
| } |
| |
| void ExynosCameraMCPipe::m_init(camera_device_info_t *deviceInfo) |
| { |
| if (deviceInfo != NULL) |
| m_deviceInfo = deviceInfo; |
| else |
| m_deviceInfo = NULL; |
| |
| /* |
| * For replace old pipe, MCPipe have all variables. |
| * but, if exist old pipe, same variable not declared by MCPipe. |
| */ |
| for (int i = OUTPUT_NODE; i < MAX_NODE; i++) { |
| /* |
| m_bufferManager[i] = NULL; |
| m_node[i] = NULL; |
| m_nodeNum[i] = -1; |
| m_sensorIds[i] = -1; |
| */ |
| m_secondaryNode[i] = NULL; |
| m_secondaryNodeNum[i] = -1; |
| m_secondarySensorIds[i] = -1; |
| m_numOfRunningFrame[i] = 0; |
| m_skipPutBuffer[i] = false; |
| m_numBuffers[i] = 0; |
| for (int j = 0; j < MAX_BUFFERS; j++) |
| m_runningFrameList[i][j] = NULL; |
| memset(&m_perframeMainNodeGroupInfo[i], 0x00, sizeof(camera_pipe_perframe_node_group_info_t)); |
| |
| if (m_deviceInfo != NULL) |
| m_pipeIdArr[i] = m_deviceInfo->pipeId[i]; |
| else |
| m_pipeIdArr[i] = 0; |
| } |
| |
| /* |
| m_parameters = NULL; |
| m_activityControl = NULL; |
| m_exynosconfig = NULL; |
| |
| memset(m_name, 0x00, sizeof(m_name)); |
| |
| m_inputFrameQ = NULL; |
| */ |
| m_requestFrameQ = NULL; |
| /* |
| m_outputFrameQ = NULL; |
| m_frameDoneQ = NULL; |
| |
| m_pipeId = 0; |
| m_cameraId = -1; |
| |
| m_setfile = 0x0; |
| |
| m_prepareBufferCount = 0; |
| |
| m_reprocessing = false; |
| m_flagStartPipe = false; |
| m_flagTryStop = false; |
| m_dvfsLocked = false; |
| m_isBoosting = false; |
| |
| m_threadCommand = 0; |
| m_timeInterval = 0; |
| m_threadState = 0; |
| m_threadRenew = 0; |
| |
| memset(&m_curNodeGroupInfo, 0x00, sizeof(camera2_node_group)); |
| */ |
| #ifdef TEST_WATCHDOG_THREAD |
| int testErrorDetect = 0; |
| #endif |
| } |
| |
| }; /* namespace android */ |