| /* |
| ** |
| ** Copyright 2017, Samsung Electronics Co. LTD |
| ** |
| ** Licensed under the Apache License, Version 2.0 (the "License"); |
| ** you may not use this file except in compliance with the License. |
| ** You may obtain a copy of the License at |
| ** |
| ** http://www.apache.org/licenses/LICENSE-2.0 |
| ** |
| ** Unless required by applicable law or agreed to in writing, software |
| ** distributed under the License is distributed on an "AS IS" BASIS, |
| ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| ** See the License for the specific language governing permissions and |
| ** limitations under the License. |
| */ |
| |
| /* #define LOG_NDEBUG 0 */ |
| #define LOG_TAG "ExynosCameraFrameReprocessingFactory" |
| #include <log/log.h> |
| |
| #include "ExynosCameraFrameReprocessingFactory.h" |
| |
| namespace android { |
| |
| ExynosCameraFrameReprocessingFactory::~ExynosCameraFrameReprocessingFactory() |
| { |
| status_t ret = NO_ERROR; |
| |
| if (m_shot_ext != NULL) { |
| delete m_shot_ext; |
| m_shot_ext = NULL; |
| } |
| |
| ret = destroy(); |
| if (ret != NO_ERROR) |
| CLOGE("destroy fail"); |
| } |
| |
| status_t ExynosCameraFrameReprocessingFactory::create(void) |
| { |
| Mutex::Autolock lock(ExynosCameraStreamMutex::getInstance()->getStreamMutex()); |
| CLOGI(""); |
| |
| status_t ret = NO_ERROR; |
| |
| ret = ExynosCameraFrameFactoryBase::create(); |
| if (ret != NO_ERROR) { |
| CLOGE("Pipe create fail, ret(%d)", ret); |
| return ret; |
| } |
| |
| /* EOS */ |
| ret = m_pipes[INDEX(PIPE_3AA_REPROCESSING)]->setControl(V4L2_CID_IS_END_OF_STREAM, 1); |
| if (ret != NO_ERROR) { |
| CLOGE("PIPE_%s V4L2_CID_IS_END_OF_STREAM fail, ret(%d)", |
| m_pipes[INDEX(PIPE_3AA_REPROCESSING)]->getPipeName(), ret); |
| /* TODO: exception handling */ |
| return INVALID_OPERATION; |
| } |
| |
| ret = m_transitState(FRAME_FACTORY_STATE_CREATE); |
| |
| return ret; |
| } |
| |
| status_t ExynosCameraFrameReprocessingFactory::initPipes(void) |
| { |
| CLOGI(""); |
| |
| status_t ret = NO_ERROR; |
| camera_pipe_info_t pipeInfo[MAX_NODE]; |
| camera_pipe_info_t nullPipeInfo; |
| |
| int pipeId = -1; |
| enum NODE_TYPE nodeType = INVALID_NODE; |
| enum NODE_TYPE leaderNodeType = OUTPUT_NODE; |
| |
| int32_t nodeNums[MAX_NODE]; |
| int32_t sensorIds[MAX_NODE]; |
| int32_t secondarySensorIds[MAX_NODE]; |
| for (int i = 0; i < MAX_NODE; i++) { |
| nodeNums[i] = -1; |
| sensorIds[i] = -1; |
| secondarySensorIds[i] = -1; |
| } |
| |
| ExynosRect tempRect; |
| ExynosRect bnsSize; |
| ExynosRect bayerCropSize; |
| int hwSensorW = 0, hwSensorH = 0; |
| int maxPreviewW = 0, maxPreviewH = 0, hwPreviewW = 0, hwPreviewH = 0; |
| int maxPictureW = 0, maxPictureH = 0, hwPictureW = 0, hwPictureH = 0; |
| int maxThumbnailW = 0, maxThumbnailH = 0; |
| int yuvWidth[ExynosCameraParameters::YUV_MAX] = {0}; |
| int yuvHeight[ExynosCameraParameters::YUV_MAX] = {0}; |
| int bayerFormat = m_parameters->getBayerFormat(PIPE_3AA_REPROCESSING); |
| int yuvFormat[ExynosCameraParameters::YUV_MAX] = {0}; |
| int dsWidth = MAX_VRA_INPUT_WIDTH; |
| int dsHeight = MAX_VRA_INPUT_HEIGHT; |
| int dsFormat = m_parameters->getHwVraInputFormat(); |
| int pictureFormat = m_parameters->getHwPictureFormat(); |
| camera_pixel_size picturePixelSize = m_parameters->getHwPicturePixelSize(); |
| struct ExynosConfigInfo *config = m_parameters->getConfig(); |
| int perFramePos = 0; |
| int yuvIndex = -1; |
| |
| memset(&nullPipeInfo, 0, sizeof(camera_pipe_info_t)); |
| |
| #ifdef DEBUG_RAWDUMP |
| if (m_parameters->checkBayerDumpEnable()) { |
| bayerFormat = CAMERA_DUMP_BAYER_FORMAT; |
| } |
| #endif |
| |
| m_parameters->getHwSensorSize(&hwSensorW, &hwSensorH); |
| m_parameters->getMaxPreviewSize(&maxPreviewW, &maxPreviewH); |
| m_parameters->getHwPreviewSize(&hwPreviewW, &hwPreviewH); |
| m_parameters->getMaxPictureSize(&maxPictureW, &maxPictureH); |
| m_parameters->getHwPictureSize(&hwPictureW, &hwPictureH); |
| m_parameters->getMaxThumbnailSize(&maxThumbnailW, &maxThumbnailH); |
| m_parameters->getPreviewBayerCropSize(&bnsSize, &bayerCropSize); |
| |
| CLOGI(" MaxPreviewSize(%dx%d), HwPreviewSize(%dx%d)", maxPreviewW, maxPreviewH, hwPreviewW, hwPreviewH); |
| CLOGI(" MaxPixtureSize(%dx%d), HwPixtureSize(%dx%d)", maxPictureW, maxPictureH, hwPictureW, hwPictureH); |
| CLOGI(" MaxThumbnailSize(%dx%d)", maxThumbnailW, maxThumbnailH); |
| CLOGI(" PreviewBayerCropSize(%dx%d)", bayerCropSize.w, bayerCropSize.h); |
| CLOGI("DS Size %dx%d Format %x Buffer count %d", |
| dsWidth, dsHeight, dsFormat, config->current->bufInfo.num_vra_buffers); |
| |
| for (int i = ExynosCameraParameters::YUV_STALL_0; i < ExynosCameraParameters::YUV_STALL_MAX; i++) { |
| yuvIndex = i % ExynosCameraParameters::YUV_MAX; |
| m_parameters->getHwYuvSize(&yuvWidth[yuvIndex], &yuvHeight[yuvIndex], i); |
| yuvFormat[yuvIndex] = m_parameters->getYuvFormat(i); |
| |
| if (m_parameters->getYuvStallPort() == yuvIndex) { |
| if ((yuvWidth[yuvIndex] == 0 && yuvHeight[yuvIndex] == 0) |
| #ifdef SAMSUNG_HIFI_CAPTURE |
| || (m_parameters->getLLSOn() == true) |
| #endif |
| ) { |
| m_parameters->getMaxPictureSize(&yuvWidth[yuvIndex], &yuvHeight[yuvIndex]); |
| yuvFormat[yuvIndex] = V4L2_PIX_FMT_NV21; |
| } |
| } |
| CLOGI("YUV_STALL[%d] Size %dx%d Format %x", |
| i, yuvWidth[yuvIndex], yuvHeight[yuvIndex], yuvFormat[yuvIndex]); |
| } |
| |
| /* |
| * 3AA for Reprocessing |
| */ |
| if (m_supportPureBayerReprocessing == true) { |
| pipeId = PIPE_3AA_REPROCESSING; |
| |
| /* 3AS */ |
| nodeType = getNodeType(PIPE_3AA_REPROCESSING); |
| bayerFormat = m_parameters->getBayerFormat(PIPE_3AA_REPROCESSING); |
| |
| /* set v4l2 buffer size */ |
| tempRect.fullW = hwSensorW; |
| tempRect.fullH = hwSensorH; |
| tempRect.colorFormat = bayerFormat; |
| |
| /* set v4l2 video node buffer count */ |
| pipeInfo[nodeType].bufInfo.count = config->current->bufInfo.num_bayer_buffers; |
| |
| /* Set output node default info */ |
| SET_OUTPUT_DEVICE_BASIC_INFO(PERFRAME_INFO_PURE_REPROCESSING_3AA); |
| |
| /* 3AC */ |
| nodeType = getNodeType(PIPE_3AC_REPROCESSING); |
| perFramePos = PERFRAME_REPROCESSING_3AC_POS; |
| bayerFormat = m_parameters->getBayerFormat(PIPE_3AC_REPROCESSING); |
| |
| /* set v4l2 buffer size */ |
| tempRect.fullW = hwSensorW; |
| tempRect.fullH = hwSensorH; |
| tempRect.colorFormat = bayerFormat; |
| |
| /* set v4l2 video node buffer count */ |
| pipeInfo[nodeType].bufInfo.count = config->current->bufInfo.num_bayer_buffers; |
| |
| /* Set capture node default info */ |
| SET_CAPTURE_DEVICE_BASIC_INFO(); |
| |
| /* 3AP */ |
| nodeType = getNodeType(PIPE_3AP_REPROCESSING); |
| perFramePos = PERFRAME_REPROCESSING_3AP_POS; |
| bayerFormat = m_parameters->getBayerFormat(PIPE_3AP_REPROCESSING); |
| |
| /* set v4l2 buffer size */ |
| tempRect.fullW = hwPictureW; |
| tempRect.fullH = hwPictureH; |
| tempRect.colorFormat = bayerFormat; |
| |
| /* set v4l2 video node bytes per plane */ |
| pipeInfo[nodeType].bytesPerPlane[0] = getBayerLineSize(tempRect.fullW, bayerFormat); |
| |
| /* set v4l2 video node buffer count */ |
| pipeInfo[nodeType].bufInfo.count = config->current->bufInfo.num_reprocessing_buffers; |
| |
| /* Set capture node default info */ |
| SET_CAPTURE_DEVICE_BASIC_INFO(); |
| |
| /* setup pipe info to 3AA pipe */ |
| if (m_flag3aaIspOTF == HW_CONNECTION_MODE_M2M) { |
| ret = m_pipes[INDEX(pipeId)]->setupPipe(pipeInfo, m_sensorIds[INDEX(pipeId)]); |
| if (ret != NO_ERROR) { |
| CLOGE("3AA setupPipe fail, ret(%d)", ret); |
| /* TODO: exception handling */ |
| return INVALID_OPERATION; |
| } |
| |
| /* clear pipeInfo for next setupPipe */ |
| for (int i = 0; i < MAX_NODE; i++) |
| pipeInfo[i] = nullPipeInfo; |
| } |
| } else { |
| /* |
| * 3A video node is opened for dirty bayer. |
| * So, we have to do setinput to 3A video node. |
| */ |
| pipeId = PIPE_3AA_REPROCESSING; |
| |
| /* setup pipe info to 3AA pipe */ |
| ret = m_pipes[INDEX(pipeId)]->setupPipe(pipeInfo, m_sensorIds[INDEX(pipeId)]); |
| if (ret != NO_ERROR) { |
| CLOGE("3AA setupPipe for dirty bayer reprocessing fail, ret(%d)", ret); |
| /* TODO: exception handling */ |
| return INVALID_OPERATION; |
| } |
| |
| /* clear pipeInfo for next setupPipe */ |
| for (int i = 0; i < MAX_NODE; i++) |
| pipeInfo[i] = nullPipeInfo; |
| } |
| |
| |
| /* |
| * ISP for Reprocessing |
| */ |
| |
| /* ISP */ |
| if (m_supportPureBayerReprocessing == false |
| || m_flagFlite3aaOTF == HW_CONNECTION_MODE_M2M) { |
| pipeId = PIPE_ISP_REPROCESSING; |
| nodeType = getNodeType(PIPE_ISP_REPROCESSING); |
| bayerFormat = m_parameters->getBayerFormat(PIPE_ISP_REPROCESSING); |
| |
| /* set v4l2 buffer size */ |
| if (m_parameters->getUsePureBayerReprocessing() == true) { |
| tempRect.fullW = hwPictureW; |
| tempRect.fullH = hwPictureH; |
| } else { |
| // Dirtybayer input is bCrop size |
| tempRect.fullW = bayerCropSize.w; |
| tempRect.fullH = bayerCropSize.h; |
| } |
| tempRect.colorFormat = bayerFormat; |
| |
| /* set v4l2 video node bytes per plane */ |
| pipeInfo[nodeType].bytesPerPlane[0] = getBayerLineSize(tempRect.fullW, bayerFormat); |
| |
| /* set v4l2 video node buffer count */ |
| if(m_supportPureBayerReprocessing) { |
| pipeInfo[nodeType].bufInfo.count = config->current->bufInfo.num_reprocessing_buffers; |
| } else if (m_parameters->isSupportZSLInput()) { |
| pipeInfo[nodeType].bufInfo.count = config->current->bufInfo.num_bayer_buffers; |
| } else { |
| pipeInfo[nodeType].bufInfo.count = config->current->bufInfo.num_sensor_buffers; |
| } |
| |
| /* Set output node default info */ |
| int ispPerframeInfoIndex = m_supportPureBayerReprocessing ? PERFRAME_INFO_PURE_REPROCESSING_ISP : PERFRAME_INFO_DIRTY_REPROCESSING_ISP; |
| SET_OUTPUT_DEVICE_BASIC_INFO(ispPerframeInfoIndex); |
| } |
| |
| /* ISPC */ |
| nodeType = getNodeType(PIPE_ISPC_REPROCESSING); |
| perFramePos = PERFRAME_REPROCESSING_ISPC_POS; |
| |
| /* set v4l2 buffer size */ |
| tempRect.fullW = hwPictureW; |
| tempRect.fullH = hwPictureH; |
| tempRect.colorFormat = pictureFormat; |
| |
| /* set YUV pixel size */ |
| pipeInfo[nodeType].pixelSize = CAMERA_PIXEL_SIZE_PACKED_10BIT; |
| |
| /* set v4l2 video node buffer count */ |
| pipeInfo[nodeType].bufInfo.count = config->current->bufInfo.num_hwdis_buffers; |
| |
| /* Set capture node default info */ |
| SET_CAPTURE_DEVICE_BASIC_INFO(); |
| |
| /* ISPP */ |
| nodeType = getNodeType(PIPE_ISPP_REPROCESSING); |
| perFramePos = PERFRAME_REPROCESSING_ISPP_POS; |
| |
| /* set v4l2 buffer size */ |
| tempRect.fullW = hwPictureW; |
| tempRect.fullH = hwPictureH; |
| tempRect.colorFormat = pictureFormat; |
| |
| /* set YUV pixel size */ |
| pipeInfo[nodeType].pixelSize = picturePixelSize; |
| |
| /* set v4l2 video node buffer count */ |
| pipeInfo[nodeType].bufInfo.count = config->current->bufInfo.num_hwdis_buffers; |
| |
| /* Set capture node default info */ |
| SET_CAPTURE_DEVICE_BASIC_INFO(); |
| |
| /* setup pipe info to ISP pipe */ |
| if (m_flagIspMcscOTF == HW_CONNECTION_MODE_M2M) { |
| ret = m_pipes[INDEX(pipeId)]->setupPipe(pipeInfo, m_sensorIds[INDEX(pipeId)]); |
| if (ret != NO_ERROR) { |
| CLOGE("ISP setupPipe fail, ret(%d)", ret); |
| /* TODO: exception handling */ |
| return INVALID_OPERATION; |
| } |
| |
| /* clear pipeInfo for next setupPipe */ |
| for (int i = 0; i < MAX_NODE; i++) |
| pipeInfo[i] = nullPipeInfo; |
| } |
| |
| /* |
| * MCSC for Reprocessing |
| */ |
| |
| /* MCSC */ |
| if (m_flagIspMcscOTF == HW_CONNECTION_MODE_M2M) { |
| pipeId = PIPE_MCSC_REPROCESSING; |
| nodeType = getNodeType(PIPE_MCSC_REPROCESSING); |
| |
| /* set v4l2 buffer size */ |
| tempRect.fullW = hwPictureW; |
| tempRect.fullH = hwPictureH; |
| tempRect.colorFormat = pictureFormat; |
| |
| /* set YUV pixel size */ |
| pipeInfo[nodeType].pixelSize = picturePixelSize; |
| |
| /* set v4l2 video node buffer count */ |
| pipeInfo[nodeType].bufInfo.count = config->current->bufInfo.num_hwdis_buffers; |
| |
| /* Set output node default info */ |
| int mcscPerframeInfoIndex = m_supportPureBayerReprocessing ? PERFRAME_INFO_PURE_REPROCESSING_MCSC : PERFRAME_INFO_DIRTY_REPROCESSING_MCSC; |
| SET_OUTPUT_DEVICE_BASIC_INFO(mcscPerframeInfoIndex); |
| } |
| |
| /* MCSC0 */ |
| nodeType = getNodeType(PIPE_MCSC0_REPROCESSING); |
| perFramePos = PERFRAME_REPROCESSING_MCSC0_POS; |
| yuvIndex = ExynosCameraParameters::YUV_STALL_0 % ExynosCameraParameters::YUV_MAX; |
| |
| /* set v4l2 buffer size */ |
| tempRect.fullW = yuvWidth[yuvIndex]; |
| tempRect.fullH = yuvHeight[yuvIndex]; |
| tempRect.colorFormat = yuvFormat[yuvIndex]; |
| |
| /* set v4l2 video node buffer count */ |
| pipeInfo[nodeType].bufInfo.count = config->current->bufInfo.num_picture_buffers; |
| /* pipeInfo[nodeType].bytesPerPlane[0] = tempRect.fullW; */ |
| |
| /* Set capture node default info */ |
| SET_CAPTURE_DEVICE_BASIC_INFO(); |
| |
| /* MCSC1 */ |
| nodeType = getNodeType(PIPE_MCSC1_REPROCESSING); |
| perFramePos = PERFRAME_REPROCESSING_MCSC1_POS; |
| yuvIndex = ExynosCameraParameters::YUV_STALL_1 % ExynosCameraParameters::YUV_MAX; |
| |
| /* set v4l2 buffer size */ |
| tempRect.fullW = yuvWidth[yuvIndex]; |
| tempRect.fullH = yuvHeight[yuvIndex]; |
| tempRect.colorFormat = yuvFormat[yuvIndex]; |
| |
| /* set v4l2 video node buffer count */ |
| pipeInfo[nodeType].bufInfo.count = config->current->bufInfo.num_picture_buffers; |
| /* pipeInfo[nodeType].bytesPerPlane[0] = tempRect.fullW; */ |
| |
| /* Set capture node default info */ |
| SET_CAPTURE_DEVICE_BASIC_INFO(); |
| |
| /* MCSC2 */ |
| nodeType = getNodeType(PIPE_MCSC2_REPROCESSING); |
| perFramePos = PERFRAME_REPROCESSING_MCSC2_POS; |
| yuvIndex = ExynosCameraParameters::YUV_STALL_2 % ExynosCameraParameters::YUV_MAX; |
| |
| /* set v4l2 buffer size */ |
| tempRect.fullW = yuvWidth[yuvIndex]; |
| tempRect.fullH = yuvHeight[yuvIndex]; |
| tempRect.colorFormat = yuvFormat[yuvIndex]; |
| |
| /* set v4l2 video node buffer count */ |
| pipeInfo[nodeType].bufInfo.count = config->current->bufInfo.num_picture_buffers; |
| /* pipeInfo[nodeType].bytesPerPlane[0] = tempRect.fullW; */ |
| |
| /* Set capture node default info */ |
| SET_CAPTURE_DEVICE_BASIC_INFO(); |
| |
| /* MCSC3 */ |
| nodeType = getNodeType(PIPE_MCSC3_REPROCESSING); |
| perFramePos = PERFRAME_REPROCESSING_MCSC3_POS; |
| |
| /* set v4l2 buffer size */ |
| tempRect.fullW = hwPictureW; |
| tempRect.fullH = hwPictureH; |
| tempRect.colorFormat = pictureFormat; |
| |
| /* set YUV pixel size */ |
| pipeInfo[nodeType].pixelSize = picturePixelSize; |
| |
| /* set v4l2 video node buffer count */ |
| pipeInfo[nodeType].bufInfo.count = config->current->bufInfo.num_reprocessing_buffers; |
| |
| /* Set capture node default info */ |
| SET_CAPTURE_DEVICE_BASIC_INFO(); |
| |
| /* MCSC4 */ |
| nodeType = getNodeType(PIPE_MCSC4_REPROCESSING); |
| perFramePos = PERFRAME_REPROCESSING_MCSC4_POS; |
| |
| /* set v4l2 buffer size */ |
| tempRect.fullW = maxThumbnailW; |
| tempRect.fullH = maxThumbnailH; |
| tempRect.colorFormat = pictureFormat; |
| |
| /* set YUV pixel size */ |
| pipeInfo[nodeType].pixelSize = picturePixelSize; |
| |
| /* set v4l2 video node buffer count */ |
| pipeInfo[nodeType].bufInfo.count = config->current->bufInfo.num_reprocessing_buffers; |
| |
| /* Set capture node default info */ |
| SET_CAPTURE_DEVICE_BASIC_INFO(); |
| |
| if (m_flagHWFCEnabled == true) { |
| #ifdef SUPPORT_HWFC_SERIALIZATION |
| /* Do serialized Q/DQ operation to guarantee the H/W flow control sequence limitation */ |
| m_pipes[INDEX(pipeId)]->needSerialization(true); |
| #endif |
| |
| /* JPEG Src */ |
| nodeType = getNodeType(PIPE_HWFC_JPEG_SRC_REPROCESSING); |
| |
| /* set v4l2 buffer size */ |
| tempRect.fullW = hwPictureW; |
| tempRect.fullH = hwPictureH; |
| tempRect.colorFormat = pictureFormat; |
| |
| /* set YUV pixel size */ |
| pipeInfo[nodeType].pixelSize = picturePixelSize; |
| |
| /* set v4l2 video node buffer count */ |
| pipeInfo[nodeType].bufInfo.count = config->current->bufInfo.num_reprocessing_buffers; |
| |
| /* Set capture node default info */ |
| pipeInfo[nodeType].rectInfo = tempRect; |
| pipeInfo[nodeType].bufInfo.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; |
| pipeInfo[nodeType].bufInfo.memory = V4L2_CAMERA_MEMORY_TYPE; |
| |
| /* Thumbnail Src */ |
| nodeType = getNodeType(PIPE_HWFC_THUMB_SRC_REPROCESSING); |
| |
| /* set v4l2 buffer size */ |
| tempRect.fullW = maxThumbnailW; |
| tempRect.fullH = maxThumbnailH; |
| tempRect.colorFormat = pictureFormat; |
| |
| /* set YUV pixel size */ |
| pipeInfo[nodeType].pixelSize = picturePixelSize; |
| |
| /* set v4l2 video node buffer count */ |
| pipeInfo[nodeType].bufInfo.count = config->current->bufInfo.num_reprocessing_buffers; |
| |
| /* Set capture node default info */ |
| pipeInfo[nodeType].rectInfo = tempRect; |
| pipeInfo[nodeType].bufInfo.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; |
| pipeInfo[nodeType].bufInfo.memory = V4L2_CAMERA_MEMORY_TYPE; |
| |
| /* JPEG Dst */ |
| nodeType = getNodeType(PIPE_HWFC_JPEG_DST_REPROCESSING); |
| |
| /* set v4l2 buffer size */ |
| tempRect.fullW = hwPictureW; |
| tempRect.fullH = hwPictureH; |
| tempRect.colorFormat = pictureFormat; |
| |
| /* set YUV pixel size */ |
| pipeInfo[nodeType].pixelSize = picturePixelSize; |
| |
| /* set v4l2 video node buffer count */ |
| pipeInfo[nodeType].bufInfo.count = config->current->bufInfo.num_picture_buffers; |
| |
| /* Set capture node default info */ |
| pipeInfo[nodeType].rectInfo = tempRect; |
| pipeInfo[nodeType].bufInfo.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; |
| pipeInfo[nodeType].bufInfo.memory = V4L2_CAMERA_MEMORY_TYPE; |
| |
| /* Thumbnail Dst */ |
| nodeType = getNodeType(PIPE_HWFC_THUMB_DST_REPROCESSING); |
| |
| /* set v4l2 buffer size */ |
| tempRect.fullW = maxThumbnailW; |
| tempRect.fullH = maxThumbnailH; |
| tempRect.colorFormat = pictureFormat; |
| |
| /* set YUV pixel size */ |
| pipeInfo[nodeType].pixelSize = picturePixelSize; |
| |
| /* set v4l2 video node buffer count */ |
| pipeInfo[nodeType].bufInfo.count = config->current->bufInfo.num_reprocessing_buffers; |
| |
| /* Set capture node default info */ |
| pipeInfo[nodeType].rectInfo = tempRect; |
| pipeInfo[nodeType].bufInfo.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; |
| pipeInfo[nodeType].bufInfo.memory = V4L2_CAMERA_MEMORY_TYPE; |
| } |
| |
| if (m_flagMcscVraOTF == HW_CONNECTION_MODE_M2M) { |
| /* MCSC5 */ |
| nodeType = getNodeType(PIPE_MCSC5_REPROCESSING); |
| perFramePos = PERFRAME_REPROCESSING_MCSC5_POS; |
| |
| /* set v4l2 buffer size */ |
| tempRect.fullW = dsWidth; |
| tempRect.fullH = dsHeight; |
| tempRect.colorFormat = dsFormat; |
| |
| /* set v4l2 video node buffer count */ |
| pipeInfo[nodeType].bufInfo.count = config->current->bufInfo.num_vra_buffers; |
| |
| /* Set capture node default info */ |
| SET_CAPTURE_DEVICE_BASIC_INFO(); |
| |
| ret = m_pipes[INDEX(pipeId)]->setupPipe(pipeInfo, m_sensorIds[INDEX(pipeId)]); |
| if (ret != NO_ERROR) { |
| CLOGE("MCSC setupPipe fail, ret(%d)", ret); |
| /* TODO: exception handling */ |
| return INVALID_OPERATION; |
| } |
| |
| /* clear pipeInfo for next setupPipe */ |
| for (int i = 0; i < MAX_NODE; i++) |
| pipeInfo[i] = nullPipeInfo; |
| } |
| |
| |
| /* VRA */ |
| if (m_flagMcscVraOTF == HW_CONNECTION_MODE_M2M) { |
| pipeId = PIPE_VRA_REPROCESSING; |
| nodeType = getNodeType(PIPE_VRA_REPROCESSING); |
| |
| /* set v4l2 buffer size */ |
| tempRect.fullW = dsWidth; |
| tempRect.fullH = dsHeight; |
| tempRect.colorFormat = dsFormat; |
| |
| /* set v4l2 video node buffer count */ |
| pipeInfo[nodeType].bufInfo.count = config->current->bufInfo.num_vra_buffers; |
| |
| /* Set output node default info */ |
| SET_OUTPUT_DEVICE_BASIC_INFO(PERFRAME_INFO_VRA); |
| } |
| |
| ret = m_pipes[INDEX(pipeId)]->setupPipe(pipeInfo, m_sensorIds[INDEX(pipeId)]); |
| if (ret != NO_ERROR) { |
| CLOGE("ISP setupPipe fail, ret(%d)", ret); |
| /* TODO: exception handling */ |
| return INVALID_OPERATION; |
| } |
| |
| m_frameCount = 0; |
| |
| ret = m_transitState(FRAME_FACTORY_STATE_INIT); |
| |
| return ret; |
| } |
| |
| status_t ExynosCameraFrameReprocessingFactory::preparePipes(void) |
| { |
| return NO_ERROR; |
| } |
| |
| status_t ExynosCameraFrameReprocessingFactory::startPipes(void) |
| { |
| status_t ret = NO_ERROR; |
| CLOGI(""); |
| |
| /* VRA Reprocessing */ |
| if (m_flagMcscVraOTF == HW_CONNECTION_MODE_M2M) { |
| ret = m_pipes[INDEX(PIPE_VRA_REPROCESSING)]->start(); |
| if (ret != NO_ERROR) { |
| CLOGE("VRA start fail, ret(%d)", ret); |
| /* TODO: exception handling */ |
| return INVALID_OPERATION; |
| } |
| } |
| |
| /* MCSC Reprocessing */ |
| if (m_flagIspMcscOTF == HW_CONNECTION_MODE_M2M) { |
| ret = m_pipes[INDEX(PIPE_MCSC_REPROCESSING)]->start(); |
| if (ret != NO_ERROR) { |
| CLOGE("MCSC start fail, ret(%d)", ret); |
| /* TODO: exception handling */ |
| return INVALID_OPERATION; |
| } |
| } |
| |
| /* ISP Reprocessing */ |
| if (m_flag3aaIspOTF == HW_CONNECTION_MODE_M2M) { |
| ret = m_pipes[INDEX(PIPE_ISP_REPROCESSING)]->start(); |
| if (ret != NO_ERROR) { |
| CLOGE("ISP start fail, ret(%d)", ret); |
| /* TODO: exception handling */ |
| return INVALID_OPERATION; |
| } |
| } |
| |
| /* 3AA Reprocessing */ |
| if (m_supportPureBayerReprocessing == true) { |
| ret = m_pipes[INDEX(PIPE_3AA_REPROCESSING)]->start(); |
| if (ret != NO_ERROR) { |
| CLOGE("ISP start fail, ret(%d)", ret); |
| /* TODO: exception handling */ |
| return INVALID_OPERATION; |
| } |
| } |
| |
| ret = m_transitState(FRAME_FACTORY_STATE_RUN); |
| if (ret != NO_ERROR) { |
| CLOGE("Failed to transitState. ret %d", ret); |
| return ret; |
| } |
| |
| CLOGI("Starting Reprocessing [SCC>ISP] Success!"); |
| |
| return NO_ERROR; |
| } |
| |
| status_t ExynosCameraFrameReprocessingFactory::stopPipes(void) |
| { |
| status_t ret = NO_ERROR; |
| status_t funcRet = NO_ERROR; |
| CLOGI(""); |
| |
| /* 3AA Reprocessing Thread stop */ |
| if (m_supportPureBayerReprocessing == true) { |
| ret = m_pipes[INDEX(PIPE_3AA_REPROCESSING)]->stopThread(); |
| if (ret != NO_ERROR) { |
| CLOGE("ISP stopThread fail, ret(%d)", ret); |
| /* TODO: exception handling */ |
| funcRet |= ret; |
| } |
| } |
| |
| /* ISP Reprocessing Thread stop */ |
| if (m_flag3aaIspOTF == HW_CONNECTION_MODE_M2M) { |
| ret = m_pipes[INDEX(PIPE_ISP_REPROCESSING)]->stopThread(); |
| if (ret != NO_ERROR) { |
| CLOGE("ISP stopThread fail, ret(%d)", ret); |
| /* TODO: exception handling */ |
| funcRet |= ret; |
| } |
| } |
| |
| /* MCSC Reprocessing Thread stop */ |
| if (m_flagIspMcscOTF == HW_CONNECTION_MODE_M2M) { |
| ret = m_pipes[INDEX(PIPE_MCSC_REPROCESSING)]->stopThread(); |
| if (ret != NO_ERROR) { |
| CLOGE("MCSC stopThread fail, ret(%d)", ret); |
| /* TODO: exception handling */ |
| funcRet |= ret; |
| } |
| } |
| |
| if (m_pipes[INDEX(PIPE_VRA_REPROCESSING)]->isThreadRunning() == true) { |
| ret = m_pipes[INDEX(PIPE_VRA_REPROCESSING)]->stopThread(); |
| if (ret != NO_ERROR) { |
| CLOGE("VRA stopThread fail, ret(%d)", ret); |
| /* TODO: exception handling */ |
| funcRet |= ret; |
| } |
| } |
| |
| /* 3AA Reprocessing stop */ |
| if (m_supportPureBayerReprocessing == true) { |
| ret = m_pipes[INDEX(PIPE_3AA_REPROCESSING)]->stop(); |
| if (ret != NO_ERROR) { |
| CLOGE("ISP stop fail, ret(%d)", ret); |
| /* TODO: exception handling */ |
| funcRet |= ret; |
| } |
| } |
| |
| /* ISP Reprocessing stop */ |
| if (m_flag3aaIspOTF == HW_CONNECTION_MODE_M2M) { |
| ret = m_pipes[INDEX(PIPE_ISP_REPROCESSING)]->stop(); |
| if (ret != NO_ERROR) { |
| CLOGE("ISP stop fail, ret(%d)", ret); |
| /* TODO: exception handling */ |
| funcRet |= ret; |
| } |
| } |
| |
| /* MCSC Reprocessing stop */ |
| if (m_flagIspMcscOTF == HW_CONNECTION_MODE_M2M) { |
| ret = m_pipes[INDEX(PIPE_MCSC_REPROCESSING)]->stop(); |
| if (ret != NO_ERROR) { |
| CLOGE("MCSC stop fail, ret(%d)", ret); |
| /* TODO: exception handling */ |
| funcRet |= ret; |
| } |
| } |
| |
| if (m_pipes[INDEX(PIPE_VRA_REPROCESSING)]->flagStart() == true) { |
| ret = m_pipes[INDEX(PIPE_VRA_REPROCESSING)]->stop(); |
| if (ret != NO_ERROR) { |
| CLOGE("VRA stop fail, ret(%d)", ret); |
| /* TODO: exception handling */ |
| funcRet |= ret; |
| } |
| } |
| |
| if (m_flagHWFCEnabled == false || (m_flagHWFCEnabled && m_parameters->isHWFCOnDemand())) { |
| /* JPEG Reprocessing stop */ |
| ret = m_pipes[INDEX(PIPE_JPEG_REPROCESSING)]->stop(); |
| if (ret != NO_ERROR) { |
| CLOGE("JPEG stop fail, ret(%d)", ret); |
| /* TODO: exception handling */ |
| funcRet |= ret; |
| } |
| } |
| |
| /* GSC2 Reprocessing stop */ |
| ret = stopThreadAndWait(PIPE_GSC_REPROCESSING2); |
| if (ret != NO_ERROR) { |
| CLOGE("PIPE_GSC_REPROCESSING2 stopThreadAndWait fail, ret(%d)", ret); |
| } |
| |
| /* GSC3 Reprocessing stop */ |
| ret = stopThreadAndWait(PIPE_GSC_REPROCESSING3); |
| if (ret != NO_ERROR) { |
| CLOGE("PIPE_GSC_REPROCESSING3 stopThreadAndWait fail, ret(%d)", ret); |
| } |
| |
| ret = m_transitState(FRAME_FACTORY_STATE_CREATE); |
| if (ret != NO_ERROR) { |
| CLOGE("Failed to transitState. ret %d", |
| ret); |
| funcRet |= ret; |
| } |
| |
| CLOGI("Stopping Reprocessing [3AA>MCSC] Success!"); |
| |
| return funcRet; |
| } |
| |
| status_t ExynosCameraFrameReprocessingFactory::startInitialThreads(void) |
| { |
| CLOGI("start pre-ordered initial pipe thread"); |
| |
| return NO_ERROR; |
| } |
| |
| status_t ExynosCameraFrameReprocessingFactory::setStopFlag(void) |
| { |
| CLOGI(""); |
| |
| status_t ret = NO_ERROR; |
| |
| if (m_pipes[INDEX(PIPE_3AA_REPROCESSING)]->flagStart() == true) |
| ret = m_pipes[INDEX(PIPE_3AA_REPROCESSING)]->setStopFlag(); |
| |
| if (m_pipes[INDEX(PIPE_ISP_REPROCESSING)]->flagStart() == true) |
| ret = m_pipes[INDEX(PIPE_ISP_REPROCESSING)]->setStopFlag(); |
| |
| if (m_pipes[INDEX(PIPE_DCPS0_REPROCESSING)]->flagStart() == true) |
| ret = m_pipes[INDEX(PIPE_DCPS0_REPROCESSING)]->setStopFlag(); |
| |
| if (m_pipes[INDEX(PIPE_MCSC_REPROCESSING)]->flagStart() == true) |
| ret = m_pipes[INDEX(PIPE_MCSC_REPROCESSING)]->setStopFlag(); |
| |
| if (m_pipes[INDEX(PIPE_VRA_REPROCESSING)]->flagStart() == true) |
| ret = m_pipes[INDEX(PIPE_VRA_REPROCESSING)]->setStopFlag(); |
| |
| return NO_ERROR; |
| } |
| |
| status_t ExynosCameraFrameReprocessingFactory::m_fillNodeGroupInfo(ExynosCameraFrameSP_sptr_t frame) |
| { |
| camera2_node_group node_group_info_3aa; |
| camera2_node_group node_group_info_isp; |
| camera2_node_group node_group_info_mcsc; |
| camera2_node_group node_group_info_vra; |
| camera2_node_group *node_group_info_temp = NULL; |
| |
| float zoomRatio = m_parameters->getZoomRatio(); |
| int pipeId = -1; |
| int nodePipeId = -1; |
| uint32_t perframePosition = 0; |
| |
| int yuvFormat[ExynosCameraParameters::YUV_MAX] = {0}; |
| int yuvWidth[ExynosCameraParameters::YUV_MAX] = {0}; |
| int yuvHeight[ExynosCameraParameters::YUV_MAX] = {0}; |
| int yuvIndex = -1; |
| |
| for (int i = ExynosCameraParameters::YUV_STALL_0; i < ExynosCameraParameters::YUV_STALL_MAX; i++) { |
| yuvIndex = i % ExynosCameraParameters::YUV_MAX; |
| m_parameters->getHwYuvSize(&yuvWidth[yuvIndex], &yuvHeight[yuvIndex], i); |
| yuvFormat[yuvIndex] = m_parameters->getYuvFormat(i); |
| } |
| |
| #ifdef SAMSUNG_HIFI_CAPTURE |
| if (m_parameters->getHiFiCatureEnable()) { |
| zoomRatio = 1.0f; |
| } |
| #endif |
| |
| memset(&node_group_info_3aa, 0x0, sizeof(camera2_node_group)); |
| memset(&node_group_info_isp, 0x0, sizeof(camera2_node_group)); |
| memset(&node_group_info_mcsc, 0x0, sizeof(camera2_node_group)); |
| memset(&node_group_info_vra, 0x0, sizeof(camera2_node_group)); |
| |
| /* 3AA for Reprocessing */ |
| if (m_supportPureBayerReprocessing == true) { |
| pipeId = INDEX(PIPE_3AA_REPROCESSING); |
| node_group_info_temp = &node_group_info_3aa; |
| node_group_info_temp->leader.request = 1; |
| node_group_info_temp->leader.pixelformat = m_parameters->getBayerFormat(pipeId); |
| |
| nodePipeId = PIPE_3AC_REPROCESSING; |
| if (m_request[INDEX(nodePipeId)] == true) { |
| node_group_info_temp->capture[perframePosition].request = m_request[INDEX(nodePipeId)]; |
| node_group_info_temp->capture[perframePosition].vid = m_deviceInfo[pipeId].nodeNum[getNodeType(nodePipeId)] - FIMC_IS_VIDEO_BAS_NUM; |
| node_group_info_temp->capture[perframePosition].pixelformat = m_parameters->getBayerFormat(nodePipeId); |
| perframePosition++; |
| } |
| |
| nodePipeId = PIPE_3AP_REPROCESSING; |
| node_group_info_temp->capture[perframePosition].request = m_request[INDEX(nodePipeId)]; |
| node_group_info_temp->capture[perframePosition].vid = m_deviceInfo[pipeId].nodeNum[getNodeType(nodePipeId)] - FIMC_IS_VIDEO_BAS_NUM; |
| node_group_info_temp->capture[perframePosition].pixelformat = m_parameters->getBayerFormat(nodePipeId); |
| perframePosition++; |
| } |
| |
| /* ISP for Reprocessing */ |
| if (m_supportPureBayerReprocessing == false |
| || m_flag3aaIspOTF == HW_CONNECTION_MODE_M2M) { |
| pipeId = INDEX(PIPE_ISP_REPROCESSING); |
| perframePosition = 0; |
| node_group_info_temp = &node_group_info_isp; |
| node_group_info_temp->leader.request = 1; |
| node_group_info_temp->leader.pixelformat = m_parameters->getBayerFormat(pipeId); |
| } |
| |
| nodePipeId = PIPE_ISPC_REPROCESSING; |
| if (m_request[INDEX(nodePipeId)] == true && node_group_info_temp != NULL) { |
| nodePipeId = PIPE_ISPC_REPROCESSING; |
| node_group_info_temp->capture[perframePosition].request = m_request[INDEX(nodePipeId)]; |
| node_group_info_temp->capture[perframePosition].vid = m_deviceInfo[pipeId].nodeNum[getNodeType(nodePipeId)] - FIMC_IS_VIDEO_BAS_NUM; |
| node_group_info_temp->capture[perframePosition].pixelformat = m_parameters->getHwPictureFormat(); |
| perframePosition++; |
| } |
| |
| nodePipeId = PIPE_ISPP_REPROCESSING; |
| if (m_request[INDEX(nodePipeId)] == true && node_group_info_temp != NULL) { |
| node_group_info_temp->capture[perframePosition].request = m_request[INDEX(nodePipeId)]; |
| node_group_info_temp->capture[perframePosition].vid = m_deviceInfo[pipeId].nodeNum[getNodeType(nodePipeId)] - FIMC_IS_VIDEO_BAS_NUM; |
| node_group_info_temp->capture[perframePosition].pixelformat = m_parameters->getHwPictureFormat(); |
| perframePosition++; |
| } |
| |
| /* MCSC for Reprocessing */ |
| if (m_flagIspMcscOTF == HW_CONNECTION_MODE_M2M) { |
| pipeId = INDEX(PIPE_MCSC_REPROCESSING); |
| perframePosition = 0; |
| node_group_info_temp = &node_group_info_mcsc; |
| node_group_info_temp->leader.request = 1; |
| node_group_info_temp->leader.pixelformat = m_parameters->getHwPictureFormat(); |
| } |
| |
| if (node_group_info_temp != NULL) { |
| nodePipeId = PIPE_MCSC0_REPROCESSING; |
| node_group_info_temp->capture[perframePosition].request = m_request[INDEX(nodePipeId)]; |
| node_group_info_temp->capture[perframePosition].vid = m_deviceInfo[pipeId].nodeNum[getNodeType(nodePipeId)] - FIMC_IS_VIDEO_BAS_NUM; |
| yuvIndex = (ExynosCameraParameters::YUV_STALL_0 % ExynosCameraParameters::YUV_MAX); |
| node_group_info_temp->capture[perframePosition].pixelformat = yuvFormat[yuvIndex]; |
| perframePosition++; |
| |
| nodePipeId = PIPE_MCSC1_REPROCESSING; |
| node_group_info_temp->capture[perframePosition].request = m_request[INDEX(nodePipeId)]; |
| node_group_info_temp->capture[perframePosition].vid = m_deviceInfo[pipeId].nodeNum[getNodeType(nodePipeId)] - FIMC_IS_VIDEO_BAS_NUM; |
| yuvIndex = (ExynosCameraParameters::YUV_STALL_1 % ExynosCameraParameters::YUV_MAX); |
| node_group_info_temp->capture[perframePosition].pixelformat = yuvFormat[yuvIndex]; |
| perframePosition++; |
| |
| nodePipeId = PIPE_MCSC2_REPROCESSING; |
| node_group_info_temp->capture[perframePosition].request = m_request[INDEX(nodePipeId)]; |
| node_group_info_temp->capture[perframePosition].vid = m_deviceInfo[pipeId].nodeNum[getNodeType(nodePipeId)] - FIMC_IS_VIDEO_BAS_NUM; |
| yuvIndex = (ExynosCameraParameters::YUV_STALL_2 % ExynosCameraParameters::YUV_MAX); |
| node_group_info_temp->capture[perframePosition].pixelformat = yuvFormat[yuvIndex]; |
| perframePosition++; |
| |
| nodePipeId = PIPE_MCSC3_REPROCESSING; |
| node_group_info_temp->capture[perframePosition].request = m_request[INDEX(nodePipeId)]; |
| node_group_info_temp->capture[perframePosition].vid = m_deviceInfo[pipeId].nodeNum[getNodeType(nodePipeId)] - FIMC_IS_VIDEO_BAS_NUM; |
| node_group_info_temp->capture[perframePosition].pixelformat = m_parameters->getHwPictureFormat(); |
| perframePosition++; |
| |
| nodePipeId = PIPE_MCSC4_REPROCESSING; |
| node_group_info_temp->capture[perframePosition].request = m_request[INDEX(nodePipeId)]; |
| node_group_info_temp->capture[perframePosition].vid = m_deviceInfo[pipeId].nodeNum[getNodeType(nodePipeId)] - FIMC_IS_VIDEO_BAS_NUM; |
| node_group_info_temp->capture[perframePosition].pixelformat = m_parameters->getHwPictureFormat(); |
| perframePosition++; |
| |
| nodePipeId = PIPE_MCSC5_REPROCESSING; |
| node_group_info_temp->capture[perframePosition].request = m_request[INDEX(nodePipeId)]; |
| node_group_info_temp->capture[perframePosition].vid = m_deviceInfo[pipeId].nodeNum[getNodeType(nodePipeId)] - FIMC_IS_VIDEO_BAS_NUM; |
| node_group_info_temp->capture[perframePosition].pixelformat = m_parameters->getHwVraInputFormat(); |
| perframePosition++; |
| } |
| |
| /* VRA */ |
| if (m_flagMcscVraOTF == HW_CONNECTION_MODE_M2M) { |
| pipeId = INDEX(PIPE_VRA_REPROCESSING); |
| perframePosition = 0; |
| node_group_info_temp = &node_group_info_vra; |
| node_group_info_temp->leader.request = 1; |
| node_group_info_temp->leader.pixelformat = m_parameters->getHwVraInputFormat(); |
| } |
| |
| frame->setZoomRatio(zoomRatio); |
| |
| updateNodeGroupInfo( |
| PIPE_3AA_REPROCESSING, |
| m_parameters, |
| &node_group_info_3aa); |
| frame->storeNodeGroupInfo(&node_group_info_3aa, PERFRAME_INFO_PURE_REPROCESSING_3AA); |
| |
| if (m_supportPureBayerReprocessing == false |
| || m_flag3aaIspOTF == HW_CONNECTION_MODE_M2M) { |
| updateNodeGroupInfo( |
| PIPE_ISP_REPROCESSING, |
| m_parameters, |
| &node_group_info_isp); |
| if (m_supportPureBayerReprocessing == true) |
| frame->storeNodeGroupInfo(&node_group_info_isp, PERFRAME_INFO_PURE_REPROCESSING_ISP); |
| else |
| frame->storeNodeGroupInfo(&node_group_info_isp, PERFRAME_INFO_DIRTY_REPROCESSING_ISP); |
| } |
| |
| if (m_flagMcscVraOTF == HW_CONNECTION_MODE_M2M) { |
| updateNodeGroupInfo( |
| PIPE_VRA_REPROCESSING, |
| m_parameters, |
| &node_group_info_vra); |
| if (m_supportPureBayerReprocessing == true) |
| frame->storeNodeGroupInfo(&node_group_info_vra, PERFRAME_INFO_PURE_REPROCESSING_VRA); |
| else |
| frame->storeNodeGroupInfo(&node_group_info_vra, PERFRAME_INFO_DIRTY_REPROCESSING_VRA); |
| } |
| |
| return NO_ERROR; |
| } |
| |
| void ExynosCameraFrameReprocessingFactory::m_init(void) |
| { |
| m_flagReprocessing = true; |
| m_flagHWFCEnabled = m_parameters->isUseHWFC(); |
| |
| m_shot_ext = new struct camera2_shot_ext; |
| } |
| |
| }; /* namespace android */ |