blob: 2113d8b1946df2288b13b7d426bd7b17cfe9b387 [file] [log] [blame]
/*
* Copyright (C) 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 "ExynosCamera"
#include <log/log.h>
#include <ui/Fence.h>
#include "ExynosCamera.h"
#include "ExynosCameraProperty.h"
namespace android {
#ifdef MONITOR_LOG_SYNC
uint32_t ExynosCamera::cameraSyncLogId = 0;
#endif
ExynosCamera::ExynosCamera(int mainCameraId, __unused int subCameraId, int scenario, camera_metadata_t **info):
m_requestMgr(NULL),
m_streamManager(NULL)
{
BUILD_DATE();
/* Camera Scenario */
m_scenario = scenario;
/* Main Camera */
m_cameraId = m_cameraIds[0] = mainCameraId;
switch (m_cameraId) {
case CAMERA_ID_BACK:
strncpy(m_name, "Back", EXYNOS_CAMERA_NAME_STR_SIZE - 1);
break;
case CAMERA_ID_FRONT:
strncpy(m_name, "Front", EXYNOS_CAMERA_NAME_STR_SIZE - 1);
break;
case CAMERA_ID_SECURE:
strncpy(m_name, "Secure", EXYNOS_CAMERA_NAME_STR_SIZE - 1);
break;
#ifdef USE_DUAL_CAMERA
case CAMERA_ID_BACK_1:
strncpy(m_name, "BackSlave", EXYNOS_CAMERA_NAME_STR_SIZE - 1);
break;
case CAMERA_ID_FRONT_1:
strncpy(m_name, "FrontSlave", EXYNOS_CAMERA_NAME_STR_SIZE - 1);
break;
#endif
default:
memset(m_name, 0x00, sizeof(m_name));
CLOGE("Invalid camera ID(%d)", m_cameraId);
break;
}
#ifdef USE_DUAL_CAMERA
/* Sub Camera */
if (subCameraId >= 0) {
m_cameraIds[1] = subCameraId;
CLOGI("Dual cameara enabled! CameraId (%d & %d) m_scenario(%d)",
m_cameraIds[0], m_cameraIds[1], m_scenario);
} else {
m_cameraIds[1] = 0;
CLOGI("Single cameara enabled! CameraId (%d) m_scenario(%d)", m_cameraIds[0], m_scenario);
}
#else
CLOGI("Single cameara enabled! CameraId (%d) m_scenario(%d)", m_cameraIds[0], m_scenario);
#endif
/* Initialize pointer variables */
m_ionAllocator = NULL;
m_bufferSupplier = NULL;
for (int i = 0; i < CAMERA_ID_MAX; i++) {
m_parameters[i] = NULL;
m_captureSelector[i] = NULL;
m_activityControl[i] = NULL;
m_currentPreviewShot[i] = NULL;
m_currentInternalShot[i] = NULL;
m_currentCaptureShot[i] = NULL;
m_currentVisionShot[i] = NULL;
}
m_captureZslSelector = NULL;
m_vendorSpecificPreConstructor(m_cameraId, m_scenario);
m_configurations = new ExynosCameraConfigurations(m_cameraIds[0], m_scenario);
#ifdef USE_DEBUG_PROPERTY
ExynosCameraProperty property;
bool obteEnable = false;
status_t ret = property.get(ExynosCameraProperty::TUNING_OBTE_ENABLE, LOG_TAG, obteEnable);
if (ret == NO_ERROR) {
m_configurations->setMode(CONFIGURATION_OBTE_MODE, obteEnable);
}
#endif
/* Create related classes */
switch (m_scenario) {
case SCENARIO_SECURE:
m_parameters[m_cameraId] = new ExynosCameraParameters(m_cameraId, m_scenario, m_configurations);
m_activityControl[m_cameraId] = m_parameters[m_cameraId]->getActivityControl();
m_currentPreviewShot[m_cameraId] = new struct camera2_shot_ext;
memset(m_currentPreviewShot[m_cameraId], 0x00, sizeof(struct camera2_shot_ext));
m_currentInternalShot[m_cameraId] = new struct camera2_shot_ext;
memset(m_currentInternalShot[m_cameraId], 0x00, sizeof(struct camera2_shot_ext));
m_currentVisionShot[m_cameraId] = new struct camera2_shot_ext;
memset(m_currentVisionShot[m_cameraId], 0x00, sizeof(struct camera2_shot_ext));
break;
#ifdef USE_DUAL_CAMERA
case SCENARIO_DUAL_REAR_ZOOM:
case SCENARIO_DUAL_REAR_PORTRAIT:
m_parameters[m_cameraIds[1]] = new ExynosCameraParameters(m_cameraIds[1], m_scenario, m_configurations);
m_activityControl[m_cameraIds[1]] = m_parameters[m_cameraIds[1]]->getActivityControl();
m_currentPreviewShot[m_cameraIds[1]] = new struct camera2_shot_ext;
memset(m_currentPreviewShot[m_cameraIds[1]], 0x00, sizeof(struct camera2_shot_ext));
m_currentInternalShot[m_cameraIds[1]] = new struct camera2_shot_ext;
memset(m_currentInternalShot[m_cameraIds[1]], 0x00, sizeof(struct camera2_shot_ext));
m_currentCaptureShot[m_cameraIds[1]] = new struct camera2_shot_ext;
memset(m_currentCaptureShot[m_cameraIds[1]], 0x00, sizeof(struct camera2_shot_ext));
/* No break: m_parameters[0] is same with normal */
#endif
case SCENARIO_NORMAL:
default:
m_parameters[m_cameraId] = new ExynosCameraParameters(m_cameraId, m_scenario, m_configurations);
m_activityControl[m_cameraId] = m_parameters[m_cameraId]->getActivityControl();
m_currentPreviewShot[m_cameraId] = new struct camera2_shot_ext;
memset(m_currentPreviewShot[m_cameraId], 0x00, sizeof(struct camera2_shot_ext));
m_currentInternalShot[m_cameraId] = new struct camera2_shot_ext;
memset(m_currentInternalShot[m_cameraId], 0x00, sizeof(struct camera2_shot_ext));
m_currentCaptureShot[m_cameraId] = new struct camera2_shot_ext;
memset(m_currentCaptureShot[m_cameraId], 0x00, sizeof(struct camera2_shot_ext));
break;
}
#ifdef USE_DUAL_CAMERA
m_metadataConverter = new ExynosCameraMetadataConverter(m_cameraId, m_configurations, m_parameters[m_cameraId],
m_parameters[m_cameraIds[1]]);
#else
m_metadataConverter = new ExynosCameraMetadataConverter(m_cameraId, m_configurations, m_parameters[m_cameraId]);
#endif
m_requestMgr = new ExynosCameraRequestManager(m_cameraId, m_configurations);
m_requestMgr->setMetaDataConverter(m_metadataConverter);
/* Create managers */
m_createManagers();
/* Create queue for preview path. If you want to control pipeDone in ExynosCamera, try to create frame queue here */
m_shotDoneQ = new ExynosCameraList<ExynosCameraFrameSP_sptr_t>();
for (int i = 0; i < MAX_PIPE_NUM; i++) {
switch (i) {
case PIPE_FLITE:
case PIPE_3AA:
case PIPE_ISP:
case PIPE_MCSC:
#ifdef SUPPORT_HW_GDC
case PIPE_GDC:
#endif
m_pipeFrameDoneQ[i] = new frame_queue_t;
break;
default:
m_pipeFrameDoneQ[i] = NULL;
break;
}
}
/* Create threads */
m_createThreads();
if (m_configurations->getMode(CONFIGURATION_GMV_MODE) == true) {
m_pipeFrameDoneQ[PIPE_GMV] = new frame_queue_t(m_previewStreamGMVThread);
}
m_pipeFrameDoneQ[PIPE_VRA] = new frame_queue_t(m_previewStreamVRAThread);
#ifdef SUPPORT_HFD
if (m_parameters[m_cameraId]->getHfdMode() == true) {
m_pipeFrameDoneQ[PIPE_HFD] = new frame_queue_t(m_previewStreamHFDThread);
}
#endif
#ifdef TIME_LOGGER_LAUNCH_ENABLE
TIME_LOGGER_INIT(m_cameraId);
#endif
#ifdef USE_DUAL_CAMERA
if (m_scenario == SCENARIO_DUAL_REAR_ZOOM
|| m_scenario == SCENARIO_DUAL_REAR_PORTRAIT) {
m_slaveShotDoneQ = new ExynosCameraList<ExynosCameraFrameSP_sptr_t>();
m_dualStandbyTriggerQ = new ExynosCameraList<dual_standby_trigger_t>();
m_pipeFrameDoneQ[PIPE_SYNC] = new frame_queue_t;
m_pipeFrameDoneQ[PIPE_FUSION] = new frame_queue_t;
m_dualTransitionCount = 0;
m_dualCaptureLockCount = 0;
m_dualMultiCaptureLockflag = false;
m_earlyTriggerRequestKey = 0;
m_flagFinishDualFrameFactoryStartThread = false;
} else {
m_slaveShotDoneQ = NULL;
m_dualStandbyTriggerQ = NULL;
m_pipeFrameDoneQ[PIPE_SYNC] = NULL;
m_pipeFrameDoneQ[PIPE_FUSION] = NULL;
m_dualTransitionCount = 0;
m_dualCaptureLockCount = 0;
m_dualMultiCaptureLockflag = false;
m_earlyTriggerRequestKey = 0;
m_flagFinishDualFrameFactoryStartThread = false;
}
#endif
for(int i = 0; i < FRAME_FACTORY_TYPE_MAX; i++)
m_frameFactory[i] = NULL;
/* Create queue for capture path */
m_yuvCaptureDoneQ = new frame_queue_t;
m_yuvCaptureDoneQ->setWaitTime(2000000000);
m_reprocessingDoneQ = new frame_queue_t;
m_reprocessingDoneQ->setWaitTime(2000000000);
m_bayerStreamQ = new frame_queue_t;
m_bayerStreamQ->setWaitTime(2000000000);
#ifdef USE_DUAL_CAMERA
if (m_scenario == SCENARIO_DUAL_REAR_ZOOM
|| m_scenario == SCENARIO_DUAL_REAR_PORTRAIT) {
m_slaveShotDoneQ->setWaitTime(4000000000);
m_selectDualSlaveBayerQ = new frame_queue_t();
} else {
m_selectDualSlaveBayerQ = NULL;
}
#endif
m_shotDoneQ->setWaitTime(4000000000);
m_frameFactoryQ = new framefactory3_queue_t;
m_selectBayerQ = new frame_queue_t();
m_captureQ = new frame_queue_t(m_captureThread);
#if defined(USE_RAW_REVERSE_PROCESSING) && defined(USE_SW_RAW_REVERSE_PROCESSING)
m_reverseProcessingBayerQ = new frame_queue_t(m_reverseProcessingBayerThread);
#endif
#ifdef SUPPORT_HW_GDC
m_gdcQ = new frame_queue_t(m_gdcThread);
#endif
/* construct static meta data information */
if (*info == NULL) {
if (ExynosCameraMetadataConverter::constructStaticInfo(-1, m_cameraId, m_scenario, info, NULL))
CLOGE("Create static meta data failed!!");
}
m_metadataConverter->setStaticInfo(m_cameraId, *info);
m_streamManager->setYuvStreamMaxCount(m_parameters[m_cameraId]->getYuvStreamMaxNum());
m_setFrameManager();
m_setConfigInform();
/* init infomation of fd orientation*/
m_configurations->setModeValue(CONFIGURATION_DEVICE_ORIENTATION, 0);
m_configurations->setModeValue(CONFIGURATION_FD_ORIENTATION, 0);
ExynosCameraActivityUCTL *uctlMgr = m_activityControl[m_cameraId]->getUCTLMgr();
if (uctlMgr != NULL) {
uctlMgr->setDeviceRotation(m_configurations->getModeValue(CONFIGURATION_FD_ORIENTATION));
}
m_state = EXYNOS_CAMERA_STATE_OPEN;
m_visionFps = 0;
m_flushLockWait = false;
m_captureStreamExist = false;
m_rawStreamExist = false;
m_videoStreamExist = false;
m_recordingEnabled = false;
m_prevStreamBit = 0;
m_firstRequestFrameNumber = 0;
m_internalFrameCount = 1;
m_isNeedRequestFrame = false;
#ifdef MONITOR_LOG_SYNC
m_syncLogDuration = 0;
#endif
m_lastFrametime = 0;
m_prepareFrameCount = 0;
#ifdef BUFFER_DUMP
m_dumpBufferQ = new buffer_dump_info_queue_t(m_dumpThread);
#endif
m_ionClient = exynos_ion_open();
if (m_ionClient < 0) {
ALOGE("ERR(%s):m_ionClient ion_open() fail", __func__);
m_ionClient = -1;
}
m_framefactoryCreateResult = NO_ERROR;
m_flagFirstPreviewTimerOn = false;
m_previewCallbackPP = NULL;
/* Construct vendor */
m_vendorSpecificConstructor();
}
status_t ExynosCamera::m_setConfigInform() {
struct ExynosConfigInfo exynosConfig;
memset((void *)&exynosConfig, 0x00, sizeof(exynosConfig));
exynosConfig.mode = CONFIG_MODE::NORMAL;
/* Internal buffers */
#ifdef USE_DUAL_CAMERA
if (m_scenario == SCENARIO_DUAL_REAR_ZOOM || m_scenario == SCENARIO_DUAL_REAR_PORTRAIT) {
exynosConfig.info[CONFIG_MODE::NORMAL].bufInfo.num_sensor_buffers = (getCameraId() == CAMERA_ID_FRONT) ? FRONT_NUM_SENSOR_BUFFERS : DUAL_NUM_SENSOR_BUFFERS;
exynosConfig.info[CONFIG_MODE::NORMAL].bufInfo.num_3aa_buffers = (getCameraId() == CAMERA_ID_FRONT) ? FRONT_NUM_3AA_BUFFERS : DUAL_NUM_3AA_BUFFERS;
exynosConfig.info[CONFIG_MODE::NORMAL].bufInfo.num_hwdis_buffers = DUAL_NUM_HW_DIS_BUFFERS;
exynosConfig.info[CONFIG_MODE::NORMAL].bufInfo.dual_num_fusion_buffers = DUAL_NUM_SYNC_FUSION_BUFFERS;
} else
#endif
{
exynosConfig.info[CONFIG_MODE::NORMAL].bufInfo.num_sensor_buffers = (getCameraId() == CAMERA_ID_FRONT) ? FRONT_NUM_SENSOR_BUFFERS : NUM_SENSOR_BUFFERS;
exynosConfig.info[CONFIG_MODE::NORMAL].bufInfo.num_3aa_buffers = (getCameraId() == CAMERA_ID_FRONT) ? FRONT_NUM_3AA_BUFFERS : NUM_3AA_BUFFERS;
exynosConfig.info[CONFIG_MODE::NORMAL].bufInfo.num_hwdis_buffers = NUM_HW_DIS_BUFFERS;
}
exynosConfig.info[CONFIG_MODE::NORMAL].bufInfo.num_fastaestable_buffer = NUM_FASTAESTABLE_BUFFERS;
exynosConfig.info[CONFIG_MODE::NORMAL].bufInfo.num_reprocessing_buffers = NUM_REPROCESSING_BUFFERS;
exynosConfig.info[CONFIG_MODE::NORMAL].bufInfo.num_nv21_picture_buffers = NUM_PICTURE_BUFFERS;
exynosConfig.info[CONFIG_MODE::NORMAL].bufInfo.num_vra_buffers = NUM_VRA_BUFFERS;
/* v4l2_reqBuf() values for stream buffers */
exynosConfig.info[CONFIG_MODE::NORMAL].bufInfo.num_bayer_buffers = VIDEO_MAX_FRAME;
exynosConfig.info[CONFIG_MODE::NORMAL].bufInfo.num_preview_buffers = VIDEO_MAX_FRAME;
exynosConfig.info[CONFIG_MODE::NORMAL].bufInfo.num_preview_cb_buffers = VIDEO_MAX_FRAME;
exynosConfig.info[CONFIG_MODE::NORMAL].bufInfo.num_recording_buffers = VIDEO_MAX_FRAME;
exynosConfig.info[CONFIG_MODE::NORMAL].bufInfo.num_picture_buffers = VIDEO_MAX_FRAME;
/* Required stream buffers for HAL */
#ifdef USE_DUAL_CAMERA
if (m_scenario == SCENARIO_DUAL_REAR_ZOOM || m_scenario == SCENARIO_DUAL_REAR_PORTRAIT) {
exynosConfig.info[CONFIG_MODE::NORMAL].bufInfo.num_request_preview_buffers = DUAL_NUM_REQUEST_PREVIEW_BUFFER;
exynosConfig.info[CONFIG_MODE::NORMAL].bufInfo.num_request_callback_buffers = DUAL_NUM_REQUEST_CALLBACK_BUFFER;
exynosConfig.info[CONFIG_MODE::NORMAL].bufInfo.num_request_video_buffers = DUAL_NUM_REQUEST_VIDEO_BUFFER;
} else
#endif
{
exynosConfig.info[CONFIG_MODE::NORMAL].bufInfo.num_request_preview_buffers = NUM_REQUEST_PREVIEW_BUFFER;
exynosConfig.info[CONFIG_MODE::NORMAL].bufInfo.num_request_callback_buffers = NUM_REQUEST_CALLBACK_BUFFER;
exynosConfig.info[CONFIG_MODE::NORMAL].bufInfo.num_request_video_buffers = NUM_REQUEST_VIDEO_BUFFER;
}
exynosConfig.info[CONFIG_MODE::NORMAL].bufInfo.num_request_raw_buffers = NUM_REQUEST_RAW_BUFFER;
exynosConfig.info[CONFIG_MODE::NORMAL].bufInfo.num_request_bayer_buffers = NUM_REQUEST_BAYER_BUFFER;
exynosConfig.info[CONFIG_MODE::NORMAL].bufInfo.num_request_burst_capture_buffers = NUM_REQUEST_BURST_CAPTURE_BUFFER;
exynosConfig.info[CONFIG_MODE::NORMAL].bufInfo.num_request_capture_buffers = NUM_REQUEST_CAPTURE_BUFFER;
exynosConfig.info[CONFIG_MODE::NORMAL].bufInfo.num_batch_buffers = 1;
/* Prepare buffers */
exynosConfig.info[CONFIG_MODE::NORMAL].pipeInfo.prepare[PIPE_FLITE] = PIPE_FLITE_PREPARE_COUNT;
exynosConfig.info[CONFIG_MODE::NORMAL].pipeInfo.prepare[PIPE_3AA] = PIPE_3AA_PREPARE_COUNT;
/* Config HIGH_SPEED 60 buffer & pipe info */
/* Internal buffers */
#ifdef USE_DUAL_CAMERA
if (m_scenario == SCENARIO_DUAL_REAR_ZOOM || m_scenario == SCENARIO_DUAL_REAR_PORTRAIT) {
exynosConfig.info[CONFIG_MODE::HIGHSPEED_60].bufInfo.num_sensor_buffers = DUAL_NUM_SENSOR_BUFFERS;
exynosConfig.info[CONFIG_MODE::HIGHSPEED_60].bufInfo.num_3aa_buffers = DUAL_NUM_3AA_BUFFERS;
exynosConfig.info[CONFIG_MODE::HIGHSPEED_60].bufInfo.num_hwdis_buffers = DUAL_NUM_HW_DIS_BUFFERS;
exynosConfig.info[CONFIG_MODE::HIGHSPEED_60].bufInfo.dual_num_fusion_buffers = DUAL_NUM_SYNC_FUSION_BUFFERS;
} else
#endif
{
exynosConfig.info[CONFIG_MODE::HIGHSPEED_60].bufInfo.num_sensor_buffers = NUM_SENSOR_BUFFERS;
exynosConfig.info[CONFIG_MODE::HIGHSPEED_60].bufInfo.num_3aa_buffers = NUM_3AA_BUFFERS;
exynosConfig.info[CONFIG_MODE::HIGHSPEED_60].bufInfo.num_hwdis_buffers = NUM_HW_DIS_BUFFERS;
}
exynosConfig.info[CONFIG_MODE::HIGHSPEED_60].bufInfo.num_fastaestable_buffer = NUM_FASTAESTABLE_BUFFERS;
exynosConfig.info[CONFIG_MODE::HIGHSPEED_60].bufInfo.num_reprocessing_buffers = NUM_REPROCESSING_BUFFERS;
exynosConfig.info[CONFIG_MODE::HIGHSPEED_60].bufInfo.num_nv21_picture_buffers = NUM_PICTURE_BUFFERS;
exynosConfig.info[CONFIG_MODE::HIGHSPEED_60].bufInfo.num_vra_buffers = NUM_VRA_BUFFERS;
/* v4l2_reqBuf() values for stream buffers */
exynosConfig.info[CONFIG_MODE::HIGHSPEED_60].bufInfo.num_bayer_buffers = VIDEO_MAX_FRAME;
exynosConfig.info[CONFIG_MODE::HIGHSPEED_60].bufInfo.num_preview_buffers = VIDEO_MAX_FRAME;
exynosConfig.info[CONFIG_MODE::HIGHSPEED_60].bufInfo.num_preview_cb_buffers = VIDEO_MAX_FRAME;
exynosConfig.info[CONFIG_MODE::HIGHSPEED_60].bufInfo.num_recording_buffers = VIDEO_MAX_FRAME;
exynosConfig.info[CONFIG_MODE::HIGHSPEED_60].bufInfo.num_picture_buffers = VIDEO_MAX_FRAME;
/* Required stream buffer for HAL */
#ifdef USE_DUAL_CAMERA
if (m_scenario == SCENARIO_DUAL_REAR_ZOOM || m_scenario == SCENARIO_DUAL_REAR_PORTRAIT) {
exynosConfig.info[CONFIG_MODE::HIGHSPEED_60].bufInfo.num_request_preview_buffers = DUAL_NUM_REQUEST_PREVIEW_BUFFER;
exynosConfig.info[CONFIG_MODE::HIGHSPEED_60].bufInfo.num_request_callback_buffers = DUAL_NUM_REQUEST_CALLBACK_BUFFER;
exynosConfig.info[CONFIG_MODE::HIGHSPEED_60].bufInfo.num_request_video_buffers = DUAL_NUM_REQUEST_VIDEO_BUFFER;
} else
#endif
{
exynosConfig.info[CONFIG_MODE::HIGHSPEED_60].bufInfo.num_request_preview_buffers = NUM_REQUEST_PREVIEW_BUFFER;
exynosConfig.info[CONFIG_MODE::HIGHSPEED_60].bufInfo.num_request_callback_buffers = NUM_REQUEST_CALLBACK_BUFFER;
exynosConfig.info[CONFIG_MODE::HIGHSPEED_60].bufInfo.num_request_video_buffers = NUM_REQUEST_VIDEO_BUFFER;
}
exynosConfig.info[CONFIG_MODE::HIGHSPEED_60].bufInfo.num_request_raw_buffers = NUM_REQUEST_RAW_BUFFER;
exynosConfig.info[CONFIG_MODE::HIGHSPEED_60].bufInfo.num_request_bayer_buffers = NUM_REQUEST_BAYER_BUFFER;
exynosConfig.info[CONFIG_MODE::HIGHSPEED_60].bufInfo.num_request_burst_capture_buffers = NUM_REQUEST_BURST_CAPTURE_BUFFER;
exynosConfig.info[CONFIG_MODE::HIGHSPEED_60].bufInfo.num_request_capture_buffers = NUM_REQUEST_CAPTURE_BUFFER;
exynosConfig.info[CONFIG_MODE::HIGHSPEED_60].bufInfo.num_batch_buffers = 1;
/* Prepare buffers */
exynosConfig.info[CONFIG_MODE::HIGHSPEED_60].pipeInfo.prepare[PIPE_FLITE] = PIPE_FLITE_PREPARE_COUNT;
exynosConfig.info[CONFIG_MODE::HIGHSPEED_60].pipeInfo.prepare[PIPE_3AA] = PIPE_3AA_PREPARE_COUNT;
#if (USE_HIGHSPEED_RECORDING)
/* Config HIGH_SPEED 120 buffer & pipe info */
/* Internal buffers */
exynosConfig.info[CONFIG_MODE::HIGHSPEED_120].bufInfo.num_fastaestable_buffer = NUM_FASTAESTABLE_BUFFERS;
exynosConfig.info[CONFIG_MODE::HIGHSPEED_120].bufInfo.num_sensor_buffers = FPS120_NUM_SENSOR_BUFFERS;
exynosConfig.info[CONFIG_MODE::HIGHSPEED_120].bufInfo.num_3aa_buffers = FPS120_NUM_3AA_BUFFERS;
exynosConfig.info[CONFIG_MODE::HIGHSPEED_120].bufInfo.num_hwdis_buffers = FPS120_NUM_HW_DIS_BUFFERS;
exynosConfig.info[CONFIG_MODE::HIGHSPEED_120].bufInfo.num_reprocessing_buffers = NUM_REPROCESSING_BUFFERS;
exynosConfig.info[CONFIG_MODE::HIGHSPEED_120].bufInfo.num_nv21_picture_buffers = NUM_PICTURE_BUFFERS;
exynosConfig.info[CONFIG_MODE::HIGHSPEED_120].bufInfo.num_vra_buffers = NUM_VRA_BUFFERS;
/* v4l2_reqBuf() values for stream buffers */
exynosConfig.info[CONFIG_MODE::HIGHSPEED_120].bufInfo.num_bayer_buffers = VIDEO_MAX_FRAME;
exynosConfig.info[CONFIG_MODE::HIGHSPEED_120].bufInfo.num_preview_buffers = VIDEO_MAX_FRAME;
exynosConfig.info[CONFIG_MODE::HIGHSPEED_120].bufInfo.num_preview_cb_buffers = VIDEO_MAX_FRAME;
exynosConfig.info[CONFIG_MODE::HIGHSPEED_120].bufInfo.num_recording_buffers = VIDEO_MAX_FRAME;
exynosConfig.info[CONFIG_MODE::HIGHSPEED_120].bufInfo.num_picture_buffers = VIDEO_MAX_FRAME;
/* Required stream buffers for HAL */
exynosConfig.info[CONFIG_MODE::HIGHSPEED_120].bufInfo.num_request_raw_buffers = FPS120_NUM_REQUEST_RAW_BUFFER;
exynosConfig.info[CONFIG_MODE::HIGHSPEED_120].bufInfo.num_request_bayer_buffers = FPS120_NUM_REQUEST_BAYER_BUFFER;
exynosConfig.info[CONFIG_MODE::HIGHSPEED_120].bufInfo.num_request_preview_buffers = FPS120_NUM_REQUEST_PREVIEW_BUFFER;
exynosConfig.info[CONFIG_MODE::HIGHSPEED_120].bufInfo.num_request_callback_buffers = FPS120_NUM_REQUEST_CALLBACK_BUFFER;
exynosConfig.info[CONFIG_MODE::HIGHSPEED_120].bufInfo.num_request_video_buffers = FPS120_NUM_REQUEST_VIDEO_BUFFER;
exynosConfig.info[CONFIG_MODE::HIGHSPEED_120].bufInfo.num_request_burst_capture_buffers = FPS120_NUM_REQUEST_BURST_CAPTURE_BUFFER;
exynosConfig.info[CONFIG_MODE::HIGHSPEED_120].bufInfo.num_request_capture_buffers = FPS120_NUM_REQUEST_CAPTURE_BUFFER;
exynosConfig.info[CONFIG_MODE::HIGHSPEED_120].bufInfo.num_batch_buffers = 2;
/* Prepare buffers */
exynosConfig.info[CONFIG_MODE::HIGHSPEED_120].pipeInfo.prepare[PIPE_FLITE] = FPS120_PIPE_FLITE_PREPARE_COUNT;
exynosConfig.info[CONFIG_MODE::HIGHSPEED_120].pipeInfo.prepare[PIPE_3AA] = FPS120_PIPE_3AA_PREPARE_COUNT;
/* Config HIGH_SPEED 240 buffer & pipe info */
/* Internal buffers */
exynosConfig.info[CONFIG_MODE::HIGHSPEED_240].bufInfo.num_fastaestable_buffer = NUM_FASTAESTABLE_BUFFERS;
exynosConfig.info[CONFIG_MODE::HIGHSPEED_240].bufInfo.num_sensor_buffers = FPS240_NUM_SENSOR_BUFFERS;
exynosConfig.info[CONFIG_MODE::HIGHSPEED_240].bufInfo.num_3aa_buffers = FPS240_NUM_3AA_BUFFERS;
exynosConfig.info[CONFIG_MODE::HIGHSPEED_240].bufInfo.num_hwdis_buffers = FPS240_NUM_HW_DIS_BUFFERS;
exynosConfig.info[CONFIG_MODE::HIGHSPEED_240].bufInfo.num_reprocessing_buffers = NUM_REPROCESSING_BUFFERS;
exynosConfig.info[CONFIG_MODE::HIGHSPEED_240].bufInfo.num_nv21_picture_buffers = NUM_PICTURE_BUFFERS;
exynosConfig.info[CONFIG_MODE::HIGHSPEED_240].bufInfo.num_vra_buffers = NUM_VRA_BUFFERS;
/* v4l2_reqBuf() values for stream buffers */
exynosConfig.info[CONFIG_MODE::HIGHSPEED_240].bufInfo.num_bayer_buffers = VIDEO_MAX_FRAME;
exynosConfig.info[CONFIG_MODE::HIGHSPEED_240].bufInfo.num_preview_buffers = VIDEO_MAX_FRAME;
exynosConfig.info[CONFIG_MODE::HIGHSPEED_240].bufInfo.num_preview_cb_buffers = VIDEO_MAX_FRAME;
exynosConfig.info[CONFIG_MODE::HIGHSPEED_240].bufInfo.num_recording_buffers = VIDEO_MAX_FRAME;
exynosConfig.info[CONFIG_MODE::HIGHSPEED_240].bufInfo.num_picture_buffers = VIDEO_MAX_FRAME;
/* Required stream buffers for HAL */
exynosConfig.info[CONFIG_MODE::HIGHSPEED_240].bufInfo.num_request_raw_buffers = FPS240_NUM_REQUEST_RAW_BUFFER;
exynosConfig.info[CONFIG_MODE::HIGHSPEED_240].bufInfo.num_request_bayer_buffers = FPS240_NUM_REQUEST_BAYER_BUFFER;
exynosConfig.info[CONFIG_MODE::HIGHSPEED_240].bufInfo.num_request_preview_buffers = FPS240_NUM_REQUEST_PREVIEW_BUFFER;
exynosConfig.info[CONFIG_MODE::HIGHSPEED_240].bufInfo.num_request_callback_buffers = FPS240_NUM_REQUEST_CALLBACK_BUFFER;
exynosConfig.info[CONFIG_MODE::HIGHSPEED_240].bufInfo.num_request_video_buffers = FPS240_NUM_REQUEST_VIDEO_BUFFER;
exynosConfig.info[CONFIG_MODE::HIGHSPEED_240].bufInfo.num_request_burst_capture_buffers = FPS240_NUM_REQUEST_BURST_CAPTURE_BUFFER;
exynosConfig.info[CONFIG_MODE::HIGHSPEED_240].bufInfo.num_request_capture_buffers = FPS240_NUM_REQUEST_CAPTURE_BUFFER;
exynosConfig.info[CONFIG_MODE::HIGHSPEED_240].bufInfo.num_batch_buffers = 4;
/* Prepare buffers */
exynosConfig.info[CONFIG_MODE::HIGHSPEED_240].pipeInfo.prepare[PIPE_FLITE] = FPS240_PIPE_FLITE_PREPARE_COUNT;
exynosConfig.info[CONFIG_MODE::HIGHSPEED_240].pipeInfo.prepare[PIPE_3AA] = FPS240_PIPE_3AA_PREPARE_COUNT;
/* Config HIGH_SPEED 480 buffer & pipe info */
/* Internal buffers */
exynosConfig.info[CONFIG_MODE::HIGHSPEED_480].bufInfo.num_fastaestable_buffer = NUM_FASTAESTABLE_BUFFERS;
exynosConfig.info[CONFIG_MODE::HIGHSPEED_480].bufInfo.num_sensor_buffers = FPS480_NUM_SENSOR_BUFFERS;
exynosConfig.info[CONFIG_MODE::HIGHSPEED_480].bufInfo.num_3aa_buffers = FPS480_NUM_3AA_BUFFERS;
exynosConfig.info[CONFIG_MODE::HIGHSPEED_480].bufInfo.num_hwdis_buffers = FPS480_NUM_HW_DIS_BUFFERS;
exynosConfig.info[CONFIG_MODE::HIGHSPEED_480].bufInfo.reprocessing_bayer_hold_count = REPROCESSING_BAYER_HOLD_COUNT;
exynosConfig.info[CONFIG_MODE::HIGHSPEED_480].bufInfo.num_reprocessing_buffers = NUM_REPROCESSING_BUFFERS;
exynosConfig.info[CONFIG_MODE::HIGHSPEED_480].bufInfo.num_nv21_picture_buffers = NUM_PICTURE_BUFFERS;
exynosConfig.info[CONFIG_MODE::HIGHSPEED_480].bufInfo.num_vra_buffers = NUM_VRA_BUFFERS;
/* v4l2_reqBuf() values for stream buffers */
exynosConfig.info[CONFIG_MODE::HIGHSPEED_480].bufInfo.num_bayer_buffers = VIDEO_MAX_FRAME;
exynosConfig.info[CONFIG_MODE::HIGHSPEED_480].bufInfo.num_preview_buffers = VIDEO_MAX_FRAME;
exynosConfig.info[CONFIG_MODE::HIGHSPEED_480].bufInfo.num_preview_cb_buffers = VIDEO_MAX_FRAME;
exynosConfig.info[CONFIG_MODE::HIGHSPEED_480].bufInfo.num_recording_buffers = VIDEO_MAX_FRAME;
exynosConfig.info[CONFIG_MODE::HIGHSPEED_480].bufInfo.num_picture_buffers = VIDEO_MAX_FRAME;
/* Required stream buffers for HAL */
exynosConfig.info[CONFIG_MODE::HIGHSPEED_480].bufInfo.num_request_raw_buffers = FPS480_NUM_REQUEST_RAW_BUFFER;
exynosConfig.info[CONFIG_MODE::HIGHSPEED_480].bufInfo.num_request_bayer_buffers = NUM_REQUEST_BAYER_BUFFER;
exynosConfig.info[CONFIG_MODE::HIGHSPEED_480].bufInfo.num_request_preview_buffers = FPS480_NUM_REQUEST_PREVIEW_BUFFER;
exynosConfig.info[CONFIG_MODE::HIGHSPEED_480].bufInfo.num_request_callback_buffers = FPS480_NUM_REQUEST_CALLBACK_BUFFER;
exynosConfig.info[CONFIG_MODE::HIGHSPEED_480].bufInfo.num_request_video_buffers = FPS480_NUM_REQUEST_VIDEO_BUFFER;
exynosConfig.info[CONFIG_MODE::HIGHSPEED_480].bufInfo.num_request_jpeg_buffers = FPS480_NUM_REQUEST_JPEG_BUFFER;
exynosConfig.info[CONFIG_MODE::HIGHSPEED_480].bufInfo.num_batch_buffers = 8;
/* Prepare buffers */
exynosConfig.info[CONFIG_MODE::HIGHSPEED_480].pipeInfo.prepare[PIPE_FLITE] = FPS480_PIPE_FLITE_PREPARE_COUNT;
exynosConfig.info[CONFIG_MODE::HIGHSPEED_480].pipeInfo.prepare[PIPE_3AA] = FPS480_PIPE_3AA_PREPARE_COUNT;
#endif
#ifdef SAMSUNG_SSM
/* Internal buffers */
exynosConfig.info[CONFIG_MODE::SSM_240].bufInfo.num_fastaestable_buffer = NUM_FASTAESTABLE_BUFFERS;
exynosConfig.info[CONFIG_MODE::SSM_240].bufInfo.num_sensor_buffers = FPS240_NUM_SENSOR_BUFFERS;
exynosConfig.info[CONFIG_MODE::SSM_240].bufInfo.num_3aa_buffers = FPS240_NUM_3AA_BUFFERS;
exynosConfig.info[CONFIG_MODE::SSM_240].bufInfo.num_hwdis_buffers = FPS240_NUM_HW_DIS_BUFFERS;
exynosConfig.info[CONFIG_MODE::SSM_240].bufInfo.num_reprocessing_buffers = NUM_REPROCESSING_BUFFERS;
exynosConfig.info[CONFIG_MODE::SSM_240].bufInfo.num_nv21_picture_buffers = NUM_PICTURE_BUFFERS;
exynosConfig.info[CONFIG_MODE::SSM_240].bufInfo.num_vra_buffers = NUM_VRA_BUFFERS;
/* v4l2_reqBuf() values for stream buffers */
exynosConfig.info[CONFIG_MODE::SSM_240].bufInfo.num_bayer_buffers = VIDEO_MAX_FRAME;
exynosConfig.info[CONFIG_MODE::SSM_240].bufInfo.num_preview_buffers = VIDEO_MAX_FRAME;
exynosConfig.info[CONFIG_MODE::SSM_240].bufInfo.num_preview_cb_buffers = VIDEO_MAX_FRAME;
exynosConfig.info[CONFIG_MODE::SSM_240].bufInfo.num_recording_buffers = VIDEO_MAX_FRAME;
exynosConfig.info[CONFIG_MODE::SSM_240].bufInfo.num_picture_buffers = VIDEO_MAX_FRAME;
/* Required stream buffers for HAL */
exynosConfig.info[CONFIG_MODE::SSM_240].bufInfo.num_request_raw_buffers = FPS240_NUM_REQUEST_RAW_BUFFER;
exynosConfig.info[CONFIG_MODE::SSM_240].bufInfo.num_request_bayer_buffers = FPS240_NUM_REQUEST_BAYER_BUFFER;
exynosConfig.info[CONFIG_MODE::SSM_240].bufInfo.num_request_preview_buffers = FPS240_NUM_REQUEST_PREVIEW_BUFFER;
exynosConfig.info[CONFIG_MODE::SSM_240].bufInfo.num_request_callback_buffers = FPS240_NUM_REQUEST_CALLBACK_BUFFER;
exynosConfig.info[CONFIG_MODE::SSM_240].bufInfo.num_request_video_buffers = FPS240_NUM_REQUEST_VIDEO_BUFFER;
exynosConfig.info[CONFIG_MODE::SSM_240].bufInfo.num_request_burst_capture_buffers = FPS240_NUM_REQUEST_BURST_CAPTURE_BUFFER;
exynosConfig.info[CONFIG_MODE::SSM_240].bufInfo.num_request_capture_buffers = FPS240_NUM_REQUEST_CAPTURE_BUFFER;
exynosConfig.info[CONFIG_MODE::SSM_240].bufInfo.num_batch_buffers = 4;
/* Prepare buffers */
exynosConfig.info[CONFIG_MODE::SSM_240].pipeInfo.prepare[PIPE_FLITE] = FPS240_PIPE_FLITE_PREPARE_COUNT;
exynosConfig.info[CONFIG_MODE::SSM_240].pipeInfo.prepare[PIPE_3AA] = FPS240_PIPE_3AA_PREPARE_COUNT;
#endif
m_configurations->setConfig(&exynosConfig);
m_exynosconfig = m_configurations->getConfig();
return NO_ERROR;
}
void ExynosCamera::m_createThreads(void)
{
m_mainPreviewThread = new mainCameraThread(this, &ExynosCamera::m_mainPreviewThreadFunc, "m_mainPreviewThreadFunc");
CLOGD("Main Preview thread created");
m_mainCaptureThread = new mainCameraThread(this, &ExynosCamera::m_mainCaptureThreadFunc, "m_mainCaptureThreadFunc");
CLOGD("Main Capture thread created");
/* m_previewStreamXXXThread is for seperated frameDone each own handler */
m_previewStreamBayerThread = new ExynosCameraStreamThread(this, "PreviewBayerThread", PIPE_FLITE);
m_previewStreamBayerThread->setFrameDoneQ(m_pipeFrameDoneQ[PIPE_FLITE]);
CLOGD("Bayer Preview stream thread created");
m_previewStream3AAThread = new ExynosCameraStreamThread(this, "Preview3AAThread", PIPE_3AA);
m_previewStream3AAThread->setFrameDoneQ(m_pipeFrameDoneQ[PIPE_3AA]);
CLOGD("3AA Preview stream thread created!!!");
#ifdef SUPPORT_GMV
if (m_configurations->getMode(CONFIGURATION_GMV_MODE) == true) {
m_previewStreamGMVThread = new mainCameraThread(this, &ExynosCamera::m_previewStreamGMVPipeThreadFunc, "PreviewGMVThread");
CLOGD("GMV Preview stream thread created");
}
#endif
m_previewStreamISPThread = new ExynosCameraStreamThread(this, "PreviewISPThread", PIPE_ISP);
m_previewStreamISPThread->setFrameDoneQ(m_pipeFrameDoneQ[PIPE_ISP]);
CLOGD("ISP Preview stream thread created");
m_previewStreamMCSCThread = new ExynosCameraStreamThread(this, "PreviewMCSCThread", PIPE_MCSC);
m_previewStreamMCSCThread->setFrameDoneQ(m_pipeFrameDoneQ[PIPE_MCSC]);
CLOGD("MCSC Preview stream thread created");
#ifdef SUPPORT_HW_GDC
m_previewStreamGDCThread = new ExynosCameraStreamThread(this, "PreviewGDCThread", PIPE_GDC);
m_previewStreamGDCThread->setFrameDoneQ(m_pipeFrameDoneQ[PIPE_GDC]);
CLOGD("GDC Preview stream thread created");
#endif
m_previewStreamVRAThread = new mainCameraThread(this, &ExynosCamera::m_previewStreamVRAPipeThreadFunc, "PreviewVRAThread");
CLOGD("VRA Preview stream thread created");
#ifdef SUPPORT_HFD
if (m_parameters[m_cameraId]->getHfdMode() == true) {
m_previewStreamHFDThread = new mainCameraThread(this, &ExynosCamera::m_previewStreamHFDPipeThreadFunc, "PreviewHFDThread");
CLOGD("HFD Preview stream thread created");
}
#endif
#ifdef USE_DUAL_CAMERA
if (m_scenario == SCENARIO_DUAL_REAR_ZOOM
|| m_scenario == SCENARIO_DUAL_REAR_PORTRAIT) {
m_slaveMainThread = new mainCameraThread(this, &ExynosCamera::m_slaveMainThreadFunc, "m_slaveMainThreadFunc");
CLOGD("Dual Slave Main thread created");
m_dualStandbyThread = new mainCameraThread(this, &ExynosCamera::m_dualStandbyThreadFunc, "m_setStandbyThreadFunc");
CLOGD("Dual Standby thread created");
m_previewStreamSyncThread = new mainCameraThread(this, &ExynosCamera::m_previewStreamSyncPipeThreadFunc, "PreviewSyncThread");
CLOGD("Sync Preview stream thread created");
m_previewStreamFusionThread = new mainCameraThread(this, &ExynosCamera::m_previewStreamFusionPipeThreadFunc, "PreviewFusionThread");
CLOGD("Fusion Preview stream thread created");
m_dualFrameFactoryStartThread = new mainCameraThread(this, &ExynosCamera::m_dualFrameFactoryStartThreadFunc, "DualFrameFactoryStartThread");
CLOGD("DualFrameFactoryStartThread created");
m_selectDualSlaveBayerThread = new mainCameraThread(this, &ExynosCamera::m_selectDualSlaveBayerThreadFunc, "SelectDualSlaveBayerThreadFunc");
CLOGD("SelectDualSlaveBayerThread created");
}
#endif
m_selectBayerThread = new mainCameraThread(this, &ExynosCamera::m_selectBayerThreadFunc, "SelectBayerThreadFunc");
CLOGD("SelectBayerThread created");
m_bayerStreamThread = new mainCameraThread(this, &ExynosCamera::m_bayerStreamThreadFunc, "BayerStreamThread");
CLOGD("Bayer stream thread created");
m_captureThread = new mainCameraThread(this, &ExynosCamera::m_captureThreadFunc, "CaptureThreadFunc");
CLOGD("CaptureThread created");
m_captureStreamThread = new mainCameraThread(this, &ExynosCamera::m_captureStreamThreadFunc, "CaptureThread");
CLOGD("Capture stream thread created");
m_setBuffersThread = new mainCameraThread(this, &ExynosCamera::m_setBuffersThreadFunc, "setBuffersThread");
CLOGD("Buffer allocation thread created");
m_framefactoryCreateThread = new mainCameraThread(this, &ExynosCamera::m_frameFactoryCreateThreadFunc, "FrameFactoryCreateThread");
CLOGD("FrameFactoryCreateThread created");
m_reprocessingFrameFactoryStartThread = new mainCameraThread(this, &ExynosCamera::m_reprocessingFrameFactoryStartThreadFunc, "m_reprocessingFrameFactoryStartThread");
CLOGD("m_reprocessingFrameFactoryStartThread created");
m_startPictureBufferThread = new mainCameraThread(this, &ExynosCamera::m_startPictureBufferThreadFunc, "startPictureBufferThread");
CLOGD("startPictureBufferThread created");
m_frameFactoryStartThread = new mainCameraThread(this, &ExynosCamera::m_frameFactoryStartThreadFunc, "FrameFactoryStartThread");
CLOGD("FrameFactoryStartThread created");
#if defined(USE_RAW_REVERSE_PROCESSING) && defined(USE_SW_RAW_REVERSE_PROCESSING)
m_reverseProcessingBayerThread = new mainCameraThread(this, &ExynosCamera::m_reverseProcessingBayerThreadFunc, "reverseProcessingBayerThread");
CLOGD("reverseProcessingBayerThread created");
#endif
#ifdef SUPPORT_HW_GDC
m_gdcThread = new mainCameraThread(this, &ExynosCamera::m_gdcThreadFunc, "GDCThread");
CLOGD("GDCThread created");
#endif
m_monitorThread = new mainCameraThread(this, &ExynosCamera::m_monitorThreadFunc, "MonitorThread");
CLOGD("MonitorThread created");
#ifdef BUFFER_DUMP
m_dumpThread = new mainCameraThread(this, &ExynosCamera::m_dumpThreadFunc, "m_dumpThreadFunc");
CLOGD("DumpThread created");
#endif
m_vendorCreateThreads();
}
ExynosCamera::~ExynosCamera()
{
TIME_LOGGER_UPDATE(m_cameraId, 0, 0, CUMULATIVE_CNT, DESTRUCTOR_START, 0);
this->release();
#ifdef TIME_LOGGER_CLOSE_ENABLE
TIME_LOGGER_UPDATE(m_cameraId, 0, 0, CUMULATIVE_CNT, DESTRUCTOR_END, 0);
TIME_LOGGER_SAVE(m_cameraId);
#endif
}
void ExynosCamera::release()
{
CLOGI("-IN-");
if (m_configurations->getMode(CONFIGURATION_OBTE_MODE) == true) {
ExynosCameraTuningInterface::stop();
}
m_vendorSpecificPreDestructor();
TIME_LOGGER_UPDATE(m_cameraId, 0, 0, CUMULATIVE_CNT, PRE_DESTRUCTOR_END, 0);
if (m_shotDoneQ != NULL) {
delete m_shotDoneQ;
m_shotDoneQ = NULL;
}
#ifdef USE_DUAL_CAMERA
if (m_slaveShotDoneQ != NULL) {
delete m_slaveShotDoneQ;
m_slaveShotDoneQ = NULL;
}
if (m_dualStandbyTriggerQ != NULL) {
delete m_dualStandbyTriggerQ;
m_dualStandbyTriggerQ = NULL;
}
if (m_selectDualSlaveBayerQ != NULL) {
delete m_selectDualSlaveBayerQ;
m_selectDualSlaveBayerQ = NULL;
}
#endif
for (int i = 0; i < MAX_PIPE_NUM; i++) {
if (m_pipeFrameDoneQ[i] != NULL) {
delete m_pipeFrameDoneQ[i];
m_pipeFrameDoneQ[i] = NULL;
}
}
if (m_yuvCaptureDoneQ != NULL) {
delete m_yuvCaptureDoneQ;
m_yuvCaptureDoneQ = NULL;
}
if (m_reprocessingDoneQ != NULL) {
delete m_reprocessingDoneQ;
m_reprocessingDoneQ = NULL;
}
if (m_bayerStreamQ != NULL) {
delete m_bayerStreamQ;
m_bayerStreamQ = NULL;
}
if (m_frameFactoryQ != NULL) {
delete m_frameFactoryQ;
m_frameFactoryQ = NULL;
}
if (m_selectBayerQ != NULL) {
delete m_selectBayerQ;
m_selectBayerQ = NULL;
}
if (m_captureQ != NULL) {
delete m_captureQ;
m_captureQ = NULL;
}
#if defined(USE_RAW_REVERSE_PROCESSING) && defined(USE_SW_RAW_REVERSE_PROCESSING)
if (m_reverseProcessingBayerQ != NULL) {
delete m_reverseProcessingBayerQ;
m_reverseProcessingBayerQ = NULL;
}
#endif
#ifdef SUPPORT_HW_GDC
if (m_gdcQ != NULL) {
delete m_gdcQ;
m_gdcQ = NULL;
}
#endif
#ifdef BUFFER_DUMP
if (m_dumpBufferQ != NULL) {
delete m_dumpBufferQ;
m_dumpBufferQ = NULL;
}
#endif
m_deinitFrameFactory();
if (m_streamManager != NULL) {
delete m_streamManager;
m_streamManager = NULL;
}
if (m_requestMgr!= NULL) {
delete m_requestMgr;
m_requestMgr = NULL;
}
for (int i = 0; i < CAMERA_ID_MAX; i++) {
if (m_parameters[i] != NULL) {
delete m_parameters[i];
m_parameters[i] = NULL;
}
if (m_currentPreviewShot[i] != NULL) {
delete m_currentPreviewShot[i];
m_currentPreviewShot[i] = NULL;
}
if (m_currentInternalShot[i] != NULL) {
delete m_currentInternalShot[i];
m_currentInternalShot[i] = NULL;
}
if (m_currentCaptureShot[i] != NULL) {
delete m_currentCaptureShot[i];
m_currentCaptureShot[i] = NULL;
}
if (m_currentVisionShot[i] != NULL) {
delete m_currentVisionShot[i];
m_currentVisionShot[i] = NULL;
}
}
if (m_configurations != NULL) {
delete m_configurations;
m_configurations = NULL;
}
if (m_metadataConverter != NULL) {
delete m_metadataConverter;
m_metadataConverter = NULL;
}
for (int i = 0; i < CAMERA_ID_MAX; i++) {
if (m_captureSelector[i] != NULL) {
delete m_captureSelector[i];
m_captureSelector[i] = NULL;
}
}
if (m_captureZslSelector != NULL) {
delete m_captureZslSelector;
m_captureZslSelector = NULL;
}
if (m_ionClient >= 0) {
exynos_ion_close(m_ionClient);
m_ionClient = -1;
}
if (m_previewCallbackPP != NULL) {
if (m_previewCallbackPP->flagCreated() == true) {
status_t ret = NO_ERROR;
ret = m_previewCallbackPP->destroy();
if (ret != NO_ERROR) {
CLOGE("m_previewCallbackPP->destroy() fail");
}
}
SAFE_DELETE(m_previewCallbackPP);
}
TIME_LOGGER_UPDATE(m_cameraId, 0, 0, CUMULATIVE_CNT, BUFFER_SUPPLIER_DEINIT_JOIN_START, 0);
m_deinitBufferSupplierThread->requestExitAndWait();
TIME_LOGGER_UPDATE(m_cameraId, 0, 0, CUMULATIVE_CNT, BUFFER_SUPPLIER_DEINIT_JOIN_END, 0);
// TODO: clean up
// m_resultBufferVectorSet
// m_processList
// m_postProcessList
// m_pipeFrameDoneQ
m_vendorSpecificDestructor();
TIME_LOGGER_UPDATE(m_cameraId, 0, 0, CUMULATIVE_CNT, POST_DESTRUCTOR_END, 0);
/* Frame manager must be deleted in the last.
* Some frame lists can call frame destructor
* which will try to access frameQueue from frame manager.
*/
if (m_frameMgr != NULL) {
delete m_frameMgr;
m_frameMgr = NULL;
}
CLOGI("-OUT-");
}
status_t ExynosCamera::initializeDevice(const camera3_callback_ops *callbackOps)
{
status_t ret = NO_ERROR;
CLOGD("");
/* set callback ops */
m_requestMgr->setCallbackOps(callbackOps);
if (m_parameters[m_cameraId]->isReprocessing() == true) {
if (m_captureSelector[m_cameraId] == NULL) {
m_captureSelector[m_cameraId] = new ExynosCameraFrameSelector(
m_cameraId,
m_configurations,
m_parameters[m_cameraId],
m_bufferSupplier,
m_frameMgr);
ret = m_captureSelector[m_cameraId]->setFrameHoldCount(REPROCESSING_BAYER_HOLD_COUNT);
if (ret < 0) {
CLOGE("m_captureSelector setFrameHoldCount(%d) is fail",
REPROCESSING_BAYER_HOLD_COUNT);
}
}
#ifdef USE_DUAL_CAMERA
if (m_configurations->getMode(CONFIGURATION_DUAL_MODE) == true
&& m_captureSelector[m_cameraIds[1]] == NULL) {
m_captureSelector[m_cameraIds[1]] = new ExynosCameraFrameSelector(
m_cameraIds[1],
m_configurations,
m_parameters[m_cameraIds[1]],
m_bufferSupplier,
m_frameMgr);
ret = m_captureSelector[m_cameraIds[1]]->setFrameHoldCount(REPROCESSING_BAYER_HOLD_COUNT);
if (ret < 0) {
CLOGE("m_captureSelector[%d] setFrameHoldCount(%d) is fail",
m_cameraIds[1], REPROCESSING_BAYER_HOLD_COUNT);
}
}
#endif
if (m_captureZslSelector == NULL) {
m_captureZslSelector = new ExynosCameraFrameSelector(
m_cameraId,
m_configurations,
m_parameters[m_cameraId],
m_bufferSupplier,
m_frameMgr);
ret = m_captureZslSelector->setFrameHoldCount(REPROCESSING_BAYER_HOLD_COUNT);
if (ret < 0) {
CLOGE("m_captureZslSelector setFrameHoldCount(%d) is fail",
REPROCESSING_BAYER_HOLD_COUNT);
}
}
}
m_frameMgr->start();
ret = m_transitState(EXYNOS_CAMERA_STATE_INITIALIZE);
if (ret != NO_ERROR) {
CLOGE("Failed to transitState into INITIALIZE. ret %d", ret);
}
return ret;
}
status_t ExynosCamera::m_reInit(void)
{
m_vendorReInit();
return NO_ERROR;
}
status_t ExynosCamera::construct_default_request_settings(camera_metadata_t **request, int type)
{
CLOGD("Type %d", type);
if ((type < 0) || (type >= CAMERA3_TEMPLATE_COUNT)) {
CLOGE("Unknown request settings template: %d", type);
return NO_INIT;
}
m_requestMgr->constructDefaultRequestSettings(type, request);
CLOGI("out");
return NO_ERROR;
}
void ExynosCamera::get_metadata_vendor_tag_ops(const camera3_device_t *, vendor_tag_query_ops_t *ops)
{
if (ops == NULL) {
CLOGE("ops is NULL");
return;
}
}
void ExynosCamera::dump()
{
ExynosCameraFrameFactory *factory = NULL;
CLOGI("");
factory = m_frameFactory[FRAME_FACTORY_TYPE_CAPTURE_PREVIEW];
if (factory == NULL) {
CLOGE("frameFactory is NULL");
return;
}
m_frameFactory[FRAME_FACTORY_TYPE_CAPTURE_PREVIEW]->dump();
m_bufferSupplier->dump();
}
int ExynosCamera::getCameraId() const
{
return m_cameraId;
}
#ifdef USE_DUAL_CAMERA
int ExynosCamera::getSubCameraId() const
{
return m_cameraIds[1];
}
#endif
status_t ExynosCamera::setPIPMode(bool enabled)
{
m_configurations->setMode(CONFIGURATION_PIP_MODE, enabled);
return NO_ERROR;
}
#ifdef USE_DUAL_CAMERA
status_t ExynosCamera::setDualMode(bool enabled)
{
m_configurations->setMode(CONFIGURATION_DUAL_MODE, enabled);
return NO_ERROR;
}
bool ExynosCamera::getDualMode(void)
{
return m_configurations->getMode(CONFIGURATION_DUAL_MODE);
}
#endif
bool ExynosCamera::m_mainPreviewThreadFunc(void)
{
status_t ret = NO_ERROR;
if (m_getState() != EXYNOS_CAMERA_STATE_RUN) {
CLOGI("Wait to run FrameFactory. state(%d)", m_getState());
if (m_getState() == EXYNOS_CAMERA_STATE_ERROR) {
return false;
}
usleep(1000);
return true;
}
if (m_configurations->getMode(CONFIGURATION_VISION_MODE) == false) {
ret = m_createPreviewFrameFunc(REQ_SYNC_WITH_3AA, true /* flagFinishFactoryStart */);
} else {
ret = m_createVisionFrameFunc(REQ_SYNC_WITH_3AA, true /* flagFinishFactoryStart */);
}
if (ret != NO_ERROR) {
CLOGE("Failed to createPreviewFrameFunc. Shotdone");
}
return true;
}
bool ExynosCamera::m_mainCaptureThreadFunc(void)
{
status_t ret = NO_ERROR;
m_reprocessingFrameFactoryStartThread->join();
if (m_getState() != EXYNOS_CAMERA_STATE_RUN) {
CLOGI("Wait to run FrameFactory. state(%d)", m_getState());
if (m_getState() == EXYNOS_CAMERA_STATE_ERROR) {
return false;
}
usleep(10000);
return true;
}
if (m_getSizeFromRequestList(&m_requestCaptureWaitingList, &m_requestCaptureWaitingLock) > 0) {
ret = m_createCaptureFrameFunc();
if (ret != NO_ERROR) {
CLOGE("Failed to createCaptureFrameFunc. Shotdone");
}
return true;
} else {
return false;
}
}
#ifdef USE_DUAL_CAMERA
bool ExynosCamera::m_slaveMainThreadFunc(void)
{
ExynosCameraFrameSP_sptr_t frame;
bool loop = false;
status_t ret = NO_ERROR;
enum DUAL_OPERATION_MODE dualOperationMode = DUAL_OPERATION_MODE_NONE;
enum DUAL_OPERATION_MODE earlyDualOperationMode = DUAL_OPERATION_MODE_NONE;
frame_type_t frameType;
ExynosCameraFrameFactory *factory;
factory_handler_t frameCreateHandler;
ExynosCameraRequestSP_sprt_t request;
List<ExynosCameraRequestSP_sprt_t>::iterator r;
if (m_getState() != EXYNOS_CAMERA_STATE_RUN) {
CLOGI("Wait to run FrameFactory. state(%d), m_earlyDualOperationMode(%d)",
m_getState(), m_earlyDualOperationMode);
if (m_getState() == EXYNOS_CAMERA_STATE_ERROR) {
return false;
}
usleep(1000);
return true;
}
/* 1. Wait the shot done with the latest frame */
ret = m_slaveShotDoneQ->waitAndPopProcessQ(&frame);
if (ret < 0) {
if (ret == TIMED_OUT)
CLOGW("wait timeout");
else
CLOGE("wait and pop fail, ret(%d)", ret);
loop = true;
goto p_exit;
} else {
Mutex::Autolock lock(m_dualOperationModeLock);
earlyDualOperationMode = m_earlyDualOperationMode;
switch (frame->getFrameType()) {
case FRAME_TYPE_TRANSITION_SLAVE:
/*
* The dualOperationMode might have not been changed by my standby.
* So I want to refer to m_earlyDualOperationMode in advance.
*/
dualOperationMode = m_earlyDualOperationMode;
break;
case FRAME_TYPE_PREVIEW_DUAL_SLAVE:
/*
* Refer to current dualOperationMode
*/
dualOperationMode = m_configurations->getDualOperationMode();
break;
case FRAME_TYPE_PREVIEW_SLAVE:
case FRAME_TYPE_INTERNAL_SLAVE:
/*
* Refer to current dualOperationMode
* But, in this generation of frame,
* DUAL_SLAVE frame may be created in m_createPreviewFrameFunc()
*/
dualOperationMode = m_configurations->getDualOperationMode();
break;
default:
CLOG_ASSERT("invalid frameType(%d)", frame->getFrameType());
break;
}
}
CLOGV("[F%d, T%d] dualOperationMode: %d / %d",
frame->getFrameCount(), frame->getFrameType(),
m_earlyDualOperationMode, m_configurations->getDualOperationMode());
switch (dualOperationMode) {
case DUAL_OPERATION_MODE_MASTER:
if (earlyDualOperationMode == DUAL_OPERATION_MODE_SYNC &&
m_parameters[m_cameraIds[1]]->getStandbyState() == DUAL_STANDBY_STATE_OFF) {
/* create slave frame for sync mode */
frameType = FRAME_TYPE_PREVIEW_DUAL_SLAVE;
factory = m_frameFactory[FRAME_FACTORY_TYPE_PREVIEW_DUAL];
frameCreateHandler = factory->getFrameCreateHandler();
/* get the latest request */
m_latestRequestListLock.lock();
if (m_essentialRequestList.size() > 0) {
r = m_essentialRequestList.begin();
request = *r;
m_essentialRequestList.erase(r);
} else {
r = m_latestRequestList.begin();
request = *r;
}
m_latestRequestListLock.unlock();
if (request != NULL) {
if (m_configurations->getDynamicMode(DYNAMIC_DUAL_FORCE_SWITCHING) == false) {
(this->*frameCreateHandler)(request, factory, frameType);
} else {
m_createInternalFrameFunc(NULL, true, REQ_SYNC_NONE, FRAME_TYPE_INTERNAL_SLAVE);
}
} else {
m_createInternalFrameFunc(NULL, true, REQ_SYNC_NONE, FRAME_TYPE_INTERNAL_SLAVE);
}
}
loop = true;
goto p_exit;
case DUAL_OPERATION_MODE_SLAVE:
ret = m_createPreviewFrameFunc(REQ_SYNC_NONE, true /* flagFinishFactoryStart */);
loop = true;
goto p_exit;
case DUAL_OPERATION_MODE_SYNC:
/* create slave frame for sync mode */
frameType = FRAME_TYPE_PREVIEW_DUAL_SLAVE;
factory = m_frameFactory[FRAME_FACTORY_TYPE_PREVIEW_DUAL];
frameCreateHandler = factory->getFrameCreateHandler();
/* get the latest request */
m_latestRequestListLock.lock();
if (m_essentialRequestList.size() > 0) {
r = m_essentialRequestList.begin();
request = *r;
m_essentialRequestList.erase(r);
} else {
r = m_latestRequestList.begin();
request = *r;
}
m_latestRequestListLock.unlock();
if (request != NULL) {
if (m_configurations->getDynamicMode(DYNAMIC_DUAL_FORCE_SWITCHING) == false) {
(this->*frameCreateHandler)(request, factory, frameType);
} else {
m_createInternalFrameFunc(NULL, true, REQ_SYNC_NONE, FRAME_TYPE_INTERNAL_SLAVE);
}
} else {
m_createInternalFrameFunc(NULL, true, REQ_SYNC_NONE, FRAME_TYPE_INTERNAL_SLAVE);
}
loop = true;
goto p_exit;
default:
goto p_exit;
}
p_exit:
return loop;
}
#endif
status_t ExynosCamera::m_createPreviewFrameFunc(enum Request_Sync_Type syncType, __unused bool flagFinishFactoryStart)
{
status_t ret = NO_ERROR;
status_t waitRet = NO_ERROR;
ExynosCameraRequestSP_sprt_t request = NULL;
struct camera2_shot_ext *service_shot_ext = NULL;
FrameFactoryList previewFactoryAddrList;
ExynosCameraFrameFactory *factory = NULL;
FrameFactoryListIterator factorylistIter;
factory_handler_t frameCreateHandler;
List<ExynosCameraRequestSP_sprt_t>::iterator r;
frame_type_t frameType = FRAME_TYPE_PREVIEW;
uint32_t waitingListSize;
uint32_t requiredRequestCount = -1;
ExynosCameraFrameSP_sptr_t reqSyncFrame = NULL;
#ifdef USE_DUAL_CAMERA
ExynosCameraFrameFactory *subFactory = NULL;
frame_type_t subFrameType = FRAME_TYPE_PREVIEW;
enum DUAL_OPERATION_MODE dualOperationMode = m_configurations->getDualOperationMode();
int32_t dualOperationModeLockCount = 0;
bool isDualMode = m_configurations->getMode(CONFIGURATION_DUAL_MODE);
#endif
#ifdef DEBUG_STREAM_CONFIGURATIONS
CLOGD("DEBUG_STREAM_CONFIGURATIONS::[R%d] generate request frame", request->getKey());
#endif
waitRet = m_waitShotDone(syncType, reqSyncFrame);
#ifdef USE_DUAL_CAMERA
/* delay this signal after updating dualOperationMode */
if (isDualMode == false)
m_captureResultDoneCondition.signal();
#else
m_captureResultDoneCondition.signal();
#endif
/* 1. Update the current shot */
{
Mutex::Autolock l(m_requestPreviewWaitingLock);
enum pipeline controlPipeId = (enum pipeline) m_parameters[m_cameraId]->getPerFrameControlPipe();
waitingListSize = m_requestPreviewWaitingList.size();
if (m_parameters[m_cameraId]->useServiceBatchMode() == true) {
requiredRequestCount = 1;
} else {
requiredRequestCount = m_parameters[m_cameraId]->getBatchSize(controlPipeId);
}
if (waitingListSize < requiredRequestCount) {
m_isNeedRequestFrame = false;
} else {
m_isNeedRequestFrame = true;
r = m_requestPreviewWaitingList.begin();
request = *r;
/* 2. Update the entire shot_ext structure */
service_shot_ext = request->getServiceShot();
if (service_shot_ext == NULL) {
CLOGE("[R%d] Get service shot is failed", request->getKey());
} else {
m_latestRequestListLock.lock();
m_latestRequestList.clear();
m_latestRequestList.push_front(request);
m_latestRequestListLock.unlock();
}
/* 3. Initial (SENSOR_REQUEST_DELAY + 1) frames must be internal frame to
* secure frame margin for sensor control.
* If sensor control delay is 0, every initial frames must be request frame.
*/
if (m_parameters[m_cameraId]->getSensorControlDelay() > 0
&& m_internalFrameCount < (m_parameters[m_cameraId]->getSensorControlDelay() + 2)) {
m_isNeedRequestFrame = false;
request = NULL;
CLOGD("[F%d]Create Initial Frame", m_internalFrameCount);
} else {
#ifdef USE_DUAL_CAMERA
if (isDualMode == true) {
ret = m_checkDualOperationMode(request, true, false, flagFinishFactoryStart);
if (ret != NO_ERROR) {
CLOGE("m_checkDualOperationMode fail! flagFinishFactoryStart(%d) ret(%d)", flagFinishFactoryStart, ret);
}
dualOperationMode = m_configurations->getDualOperationMode();
dualOperationModeLockCount = m_configurations->getDualOperationModeLockCount();
switch (dualOperationMode) {
case DUAL_OPERATION_MODE_SLAVE:
/* source from master */
if (syncType == REQ_SYNC_WITH_3AA) {
if (reqSyncFrame != NULL) {
/*
* Early SensorStandby-off case in MASTER only.
* The request to trigger Early SensorStandby-off has not been yet arrived here.
* So we generate Transition frame to keep the count of queued buffers.
* We don't care Early SensorStandby-off in SLAVE cause of independent
* slaveMainThread.
*/
if (m_earlyTriggerRequestKey > request->getKey() ||
dualOperationModeLockCount > 0) {
CLOGI("generate transition frame more due to early sensorStandby off [%d, %d] lockCnt(%d)",
m_earlyTriggerRequestKey,
request->getKey(),
dualOperationModeLockCount);
ret = m_createInternalFrameFunc(NULL, flagFinishFactoryStart, REQ_SYNC_NONE, FRAME_TYPE_TRANSITION);
if (ret != NO_ERROR) {
CLOGE("Failed to createInternalFrameFunc(%d)", ret);
}
} else {
CLOGW("[R%d F%d T%d]skip this request for slave",
request->getKey(),
reqSyncFrame->getFrameCount(),
reqSyncFrame->getFrameType());
}
} else {
CLOGW("skip this request for slave");
}
return ret;
}
break;
case DUAL_OPERATION_MODE_SYNC:
case DUAL_OPERATION_MODE_MASTER:
/* source from slave */
if (syncType == REQ_SYNC_NONE && flagFinishFactoryStart == true) {
if (m_configurations->getDynamicMode(DYNAMIC_DUAL_FORCE_SWITCHING) == false) {
/* create slave frame for sync mode */
frameType = FRAME_TYPE_PREVIEW_DUAL_SLAVE;
factory = m_frameFactory[FRAME_FACTORY_TYPE_PREVIEW_DUAL];
frameCreateHandler = factory->getFrameCreateHandler();
(this->*frameCreateHandler)(request, factory, frameType);
} else {
m_createInternalFrameFunc(NULL, flagFinishFactoryStart, REQ_SYNC_NONE, FRAME_TYPE_INTERNAL_SLAVE);
}
return ret;
}
break;
default:
break;
}
}
#endif
#ifdef USE_DUAL_CAMERA
/* save the latest request */
m_latestRequestListLock.lock();
if (isDualMode == true
&& m_isRequestEssential(request) == true) {
if (m_essentialRequestList.size() > 10) {
CLOGW("Essential request list(%d)", m_essentialRequestList.size());
}
m_essentialRequestList.push_back(request);
}
m_latestRequestListLock.unlock();
#endif
m_requestPreviewWaitingList.erase(r);
}
}
}
#ifdef USE_DUAL_CAMERA
if (isDualMode == true)
m_captureResultDoneCondition.signal();
#endif
CLOGV("Create New Frame %d needRequestFrame %d waitingSize %d",
m_internalFrameCount, m_isNeedRequestFrame, waitingListSize);
/* 4. Select the frame creation logic between request frame and internal frame */
if (m_isNeedRequestFrame == true) {
previewFactoryAddrList.clear();
request->getFactoryAddrList(FRAME_FACTORY_TYPE_CAPTURE_PREVIEW, &previewFactoryAddrList);
m_configurations->updateMetaParameter(request->getMetaParameters());
/* Call the frame create handler for each frame factory */
/* Frame creation handler calling sequence is ordered in accordance with
its frame factory type, because there are dependencies between frame
processing routine.
*/
if (previewFactoryAddrList.empty() == false) {
ExynosCameraRequestSP_sprt_t serviceRequest = NULL;
m_popServiceRequest(serviceRequest);
serviceRequest = NULL;
for (factorylistIter = previewFactoryAddrList.begin(); factorylistIter != previewFactoryAddrList.end(); ) {
factory = *factorylistIter;
CLOGV("frameFactory (%p)", factory);
switch(factory->getFactoryType()) {
case FRAME_FACTORY_TYPE_CAPTURE_PREVIEW:
frameType = FRAME_TYPE_PREVIEW;
break;
case FRAME_FACTORY_TYPE_REPROCESSING:
frameType = FRAME_TYPE_REPROCESSING;
break;
case FRAME_FACTORY_TYPE_JPEG_REPROCESSING:
frameType = FRAME_TYPE_JPEG_REPROCESSING;
break;
case FRAME_FACTORY_TYPE_VISION:
frameType = FRAME_TYPE_VISION;
break;
default:
CLOGE("[R%d] Factory type is not available", request->getKey());
break;
}
#ifdef USE_DUAL_CAMERA
if (isDualMode == true) {
switch (factory->getFactoryType()) {
case FRAME_FACTORY_TYPE_CAPTURE_PREVIEW:
if (dualOperationMode == DUAL_OPERATION_MODE_SYNC) {
frameType = FRAME_TYPE_PREVIEW_DUAL_MASTER;
} else if (dualOperationMode == DUAL_OPERATION_MODE_SLAVE) {
factory = m_frameFactory[FRAME_FACTORY_TYPE_PREVIEW_DUAL];
frameType = FRAME_TYPE_PREVIEW_SLAVE;
}
break;
case FRAME_FACTORY_TYPE_REPROCESSING:
if (dualOperationMode == DUAL_OPERATION_MODE_SYNC) {
subFrameType = FRAME_TYPE_REPROCESSING_DUAL_SLAVE;
subFactory = m_frameFactory[FRAME_FACTORY_TYPE_REPROCESSING_DUAL];
frameCreateHandler = subFactory->getFrameCreateHandler();
(this->*frameCreateHandler)(request, subFactory, subFrameType);
frameType = FRAME_TYPE_REPROCESSING_DUAL_MASTER;
} else if (dualOperationMode == DUAL_OPERATION_MODE_SLAVE) {
factory = m_frameFactory[FRAME_FACTORY_TYPE_REPROCESSING_DUAL];
frameType = FRAME_TYPE_REPROCESSING_SLAVE;
}
break;
default:
CLOGE("[R%d] Factory type is not available", request->getKey());
break;
}
}
#endif
frameCreateHandler = factory->getFrameCreateHandler();
(this->*frameCreateHandler)(request, factory, frameType);
factorylistIter++;
}
} else {
frame_type_t internalFrameType = FRAME_TYPE_INTERNAL;
#ifdef USE_DUAL_CAMERA
if (isDualMode == true && dualOperationMode == DUAL_OPERATION_MODE_SLAVE &&
syncType == REQ_SYNC_NONE) {
internalFrameType = FRAME_TYPE_INTERNAL_SLAVE;
}
#endif
m_createInternalFrameFunc(request, flagFinishFactoryStart, syncType, internalFrameType);
}
} else {
frame_type_t internalFrameType = FRAME_TYPE_INTERNAL;
#ifdef USE_DUAL_CAMERA
if (isDualMode == true && dualOperationMode == DUAL_OPERATION_MODE_SLAVE &&
syncType == REQ_SYNC_NONE) {
internalFrameType = FRAME_TYPE_INTERNAL_SLAVE;
}
#endif
m_createInternalFrameFunc(NULL, flagFinishFactoryStart, syncType, internalFrameType);
}
previewFactoryAddrList.clear();
return ret;
}
status_t ExynosCamera::m_createVisionFrameFunc(enum Request_Sync_Type syncType, __unused bool flagFinishFactoryStart)
{
status_t ret = NO_ERROR;
ExynosCameraRequestSP_sprt_t request = NULL;
struct camera2_shot_ext *service_shot_ext = NULL;
FrameFactoryList visionFactoryAddrList;
ExynosCameraFrameFactory *factory = NULL;
FrameFactoryListIterator factorylistIter;
factory_handler_t frameCreateHandler;
List<ExynosCameraRequestSP_sprt_t>::iterator r;
frame_type_t frameType = FRAME_TYPE_VISION;
uint32_t watingListSize = 0;
ExynosCameraFrameSP_sptr_t reqSyncFrame = NULL;
#ifdef DEBUG_STREAM_CONFIGURATIONS
CLOGD("DEBUG_STREAM_CONFIGURATIONS::[R%d] generate request frame", request->getKey());
#endif
m_waitShotDone(syncType, reqSyncFrame);
m_captureResultDoneCondition.signal();
/* 1. Update the current shot */
{
Mutex::Autolock l(m_requestPreviewWaitingLock);
watingListSize = m_requestPreviewWaitingList.size();
if (m_requestPreviewWaitingList.empty() == true) {
m_isNeedRequestFrame = false;
} else {
m_isNeedRequestFrame = true;
r = m_requestPreviewWaitingList.begin();
request = *r;
/* Update the entire shot_ext structure */
service_shot_ext = request->getServiceShot();
if (service_shot_ext == NULL) {
CLOGE("[R%d] Get service shot is failed", request->getKey());
} else {
m_latestRequestListLock.lock();
m_latestRequestList.clear();
m_latestRequestList.push_front(request);
m_latestRequestListLock.unlock();
}
/* 2. Initial (SENSOR_CONTROL_DELAY + 1) frames must be internal frame to
* secure frame margin for sensor control.
* If sensor control delay is 0, every initial frames must be request frame.
*/
if (m_parameters[m_cameraId]->getSensorControlDelay() > 0
&& m_internalFrameCount < (m_parameters[m_cameraId]->getSensorControlDelay() + 2)) {
m_isNeedRequestFrame = false;
request = NULL;
} else {
m_requestPreviewWaitingList.erase(r);
}
}
}
CLOGV("Create New Frame %d needRequestFrame %d waitingSize %d",
m_internalFrameCount, m_isNeedRequestFrame, watingListSize);
/* 3. Select the frame creation logic between request frame and internal frame */
if (m_isNeedRequestFrame == true) {
visionFactoryAddrList.clear();
request->getFactoryAddrList(FRAME_FACTORY_TYPE_VISION, &visionFactoryAddrList);
/* Call the frame create handler fro each frame factory */
/* Frame createion handler calling sequence is ordered in accordance with
its frame factory type, because there are dependencies between frame
processing routine.
*/
if (visionFactoryAddrList.empty() == false) {
ExynosCameraRequestSP_sprt_t serviceRequest = NULL;
m_popServiceRequest(serviceRequest);
serviceRequest = NULL;
for (factorylistIter = visionFactoryAddrList.begin(); factorylistIter != visionFactoryAddrList.end(); ) {
factory = *factorylistIter;
CLOGV("frameFactory (%p)", factory);
switch(factory->getFactoryType()) {
case FRAME_FACTORY_TYPE_CAPTURE_PREVIEW:
frameType = FRAME_TYPE_PREVIEW;
break;
case FRAME_FACTORY_TYPE_REPROCESSING:
case FRAME_FACTORY_TYPE_JPEG_REPROCESSING:
frameType = FRAME_TYPE_REPROCESSING;
break;
case FRAME_FACTORY_TYPE_VISION:
frameType = FRAME_TYPE_VISION;
break;
default:
CLOGE("[R%d] Factory type is not available", request->getKey());
break;
}
frameCreateHandler = factory->getFrameCreateHandler();
(this->*frameCreateHandler)(request, factory, frameType);
factorylistIter++;
}
} else {
m_createInternalFrameFunc(request, flagFinishFactoryStart, syncType);
}
} else {
m_createInternalFrameFunc(NULL, flagFinishFactoryStart, syncType);
}
visionFactoryAddrList.clear();
return ret;
}
status_t ExynosCamera::m_waitShotDone(enum Request_Sync_Type syncType, ExynosCameraFrameSP_dptr_t reqSyncFrame)
{
status_t ret = NO_ERROR;
ExynosCameraFrameSP_sptr_t frame = NULL;
if (syncType == REQ_SYNC_WITH_3AA && m_shotDoneQ != NULL) {
/* 1. Wait the shot done with the latest framecount */
ret = m_shotDoneQ->waitAndPopProcessQ(&frame);
if (ret < 0) {
if (ret == TIMED_OUT)
CLOGW("wait timeout");
else
CLOGE("wait and pop fail, ret(%d)", ret);
return ret;
}
}
reqSyncFrame = frame;
return ret;
}
status_t ExynosCamera::m_sendJpegStreamResult(ExynosCameraRequestSP_sprt_t request,
ExynosCameraBuffer *buffer, int size)
{
status_t ret = NO_ERROR;
ExynosCameraStream *stream = NULL;
camera3_stream_buffer_t *streamBuffer = NULL;
ResultRequest resultRequest = NULL;
camera3_capture_result_t *requestResult = NULL;
ret = m_streamManager->getStream(HAL_STREAM_ID_JPEG, &stream);
if (ret != NO_ERROR) {
CLOGE("Failed to getStream from StreamMgr. streamId HAL_STREAM_ID_JPEG");
return ret;
}
if (stream == NULL) {
CLOGE("stream is NULL");
return INVALID_OPERATION;
}
resultRequest = m_requestMgr->createResultRequest(request->getKey(), request->getFrameCount(),
EXYNOS_REQUEST_RESULT::CALLBACK_BUFFER_ONLY);
if (resultRequest == NULL) {
CLOGE("[R%d F%d] createResultRequest fail. streamId HAL_STREAM_ID_JPEG",
request->getKey(), request->getFrameCount());
ret = INVALID_OPERATION;
return ret;
}
requestResult = resultRequest->getCaptureResult();
if (requestResult == NULL) {
CLOGE("[R%d F%d] getCaptureResult fail. streamId HAL_STREAM_ID_JPEG",
request->getKey(), request->getFrameCount());
ret = INVALID_OPERATION;
return ret;
}
streamBuffer = resultRequest->getStreamBuffer();
if (streamBuffer == NULL) {
CLOGE("[R%d F%d] getStreamBuffer fail. streamId HAL_STREAM_ID_JPEG",
request->getKey(), request->getFrameCount());
ret = INVALID_OPERATION;
return ret;
}
ret = stream->getStream(&(streamBuffer->stream));
if (ret != NO_ERROR) {
CLOGE("Failed to getStream from ExynosCameraStream. streamId HAL_STREAM_ID_JPEG");
return ret;
}
streamBuffer->buffer = buffer->handle[0];
ret = m_checkStreamBufferStatus(request, stream, &streamBuffer->status);
if (ret != NO_ERROR) {
CLOGE("[R%d F%d S%d B%d]Failed to checkStreamBufferStatus.",
request->getKey(), request->getFrameCount(),
HAL_STREAM_ID_JPEG, buffer->index);
return ret;
}
streamBuffer->acquire_fence = -1;
streamBuffer->release_fence = -1;
camera3_jpeg_blob_t jpeg_bolb;
jpeg_bolb.jpeg_blob_id = CAMERA3_JPEG_BLOB_ID;
jpeg_bolb.jpeg_size = size;
int32_t jpegBufferSize = ((private_handle_t *)(*(streamBuffer->buffer)))->width;
memcpy(buffer->addr[0] + jpegBufferSize - sizeof(camera3_jpeg_blob_t), &jpeg_bolb, sizeof(camera3_jpeg_blob_t));
/* update jpeg size */
request->setRequestLock();
CameraMetadata *setting = request->getServiceMeta();
int32_t jpegsize = size;
ret = setting->update(ANDROID_JPEG_SIZE, &jpegsize, 1);
if (ret < 0) {
CLOGE("ANDROID_JPEG_SIZE update failed(%d)", ret);
}
request->setRequestUnlock();
CLOGD("Set JPEG result Done. frameCount %d", request->getFrameCount());
/* construct result for service */
requestResult->frame_number = request->getKey();
requestResult->result = NULL;
requestResult->num_output_buffers = 1;
requestResult->output_buffers = streamBuffer;
requestResult->input_buffer = request->getInputBuffer();
requestResult->partial_result = 0;
CLOGV("frame number(%d), #out(%d)",
requestResult->frame_number, requestResult->num_output_buffers);
m_requestMgr->pushResultRequest(resultRequest);
ret = m_bufferSupplier->putBuffer(*buffer);
if (ret != NO_ERROR) {
CLOGE("[R%d F%d B%d]Failed to putBuffer. ret %d",
request->getKey(), request->getFrameCount(), buffer->index, ret);
}
return ret;
}
status_t ExynosCamera::m_sendRawStreamResult(ExynosCameraRequestSP_sprt_t request, ExynosCameraBuffer *buffer)
{
status_t ret = NO_ERROR;
ExynosCameraStream *stream = NULL;
camera3_stream_buffer_t *streamBuffer = NULL;
ResultRequest resultRequest = NULL;
camera3_capture_result_t *requestResult = NULL;
/* 1. Get stream object for RAW */
ret = m_streamManager->getStream(HAL_STREAM_ID_RAW, &stream);
if (ret < 0) {
CLOGE("getStream is failed, from streammanager. Id error:HAL_STREAM_ID_RAW");
return ret;
}
resultRequest = m_requestMgr->createResultRequest(request->getKey(), request->getFrameCount(),
EXYNOS_REQUEST_RESULT::CALLBACK_BUFFER_ONLY);
if (resultRequest == NULL) {
CLOGE("[R%d F%d] createResultRequest fail. streamId HAL_STREAM_ID_RAW",
request->getKey(), request->getFrameCount());
ret = INVALID_OPERATION;
return ret;
}
requestResult = resultRequest->getCaptureResult();
if (requestResult == NULL) {
CLOGE("[R%d F%d] getCaptureResult fail. streamId HAL_STREAM_ID_RAW",
request->getKey(), request->getFrameCount());
ret = INVALID_OPERATION;
return ret;
}
streamBuffer = resultRequest->getStreamBuffer();
if (streamBuffer == NULL) {
CLOGE("[R%d F%d] getStreamBuffer fail. streamId HAL_STREAM_ID_RAW",
request->getKey(), request->getFrameCount());
ret = INVALID_OPERATION;
return ret;
}
/* 2. Get camera3_stream structure from stream object */
ret = stream->getStream(&(streamBuffer->stream));
if (ret < 0) {
CLOGE("getStream is failed, from exynoscamerastream. Id error:HAL_STREAM_ID_RAW");
return ret;
}
/* 3. Get the service buffer handle */
streamBuffer->buffer = buffer->handle[0];
/* 4. Update the remained buffer info */
ret = m_checkStreamBufferStatus(request, stream, &streamBuffer->status);
if (ret != NO_ERROR) {
CLOGE("[R%d F%d S%d B%d]Failed to checkStreamBufferStatus.",
request->getKey(), request->getFrameCount(),
HAL_STREAM_ID_RAW, buffer->index);
return ret;
}
streamBuffer->acquire_fence = -1;
streamBuffer->release_fence = -1;
/* 5. Create new result for RAW buffer */
requestResult->frame_number = request->getKey();
requestResult->result = NULL;
requestResult->num_output_buffers = 1;
requestResult->output_buffers = streamBuffer;
requestResult->input_buffer = NULL;
requestResult->partial_result = 0;
CLOGV("frame number(%d), #out(%d)", requestResult->frame_number, requestResult->num_output_buffers);
/* 6. Request to callback the result to request manager */
m_requestMgr->pushResultRequest(resultRequest);
ret = m_bufferSupplier->putBuffer(*buffer);
if (ret != NO_ERROR) {
CLOGE("[R%d F%d B%d]Failed to putBuffer. ret %d",
request->getKey(), request->getFrameCount(), buffer->index, ret);
}
CLOGV("request->frame_number(%d), request->getNumOfOutputBuffer(%d)"
" request->getCompleteBufferCount(%d) frame->getFrameCapture(%d)",
request->getKey(),
request->getNumOfOutputBuffer(),
request->getCompleteBufferCount(),
request->getFrameCount());
CLOGV("streamBuffer info: stream (%p), handle(%p)",
streamBuffer->stream, streamBuffer->buffer);
return ret;
}
status_t ExynosCamera::m_sendZslStreamResult(ExynosCameraRequestSP_sprt_t request, ExynosCameraBuffer *buffer)
{
status_t ret = NO_ERROR;
ExynosCameraStream *stream = NULL;
camera3_stream_buffer_t *streamBuffer = NULL;
ResultRequest resultRequest = NULL;
camera3_capture_result_t *requestResult = NULL;
List<int> *outputStreamList = NULL;
/* 1. Get stream object for ZSL */
/* Refer to the ZSL stream ID requested by the service request */
request->getAllRequestOutputStreams(&outputStreamList);
for (List<int>::iterator iter = outputStreamList->begin(); iter != outputStreamList->end(); iter++) {
if ((*iter % HAL_STREAM_ID_MAX) == HAL_STREAM_ID_ZSL_OUTPUT) {
CLOGV("[R%d F%d] request ZSL Stream ID %d",
request->getKey(), request->getFrameCount(), *iter);
ret = m_streamManager->getStream(*iter, &stream);
if (ret < 0) {
CLOGE("getStream is failed, from streammanager. Id error:HAL_STREAM_ID_ZSL");
return ret;
}
break;
}
}
if (stream == NULL) {
CLOGE("can not find the ZSL stream ID in the current request");
return NAME_NOT_FOUND;
}
resultRequest = m_requestMgr->createResultRequest(request->getKey(), request->getFrameCount(),
EXYNOS_REQUEST_RESULT::CALLBACK_BUFFER_ONLY);
if (resultRequest == NULL) {
CLOGE("[R%d F%d] createResultRequest fail. streamId HAL_STREAM_ID_ZSL",
request->getKey(), request->getFrameCount());
ret = INVALID_OPERATION;
return ret;
}
requestResult = resultRequest->getCaptureResult();
if (requestResult == NULL) {
CLOGE("[R%d F%d] getCaptureResult fail. streamId HAL_STREAM_ID_ZSL",
request->getKey(), request->getFrameCount());
ret = INVALID_OPERATION;
return ret;
}
streamBuffer = resultRequest->getStreamBuffer();
if (streamBuffer == NULL) {
CLOGE("[R%d F%d] getStreamBuffer fail. streamId HAL_STREAM_ID_ZSL",
request->getKey(), request->getFrameCount());
ret = INVALID_OPERATION;
return ret;
}
/* 2. Get camera3_stream structure from stream object */
ret = stream->getStream(&(streamBuffer->stream));
if (ret < 0) {
CLOGE("getStream is failed, from exynoscamerastream. Id error:HAL_STREAM_ID_ZSL");
return ret;
}
/* 3. Get zsl buffer */
streamBuffer->buffer = buffer->handle[0];
/* 4. Update the remained buffer info */
ret = m_checkStreamBufferStatus(request, stream, &streamBuffer->status);
if (ret != NO_ERROR) {
CLOGE("[R%d F%d S%d]Failed to checkStreamBufferStatus.",
request->getKey(), request->getFrameCount(),
HAL_STREAM_ID_ZSL_OUTPUT);
return ret;
}
streamBuffer->acquire_fence = -1;
streamBuffer->release_fence = -1;
/* construct result for service */
requestResult->frame_number = request->getKey();
requestResult->result = NULL;
requestResult->num_output_buffers = 1;
requestResult->output_buffers = streamBuffer;
requestResult->input_buffer = request->getInputBuffer();
requestResult->partial_result = 0;
CLOGV("frame number(%d), #out(%d)",
requestResult->frame_number, requestResult->num_output_buffers);
/* 6. Request to callback the result to request manager */
m_requestMgr->pushResultRequest(resultRequest);
ret = m_bufferSupplier->putBuffer(*buffer);
if (ret != NO_ERROR) {
CLOGE("[R%d F%d B%d]Failed to putBuffer. ret %d",
request->getKey(), request->getFrameCount(), buffer->index, ret);
}
CLOGV("request->frame_number(%d), request->getNumOfOutputBuffer(%d)"
"request->getCompleteBufferCount(%d) frame->getFrameCapture(%d)",
request->getKey(), request->getNumOfOutputBuffer(),
request->getCompleteBufferCount(), request->getFrameCount());
CLOGV("streamBuffer info: stream (%p), handle(%p)",
streamBuffer->stream, streamBuffer->buffer);
return ret;
}
status_t ExynosCamera::m_sendMeta(ExynosCameraRequestSP_sprt_t request, EXYNOS_REQUEST_RESULT::TYPE type)
{
ResultRequest resultRequest = NULL;
uint32_t frameNumber = 0;
camera3_capture_result_t *requestResult = NULL;
status_t ret = OK;
resultRequest = m_requestMgr->createResultRequest(request->getKey(), request->getFrameCount(), type);
if (resultRequest == NULL) {
CLOGE("[R%d F%d] createResultRequest fail. ALL_META",
request->getKey(), request->getFrameCount());
ret = INVALID_OPERATION;
return ret;
}
requestResult = resultRequest->getCaptureResult();
if (requestResult == NULL) {
CLOGE("[R%d F%d] getCaptureResult fail. ALL_META",
request->getKey(), request->getFrameCount());
ret = INVALID_OPERATION;
return ret;
}
frameNumber = request->getKey();
request->setRequestLock();
request->updatePipelineDepth();
request->setRequestUnlock();
/* CameraMetadata will be released by RequestManager
* to keep the order of request
*/
requestResult->frame_number = frameNumber;
requestResult->result = NULL;
requestResult->num_output_buffers = 0;
requestResult->output_buffers = NULL;
requestResult->input_buffer = NULL;
requestResult->partial_result = 2;
CLOGV("framecount %d request %d", request->getFrameCount(), request->getKey());
m_requestMgr->pushResultRequest(resultRequest);
return ret;
}
status_t ExynosCamera::m_sendNotifyShutter(ExynosCameraRequestSP_sprt_t request, uint64_t timeStamp)
{
camera3_notify_msg_t *notify = NULL;
ResultRequest resultRequest = NULL;
uint32_t requestKey = 0;
requestKey = request->getKey();
if (timeStamp <= 0) {
timeStamp = request->getSensorTimestamp();
}
resultRequest = m_requestMgr->createResultRequest(request->getKey(), request->getFrameCount(), EXYNOS_REQUEST_RESULT::CALLBACK_NOTIFY_ONLY);
if (resultRequest == NULL) {
CLOGE("[R%d F%d] createResultRequest fail. Notify Callback",
request->getKey(), request->getFrameCount());
return INVALID_OPERATION;
}
notify = resultRequest->getNotifyMsg();
if (notify == NULL) {
CLOGE("[R%d F%d] getNotifyResult fail. Notify Callback",
request->getKey(), request->getFrameCount());
return INVALID_OPERATION;
}
CLOGV("[R%d] SHUTTER frame t(%ju)", requestKey, timeStamp);
notify->type = CAMERA3_MSG_SHUTTER;
notify->message.shutter.frame_number = requestKey;
notify->message.shutter.timestamp = timeStamp;
m_requestMgr->pushResultRequest(resultRequest);
return OK;
}
status_t ExynosCamera::m_sendNotifyError(ExynosCameraRequestSP_sprt_t request,
EXYNOS_REQUEST_RESULT::ERROR resultError,
camera3_stream_t *stream)
{
ResultRequest resultRequest = NULL;
camera3_notify_msg_t *notify = NULL;
ExynosCameraStream *streamInfo = NULL;
EXYNOS_REQUEST_RESULT::TYPE cbType = EXYNOS_REQUEST_RESULT::CALLBACK_NOTIFY_ERROR;
int streamId = 0;
uint32_t requestKey = 0;
if (request->getRequestState() == EXYNOS_REQUEST::STATE_ERROR) {
CLOGV("[F%d] already send notify Error by ERROR_REQUEST", request->getFrameCount());
return OK;
}
resultRequest = m_requestMgr->createResultRequest(request->getKey(), request->getFrameCount(), cbType);
if (resultRequest == NULL) {
CLOGE("[R%d F%d] createResultRequest fail. Notify Callback",
request->getKey(), request->getFrameCount());
return INVALID_OPERATION;
}
requestKey = request->getKey();
notify = resultRequest->getNotifyMsg();
if (notify == NULL) {
CLOGE("[R%d F%d] getNotifyResult fail. Notify Callback",
requestKey, request->getFrameCount());
return INVALID_OPERATION;
}
notify->type = CAMERA3_MSG_ERROR;
notify->message.error.frame_number = requestKey;
switch (resultError) {
case EXYNOS_REQUEST_RESULT::ERROR_REQUEST:
CLOGE("[R%d F%d] REQUEST ERROR", requestKey, request->getFrameCount());
notify->message.error.error_code = CAMERA3_MSG_ERROR_REQUEST;
/* The error state of the request is set only if the error message is ERROR_REQUEST. */
request->setRequestState(EXYNOS_REQUEST::STATE_ERROR);
break;
case EXYNOS_REQUEST_RESULT::ERROR_RESULT:
CLOGE("[R%d F%d] RESULT ERROR", requestKey, request->getFrameCount());
notify->message.error.error_code = CAMERA3_MSG_ERROR_RESULT;
break;
case EXYNOS_REQUEST_RESULT::ERROR_BUFFER:
if (stream == NULL) {
CLOGE("[R%d F%d] BUFFER ERROR. But stream value is NULL", requestKey, request->getFrameCount());
} else {
streamInfo = static_cast<ExynosCameraStream*>(stream->priv);
streamInfo->getID(&streamId);
CLOGE("[R%d F%d S%d] BUFFER ERROR",
requestKey, request->getFrameCount(), streamId);
}
notify->message.error.error_code = CAMERA3_MSG_ERROR_BUFFER;
notify->message.error.error_stream = stream;
break;
case EXYNOS_REQUEST_RESULT::ERROR_UNKNOWN:
CLOGE("[R%d F%d] UNKNOWN ERROR", requestKey, request->getFrameCount());
return INVALID_OPERATION;
}
m_requestMgr->pushResultRequest(resultRequest);
return OK;
}
status_t ExynosCamera::m_searchFrameFromList(List<ExynosCameraFrameSP_sptr_t> *list, Mutex *listLock, uint32_t frameCount, ExynosCameraFrameSP_dptr_t frame)
{
ExynosCameraFrameSP_sptr_t curFrame = NULL;
List<ExynosCameraFrameSP_sptr_t>::iterator r;
Mutex::Autolock l(listLock);
if (list->empty()) {
CLOGD("list is empty");
return NO_ERROR;
}
r = list->begin()++;
do {
curFrame = *r;
if (curFrame == NULL) {
CLOGE("curFrame is empty");
return INVALID_OPERATION;
}
if (frameCount == curFrame->getFrameCount()) {
CLOGV("frame count match: expected(%d)", frameCount);
frame = curFrame;
return NO_ERROR;
}
r++;
} while (r != list->end());
CLOGV("Cannot find match frame, frameCount(%d)", frameCount);
return OK;
}
status_t ExynosCamera::m_removeFrameFromList(List<ExynosCameraFrameSP_sptr_t> *list, Mutex *listLock, ExynosCameraFrameSP_sptr_t frame)
{
ExynosCameraFrameSP_sptr_t curFrame = NULL;
uint32_t frameUniqueKey = 0;
uint32_t curFrameUniqueKey = 0;
int frameCount = 0;
int curFrameCount = 0;
List<ExynosCameraFrameSP_sptr_t>::iterator r;
if (frame == NULL) {
CLOGE("frame is NULL");
return BAD_VALUE;
}
Mutex::Autolock l(listLock);
if (list->empty()) {
CLOGE("list is empty");
return INVALID_OPERATION;
} else if (list->size() > MAX_BUFFERS) {
CLOGW("There are too many frames(%zu) in this list. frame(F%d, T%d)",
list->size(), frame->getFrameCount(), frame->getFrameType());
}
frameCount = frame->getFrameCount();
frameUniqueKey = frame->getUniqueKey();
r = list->begin()++;
do {
curFrame = *r;
if (curFrame == NULL) {
CLOGE("curFrame is empty");
return INVALID_OPERATION;
}
curFrameCount = curFrame->getFrameCount();
curFrameUniqueKey = curFrame->getUniqueKey();
if (frameCount == curFrameCount
&& frameUniqueKey == curFrameUniqueKey) {
CLOGV("frame count match: expected(%d, %u), current(%d, %u)",
frameCount, frameUniqueKey, curFrameCount, curFrameUniqueKey);
list->erase(r);
return NO_ERROR;
}
if (frameCount != curFrameCount
&& frameUniqueKey != curFrameUniqueKey) {
#ifndef USE_DUAL_CAMERA // HACK: Remove!
CLOGW("frame count mismatch: expected(%d, %u), current(%d, %u)",
frameCount, frameUniqueKey, curFrameCount, curFrameUniqueKey);
/* curFrame->printEntity(); */
curFrame->printNotDoneEntity();
#endif
}
r++;
} while (r != list->end());
#ifdef USE_DUAL_CAMERA // HACK: Remove!
return NO_ERROR;
#else
CLOGE("[F%d U%d]Cannot find match frame!!!", frameCount, frameUniqueKey);
return INVALID_OPERATION;
#endif
}
uint32_t ExynosCamera::m_getSizeFromFrameList(List<ExynosCameraFrameSP_sptr_t> *list, Mutex *listLock)
{
uint32_t count = 0;
Mutex::Autolock l(listLock);
count = list->size();
return count;
}
status_t ExynosCamera::m_clearList(List<ExynosCameraFrameSP_sptr_t> *list, Mutex *listLock)
{
ExynosCameraFrameSP_sptr_t curFrame = NULL;
List<ExynosCameraFrameSP_sptr_t>::iterator r;
CLOGD("remaining frame(%zu), we remove them all", list->size());
Mutex::Autolock l(listLock);
while (!list->empty()) {
r = list->begin()++;
curFrame = *r;
if (curFrame != NULL) {
CLOGV("remove frame count(%d)", curFrame->getFrameCount());
curFrame = NULL;
}
list->erase(r);
}
return OK;
}
status_t ExynosCamera::m_removeInternalFrames(List<ExynosCameraFrameSP_sptr_t> *list, Mutex *listLock)
{
ExynosCameraFrameSP_sptr_t curFrame = NULL;
List<ExynosCameraFrameSP_sptr_t>::iterator r;
CLOGD("remaining frame(%zu), we remove internal frames",
list->size());
Mutex::Autolock l(listLock);
while (!list->empty()) {
r = list->begin()++;
curFrame = *r;
if (curFrame != NULL) {
if (curFrame->getFrameType() == FRAME_TYPE_INTERNAL
#ifdef USE_DUAL_CAMERA
|| curFrame->getFrameType() == FRAME_TYPE_INTERNAL_SLAVE
#endif
) {
CLOGV("remove internal frame(%d)",
curFrame->getFrameCount());
m_releaseInternalFrame(curFrame);
} else {
CLOGW("frame(%d) is NOT internal frame and will be remained in List",
curFrame->getFrameCount());
}
}
list->erase(r);
curFrame = NULL;
}
return OK;
}
status_t ExynosCamera::m_releaseInternalFrame(ExynosCameraFrameSP_sptr_t frame)
{
status_t ret = NO_ERROR;
ExynosCameraBuffer buffer;
ExynosCameraFrameFactory *factory = m_frameFactory[FRAME_FACTORY_TYPE_CAPTURE_PREVIEW];
if (frame == NULL) {
CLOGE("frame is NULL");
return BAD_VALUE;
}
if (frame->getFrameType() != FRAME_TYPE_INTERNAL
#ifdef USE_DUAL_CAMERA
&& frame->getFrameType() != FRAME_TYPE_INTERNAL_SLAVE
#endif
) {
CLOGE("frame(%d) is NOT internal frame",
frame->getFrameCount());
return BAD_VALUE;
}
/* Return bayer buffer */
if (frame->getRequest(PIPE_VC0) == true) {
int pipeId = m_getBayerPipeId();
int dstPos = factory->getNodeType(PIPE_VC0);
ret = frame->getDstBuffer(pipeId, &buffer, dstPos);
if (ret != NO_ERROR) {
CLOGE("getDstBuffer(pipeId(%d), dstPos(%d)) fail", pipeId, dstPos);
} else if (buffer.index >= 0) {
ret = m_bufferSupplier->putBuffer(buffer);
if (ret != NO_ERROR) {
CLOGE("[F%d B%d]Failed to putBuffer for VC0. ret %d",
frame->getFrameCount(), buffer.index, ret);
}
}
}
/* Return 3AS buffer */
ret = frame->getSrcBuffer(PIPE_3AA, &buffer);
if (ret != NO_ERROR) {
CLOGE("getSrcBuffer failed. PIPE_3AA, ret(%d)", ret);
} else if (buffer.index >= 0) {
ret = m_bufferSupplier->putBuffer(buffer);
if (ret != NO_ERROR) {
CLOGE("[F%d B%d]Failed to putBuffer for 3AS. ret %d",
frame->getFrameCount(), buffer.index, ret);
}
}
/* Return 3AP buffer */
if (frame->getRequest(PIPE_3AP) == true) {
ret = frame->getDstBuffer(PIPE_3AA, &buffer);
if (ret != NO_ERROR) {
CLOGE("getDstBuffer failed. PIPE_3AA, ret %d",
ret);
} else if (buffer.index >= 0) {
ret = m_bufferSupplier->putBuffer(buffer);
if (ret != NO_ERROR) {
CLOGE("[F%d B%d]Failed to putBuffer for 3AP. ret %d",
frame->getFrameCount(), buffer.index, ret);
}
}
}
frame = NULL;
return ret;
}
uint32_t ExynosCamera::m_getSizeFromRequestList(List<ExynosCameraRequestSP_sprt_t> *list, Mutex *listLock)
{
uint32_t count = 0;
Mutex::Autolock l(listLock);
count = list->size();
return count;
}
status_t ExynosCamera::m_clearRequestList(List<ExynosCameraRequestSP_sprt_t> *list, Mutex *listLock)
{
ExynosCameraRequestSP_sprt_t curRequest = NULL;
List<ExynosCameraRequestSP_sprt_t>::iterator r;
CLOGD("remaining request(%zu), we remove them all", list->size());
Mutex::Autolock l(listLock);
while (!list->empty()) {
r = list->begin()++;
curRequest = *r;
if (curRequest != NULL) {
CLOGV("remove request key(%d), fcount(%d)", curRequest->getKey(), curRequest->getFrameCount());
curRequest = NULL;
}
list->erase(r);
}
return OK;
}
status_t ExynosCamera::m_checkStreamBufferStatus(ExynosCameraRequestSP_sprt_t request, ExynosCameraStream *stream,
int *status, bool bufferSkip)
{
status_t ret = NO_ERROR;
int streamId = 0;
camera3_stream_t *serviceStream = NULL;
if (stream == NULL) {
CLOGE("stream is NULL");
return BAD_VALUE;
}
stream->getID(&streamId);
if (request->getRequestState() == EXYNOS_REQUEST::STATE_ERROR) {
/* If the request state is error, the buffer status is always error. */
request->setStreamBufferStatus(streamId, CAMERA3_BUFFER_STATUS_ERROR);
} else {
if (request->getStreamBufferStatus(streamId) == CAMERA3_BUFFER_STATUS_ERROR) {
/* Temp code */
if (m_configurations->getSamsungCamera() != true) {
ret = stream->getStream(&serviceStream);
if (ret != NO_ERROR) {
CLOGE("Failed to getStream from ExynosCameraStream. streamId(%d)", streamId);
return ret;
}
ret = m_sendNotifyError(request, EXYNOS_REQUEST_RESULT::ERROR_BUFFER, serviceStream);
if (ret != NO_ERROR) {
CLOGE("[F%d R%d S%d] sendNotifyError fail. ret %d",
request->getFrameCount(), request->getKey(), streamId, ret);
return ret;
}
}
} else {
if (bufferSkip == true) {
/* The state of the buffer is normal,
* but if you want to skip the buffer, set the buffer status to ERROR.
* NotifyError is not given. */
request->setStreamBufferStatus(streamId, CAMERA3_BUFFER_STATUS_ERROR);
}
}
}
*status = request->getStreamBufferStatus(streamId);
CLOGV("[R%d F%d S%d] buffer status(%d)",
request->getKey(), request->getFrameCount(), streamId, *status);
return ret;
}
void ExynosCamera::m_checkUpdateResult(ExynosCameraFrameSP_sptr_t frame, uint32_t streamConfigBit)
{
enum FRAME_TYPE frameType;
bool previewFlag = false;
bool captureFlag= false;
bool zslInputFlag = false;
uint32_t targetBit = 0;
frameType = (enum FRAME_TYPE) frame->getFrameType();
switch (frameType) {
case FRAME_TYPE_PREVIEW:
#ifdef USE_DUAL_CAMERA
case FRAME_TYPE_PREVIEW_SLAVE:
case FRAME_TYPE_PREVIEW_DUAL_MASTER:
case FRAME_TYPE_PREVIEW_DUAL_SLAVE:
#endif
SET_STREAM_CONFIG_BIT(targetBit, HAL_STREAM_ID_PREVIEW);
SET_STREAM_CONFIG_BIT(targetBit, HAL_STREAM_ID_VIDEO);
SET_STREAM_CONFIG_BIT(targetBit, HAL_STREAM_ID_CALLBACK);
SET_STREAM_CONFIG_BIT(targetBit, HAL_STREAM_ID_PREVIEW_VIDEO);
SET_STREAM_CONFIG_BIT(targetBit, HAL_STREAM_ID_ZSL_OUTPUT);
SET_STREAM_CONFIG_BIT(targetBit, HAL_STREAM_ID_DEPTHMAP);
previewFlag = (COMPARE_STREAM_CONFIG_BIT(streamConfigBit, targetBit) > 0) ? true : false;
if (previewFlag == true) {
frame->setStatusForResultUpdate(ExynosCameraFrame::RESULT_UPDATE_TYPE_PARTIAL,
ExynosCameraFrame::RESULT_UPDATE_STATUS_REQUIRED);
frame->setStatusForResultUpdate(ExynosCameraFrame::RESULT_UPDATE_TYPE_BUFFER,
ExynosCameraFrame::RESULT_UPDATE_STATUS_REQUIRED);
}
targetBit = 0;
SET_STREAM_CONFIG_BIT(targetBit, HAL_STREAM_ID_RAW);
SET_STREAM_CONFIG_BIT(targetBit, HAL_STREAM_ID_ZSL_INPUT);
SET_STREAM_CONFIG_BIT(targetBit, HAL_STREAM_ID_JPEG);
SET_STREAM_CONFIG_BIT(targetBit, HAL_STREAM_ID_CALLBACK_STALL);
SET_STREAM_CONFIG_BIT(targetBit, HAL_STREAM_ID_DEPTHMAP_STALL);
SET_STREAM_CONFIG_BIT(targetBit, HAL_STREAM_ID_THUMBNAIL_CALLBACK);
captureFlag = (COMPARE_STREAM_CONFIG_BIT(streamConfigBit, targetBit) > 0) ? true : false;
if (captureFlag == false) {
frame->setStatusForResultUpdate(ExynosCameraFrame::RESULT_UPDATE_TYPE_ALL,
ExynosCameraFrame::RESULT_UPDATE_STATUS_REQUIRED);
}
break;
case FRAME_TYPE_REPROCESSING:
case FRAME_TYPE_JPEG_REPROCESSING:
#ifdef USE_DUAL_CAMERA
case FRAME_TYPE_REPROCESSING_SLAVE:
case FRAME_TYPE_REPROCESSING_DUAL_MASTER:
case FRAME_TYPE_REPROCESSING_DUAL_SLAVE:
#endif
targetBit = 0;
SET_STREAM_CONFIG_BIT(targetBit, HAL_STREAM_ID_RAW);
SET_STREAM_CONFIG_BIT(targetBit, HAL_STREAM_ID_ZSL_INPUT);
SET_STREAM_CONFIG_BIT(targetBit, HAL_STREAM_ID_JPEG);
SET_STREAM_CONFIG_BIT(targetBit, HAL_STREAM_ID_CALLBACK_STALL);
SET_STREAM_CONFIG_BIT(targetBit, HAL_STREAM_ID_DEPTHMAP_STALL);
SET_STREAM_CONFIG_BIT(targetBit, HAL_STREAM_ID_THUMBNAIL_CALLBACK);
zslInputFlag = (COMPARE_STREAM_CONFIG_BIT(streamConfigBit, SET_BIT(HAL_STREAM_ID_ZSL_INPUT)) > 0) ? true : false;
captureFlag = (COMPARE_STREAM_CONFIG_BIT(streamConfigBit, targetBit) > 0) ? true : false;
/*
* Partial update will be done by internal frame or preview frame
* However, if the ZSL input is present, the meta value will not be known in the preview stream.
* So partial update will be performed after the capture stream is finished.
*/
if (zslInputFlag == true) {
frame->setStatusForResultUpdate(ExynosCameraFrame::RESULT_UPDATE_TYPE_PARTIAL,
ExynosCameraFrame::RESULT_UPDATE_STATUS_REQUIRED);
}
if (captureFlag == true) {
frame->setStatusForResultUpdate(ExynosCameraFrame::RESULT_UPDATE_TYPE_BUFFER,
ExynosCameraFrame::RESULT_UPDATE_STATUS_REQUIRED);
frame->setStatusForResultUpdate(ExynosCameraFrame::RESULT_UPDATE_TYPE_ALL,
ExynosCameraFrame::RESULT_UPDATE_STATUS_REQUIRED);
}
break;
case FRAME_TYPE_VISION:
targetBit = 0;
SET_STREAM_CONFIG_BIT(targetBit, HAL_STREAM_ID_VISION);
previewFlag = (COMPARE_STREAM_CONFIG_BIT(streamConfigBit, targetBit) > 0) ? true : false;
if (previewFlag == true) {
frame->setStatusForResultUpdate(ExynosCameraFrame::RESULT_UPDATE_TYPE_PARTIAL,
ExynosCameraFrame::RESULT_UPDATE_STATUS_REQUIRED);
frame->setStatusForResultUpdate(ExynosCameraFrame::RESULT_UPDATE_TYPE_BUFFER,
ExynosCameraFrame::RESULT_UPDATE_STATUS_REQUIRED);
frame->setStatusForResultUpdate(ExynosCameraFrame::RESULT_UPDATE_TYPE_ALL,
ExynosCameraFrame::RESULT_UPDATE_STATUS_REQUIRED);
}
break;
default:
CLOGE("[F%d]Unsupported frame type %d", frame->getFrameCount(), frameType);
break;
}
CLOGV("[F%d T%d]flags %d/%d streamConfig %x",
frame->getFrameCount(),
frame->getFrameType(),
previewFlag, captureFlag,
streamConfigBit);
return;
}
status_t ExynosCamera::m_setFrameManager()
{
sp<FrameWorker> worker;
m_frameMgr = new ExynosCameraFrameManager("FRAME MANAGER", m_cameraId, FRAMEMGR_OPER::SLIENT);
worker = new CreateWorker("CREATE FRAME WORKER", m_cameraId, FRAMEMGR_OPER::SLIENT, 300, 200);
m_frameMgr->setWorker(FRAMEMGR_WORKER::CREATE, worker);
worker = new RunWorker("RUNNING FRAME WORKER", m_cameraId, FRAMEMGR_OPER::SLIENT, 100, 300);
m_frameMgr->setWorker(FRAMEMGR_WORKER::RUNNING, worker);
sp<KeyBox> key = new KeyBox("FRAME KEYBOX", m_cameraId);
m_frameMgr->setKeybox(key);
return NO_ERROR;
}
bool ExynosCamera::m_frameFactoryCreateThreadFunc(void)
{
CLOGI("");
ExynosCameraAutoTimer autoTimer(__FUNCTION__);
bool loop = false;
status_t ret = NO_ERROR;
ExynosCameraFrameFactory *framefactory = NULL;
m_framefactoryCreateResult = NO_ERROR;
ret = m_frameFactoryQ->waitAndPopProcessQ(&framefactory);
if (ret < 0) {
CLOGE("wait and pop fail, ret(%d)", ret);
goto func_exit;
}
if (framefactory == NULL) {
CLOGE("framefactory is NULL");
goto func_exit;
}
if (framefactory->isCreated() == false) {
CLOGD("framefactory create");
TIME_LOGGER_UPDATE(m_cameraId, 0, 0, CUMULATIVE_CNT, FACTORY_CREATE_START, 0);
ret = framefactory->create();
TIME_LOGGER_UPDATE(m_cameraId, 0, 0, CUMULATIVE_CNT, FACTORY_CREATE_END, 0);
if (ret != NO_ERROR) {
CLOGD("failed to create framefactory (%d)", ret);
m_framefactoryCreateResult = NO_INIT;
return false;
}
} else {
CLOGD("framefactory already create");
}
func_exit:
if (0 < m_frameFactoryQ->getSizeOfProcessQ()) {
loop = true;
}
return loop;
}
status_t ExynosCamera::m_startFrameFactory(ExynosCameraFrameFactory *factory)
{
status_t ret = OK;
if (factory == NULL) {
CLOGE("frameFactory is NULL");
return BAD_VALUE;
}
/* prepare pipes */
ret = factory->preparePipes();
if (ret != NO_ERROR) {
CLOGW("Failed to prepare FLITE");
}
/* stream on pipes */
ret = factory->startPipes();
if (ret != NO_ERROR) {
CLOGE("startPipe fail");
return ret;
}
/* start all thread */
ret = factory->startInitialThreads();
if (ret != NO_ERROR) {
CLOGE("startInitialThreads fail");
return ret;
}
return ret;
}
status_t ExynosCamera::m_stopFrameFactory(ExynosCameraFrameFactory *factory)
{
int ret = 0;
CLOGD("");
if (factory != NULL && factory->isRunning() == true) {
ret = factory->stopPipes();
if (ret < 0) {
CLOGE("stopPipe fail");
return ret;
}
}
return ret;
}
status_t ExynosCamera::m_deinitFrameFactory()
{
CLOGI("-IN-");
ExynosCameraAutoTimer autoTimer(__FUNCTION__);
status_t ret = NO_ERROR;
ExynosCameraFrameFactory *frameFactory = NULL;
for (int i = 0; i < FRAME_FACTORY_TYPE_MAX; i++) {
if (m_frameFactory[i] != NULL) {
frameFactory = m_frameFactory[i];
for (int k = i + 1; k < FRAME_FACTORY_TYPE_MAX; k++) {
if (frameFactory == m_frameFactory[k]) {
CLOGD("m_frameFactory index(%d) and index(%d) are same instance, "
"set index(%d) = NULL", i, k, k);
m_frameFactory[k] = NULL;
}
}
if (m_frameFactory[i]->isCreated() == true) {
TIME_LOGGER_UPDATE(m_cameraId, i, 0, CUMULATIVE_CNT, FACTORY_DESTROY_START, 0);
ret = m_frameFactory[i]->destroy();
TIME_LOGGER_UPDATE(m_cameraId, i, 0, CUMULATIVE_CNT, FACTORY_DESTROY_END, 0);
if (ret < 0)
CLOGE("m_frameFactory[%d] destroy fail", i);
SAFE_DELETE(m_frameFactory[i]);
CLOGD("m_frameFactory[%d] destroyed", i);
}
}
}
CLOGI("-OUT-");
return ret;
}
status_t ExynosCamera::m_setupPipeline(ExynosCameraFrameFactory *factory)
{
status_t ret = NO_ERROR;
if (factory == NULL) {
CLOGE("Frame factory is NULL!!");
return BAD_VALUE;
}
int pipeId = MAX_PIPE_NUM;
int nodePipeId = MAX_PIPE_NUM;
int32_t cameraId = factory->getCameraId();
int32_t reprocessingBayerMode = m_parameters[cameraId]->getReprocessingBayerMode();
bool flagFlite3aaM2M = (m_parameters[cameraId]->getHwConnectionMode(PIPE_FLITE, PIPE_3AA) == HW_CONNECTION_MODE_M2M);
bool flag3aaIspM2M = (m_parameters[cameraId]->getHwConnectionMode(PIPE_3AA, PIPE_ISP) == HW_CONNECTION_MODE_M2M);
bool flagIspMcscM2M = (m_parameters[cameraId]->getHwConnectionMode(PIPE_ISP, PIPE_MCSC) == HW_CONNECTION_MODE_M2M);
bool flag3aaVraM2M = (m_parameters[cameraId]->getHwConnectionMode(PIPE_3AA, PIPE_VRA) == HW_CONNECTION_MODE_M2M);
bool flagMcscVraM2M = (m_parameters[cameraId]->getHwConnectionMode(PIPE_MCSC, PIPE_VRA) == HW_CONNECTION_MODE_M2M);
#ifdef USE_DUAL_CAMERA
bool isDualMode = m_configurations->getMode(CONFIGURATION_DUAL_MODE);
enum DUAL_PREVIEW_MODE dualPreviewMode = m_configurations->getDualPreviewMode();
#endif
int flipHorizontal = 0;
enum NODE_TYPE nodeType;
if (flag3aaVraM2M)
flagMcscVraM2M = false;
m_setSetfile();
/* Setting default Bayer DMA-out request flag */
switch (reprocessingBayerMode) {
case REPROCESSING_BAYER_MODE_NONE : /* Not using reprocessing */
CLOGD("Use REPROCESSING_BAYER_MODE_NONE");
factory->setRequest(PIPE_VC0, false);
factory->setRequest(PIPE_3AC, false);
break;
case REPROCESSING_BAYER_MODE_PURE_ALWAYS_ON :
CLOGD("Use REPROCESSING_BAYER_MODE_PURE_ALWAYS_ON");
factory->setRequest(PIPE_VC0, true);
factory->setRequest(PIPE_3AC, false);
break;
case REPROCESSING_BAYER_MODE_DIRTY_ALWAYS_ON :
CLOGD("Use REPROCESSING_BAYER_MODE_DIRTY_ALWAYS_ON");
factory->setRequest(PIPE_VC0, false);
factory->setRequest(PIPE_3AC, true);
break;
case REPROCESSING_BAYER_MODE_PURE_DYNAMIC :
CLOGD("Use REPROCESSING_BAYER_MODE_PURE_DYNAMIC");
factory->setRequest(PIPE_VC0, false);
factory->setRequest(PIPE_3AC, false);
break;
case REPROCESSING_BAYER_MODE_DIRTY_DYNAMIC :
CLOGD("Use REPROCESSING_BAYER_MODE_DIRTY_DYNAMIC");
factory->setRequest(PIPE_VC0, false);
factory->setRequest(PIPE_3AC, false);
break;
default :
CLOGE("Unknown dynamic bayer mode");
factory->setRequest(PIPE_3AC, false);
break;
}
if (flagFlite3aaM2M == true) {
factory->setRequest(PIPE_VC0, true);
}
if (flagMcscVraM2M == true) {
factory->setRequest(PIPE_MCSC5, true);
}
if (flag3aaVraM2M)
factory->setRequest(PIPE_3AF, true);
/* Setting bufferSupplier based on H/W pipeline */
if (flagFlite3aaM2M == true) {
pipeId = PIPE_FLITE;
ret = factory->setBufferSupplierToPipe(m_bufferSupplier, pipeId);
if (ret != NO_ERROR) {
CLOGE("Failed to setBufferSupplierToPipe into pipeId %d", pipeId);
return ret;
}
/* Setting OutputFrameQ/FrameDoneQ to Pipe */
factory->setOutputFrameQToPipe(m_pipeFrameDoneQ[pipeId], pipeId);
}
pipeId = PIPE_3AA;
if (flag3aaIspM2M == true) {
ret = factory->setBufferSupplierToPipe(m_bufferSupplier, pipeId);
if (ret != NO_ERROR) {
CLOGE("Failed to setBufferSupplierToPipe into pipeId %d", pipeId);
return ret;
}
/* Setting OutputFrameQ/FrameDoneQ to Pipe */
factory->setOutputFrameQToPipe(m_pipeFrameDoneQ[pipeId], pipeId);
if (m_configurations->getMode(CONFIGURATION_GMV_MODE) == true) {
pipeId = PIPE_GMV;
factory->setOutputFrameQToPipe(m_pipeFrameDoneQ[pipeId], pipeId);
}
pipeId = PIPE_ISP;
}
if (flagIspMcscM2M == true) {
ret = factory->setBufferSupplierToPipe(m_bufferSupplier, pipeId);
if (ret != NO_ERROR) {
CLOGE("Failed to setBufferSupplierToPipe into pipeId %d", pipeId);
return ret;
}
/* Setting OutputFrameQ/FrameDoneQ to Pipe */
factory->setOutputFrameQToPipe(m_pipeFrameDoneQ[pipeId], pipeId);
pipeId = PIPE_MCSC;
}
ret = factory->setBufferSupplierToPipe(m_bufferSupplier, pipeId);
if (ret != NO_ERROR) {
CLOGE("Failed to setBufferSupplierToPipe into pipeId %d ", pipeId);
return ret;
}
/* Setting OutputFrameQ/FrameDoneQ to Pipe */
factory->setOutputFrameQToPipe(m_pipeFrameDoneQ[pipeId], pipeId);
if (cameraId == m_cameraId) {
flipHorizontal = m_configurations->getModeValue(CONFIGURATION_FLIP_HORIZONTAL);
nodeType = factory->getNodeType(PIPE_MCSC0);
factory->setControl(V4L2_CID_HFLIP, 0, pipeId, nodeType);
nodeType = factory->getNodeType(PIPE_MCSC1);
factory->setControl(V4L2_CID_HFLIP, 0, pipeId, nodeType);
nodeType = factory->getNodeType(PIPE_MCSC2);
factory->setControl(V4L2_CID_HFLIP, 0, pipeId, nodeType);
#ifdef SAMSUNG_SW_VDIS
if (m_configurations->getMode(CONFIGURATION_SWVDIS_MODE) == true) {
nodePipeId = m_streamManager->getOutputPortId(HAL_STREAM_ID_PREVIEW);
} else
#endif
#ifdef SAMSUNG_VIDEO_BEAUTY
if (m_configurations->getMode(CONFIGURATION_VIDEO_BEAUTY_MODE) == true && m_flagVideoStreamPriority == true) {
nodePipeId = m_streamManager->getOutputPortId(HAL_STREAM_ID_PREVIEW);
} else
#endif
#ifdef SAMSUNG_HIFI_VIDEO
if (m_configurations->getMode(CONFIGURATION_HIFIVIDEO_MODE) == true && m_flagVideoStreamPriority == true) {
nodePipeId = m_streamManager->getOutputPortId(HAL_STREAM_ID_PREVIEW);
} else
#endif
{
nodePipeId = m_streamManager->getOutputPortId(HAL_STREAM_ID_VIDEO);
}
if (nodePipeId != -1) {
nodePipeId = nodePipeId + PIPE_MCSC0;
nodeType = factory->getNodeType(nodePipeId);
ret = factory->setControl(V4L2_CID_HFLIP, flipHorizontal, pipeId, nodeType);
if (ret < 0)
CLOGE("V4L2_CID_HFLIP fail, ret(%d)", ret);
CLOGD("set FlipHorizontal, flipHorizontal(%d) Recording pipeId(%d)",
flipHorizontal, nodePipeId);
}
}
if (flagMcscVraM2M || flag3aaVraM2M) {
pipeId = PIPE_VRA;
ret = factory->setBufferSupplierToPipe(m_bufferSupplier, pipeId);
if (ret != NO_ERROR) {
CLOGE("Failed to setBufferSupplierToPipe into pipeId %d", pipeId);
return ret;
}
/* Setting OutputFrameQ/FrameDoneQ to Pipe */
factory->setOutputFrameQToPipe(m_pipeFrameDoneQ[pipeId], pipeId);
#ifdef SUPPORT_HFD
if (m_parameters[m_cameraId]->getHfdMode() == true) {
pipeId = PIPE_HFD;
factory->setOutputFrameQToPipe(m_pipeFrameDoneQ[pipeId], pipeId);
}
#endif
}
#ifdef USE_DUAL_CAMERA
if (cameraId == m_cameraId && isDualMode == true) {
pipeId = PIPE_SYNC;
ret = factory->setBufferSupplierToPipe(m_bufferSupplier, pipeId);
if (ret != NO_ERROR) {
CLOGE("Failed to setBufferSupplierToPipe into pipeId %d", pipeId);
return ret;
}
/* Setting OutputFrameQ/FrameDoneQ to Pipe */
factory->setOutputFrameQToPipe(m_pipeFrameDoneQ[pipeId], pipeId);
if (dualPreviewMode == DUAL_PREVIEW_MODE_SW) {
pipeId = PIPE_FUSION;
ret = factory->setBufferSupplierToPipe(m_bufferSupplier, pipeId);
if (ret != NO_ERROR) {
CLOGE("Failed to setBufferSupplierToPipe into pipeId %d", pipeId);
return ret;
}
/* Setting OutputFrameQ/FrameDoneQ to Pipe */
factory->setOutputFrameQToPipe(m_pipeFrameDoneQ[pipeId], pipeId);
}
}
#endif
#ifdef SUPPORT_HW_GDC
pipeId = PIPE_GDC;
factory->setOutputFrameQToPipe(m_pipeFrameDoneQ[pipeId], pipeId);
#endif
return ret;
}
status_t ExynosCamera::m_updateLatestInfoToShot(struct camera2_shot_ext *shot_ext, frame_type_t frameType)
{
status_t ret = NO_ERROR;
bool isReprocessing = false;
if (shot_ext == NULL) {
CLOGE("shot_ext is NULL");
return BAD_VALUE;
}
switch (frameType) {
case FRAME_TYPE_VISION:
isReprocessing = false;
break;
case FRAME_TYPE_PREVIEW:
case FRAME_TYPE_PREVIEW_FRONT:
case FRAME_TYPE_INTERNAL:
#ifdef USE_DUAL_CAMERA
case FRAME_TYPE_PREVIEW_SLAVE:
case FRAME_TYPE_PREVIEW_DUAL_MASTER:
case FRAME_TYPE_PREVIEW_DUAL_SLAVE:
case FRAME_TYPE_INTERNAL_SLAVE:
case FRAME_TYPE_TRANSITION:
case FRAME_TYPE_TRANSITION_SLAVE:
#endif
isReprocessing = false;
#ifdef SAMSUNG_TN_FEATURE
m_updateTemperatureInfo(shot_ext);
#endif
m_updateSetfile(shot_ext, isReprocessing);
#ifdef SAMSUNG_RTHDR
m_updateWdrMode(shot_ext, isReprocessing);
#endif
break;
case FRAME_TYPE_REPROCESSING:
#ifdef USE_DUAL_CAMERA
case FRAME_TYPE_REPROCESSING_SLAVE:
case FRAME_TYPE_REPROCESSING_DUAL_MASTER:
case FRAME_TYPE_REPROCESSING_DUAL_SLAVE:
#endif
isReprocessing = true;
m_updateJpegControlInfo(shot_ext);
m_updateSetfile(shot_ext, isReprocessing);
#ifdef SAMSUNG_RTHDR
m_updateWdrMode(shot_ext, isReprocessing);
#endif
break;
default:
CLOGE("Invalid frame type(%d)", frameType);
break;
}
/* This section is common function */
m_updateCropRegion(shot_ext);
m_updateMasterCam(shot_ext);
m_updateEdgeNoiseMode(shot_ext, isReprocessing);
return ret;
}
void ExynosCamera::m_updateCropRegion(struct camera2_shot_ext *shot_ext)
{
int sensorMaxW = 0, sensorMaxH = 0;
int cropRegionMinW = 0, cropRegionMinH = 0;
int maxZoom = 0;
float activeZoomRatio = 1.0f;
ExynosRect targetActiveZoomRect = {0, };
#if defined(USE_DUAL_CAMERA)
int newCropRegion[4] = {0, };
bool isDualMode = m_configurations->getMode(CONFIGURATION_DUAL_MODE);
#ifdef SAMSUNG_DUAL_ZOOM_PREVIEW
ExynosRect subActiveZoomRect = {0, };
float zoomRatio = 1.0f;
float prevZoomRatio = 1.0f;
int mainSolutionMargin = 0, subSolutionMargin = 0;
#if defined(SAMSUNG_HIFI_VIDEO) && defined(HIFIVIDEO_ZOOM_SUPPORTED)
int cropMinWidth = 0, cropMinHeight = 0;
int cropWidth = 0, cropHeight = 0;
int cropWideWidth = 0, cropWideHeight = 0;
int cropTeleWidth = 0, cropTeleHeight = 0;
#endif
#endif /* SAMSUNGDUAL_SOLUTION */
#endif /* USE_DUAL_CAMERA */
m_parameters[m_cameraId]->getSize(HW_INFO_MAX_SENSOR_SIZE, (uint32_t *)&sensorMaxW, (uint32_t *)&sensorMaxH);
shot_ext->shot.ctl.scaler.cropRegion[0] = ALIGN_DOWN(shot_ext->shot.ctl.scaler.cropRegion[0], 2);
shot_ext->shot.ctl.scaler.cropRegion[1] = ALIGN_DOWN(shot_ext->shot.ctl.scaler.cropRegion[1], 2);
shot_ext->shot.ctl.scaler.cropRegion[2] = ALIGN_UP(shot_ext->shot.ctl.scaler.cropRegion[2], 2);
shot_ext->shot.ctl.scaler.cropRegion[3] = ALIGN_UP(shot_ext->shot.ctl.scaler.cropRegion[3], 2);
targetActiveZoomRect.x = shot_ext->shot.ctl.scaler.cropRegion[0];
targetActiveZoomRect.y = shot_ext->shot.ctl.scaler.cropRegion[1];
targetActiveZoomRect.w = shot_ext->shot.ctl.scaler.cropRegion[2];
targetActiveZoomRect.h = shot_ext->shot.ctl.scaler.cropRegion[3];
#if defined(USE_DUAL_CAMERA) && defined(SAMSUNG_DUAL_ZOOM_PREVIEW)
if (isDualMode == true && m_scenario == SCENARIO_DUAL_REAR_ZOOM) {
m_updateCropRegion_vendor(shot_ext, sensorMaxW, sensorMaxH, targetActiveZoomRect, subActiveZoomRect, subSolutionMargin);
} else
#endif
#if defined(SAMSUNG_HIFI_VIDEO) && defined(HIFIVIDEO_ZOOM_SUPPORTED)
if (m_configurations->getMode(CONFIGURATION_HIFIVIDEO_MODE) == true) {
float orgZoomRatio = 0.0f;
float hifiVideoZoomRatio = 0.0f;
int hifiVideoMargin = 0;
int hifiVideoCropRegion[4] = {0};
orgZoomRatio = m_configurations->getZoomRatio();
m_parameters[m_cameraId]->getHiFiVideoZoomRatio(orgZoomRatio, &hifiVideoZoomRatio, &hifiVideoMargin);
if (orgZoomRatio != hifiVideoZoomRatio) {
CLOGV("[HIFIVIDEO] zoomRatio (%f -> %f), margin(%d)", orgZoomRatio, hifiVideoZoomRatio, hifiVideoMargin);
hifiVideoCropRegion[2] = ALIGN_UP((int)ceil((float)sensorMaxW / hifiVideoZoomRatio), 2);
hifiVideoCropRegion[3] = ALIGN_UP((int)ceil((float)sensorMaxH / hifiVideoZoomRatio), 2);
hifiVideoCropRegion[0] = ALIGN_DOWN((sensorMaxW - hifiVideoCropRegion[2]) / 2, 2);
hifiVideoCropRegion[1] = ALIGN_DOWN((sensorMaxH - hifiVideoCropRegion[3]) / 2, 2);
CLOGV("[HIFIVIDEO] Change CropRegion.(%d, %d, %d, %d -> %d, %d, %d, %d)",
shot_ext->shot.ctl.scaler.cropRegion[0],
shot_ext->shot.ctl.scaler.cropRegion[1],
shot_ext->shot.ctl.scaler.cropRegion[2],
shot_ext->shot.ctl.scaler.cropRegion[3],
hifiVideoCropRegion[0],
hifiVideoCropRegion[1],
hifiVideoCropRegion[2],
hifiVideoCropRegion[3]
);
targetActiveZoomRect.x = hifiVideoCropRegion[0];
targetActiveZoomRect.y = hifiVideoCropRegion[1];
targetActiveZoomRect.w = hifiVideoCropRegion[2];
targetActiveZoomRect.h = hifiVideoCropRegion[3];
}
m_parameters[m_cameraId]->setActiveZoomMargin(hifiVideoMargin);
} else
#endif
{
m_parameters[m_cameraId]->setActiveZoomMargin(0);
}
/* Check the validation of the crop size(width x height).
The width and height of the crop region cannot be set to be smaller than
floor( activeArraySize.width / android.scaler.availableMaxDigitalZoom )
and floor( activeArraySize.height / android.scaler.availableMaxDigitalZoom )
*/
maxZoom = (int) (m_parameters[m_cameraId]->getMaxZoomRatio() / 1000);
cropRegionMinW = (int)ceil((float)sensorMaxW / maxZoom);
cropRegionMinH = (int)ceil((float)sensorMaxH / maxZoom);
cropRegionMinW = ALIGN_UP(cropRegionMinW, 2);
cropRegionMinH = ALIGN_UP(cropRegionMinH, 2);
if (cropRegionMinW > (int) targetActiveZoomRect.w
|| cropRegionMinH > (int) targetActiveZoomRect.h){
CLOGE("Invalid Crop Size(%d, %d),Change to cropRegionMin(%d, %d)",
targetActiveZoomRect.w,
targetActiveZoomRect.h,
cropRegionMinW, cropRegionMinH);
targetActiveZoomRect.w = cropRegionMinW;
targetActiveZoomRect.h = cropRegionMinH;
}
/* 1. Check the validation of the crop size(width x height).
* The crop size must be smaller than sensor max size.
*/
if (sensorMaxW < (int) targetActiveZoomRect.w
|| sensorMaxH < (int)targetActiveZoomRect.h) {
CLOGE("Invalid Crop Size(%d, %d), sensorMax(%d, %d)",
targetActiveZoomRect.w,
targetActiveZoomRect.h,
sensorMaxW, sensorMaxH);
targetActiveZoomRect.w = sensorMaxW;
targetActiveZoomRect.h = sensorMaxH;
}
/* 2. Check the validation of the crop offset.
* Offset coordinate + width or height must be smaller than sensor max size.
*/
if (sensorMaxW < (int) targetActiveZoomRect.x
+ (int) targetActiveZoomRect.w) {
CLOGE("Invalid Crop Region, offsetX(%d), width(%d) sensorMaxW(%d)",
targetActiveZoomRect.x,
targetActiveZoomRect.w,
sensorMaxW);
targetActiveZoomRect.x = sensorMaxW - targetActiveZoomRect.w;
}
if (sensorMaxH < (int) targetActiveZoomRect.y
+ (int) targetActiveZoomRect.h) {
CLOGE("Invalid Crop Region, offsetY(%d), height(%d) sensorMaxH(%d)",
targetActiveZoomRect.y,
targetActiveZoomRect.h,
sensorMaxH);
targetActiveZoomRect.y = sensorMaxH - targetActiveZoomRect.h;
}
m_parameters[m_cameraId]->setCropRegion(targetActiveZoomRect.x,
targetActiveZoomRect.y,
targetActiveZoomRect.w,
targetActiveZoomRect.h);
/* set main active zoom rect */
m_parameters[m_cameraId]->setActiveZoomRect(targetActiveZoomRect);
/* set main active zoom ratio */
activeZoomRatio = (float)(sensorMaxW) / (float)(targetActiveZoomRect.w);
m_parameters[m_cameraId]->setActiveZoomRatio(activeZoomRatio);
#ifdef USE_DUAL_CAMERA
if (isDualMode == true) {
ExynosRect slaveRect;
m_parameters[m_cameraIds[1]]->getSize(HW_INFO_MAX_SENSOR_SIZE, (uint32_t *)&sensorMaxW, (uint32_t *)&sensorMaxH);
if (m_scenario == SCENARIO_DUAL_REAR_ZOOM) {
#ifdef SAMSUNG_DUAL_ZOOM_PREVIEW
if (m_configurations->getDynamicMode(DYNAMIC_DUAL_FORCE_SWITCHING) == false) {
if (subActiveZoomRect.x < 0 || subActiveZoomRect.y < 0
|| subActiveZoomRect.w > sensorMaxW||subActiveZoomRect.h > sensorMaxH) {
CLOGE("Invalid sub zoom rect(%d,%d,%d,%d",
subActiveZoomRect.x, subActiveZoomRect.y,
subActiveZoomRect.w, subActiveZoomRect.h);
/* set Default Zoom Rect */
m_parameters[m_cameraIds[1]]->setActiveZoomMargin(0);
newCropRegion[2] = targetActiveZoomRect.w * DUAL_CAMERA_TELE_RATIO;
newCropRegion[3] = targetActiveZoomRect.h * DUAL_CAMERA_TELE_RATIO;
newCropRegion[0] = (sensorMaxW - ALIGN_UP(newCropRegion[2], 2)) / 2;
newCropRegion[1] = (sensorMaxH - ALIGN_UP(newCropRegion[3], 2)) / 2;
} else {
m_parameters[m_cameraIds[1]]->setActiveZoomMargin(subSolutionMargin);
newCropRegion[0] = subActiveZoomRect.x;
newCropRegion[1] = subActiveZoomRect.y;
newCropRegion[2] = subActiveZoomRect.w;
newCropRegion[3] = subActiveZoomRect.h;
}
} else {
m_parameters[m_cameraIds[1]]->setActiveZoomMargin(0);
newCropRegion[2] = targetActiveZoomRect.w * DUAL_CAMERA_TELE_RATIO;
newCropRegion[3] = targetActiveZoomRect.h * DUAL_CAMERA_TELE_RATIO;
newCropRegion[0] = (sensorMaxW - ALIGN_UP(newCropRegion[2], 2)) / 2;
newCropRegion[1] = (sensorMaxH - ALIGN_UP(newCropRegion[3], 2)) / 2;
}
#else
m_parameters[m_cameraIds[1]]->setActiveZoomMargin(0);
newCropRegion[2] = targetActiveZoomRect.w * DUAL_CAMERA_TELE_RATIO;
newCropRegion[3] = targetActiveZoomRect.h * DUAL_CAMERA_TELE_RATIO;
newCropRegion[0] = (sensorMaxW - ALIGN_UP(newCropRegion[2], 2)) / 2;
newCropRegion[1] = (sensorMaxH - ALIGN_UP(newCropRegion[3], 2)) / 2;
#endif
} else if (m_scenario == SCENARIO_DUAL_REAR_PORTRAIT) {
m_parameters[m_cameraIds[1]]->setActiveZoomMargin(0);
newCropRegion[0] = targetActiveZoomRect.x;
newCropRegion[1] = targetActiveZoomRect.y;
newCropRegion[2] = targetActiveZoomRect.w;
newCropRegion[3] = targetActiveZoomRect.h;
}
slaveRect.x = ALIGN_DOWN(newCropRegion[0], 2);
slaveRect.y = ALIGN_DOWN(newCropRegion[1], 2);
slaveRect.w = ALIGN_UP(newCropRegion[2], 2);
slaveRect.h = ALIGN_UP(newCropRegion[3], 2);
#if defined(SAMSUNG_HIFI_VIDEO) && defined(HIFIVIDEO_ZOOM_SUPPORTED)
// Temp for DualPreview Solution
if (m_configurations->getMode(CONFIGURATION_HIFIVIDEO_MODE) == true && zoomRatio != 1.0f) {
m_parameters[m_cameraIds[1]]->getDualSolutionSize(&cropWidth, &cropHeight,
&cropWideWidth, &cropWideHeight,
&cropTeleWidth, &cropTeleHeight,
subSolutionMargin);
CLOGV("[HIFIVIDEO] sensorMax (%dx%d), crop (%dx%d), cropWide (%dx%d), cropTele (%dx%d), subSolutionMargin %d",
sensorMaxW,
sensorMaxH,
cropWidth,
cropHeight,
cropWideWidth,
cropWideHeight,
cropTeleWidth,
cropTeleHeight,
subSolutionMargin);
CLOGV("[HIFIVIDEO] Org newCropRegion x %d, y %d, w %d, h %d",
newCropRegion[0],
newCropRegion[1],
newCropRegion[2],
newCropRegion[3]);
if (mainSolutionMargin == DUAL_SOLUTION_MARGIN_VALUE_30 ||
mainSolutionMargin == DUAL_SOLUTION_MARGIN_VALUE_20) {
cropMinWidth = cropTeleWidth;
cropMinHeight = cropTeleHeight;
} else {
cropMinWidth = cropWidth;
cropMinHeight = cropHeight;
}
if (newCropRegion[2] < cropMinWidth) {
slaveRect.w = cropMinWidth;
slaveRect.x = ALIGN_DOWN((sensorMaxW - cropMinWidth) / 2, 2);
}
if (newCropRegion[3] < cropMinHeight) {
slaveRect.h = cropMinHeight;
slaveRect.y = ALIGN_DOWN((sensorMaxH - cropMinHeight) / 2, 2);
}
CLOGV("[HIFIVIDEO] New slaveRect x %d, y %d, w %d, h %d",
slaveRect.x,
slaveRect.y,
slaveRect.w,
slaveRect.h);
}
#endif
/* 1. Check the validation of the crop size(width x height).
* The crop size must be smaller than sensor max size.
*/
if (sensorMaxW < slaveRect.w
|| sensorMaxH < slaveRect.h) {
slaveRect.w = sensorMaxW;
slaveRect.h = sensorMaxH;
}
/* 2. Check the validation of the crop offset.
* Offset coordinate + width or height must be smaller than sensor max size.
*/
if (sensorMaxW < slaveRect.x + slaveRect.w) {
slaveRect.x = ALIGN_DOWN((sensorMaxW - slaveRect.w) / 2, 2);
}
if (sensorMaxH < slaveRect.y + slaveRect.h) {
slaveRect.y = ALIGN_DOWN((sensorMaxH - slaveRect.h) / 2, 2);
}
m_parameters[m_cameraIds[1]]->setCropRegion(
slaveRect.x, slaveRect.y, slaveRect.w, slaveRect.h);
/* set sub active zoom rect */
m_parameters[m_cameraIds[1]]->setActiveZoomRect(slaveRect);
/* set main active zoom ratio */
activeZoomRatio = (float)(sensorMaxW) / (float)(slaveRect.w);
m_parameters[m_cameraIds[1]]->setActiveZoomRatio(activeZoomRatio);
}
#endif
}
void ExynosCamera::m_updateFD(struct camera2_shot_ext *shot_ext, enum facedetect_mode fdMode,
int dsInputPortId, bool isReprocessing, bool isEarlyFd)
{
if (fdMode <= FACEDETECT_MODE_OFF
#ifdef USE_ALWAYS_FD_ON
&& m_configurations->getMode(CONFIGURATION_ALWAYS_FD_ON_MODE) == false
#endif
) {
shot_ext->fd_bypass = 1;
shot_ext->shot.ctl.stats.faceDetectMode = FACEDETECT_MODE_OFF;
shot_ext->shot.uctl.scalerUd.mcsc_sub_blk_port[INTERFACE_TYPE_DS] = MCSC_PORT_NONE;
} else {
if (isReprocessing == true) {
shot_ext->shot.ctl.stats.faceDetectMode = FACEDETECT_MODE_OFF;
shot_ext->shot.uctl.scalerUd.mcsc_sub_blk_port[INTERFACE_TYPE_DS] = MCSC_PORT_NONE;
if (isEarlyFd) {
// TODO: need to check it.
shot_ext->fd_bypass = 1;
} else if (dsInputPortId < MCSC_PORT_MAX) {
shot_ext->fd_bypass = 1;
} else {
#ifdef CAPTURE_FD_SYNC_WITH_PREVIEW
shot_ext->fd_bypass = 1;
shot_ext->shot.uctl.scalerUd.mcsc_sub_blk_port[INTERFACE_TYPE_DS] = MCSC_PORT_NONE;
#else
shot_ext->fd_bypass = 0;
shot_ext->shot.uctl.scalerUd.mcsc_sub_blk_port[INTERFACE_TYPE_DS] = (enum mcsc_port) (dsInputPortId % MCSC_PORT_MAX);
#endif
shot_ext->shot.ctl.stats.faceDetectMode = fdMode;
}
} else {
shot_ext->shot.ctl.stats.faceDetectMode = FACEDETECT_MODE_OFF;
shot_ext->shot.uctl.scalerUd.mcsc_sub_blk_port[INTERFACE_TYPE_DS] = MCSC_PORT_NONE;
if (m_configurations->getMode(CONFIGURATION_PIP_MODE) == true && getCameraId() == CAMERA_ID_BACK) {
shot_ext->fd_bypass = 1;
} else {
if (isEarlyFd) {
shot_ext->fd_bypass = 0;
shot_ext->shot.ctl.stats.faceDetectMode = fdMode;
} else if (dsInputPortId < MCSC_PORT_MAX) {
shot_ext->fd_bypass = 0;
shot_ext->shot.ctl.stats.faceDetectMode = fdMode;
shot_ext->shot.uctl.scalerUd.mcsc_sub_blk_port[INTERFACE_TYPE_DS] = (enum mcsc_port) dsInputPortId ;
} else {
shot_ext->fd_bypass = 1;
}
}
}
}
}
void ExynosCamera::m_updateEdgeNoiseMode(struct camera2_shot_ext *shot_ext, bool isCaptureFrame)
{
enum processing_mode mode = PROCESSING_MODE_FAST;
if (shot_ext == NULL) {
CLOGE("shot_ext is NULL");
return;
}
if (isCaptureFrame == true) {
mode = PROCESSING_MODE_OFF;
} else {
mode = PROCESSING_MODE_FAST;
}
if (shot_ext->shot.ctl.noise.mode
== (enum processing_mode) FIMC_IS_METADATA(ANDROID_NOISE_REDUCTION_MODE_ZERO_SHUTTER_LAG)) {
shot_ext->shot.ctl.noise.mode = mode;
}
if (shot_ext->shot.ctl.edge.mode
== (enum processing_mode) FIMC_IS_METADATA(ANDROID_EDGE_MODE_ZERO_SHUTTER_LAG)) {
shot_ext->shot.ctl.edge.mode = mode;
}
}
status_t ExynosCamera::m_updateJpegControlInfo(const struct camera2_shot_ext *shot_ext)
{
status_t ret = NO_ERROR;
if (shot_ext == NULL) {
CLOGE("shot_ext is NULL");
return BAD_VALUE;
}
ret = m_configurations->setModeValue(CONFIGURATION_JPEG_QUALITY, shot_ext->shot.ctl.jpeg.quality);
if (ret != NO_ERROR) {
CLOGE("Failed to setJpegQuality. quality %d",
shot_ext->shot.ctl.jpeg.quality);
}
ret = m_parameters[m_cameraId]->checkThumbnailSize(
shot_ext->shot.ctl.jpeg.thumbnailSize[0],
shot_ext->shot.ctl.jpeg.thumbnailSize[1]);
if (ret != NO_ERROR) {
CLOGE("Failed to checkThumbnailSize. size %dx%d",
shot_ext->shot.ctl.jpeg.thumbnailSize[0],
shot_ext->shot.ctl.jpeg.thumbnailSize[1]);
}
#ifdef USE_DUAL_CAMERA
if (m_configurations->getMode(CONFIGURATION_DUAL_MODE) == true) {
ret = m_parameters[m_cameraIds[1]]->checkThumbnailSize(
shot_ext->shot.ctl.jpeg.thumbnailSize[0],
shot_ext->shot.ctl.jpeg.thumbnailSize[1]);
if (ret != NO_ERROR) {
CLOGE("Failed to checkThumbnailSize. size %dx%d",
shot_ext->shot.ctl.jpeg.thumbnailSize[0],
shot_ext->shot.ctl.jpeg.thumbnailSize[1]);
}
}
#endif
ret = m_configurations->setModeValue(CONFIGURATION_THUMBNAIL_QUALITY, shot_ext->shot.ctl.jpeg.thumbnailQuality);
if (ret != NO_ERROR) {
CLOGE("Failed to setThumbnailQuality. quality %d",
shot_ext->shot.ctl.jpeg.thumbnailQuality);
}
return ret;
}
void ExynosCamera::m_updateSetfile(struct camera2_shot_ext *shot_ext, bool isCaptureFrame)
{
int yuvRange = 0;
int setfile = 0;
if (shot_ext == NULL) {
CLOGE("shot_ext is NULL");
return;
}
if (isCaptureFrame == true) {
m_parameters[m_cameraId]->setSetfileYuvRange();
}
m_parameters[m_cameraId]->getSetfileYuvRange(isCaptureFrame, &setfile, &yuvRange);
shot_ext->setfile = setfile;
}
status_t ExynosCamera::m_generateFrame(ExynosCameraFrameFactory *factory, List<ExynosCameraFrameSP_sptr_t> *list,
Mutex *listLock, ExynosCameraFrameSP_dptr_t newFrame,
ExynosCameraRequestSP_sprt_t request)
{
status_t ret = OK;
newFrame = NULL;
uint32_t frameCount = request->getFrameCount();
CLOGV("(%d)", frameCount);
#if 0 /* Use the same frame count in dual camera, lls capture scenario */
ret = m_searchFrameFromList(list, listLock, frameCount, newFrame);
if (ret < 0) {
CLOGE("searchFrameFromList fail");
return INVALID_OPERATION;
}
#endif
if (newFrame == NULL) {
CLOG_PERFORMANCE(FPS, factory->getCameraId(),
factory->getFactoryType(), DURATION,
FRAME_CREATE, 0, request->getKey(), nullptr);
newFrame = factory->createNewFrame(frameCount);
if (newFrame == NULL) {
CLOGE("newFrame is NULL");
return UNKNOWN_ERROR;
}
/* debug */
if (request != nullptr)
newFrame->setRequestKey(request->getKey());
listLock->lock();
list->push_back(newFrame);
listLock->unlock();
}
newFrame->setHasRequest(true);
CLOG_PERFRAME(PATH, m_cameraId, m_name, newFrame.get(), nullptr, newFrame->getRequestKey(), "");
return ret;
}
status_t ExynosCamera::m_generateFrame(ExynosCameraFrameFactory *factory, List<ExynosCameraFrameSP_sptr_t> *list,
Mutex *listLock, ExynosCameraFrameSP_dptr_t newFrame,
ExynosCameraRequestSP_sprt_t request, bool useJpegFlag)
{
status_t ret = OK;
newFrame = NULL;
uint32_t frameCount = request->getFrameCount();
CLOGV("(%d)", frameCount);
#if 0 /* Use the same frame count in dual camera, lls capture scenario */
ret = m_searchFrameFromList(list, listLock, frameCount, newFrame);
if (ret < 0) {
CLOGE("searchFrameFromList fail");
return INVALID_OPERATION;
}
#endif
if (newFrame == NULL) {
CLOG_PERFORMANCE(FPS, factory->getCameraId(),
factory->getFactoryType(), DURATION,
FRAME_CREATE, 0, request->getKey(), nullptr);
newFrame = factory->createNewFrame(frameCount, useJpegFlag);
if (newFrame == NULL) {
CLOGE("newFrame is NULL");
return UNKNOWN_ERROR;
}
/* debug */
if (request != nullptr)
newFrame->setRequestKey(request->getKey());
listLock->lock();
list->push_back(newFrame);
listLock->unlock();
}
newFrame->setHasRequest(true);
CLOG_PERFRAME(PATH, m_cameraId, m_name, newFrame.get(), nullptr, newFrame->getRequestKey(), "");
return ret;
}
status_t ExynosCamera::m_setupEntity(uint32_t pipeId,
ExynosCameraFrameSP_sptr_t newFrame,
ExynosCameraBuffer *srcBuf,
ExynosCameraBuffer *dstBuf,
int dstNodeIndex,
int dstPipeId)
{
status_t ret = OK;
entity_buffer_state_t entityBufferState;
CLOGV("(%d)", pipeId);
/* set SRC buffer */
ret = newFrame->getSrcBufferState(pipeId, &entityBufferState);
if (ret < 0) {
CLOGE("getSrcBufferState fail, pipeId(%d), ret(%d)", pipeId, ret);
return ret;
}
if (entityBufferState == ENTITY_BUFFER_STATE_REQUESTED) {
ret = m_setSrcBuffer(pipeId, newFrame, srcBuf);
if (ret < 0) {
CLOGE("m_setSrcBuffer fail, pipeId(%d), ret(%d)", pipeId, ret);
return ret;
}
}
/* set DST buffer */
ret = newFrame->getDstBufferState(pipeId, &entityBufferState, dstNodeIndex);
if (ret < 0) {
CLOGE("getDstBufferState fail, pipeId(%d), ret(%d)", pipeId, ret);
return ret;
}
if (entityBufferState == ENTITY_BUFFER_STATE_REQUESTED) {
ret = m_setDstBuffer(pipeId, newFrame, dstBuf, dstNodeIndex, dstPipeId);
if (ret < 0) {
CLOGE("m_setDstBuffer fail, pipeId(%d), ret(%d)", pipeId, ret);
return ret;
}
}
ret = newFrame->setEntityState(pipeId, ENTITY_STATE_PROCESSING);
if (ret < 0) {
CLOGE("setEntityState(ENTITY_STATE_PROCESSING) fail, pipeId(%d), ret(%d)",
pipeId, ret);
return ret;
}
return ret;
}
status_t ExynosCamera::m_setSrcBuffer(uint32_t pipeId, ExynosCameraFrameSP_sptr_t newFrame, ExynosCameraBuffer *buffer)
{
status_t ret = OK;
ExynosCameraBuffer srcBuffer;
CLOGV("(%d)", pipeId);
if (buffer == NULL) {
buffer_manager_tag_t bufTag;
bufTag.pipeId[0] = pipeId;
bufTag.managerType = BUFFER_MANAGER_ION_TYPE;
buffer = &srcBuffer;
ret = m_bufferSupplier->getBuffer(bufTag, buffer);
if (ret != NO_ERROR) {
CLOGE("[F%d]Failed to getBuffer. pipeId %d ret %d",
newFrame->getFrameCount(), pipeId, ret);
return ret;
}
}
/* set buffers */
ret = newFrame->setSrcBuffer(pipeId, *buffer);
if (ret < 0) {
CLOGE("[F%d B%d]Failed to setSrcBuffer. pipeId %d ret %d",
newFrame->getFrameCount(), buffer->index, pipeId, ret);
return ret;
}
return ret;
}
status_t ExynosCamera::m_setDstBuffer(uint32_t pipeId,
ExynosCameraFrameSP_sptr_t newFrame,
ExynosCameraBuffer *buffer,
int nodeIndex,
__unused int dstPipeId)
{
status_t ret = OK;
if (buffer == NULL) {
CLOGE("[F%d]Buffer is NULL", newFrame->getFrameCount());
return BAD_VALUE;
}
/* set buffers */
ret = newFrame->setDstBuffer(pipeId, *buffer, nodeIndex);
if (ret < 0) {
CLOGE("[F%d B%d]Failed to setDstBuffer. pipeId %d nodeIndex %d ret %d",
newFrame->getFrameCount(), buffer->index, pipeId, nodeIndex, ret);
return ret;
}
return ret;
}
status_t ExynosCamera::m_setVOTFBuffer(uint32_t pipeId,
ExynosCameraFrameSP_sptr_t newFrame,
uint32_t srcPipeId,
uint32_t dstPipeId)
{
status_t ret = NO_ERROR;
ExynosCameraBuffer buffer;
const buffer_manager_tag_t initBufTag;
buffer_manager_tag_t bufTag;
int srcPos = -1;
int dstPos = -1;
/*
COUTION: getNodeType is common function, So, use preview frame factory.
If, getNodeType is seperated, frame factory must seperate.
*/
ExynosCameraFrameFactory *factory = m_frameFactory[FRAME_FACTORY_TYPE_CAPTURE_PREVIEW];
if (newFrame == NULL) {
CLOGE("New frame is NULL!!");
return BAD_VALUE;
}
/* Get buffer from buffer supplier */
ret = m_checkBufferAvailable(srcPipeId);
if (ret != NO_ERROR) {
CLOGE("Waiting buffer for Pipe(%d) timeout. ret %d", srcPipeId, ret);
return INVALID_OPERATION;
}
bufTag = initBufTag;
bufTag.pipeId[0] = srcPipeId;
bufTag.managerType = BUFFER_MANAGER_ION_TYPE;
buffer.index = -2;
ret = m_bufferSupplier->getBuffer(bufTag, &buffer);
if (ret != NO_ERROR) {
CLOGE("[F%d]Failed to get Buffer(Pipeid:%d). ret %d",
newFrame->getFrameCount(), srcPipeId, ret);
return INVALID_OPERATION;
}
if (buffer.index < 0) {
CLOGE("[F%d]Invalid Buffer index(%d), Pipeid %d. ret %d",
newFrame->getFrameCount(), buffer.index, srcPipeId, ret);
return INVALID_OPERATION;
}
/* Set Buffer to srcPosition in Frame */
if (newFrame->getRequest(srcPipeId) == true) {
srcPos = factory->getNodeType(srcPipeId);
ret = newFrame->setDstBufferState(pipeId, ENTITY_BUFFER_STATE_REQUESTED, srcPos);
if (ret != NO_ERROR) {
CLOGE("Failed to setDstBufferState. pipeId %d(%d) pos %d",
pipeId, srcPipeId, srcPos);
newFrame->setRequest(srcPipeId, false);
} else {
ret = newFrame->setDstBuffer(pipeId, buffer, srcPos);
if (ret != NO_ERROR) {
CLOGE("Failed to setDstBuffer. pipeId %d(%d) pos %d",
pipeId, srcPipeId, srcPos);
newFrame->setRequest(srcPipeId, false);
}
}
}
/* Set Buffer to dstPosition in Frame */
if (newFrame->getRequest(srcPipeId) == true) {
dstPos = factory->getNodeType(dstPipeId);
ret = newFrame->setDstBufferState(pipeId, ENTITY_BUFFER_STATE_REQUESTED, dstPos);
if (ret != NO_ERROR) {
CLOGE("Failed to setDstBufferState. pipeId %d(%d) pos %d",
pipeId, srcPipeId, dstPos);
newFrame->setRequest(srcPipeId, false);
} else {
ret = newFrame->setDstBuffer(pipeId, buffer, dstPos);
if (ret != NO_ERROR) {
CLOGE("Failed to setDstBuffer. pipeId %d(%d) pos %d",
pipeId, srcPipeId, dstPos);
newFrame->setRequest(srcPipeId, false);
}
}
}
/* If setBuffer failed, return buffer */
if (newFrame->getRequest(srcPipeId) == false) {
ret = m_bufferSupplier->putBuffer(buffer);
if (ret != NO_ERROR) {
CLOGE("[F%d]Failed to put Buffer(Pipeid:%d). ret %d",
newFrame->getFrameCount(), srcPipeId, ret);
ret = INVALID_OPERATION;
}
}
return ret;
}
status_t ExynosCamera::m_setHWFCBuffer(uint32_t pipeId,
ExynosCameraFrameSP_sptr_t newFrame,
uint32_t srcPipeId,
uint32_t dstPipeId)
{
/* This function is same logic with m_setVOTFBuffer */
return m_setVOTFBuffer(pipeId, newFrame, srcPipeId, dstPipeId);
}
status_t ExynosCamera::m_createIonAllocator(ExynosCameraIonAllocator **allocator)
{
status_t ret = NO_ERROR;
int retry = 0;
do {
retry++;
CLOGI("try(%d) to create IonAllocator", retry);
*allocator = new ExynosCameraIonAllocator();
ret = (*allocator)->init(false);
if (ret < 0)
CLOGE("create IonAllocator fail (retryCount=%d)", retry);
else {
CLOGD("m_createIonAllocator success (allocator=%p)", *allocator);
break;
}
} while ((ret < 0) && (retry < 3));
if ((ret < 0) && (retry >=3)) {
CLOGE("create IonAllocator fail (retryCount=%d)", retry);
ret = INVALID_OPERATION;
}
return ret;
}
bool ExynosCamera::m_captureThreadFunc()
{
ExynosCameraAutoTimer autoTimer(__FUNCTION__);
status_t ret = NO_ERROR;
ExynosCameraFrameSP_sptr_t frame = NULL;
ExynosCameraRequestSP_sprt_t request = NULL;
ExynosCameraFrameEntity *entity = NULL;
uint32_t pipeId = 0;
int retryCount = 1;
frame_handle_components_t components;
ret = m_captureQ->waitAndPopProcessQ(&frame);
if (ret != NO_ERROR) {
/* TODO: We need to make timeout duration depends on FPS */
if (ret == TIMED_OUT) {
CLOGV("Wait timeout");
} else {
CLOGE("Failed to wait&pop captureQ, ret %d", ret);
/* TODO: doing exception handling */
}
goto CLEAN;
} else if (frame == NULL) {
CLOGE("frame is NULL!!");
goto FUNC_EXIT;
}
entity = frame->getFirstEntityNotComplete();
pipeId = (entity == NULL) ? -1 : entity->getPipeId();
CLOGI("[F%d T%d P%d] frame frameCount",
frame->getFrameCount(), frame->getFrameType(), pipeId);
getFrameHandleComponents((enum FRAME_TYPE)frame->getFrameType(), &components);
m_captureStreamThread->run(PRIORITY_DEFAULT);
if (frame->getStreamRequested(STREAM_TYPE_CAPTURE) == false
#ifdef USE_DUAL_CAMERA
&& frame->getFrameType() != FRAME_TYPE_REPROCESSING_DUAL_SLAVE
#endif
&& frame->getStreamRequested(STREAM_TYPE_RAW) == false) {
ret = frame->setEntityState(pipeId, ENTITY_STATE_FRAME_DONE);
if (ret != NO_ERROR) {
CLOGE("[F%d]Failed to setEntityState(FRAME_DONE). pipeId %d ret %d",
frame->getFrameCount(), pipeId, ret);
/* continue */
}
m_yuvCaptureDoneQ->pushProcessQ(&frame);
} else {
if (components.reprocessingFactory == NULL) {
CLOGE("frame factory is NULL");
goto FUNC_EXIT;
}
while (components.reprocessingFactory->isRunning() == false) {
CLOGD("[F%d]Wait to start reprocessing stream", frame->getFrameCount());
if (m_getState() == EXYNOS_CAMERA_STATE_FLUSH) {
CLOGD("[F%d]Flush is in progress.", frame->getFrameCount());
goto FUNC_EXIT;
}
usleep(5000);
}
#ifdef USE_HW_RAW_REVERSE_PROCESSING
/* To let the 3AA reprocessing pipe twice */
if (components.parameters->isUseRawReverseReprocessing() == true &&
frame->getStreamRequested(STREAM_TYPE_RAW) == true) {
frame->backupRequest();
if (frame->getRequest(PIPE_3AC_REPROCESSING) == true) {
bool twiceRun;
/* Raw Capture will be processed last time */
twiceRun = frame->reverseExceptForSpecificReq(PIPE_3AC_REPROCESSING, false);
if (!twiceRun) {
/* just only one loop for raw */
frame->reverseExceptForSpecificReq(PIPE_3AC_REPROCESSING, true);
/* for raw capture setfile index */
frame->setSetfile(ISS_SUB_SCENARIO_STILL_CAPTURE_DNG_REPROCESSING);
}
CLOGD("[F%d] This frame will be processed %d th time", frame->getFrameCount(), twiceRun ? 2 : 1);
}
}
#endif
#ifdef USE_DUAL_CAMERA
if (m_configurations->getDualReprocessingMode() == DUAL_REPROCESSING_MODE_HW
&& frame->getFrameType() == FRAME_TYPE_REPROCESSING_DUAL_MASTER) {
components.reprocessingFactory->pushFrameToPipe(frame, PIPE_SYNC_REPROCESSING);
} else
#endif
{
components.reprocessingFactory->pushFrameToPipe(frame, pipeId);
}
/* When enabled SCC capture or pureBayerReprocessing, we need to start bayer pipe thread */
if (components.parameters->isReprocessing() == true)
components.reprocessingFactory->startThread(pipeId);
/* Wait reprocesisng done */
do {
ret = m_reprocessingDoneQ->waitAndPopProcessQ(&frame);
} while (ret == TIMED_OUT && retryCount-- > 0);
if (ret != NO_ERROR) {
CLOGW("[F%d]Failed to waitAndPopProcessQ to reprocessingDoneQ. ret %d",
frame->getFrameCount(), ret);
}
CLOGI("[F%d]Wait reprocessing done", frame->getFrameCount());
}
/* Thread can exit only if timeout or error occured from inputQ (at CLEAN: label) */
return true;
CLEAN:
if (frame != NULL && m_getState() != EXYNOS_CAMERA_STATE_FLUSH) {
ret = m_removeFrameFromList(&m_captureProcessList, &m_captureProcessLock, frame);
if (ret != NO_ERROR) {
CLOGE("[F%d]Failed to removeFrameFromList for captureProcessList. ret %d",
frame->getFrameCount(), ret);
}
frame->printEntity();
CLOGD("[F%d]Delete frame from captureProcessList", frame->getFrameCount());
frame = NULL;
}
FUNC_EXIT:
if (m_captureQ->getSizeOfProcessQ() > 0 || m_captureProcessList.size() > 0) {
return true;
} else {
return false;
}
}
status_t ExynosCamera::m_getBayerServiceBuffer(ExynosCameraFrameSP_sptr_t frame,
ExynosCameraBuffer *buffer,
ExynosCameraRequestSP_sprt_t request)
{
status_t ret = NO_ERROR;
ExynosCameraFrameSP_sptr_t bayerFrame = NULL;
int retryCount = 30;
frame_handle_components_t components;
if (frame == NULL) {
CLOGE("frame is NULL");
/* TODO: doing exception handling */
return BAD_VALUE;
}
getFrameHandleComponents((enum FRAME_TYPE)frame->getFrameType(), &components);
ExynosCameraFrameFactory *factory = components.previewFactory;
int dstPos = factory->getNodeType(PIPE_VC0);
int pipeId = -1;
if (components.parameters->getUsePureBayerReprocessing() == true) {
pipeId = PIPE_3AA_REPROCESSING;
} else {
pipeId = PIPE_ISP_REPROCESSING;
}
if (frame->getStreamRequested(STREAM_TYPE_RAW)) {
m_captureZslSelector->setWaitTime(200000000);
bayerFrame = m_captureZslSelector->selectDynamicFrames(1, retryCount);
if (bayerFrame == NULL) {
CLOGE("bayerFrame is NULL");
return INVALID_OPERATION;
}
if (bayerFrame->getMetaDataEnable() == true)
CLOGI("Frame metadata is updated. frameCount %d",
bayerFrame->getFrameCount());
ret = bayerFrame->getDstBuffer(m_getBayerPipeId(), buffer, dstPos);
if (ret != NO_ERROR) {
CLOGE("Failed to getDstBuffer. pipeId %d ret %d",
m_getBayerPipeId(), ret);
return ret;
}
} else {
if (request != NULL) {
camera3_stream_buffer_t *stream_buffer = request->getInputBuffer();
buffer_handle_t *handle = stream_buffer->buffer;
buffer_manager_tag_t bufTag;
CLOGI("[R%d F%d H%p]Getting Bayer from getRunningRequest",
request->getKey(), frame->getFrameCount(), handle);
bufTag.pipeId[0] = pipeId;
bufTag.managerType = BUFFER_MANAGER_SERVICE_GRALLOC_TYPE;
buffer->handle[0] = handle;
buffer->acquireFence[0] = stream_buffer->acquire_fence;
buffer->releaseFence[0] = stream_buffer->release_fence;
ret = m_bufferSupplier->getBuffer(bufTag, buffer);
ret = request->setAcquireFenceDone(handle, (buffer->acquireFence[0] == -1) ? true : false);
if (ret != NO_ERROR) {
CLOGE("[R%d F%d B%d]Failed to setAcquireFenceDone. ret %d",
request->getKey(), frame->getFrameCount(), buffer->index, ret);
return ret;
}
CLOGI("[R%d F%d B%d H%p]Service bayer selected. ret %d",
request->getKey(), frame->getFrameCount(), buffer->index, handle, ret);
} else {
CLOGE("request if NULL(fcount:%d)", frame->getFrameCount());
ret = BAD_VALUE;
}
}
return ret;
}
bool ExynosCamera::m_previewStreamGMVPipeThreadFunc(void)
{
status_t ret = NO_ERROR;
ExynosCameraFrameSP_sptr_t newFrame = NULL;
ret = m_pipeFrameDoneQ[PIPE_GMV]->waitAndPopProcessQ(&newFrame);
if (ret < 0) {
/* TODO: We need to make timeout duration depends on FPS */
if (ret == TIMED_OUT) {
CLOGW("wait timeout");
goto retry_thread_loop;
} else if (ret != NO_ERROR) {
CLOGE("wait and pop fail, ret(%d)", ret);
/* TODO: doing exception handling */
goto retry_thread_loop;
} else if (newFrame == NULL) {
CLOGE("Frame is NULL");
goto retry_thread_loop;
}
}
return m_previewStreamFunc(newFrame, PIPE_GMV);
retry_thread_loop:
if (m_pipeFrameDoneQ[PIPE_GMV]->getSizeOfProcessQ() > 0) {
return true;
} else {
return false;
}
}
bool ExynosCamera::m_previewStreamVRAPipeThreadFunc(void)
{
status_t ret = NO_ERROR;
ExynosCameraFrameSP_sptr_t newFrame = NULL;
ret = m_pipeFrameDoneQ[PIPE_VRA]->waitAndPopProcessQ(&newFrame);
if (ret != NO_ERROR) {
if (ret == TIMED_OUT) {
CLOGW("wait timeout");
} else {
CLOGE("wait and pop fail, ret(%d)", ret);
/* TODO: doing exception handling */
}
goto retry_thread_loop;
} else if (newFrame == NULL) {
CLOGE("Frame is NULL");
goto retry_thread_loop;
}
return m_previewStreamFunc(newFrame, PIPE_VRA);
retry_thread_loop:
if (m_pipeFrameDoneQ[PIPE_VRA]->getSizeOfProcessQ() > 0) {
return true;
} else {
return false;
}
}
#ifdef SUPPORT_HFD
bool ExynosCamera::m_previewStreamHFDPipeThreadFunc(void)
{
status_t ret = NO_ERROR;
ExynosCameraFrameSP_sptr_t newFrame = NULL;
ret = m_pipeFrameDoneQ[PIPE_HFD]->waitAndPopProcessQ(&newFrame);
if (ret != NO_ERROR) {
/* TODO: We need to make timeout duration depends on FPS */
if (ret == TIMED_OUT) {
CLOGW("wait timeout");
} else {
CLOGE("wait and pop fail, ret(%d)", ret);
/* TODO: doing exception handling */
}
goto retry_thread_loop;
} else if (newFrame == NULL) {
CLOGE("Frame is NULL");
goto retry_thread_loop;
}
return m_previewStreamFunc(newFrame, PIPE_HFD);
retry_thread_loop:
if (m_pipeFrameDoneQ[PIPE_HFD]->getSizeOfProcessQ() > 0) {
return true;
} else {
return false;
}
}
#endif
#ifdef USE_DUAL_CAMERA
bool ExynosCamera::m_previewStreamSyncPipeThreadFunc(void)
{
status_t ret = NO_ERROR;
ExynosCameraFrameSP_sptr_t newFrame = NULL;
ret = m_pipeFrameDoneQ[PIPE_SYNC]->waitAndPopProcessQ(&newFrame);
if (ret < 0) {
/* TODO: We need to make timeout duration depends on FPS */
if (ret == TIMED_OUT) {
enum DUAL_OPERATION_MODE dualOperationMode = m_configurations->getDualOperationMode();
if (dualOperationMode == DUAL_OPERATION_MODE_SYNC) {
CLOGW("wait timeout");
}
} else {
CLOGE("wait and pop fail, ret(%d)", ret);
/* TODO: doing exception handling */
}
return true;
}
return m_previewStreamFunc(newFrame, PIPE_SYNC);
}
bool ExynosCamera::m_previewStreamFusionPipeThreadFunc(void)
{
status_t ret = NO_ERROR;
ExynosCameraFrameSP_sptr_t newFrame = NULL;
ret = m_pipeFrameDoneQ[PIPE_FUSION]->waitAndPopProcessQ(&newFrame);
if (ret < 0) {
/* TODO: We need to make timeout duration depends on FPS */
if (ret == TIMED_OUT) {
enum DUAL_OPERATION_MODE dualOperationMode = m_configurations->getDualOperationMode();
if (dualOperationMode == DUAL_OPERATION_MODE_SYNC) {
CLOGW("wait timeout");
}
} else {
CLOGE("wait and pop fail, ret(%d)", ret);
/* TODO: doing exception handling */
}
return true;
}
return m_previewStreamFunc(newFrame, PIPE_FUSION);
}
#endif
status_t ExynosCamera::m_allocBuffers(
const buffer_manager_tag_t tag,
const buffer_manager_configuration_t info)
{
status_t ret = NO_ERROR;
ret = m_bufferSupplier->setInfo(tag, info);
if (ret != NO_ERROR) {
CLOGE("Failed to setInfo. ret %d", ret);
return ret;
}
return m_bufferSupplier->alloc(tag);
}
bool ExynosCamera::m_setBuffersThreadFunc(void)
{
CLOGI("");
ExynosCameraAutoTimer autoTimer(__FUNCTION__);
int ret;
TIME_LOGGER_UPDATE(m_cameraId, 0, 0, CUMULATIVE_CNT, SET_BUFFER_THREAD_START, 0);
if (m_configurations->getMode(CONFIGURATION_VISION_MODE) == false) {
#ifdef ADAPTIVE_RESERVED_MEMORY
ret = m_allocAdaptiveNormalBuffers();
#else
ret = m_setBuffers();
#endif
} else {
ret = m_setVisionBuffers();
}
if (ret < 0) {
CLOGE("m_setBuffers failed");
m_bufferSupplier->deinit();
return false;
}
return false;
}
bool ExynosCamera::m_deinitBufferSupplierThreadFunc(void)
{
TIME_LOGGER_UPDATE(m_cameraId, 0, 0, CUMULATIVE_CNT, BUFFER_SUPPLIER_DEINIT_START, 0);
if (m_bufferSupplier != NULL) {
delete m_bufferSupplier;
m_bufferSupplier = NULL;
}
if (m_ionAllocator != NULL) {
delete m_ionAllocator;
m_ionAllocator = NULL;
}
TIME_LOGGER_UPDATE(m_cameraId, 0, 0, CUMULATIVE_CNT, BUFFER_SUPPLIER_DEINIT_END, 0);
return false;
}
uint32_t ExynosCamera::m_getBayerPipeId(void)
{
uint32_t pipeId = 0;
if (m_parameters[m_cameraId]->getHwConnectionMode(PIPE_FLITE, PIPE_3AA) == HW_CONNECTION_MODE_M2M) {
pipeId = PIPE_FLITE;
} else {
pipeId = PIPE_3AA;
}
return pipeId;
}
status_t ExynosCamera::m_pushServiceRequest(camera3_capture_request *request_in,
ExynosCameraRequestSP_dptr_t req, bool skipRequest)
{
status_t ret = OK;
CLOGV("m_pushServiceRequest frameCnt(%d)", request_in->frame_number);
req = m_requestMgr->registerToServiceList(request_in, skipRequest);
if (req == NULL) {
CLOGE("registerToServiceList failed, FrameNumber = [%d]", request_in->frame_number);
return ret;
}
return NO_ERROR;
}
status_t ExynosCamera::m_popServiceRequest(ExynosCameraRequestSP_dptr_t request)
{
status_t ret = OK;
CLOGV("m_popServiceRequest ");
request = m_requestMgr->eraseFromServiceList();
if (request == NULL) {
CLOGE("createRequest failed ");
ret = INVALID_OPERATION;
}
return ret;
}
status_t ExynosCamera::m_pushRunningRequest(ExynosCameraRequestSP_dptr_t request_in)
{
status_t ret = NO_ERROR;
CLOGV("[R%d F%d] Push Request in runningRequest",
request_in->getKey(), request_in->getFrameCount());
ret = m_requestMgr->registerToRunningList(request_in);
if (ret != NO_ERROR) {
CLOGE("[R%d] registerToRunningList is failed", request_in->getKey());
return ret;
}
return ret;
}
status_t ExynosCamera::m_setFactoryAddr(ExynosCameraRequestSP_dptr_t request)
{
status_t ret = NO_ERROR;
FrameFactoryList factorylist;
FrameFactoryListIterator factorylistIter;
ExynosCameraFrameFactory *factory = NULL;
ExynosCameraFrameFactory *factoryAddr[FRAME_FACTORY_TYPE_MAX] = {NULL, };
factorylist.clear();
request->getFrameFactoryList(&factorylist);
for (factorylistIter = factorylist.begin(); factorylistIter != factorylist.end(); ) {
factory = *factorylistIter;
if (factory->getFactoryType() < FRAME_FACTORY_TYPE_MAX && factoryAddr[factory->getFactoryType()] == NULL) {
factoryAddr[factory->getFactoryType()] = factory;
CLOGV("list Factory(%p) Type(%d)", factory, factory->getFactoryType());
}
factorylistIter++;
}
request->setFactoryAddrList(factoryAddr);
return ret;
}
bool ExynosCamera::m_reprocessingFrameFactoryStartThreadFunc(void)
{
status_t ret = 0;
ExynosCameraFrameFactory *factory = NULL;
ExynosCameraFrameFactory *factoryList[FRAME_FACTORY_TYPE_MAX] = {NULL, };
factoryList[FRAME_FACTORY_TYPE_REPROCESSING] = m_frameFactory[FRAME_FACTORY_TYPE_REPROCESSING];
if (m_parameters[m_cameraId]->getNumOfMcscOutputPorts() < 5)
factoryList[FRAME_FACTORY_TYPE_JPEG_REPROCESSING] = m_frameFactory[FRAME_FACTORY_TYPE_JPEG_REPROCESSING];
for (int i = 0; i < FRAME_FACTORY_TYPE_MAX; i++) {
factory = factoryList[i];
if (factory == NULL)
continue;
if (factory->isCreated() == false) {
CLOGE("Reprocessing FrameFactory is NOT created!");
return false;
} else if (factory->isRunning() == true) {
CLOGW("Reprocessing FrameFactory is already running");
return false;
}
/* Set buffer manager */
ret = m_setupReprocessingPipeline(factory);
if (ret != NO_ERROR) {
CLOGE("Failed to setupReprocessingPipeline. ret %d",
ret);
return false;
}
#ifdef USE_DUAL_CAMERA
if (m_configurations->getMode(CONFIGURATION_DUAL_MODE) == true
&& m_dualFrameFactoryStartThread != NULL) {
/* reprocessing instance must be create after creation of preview instance */
CLOGI("m_dualFrameFactoryStartThread join E");
m_dualFrameFactoryStartThread->join();
CLOGI("m_dualFrameFactoryStartThread join X");
}
#endif
ret = factory->initPipes();
if (ret < 0) {
CLOGE("Failed to initPipes. ret %d",
ret);
return false;
}
ret = m_startReprocessingFrameFactory(factory);
if (ret < 0) {
CLOGE("Failed to startReprocessingFrameFactory");
/* TODO: Need release buffers and error exit */
return false;
}
}
#ifdef USE_DUAL_CAMERA
if (m_configurations->getMode(CONFIGURATION_DUAL_MODE) == true) {
factory = m_frameFactory[FRAME_FACTORY_TYPE_REPROCESSING_DUAL];
if (factory == NULL) {
CLOGE("Can't start FrameFactory!!!! FrameFactory is NULL!!");
return false;
} else if (factory->isCreated() == false) {
CLOGE("Reprocessing FrameFactory is NOT created!");
return false;
} else if (factory->isRunning() == true) {
CLOGW("Reprocessing FrameFactory is already running");
return false;
}
/* Set buffer manager */
ret = m_setupReprocessingPipeline(factory);
if (ret != NO_ERROR) {
CLOGE("Failed to setupReprocessingPipeline. ret %d",
ret);
return false;
}
ret = factory->initPipes();
if (ret < 0) {
CLOGE("Failed to initPipes. ret %d",
ret);
return false;
}
ret = m_startReprocessingFrameFactory(factory);
if (ret < 0) {
CLOGE("Failed to startReprocessingFrameFactory");
/* TODO: Need release buffers and error exit */
return false;
}
}
#endif
return false;
}
status_t ExynosCamera::m_startReprocessingFrameFactory(ExynosCameraFrameFactory *factory)
{
ExynosCameraAutoTimer autoTimer(__FUNCTION__);
status_t ret = 0;
CLOGD("- IN -");
ret = factory->preparePipes();
if (ret < 0) {
CLOGE("m_reprocessingFrameFactory preparePipe fail");
return ret;
}
/* stream on pipes */
ret = factory->startPipes();
if (ret < 0) {
CLOGE("m_reprocessingFrameFactory startPipe fail");
return ret;
}
return NO_ERROR;
}
status_t ExynosCamera::m_stopReprocessingFrameFactory(ExynosCameraFrameFactory *factory)
{
CLOGI("");
status_t ret = 0;
if (factory != NULL && factory->isRunning() == true) {
ret = factory->stopPipes();
if (ret < 0) {
CLOGE("m_reprocessingFrameFactory->stopPipe() fail");
}
}
CLOGD("clear m_captureProcessList(Picture) Frame list");
ret = m_clearList(&m_captureProcessList, &m_captureProcessLock);
if (ret < 0) {
CLOGE("m_clearList fail");
return ret;
}
return NO_ERROR;
}
status_t ExynosCamera::m_checkBufferAvailable(uint32_t pipeId)
{
status_t ret = TIMED_OUT;
buffer_manager_tag_t bufTag;
int retry = 0;
bufTag.pipeId[0] = pipeId;
bufTag.managerType = BUFFER_MANAGER_ION_TYPE;
do {
ret = -1;
retry++;
if (m_bufferSupplier->getNumOfAvailableBuffer(bufTag) > 0) {
ret = OK;
} else {
/* wait available ISP buffer */
usleep(WAITING_TIME);
}
if (retry % 10 == 0)
CLOGW("retry(%d) setupEntity for pipeId(%d)", retry, pipeId);
} while(ret < 0 && retry < (TOTAL_WAITING_TIME/WAITING_TIME));
return ret;
}
bool ExynosCamera::m_checkValidBayerBufferSize(struct camera2_stream *stream, ExynosCameraFrameSP_sptr_t frame, bool flagForceRecovery)
{
status_t ret = NO_ERROR;
ExynosRect bayerRect;
ExynosRect reprocessingInputRect;
struct camera2_node_group nodeGroupInfo;
frame_handle_components_t components;
int perframeIndex = -1;
if (stream == NULL) {
CLOGE("[F%d]stream is NULL", frame->getFrameCount());
return false;
}
if (frame == NULL) {
CLOGE("frame is NULL");
/* TODO: doing exception handling */
return false;
}
getFrameHandleComponents((enum FRAME_TYPE)frame->getFrameType(), &components);
bool usePureBayerReprocessing = components.parameters->getUsePureBayerReprocessing();
if (usePureBayerReprocessing == true) {
CLOGV("[F%d]Skip. Reprocessing mode is PURE bayer", frame->getFrameCount());
return true;
} else {
perframeIndex = PERFRAME_INFO_DIRTY_REPROCESSING_ISP;
}
/* Get per-frame size info from stream.
* Set by driver.
*/
bayerRect.x = stream->output_crop_region[0];
bayerRect.y = stream->output_crop_region[1];
bayerRect.w = stream->output_crop_region[2];
bayerRect.h = stream->output_crop_region[3];
/* Get per-frame size info from frame.
* Set by FrameFactory.
*/
ret = frame->getNodeGroupInfo(&nodeGroupInfo, perframeIndex);
if (ret != NO_ERROR) {
CLOGE("[F%d]Failed to getNodeGroupInfo. perframeIndex %d ret %d",
frame->getFrameCount(), perframeIndex, ret);
return true;
}
reprocessingInputRect.x = nodeGroupInfo.leader.input.cropRegion[0];
reprocessingInputRect.y = nodeGroupInfo.leader.input.cropRegion[1];
reprocessingInputRect.w = nodeGroupInfo.leader.input.cropRegion[2];
reprocessingInputRect.h = nodeGroupInfo.leader.input.cropRegion[3];
/* Compare per-frame size. */
if (bayerRect.w != reprocessingInputRect.w
|| bayerRect.h != reprocessingInputRect.h) {
CLOGW("[F%d(%d)]Bayer size mismatch. Bayer %dx%d Control %dx%d, forceRecovery(%d)",
frame->getFrameCount(),
stream->fcount,
bayerRect.w, bayerRect.h,
reprocessingInputRect.w, reprocessingInputRect.h,
flagForceRecovery);
if (flagForceRecovery) {
/* recovery based on this node's real perframe size */
nodeGroupInfo.leader.input.cropRegion[0] = bayerRect.x;
nodeGroupInfo.leader.input.cropRegion[1] = bayerRect.y;
nodeGroupInfo.leader.input.cropRegion[2] = bayerRect.w;
nodeGroupInfo.leader.input.cropRegion[3] = bayerRect.h;
/* also forcely set the input crop */
for (int i = 0; i < CAPTURE_NODE_MAX; i++) {
if (nodeGroupInfo.capture[i].vid) {
nodeGroupInfo.capture[i].input.cropRegion[0] = 0;
nodeGroupInfo.capture[i].input.cropRegion[1] = 0;
nodeGroupInfo.capture[i].input.cropRegion[2] = bayerRect.w;
nodeGroupInfo.capture[i].input.cropRegion[3] = bayerRect.h;
}
}
ret = frame->storeNodeGroupInfo(&nodeGroupInfo, perframeIndex);
if (ret != NO_ERROR) {
CLOGE("[F%d]Failed to getNodeGroupInfo. perframeIndex %d ret %d",
frame->getFrameCount(), perframeIndex, ret);
}
} else {
return false;
}
}
return true;
}
bool ExynosCamera::m_startPictureBufferThreadFunc(void)
{
CLOGI("");
ExynosCameraAutoTimer autoTimer(__FUNCTION__);
int ret = 0;
if (m_parameters[m_cameraId]->isReprocessing() == true) {
#ifdef ADAPTIVE_RESERVED_MEMORY
ret = m_allocAdaptiveReprocessingBuffers();
#else
ret = m_setReprocessingBuffer();
#endif
if (ret < 0) {
CLOGE("m_setReprocessing Buffer fail");
m_bufferSupplier->deinit();
return false;
}
}
return false;
}
status_t ExynosCamera::m_generateInternalFrame(ExynosCameraFrameFactory *factory, List<ExynosCameraFrameSP_sptr_t> *list,
Mutex *listLock, ExynosCameraFrameSP_dptr_t newFrame, frame_type_t frameType,
ExynosCameraRequestSP_sprt_t request)
{
status_t ret = OK;
newFrame = NULL;
uint32_t frameCount = 0;
bool hasReques = false;
if (request != NULL) {
frameCount = request->getFrameCount();
hasReques = true;
} else {
m_frameCountLock.lock();
frameCount = m_internalFrameCount++;
m_frameCountLock.unlock();
hasReques = false;
}
CLOGV("(%d)", frameCount);
#if 0 /* Use the same frame count in dual camera, lls capture scenario */
ret = m_searchFrameFromList(list, listLock, frameCount, newFrame);
if (ret < 0) {
CLOGE("searchFrameFromList fail");
return INVALID_OPERATION;
}
#endif
if (newFrame == NULL) {
CLOG_PERFORMANCE(FPS, factory->getCameraId(),
factory->getFactoryType(), DURATION,
FRAME_CREATE, 0, request == nullptr ? 0 : request->getKey(), nullptr);
newFrame = factory->createNewFrame(frameCount);
if (newFrame == NULL) {
CLOGE("newFrame is NULL");
return UNKNOWN_ERROR;
}
/* debug */
if (request != nullptr)
newFrame->setRequestKey(request->getKey());
listLock->lock();
list->push_back(newFrame);
listLock->unlock();
}
/* Set frame type into FRAME_TYPE_INTERNAL */
ret = newFrame->setFrameInfo(m_configurations, factory->getParameters(), frameCount, frameType);
if (ret != NO_ERROR) {
CLOGE("Failed to setFrameInfo with INTERNAL. frameCount %d", frameCount);
return ret;
}
newFrame->setHasRequest(hasReques);
CLOG_PERFRAME(PATH, m_cameraId, m_name, newFrame.get(), nullptr, newFrame->getRequestKey(), "");
return ret;
}
#ifdef USE_DUAL_CAMERA
status_t ExynosCamera::m_generateTransitionFrame(ExynosCameraFrameFactory *factory, List<ExynosCameraFrameSP_sptr_t> *list,
Mutex *listLock, ExynosCameraFrameSP_dptr_t newFrame, frame_type_t frameType)
{
status_t ret = NO_ERROR;
newFrame = NULL;
uint32_t frameCount = m_internalFrameCount;
bool hasReques = false;
m_frameCountLock.lock();
frameCount = m_internalFrameCount++;
m_frameCountLock.unlock();
CLOGV("(%d)", frameCount);
#if 0 /* Use the same frame count in dual camera, lls capture scenario */
ret = m_searchFrameFromList(list, listLock, frameCount, newFrame);
if (ret < 0) {
CLOGE("searchFrameFromList fail");
return INVALID_OPERATION;
}
#endif
if (newFrame == NULL) {
CLOG_PERFORMANCE(FPS, factory->getCameraId(),
factory->getFactoryType(), DURATION,
FRAME_CREATE, 0, 0, nullptr);
newFrame = factory->createNewFrame(frameCount);
if (newFrame == NULL) {
CLOGE("newFrame is NULL");
return UNKNOWN_ERROR;
}
listLock->lock();
list->push_back(newFrame);
listLock->unlock();
}
/* Set frame type into FRAME_TYPE_TRANSITION */
ret = newFrame->setFrameInfo(m_configurations, factory->getParameters(), frameCount, frameType);
if (ret != NO_ERROR) {
CLOGE("Failed to setFrameInfo with INTERNAL. frameCount %d", frameCount);
return ret;
}
newFrame->setHasRequest(hasReques);
CLOG_PERFRAME(PATH, m_cameraId, m_name, newFrame.get(), nullptr, newFrame->getRequestKey(), "");
return ret;
}
status_t ExynosCamera::m_checkDualOperationMode(ExynosCameraRequestSP_sprt_t request,
bool isNeedModeChange, bool isReprocessing, bool flagFinishFactoryStart)
{
Mutex::Autolock lock(m_dualOperationModeLock);
status_t ret = NO_ERROR;
flagFinishFactoryStart &= m_flagFinishDualFrameFactoryStartThread;
if (request == NULL) {
CLOGE("request is NULL!!");
return BAD_VALUE;
}
enum DUAL_OPERATION_MODE newOperationMode = DUAL_OPERATION_MODE_NONE;
enum DUAL_OPERATION_MODE oldOperationMode = m_configurations->getDualOperationMode();
enum DUAL_OPERATION_MODE newOperationModeReprocessing = DUAL_OPERATION_MODE_NONE;
enum DUAL_OPERATION_MODE oldOperationModeReprocessing = m_configurations->getDualOperationModeReprocessing();
float zoomRatio = request->getMetaParameters()->m_zoomRatio; /* zoom ratio by current request */
int32_t dualOperationModeLockCount = m_configurations->getDualOperationModeLockCount();
#ifdef DEBUG_IQ_CAPTURE_MODE
int debugCaptureMode = m_configurations->getModeValue(CONFIGURATION_DEBUG_FUSION_CAPTURE_MODE);
#endif
bool needCheckMasterStandby = false;
bool needCheckSlaveStandby = false;
bool isTriggered = false;
#ifdef SAMSUNG_DUAL_ZOOM_PREVIEW
int dispCamType = m_configurations->getModeValue(CONFIGURATION_DUAL_DISP_CAM_TYPE);
int dispFallbackState = m_configurations->getStaticValue(CONFIGURATION_DUAL_DISP_FALLBACK_RESULT);
int targetFallbackState = m_configurations->getStaticValue(CONFIGURATION_DUAL_TARGET_FALLBACK_RESULT);
#endif
int dualOperationFallback = -1;
#ifdef SAMSUNG_DUAL_ZOOM_FALLBACK
dualOperationFallback = m_configurations->getStaticValue(CONFIGURATION_DUAL_OP_MODE_FALLBACK);
#endif
if (isReprocessing) {
if (m_scenario == SCENARIO_DUAL_REAR_ZOOM) {
/* reprocessingDualMode */
if (m_configurations->getDynamicMode(DYNAMIC_DUAL_FORCE_SWITCHING) == true) {
if (zoomRatio >= DUAL_SWITCHING_SYNC_MODE_MAX_ZOOM_RATIO) {
#ifdef SAMSUNG_DUAL_ZOOM_FALLBACK
if (dispCamType == UNI_PLUGIN_CAMERA_TYPE_WIDE) {
newOperationModeReprocessing = DUAL_OPERATION_MODE_MASTER;
} else
#endif
{
newOperationModeReprocessing = DUAL_OPERATION_MODE_SLAVE;
}
} else {
newOperationModeReprocessing = DUAL_OPERATION_MODE_MASTER;
}
} else {
if (zoomRatio < DUAL_CAPTURE_SYNC_MODE_MIN_ZOOM_RATIO) {
newOperationModeReprocessing = DUAL_OPERATION_MODE_MASTER;
} else if (zoomRatio >= DUAL_CAPTURE_SYNC_MODE_MAX_ZOOM_RATIO) {
newOperationModeReprocessing = DUAL_OPERATION_MODE_SLAVE;
} else {
newOperationModeReprocessing = DUAL_OPERATION_MODE_SYNC;
}
m_dualCaptureLockCount = DUAL_CAPTURE_LOCK_COUNT;
#ifdef SAMSUNG_DUAL_ZOOM_PREVIEW
int fallbackState = m_configurations->getStaticValue(CONFIGURATION_DUAL_DISP_FALLBACK_RESULT);
switch (newOperationModeReprocessing) {
case DUAL_OPERATION_MODE_SYNC:
if (oldOperationMode != DUAL_OPERATION_MODE_SYNC
|| (m_configurations->getMode(CONFIGURATION_RECORDING_MODE) == true)
|| m_currentMultiCaptureMode == MULTI_CAPTURE_MODE_BURST
|| m_currentMultiCaptureMode == MULTI_CAPTURE_MODE_AGIF
#ifdef SAMSUNG_TN_FEATURE
|| m_configurations->getModeValue(CONFIGURATION_MULTI_CAPTURE_MODE) == MULTI_CAPTURE_MODE_BURST
|| m_configurations->getModeValue(CONFIGURATION_MULTI_CAPTURE_MODE) == MULTI_CAPTURE_MODE_AGIF
#endif
|| (fallbackState == true
#ifdef DEBUG_IQ_CAPTURE_MODE
&& debugCaptureMode == DEBUG_IQ_CAPTURE_MODE_NORMAL
#endif
)) {
newOperationModeReprocessing = DUAL_OPERATION_MODE_MASTER;
CLOGD("[Fusion] SYNC, set to MASTER: "
"[R%d] oldOperationMode(%d) m_currentMultiCaptureMode(%d) fallbackState(%d)",
request->getKey(), oldOperationMode, m_currentMultiCaptureMode, fallbackState);
}
break;
case DUAL_OPERATION_MODE_SLAVE:
if (oldOperationMode == DUAL_OPERATION_MODE_SYNC
&& dispCamType != UNI_PLUGIN_CAMERA_TYPE_TELE) {
newOperationModeReprocessing = DUAL_OPERATION_MODE_MASTER;
CLOGD("[Fusion] SLAVE1, set to MASTER: [R%d] oldOperationMode(%d) dispCamType(%d)",
request->getKey(), oldOperationMode, dispCamType);
} else if (oldOperationMode == DUAL_OPERATION_MODE_MASTER) {
CLOGW("Forcely set to MASTER: [R%d] oldOperationMode(%d) dispCamType(%d)",
request->getKey(), oldOperationMode, dispCamType);
newOperationModeReprocessing = DUAL_OPERATION_MODE_MASTER;
}
break;
case DUAL_OPERATION_MODE_MASTER:
if (oldOperationMode == DUAL_OPERATION_MODE_SLAVE) {
CLOGW("Forcely set to SLAVE: [R%d] oldOperationMode(%d) dispCamType(%d)",
request->getKey(), oldOperationMode, dispCamType);
newOperationModeReprocessing = DUAL_OPERATION_MODE_SLAVE;
}
break;
default:
break;
}
#else
if (newOperationModeReprocessing == DUAL_OPERATION_MODE_SYNC
&& (m_currentMultiCaptureMode == MULTI_CAPTURE_MODE_BURST
|| m_currentMultiCaptureMode == MULTI_CAPTURE_MODE_AGIF)) {
newOperationModeReprocessing = DUAL_OPERATION_MODE_MASTER;
}
#endif
if (m_currentMultiCaptureMode == MULTI_CAPTURE_MODE_BURST
|| m_currentMultiCaptureMode == MULTI_CAPTURE_MODE_AGIF
#ifdef SAMSUNG_TN_FEATURE
|| m_configurations->getModeValue(CONFIGURATION_MULTI_CAPTURE_MODE) == MULTI_CAPTURE_MODE_BURST
|| m_configurations->getModeValue(CONFIGURATION_MULTI_CAPTURE_MODE) == MULTI_CAPTURE_MODE_AGIF
#endif
) {
if (m_dualMultiCaptureLockflag == false) {
m_dualMultiCaptureLockflag = true;
} else {
if (oldOperationModeReprocessing != newOperationModeReprocessing) {
newOperationModeReprocessing = oldOperationModeReprocessing;
}
}
}
}
if (dualOperationModeLockCount > 0 &&
oldOperationModeReprocessing != DUAL_OPERATION_MODE_NONE &&
oldOperationMode != DUAL_OPERATION_MODE_SYNC) {
/* keep this dualOperationModeReprocessing with current dualOperationMode */
if (oldOperationMode != newOperationModeReprocessing) {
CLOGW("[R%d] lock reprocessing operation mode(%d / %d) for capture, lock(%d)",
request->getKey(), newOperationModeReprocessing, oldOperationMode,
dualOperationModeLockCount);
newOperationModeReprocessing = oldOperationMode;
}
}
} else if (m_scenario == SCENARIO_DUAL_REAR_PORTRAIT || m_scenario == SCENARIO_DUAL_FRONT_PORTRAIT) {
#ifdef SAMSUNG_TN_FEATURE
if (m_configurations->getMode(CONFIGURATION_FACTORY_TEST_MODE) == true) {
CameraMetadata *meta = request->getServiceMeta();
int32_t capture_hint = SAMSUNG_ANDROID_CONTROL_CAPTURE_HINT_NONE;
if (meta->exists(SAMSUNG_ANDROID_CONTROL_CAPTURE_HINT)) {
camera_metadata_entry_t entry;
entry = meta->find(SAMSUNG_ANDROID_CONTROL_CAPTURE_HINT);
capture_hint = entry.data.i32[0];
}
if (capture_hint == SAMSUNG_ANDROID_CONTROL_CAPTURE_HINT_FACTORY_MAIN) {
newOperationModeReprocessing = DUAL_OPERATION_MODE_MASTER;
} else if (capture_hint == SAMSUNG_ANDROID_CONTROL_CAPTURE_HINT_FACTORY_SECONDARY) {
newOperationModeReprocessing = DUAL_OPERATION_MODE_SLAVE;
} else {
newOperationModeReprocessing = DUAL_OPERATION_MODE_MASTER;
}
} else
#endif
{
#ifdef SAMSUNG_DUAL_PORTRAIT_SOLUTION
newOperationModeReprocessing = DUAL_OPERATION_MODE_SYNC;
#else
newOperationModeReprocessing = DUAL_OPERATION_MODE_MASTER;
#endif
}
}
m_configurations->setDualOperationModeReprocessing(newOperationModeReprocessing);
} else {
if (m_scenario == SCENARIO_DUAL_REAR_ZOOM) {
if (m_configurations->getDynamicMode(DYNAMIC_DUAL_FORCE_SWITCHING) == true) {
if (zoomRatio >= DUAL_SWITCHING_SYNC_MODE_MAX_ZOOM_RATIO) {
#ifdef SAMSUNG_DUAL_ZOOM_FALLBACK
if (dualOperationFallback == 1 && oldOperationMode != DUAL_OPERATION_MODE_SLAVE) {
if (m_configurations->getStaticValue(CONFIGURATION_DUAL_DISP_FALLBACK_RESULT)) {
newOperationMode = DUAL_OPERATION_MODE_MASTER;
} else {
newOperationMode = DUAL_OPERATION_MODE_SYNC;
}
} else
#endif
{
newOperationMode = DUAL_OPERATION_MODE_SLAVE;
}
} else {
newOperationMode = DUAL_OPERATION_MODE_MASTER;
}
} else {
if (zoomRatio < DUAL_PREVIEW_SYNC_MODE_MIN_ZOOM_RATIO) {
/* DUAL_OPERATION_MODE_MASTER */
#ifdef SAMSUNG_DUAL_ZOOM_FALLBACK
/* clear dual operation mode fallback flag */
if (m_configurations->getStaticValue(CONFIGURATION_DUAL_TARGET_FALLBACK_RESULT) == false) {
m_configurations->setStaticValue(CONFIGURATION_DUAL_OP_MODE_FALLBACK, 0);
}
#endif
newOperationMode = DUAL_OPERATION_MODE_MASTER;
} else if (zoomRatio > DUAL_PREVIEW_SYNC_MODE_MAX_ZOOM_RATIO) {
/* DUAL_OPERATION_MODE_SLAVE */
#ifdef SAMSUNG_DUAL_ZOOM_FALLBACK
if (dualOperationFallback == 1 || dispCamType != UNI_PLUGIN_CAMERA_TYPE_TELE) {
newOperationMode = DUAL_OPERATION_MODE_SYNC;
} else
#endif
{
newOperationMode = DUAL_OPERATION_MODE_SLAVE;
}
} else {
/* DUAL_OPERATION_MODE_SYNC */
newOperationMode = DUAL_OPERATION_MODE_SYNC;
}
}
#ifdef SAMSUNG_DUAL_ZOOM_FALLBACK
if (m_configurations->getDynamicMode(DYNAMIC_DUAL_CAMERA_DISABLE) == true) {
newOperationMode = DUAL_OPERATION_MODE_MASTER;
}
#endif
} else if (m_scenario == SCENARIO_DUAL_REAR_PORTRAIT || m_scenario == SCENARIO_DUAL_FRONT_PORTRAIT) {
newOperationMode = DUAL_OPERATION_MODE_SYNC;
}
if (m_dualTransitionCount > 0) {
if (oldOperationMode == DUAL_OPERATION_MODE_SYNC) {
if (isNeedModeChange == true) {
CLOGD("[R%d]Return for dual transition, transitionCount(%d)",
request->getKey(), m_dualTransitionCount);
}
m_dualTransitionCount--;
return NO_ERROR;
}
/* keep previous sync for at least remained m_dualTransitionCount */
if (newOperationMode != DUAL_OPERATION_MODE_SYNC)
/* DUAL_OPERATION_MODE_SYNC */
newOperationMode = DUAL_OPERATION_MODE_SYNC;
}
if (newOperationMode != oldOperationMode) {
switch (oldOperationMode) {
case DUAL_OPERATION_MODE_MASTER:
case DUAL_OPERATION_MODE_SLAVE:
if (newOperationMode != DUAL_OPERATION_MODE_SYNC) {
newOperationMode = DUAL_OPERATION_MODE_SYNC;
}
break;
default:
break;
}
if (isNeedModeChange == true) {
bool lockStandby = false;
{
/* don't off alive sensor cause of not finished capture */
Mutex::Autolock l(m_captureProcessLock);
lockStandby = (m_dualCaptureLockCount > 0 || m_captureProcessList.size() > 0);
}
if (dualOperationModeLockCount > 0)
lockStandby = true;
CLOGD("Change dual mode old(%d), new(%d), fallback(%d), finishFactoryStart(%d), standby(M:%d, S:%d) count(%d, %d) capturelock(%d) lock(%d)",
oldOperationMode, newOperationMode, dualOperationFallback, flagFinishFactoryStart,
m_parameters[m_cameraId]->getStandbyState(),
m_parameters[m_cameraIds[1]]->getStandbyState(),
m_dualTransitionCount,
m_dualCaptureLockCount,
lockStandby,
dualOperationModeLockCount);
switch (newOperationMode) {
case DUAL_OPERATION_MODE_MASTER:
needCheckMasterStandby = true;
break;
case DUAL_OPERATION_MODE_SLAVE:
needCheckSlaveStandby = true;
break;
case DUAL_OPERATION_MODE_SYNC:
needCheckMasterStandby = true;
needCheckSlaveStandby = true;
break;
default:
break;
}
m_earlyDualOperationMode = newOperationMode;
if (newOperationMode == DUAL_OPERATION_MODE_SYNC) {
if (m_configurations->getDynamicMode(DYNAMIC_DUAL_FORCE_SWITCHING) == false)
m_dualTransitionCount = DUAL_TRANSITION_FRAME_COUNT;
else
m_dualTransitionCount = DUAL_SWITCH_TRANSITION_FRAME_COUNT;
}
if ((oldOperationMode != newOperationMode) && (lockStandby == false)) {
CLOGD("[R%d] stanby mode trigger start, modeChange(%d)",
request->getKey(), isNeedModeChange);
ret = m_setStandbyModeTrigger(flagFinishFactoryStart, newOperationMode, oldOperationMode, isNeedModeChange, &isTriggered);
if (ret != NO_ERROR) {
CLOGE("Set Standby mode(false) fail! ret(%d)", ret);
}
}
if (oldOperationMode != DUAL_OPERATION_MODE_NONE) {
if (flagFinishFactoryStart == false) {
CLOGW("[R%d] not finish dualFrameFactoryStartThread forcely set to dualOperationMode(%d -> %d)",
request->getKey(), newOperationMode, oldOperationMode);
newOperationMode = oldOperationMode;
needCheckMasterStandby = false;
needCheckSlaveStandby = false;
}
if (needCheckMasterStandby &&
m_parameters[m_cameraId]->getStandbyState() != DUAL_STANDBY_STATE_OFF) {
CLOGW("[R%d] not ready of cameraId(%d) state(%d) forcely set to dualOperationMode(%d -> %d)",
request->getKey(), m_cameraId, m_parameters[m_cameraId]->getStandbyState(),
newOperationMode, oldOperationMode);
newOperationMode = oldOperationMode;
}
if (needCheckSlaveStandby &&
m_parameters[m_cameraIds[1]]->getStandbyState() != DUAL_STANDBY_STATE_OFF) {
CLOGW("[R%d] not ready of cameraId(%d) state(%d) forcely set to dualOperationMode(%d -> %d)",
request->getKey(), m_cameraIds[1], m_parameters[m_cameraIds[1]]->getStandbyState(),
newOperationMode, oldOperationMode);
newOperationMode = oldOperationMode;
}
if (lockStandby == true) {
switch (newOperationMode) {
case DUAL_OPERATION_MODE_MASTER:
if (oldOperationMode == DUAL_OPERATION_MODE_SYNC) {
CLOGW("[R%d] please keep the previous operation mode(%d / %d) for capture. cnt(%d/%d)",
request->getKey(), newOperationMode, oldOperationMode,
m_dualCaptureLockCount, m_captureProcessList.size());
newOperationMode = oldOperationMode;
}
break;
case DUAL_OPERATION_MODE_SLAVE:
if (oldOperationMode == DUAL_OPERATION_MODE_SYNC) {
CLOGW("[R%d] please keep the previous operation mode(%d / %d) for capture, cnt(%d/%d)",
request->getKey(), newOperationMode, oldOperationMode,
m_dualCaptureLockCount, m_captureProcessList.size());
newOperationMode = oldOperationMode;
}
break;
default:
break;
}
}
if (dualOperationModeLockCount > 0) {
CLOGW("[R%d] lock previous operation mode(%d / %d), lockCnt(%d)",
request->getKey(), newOperationMode, oldOperationMode,
dualOperationModeLockCount);
newOperationMode = oldOperationMode;
}
}
m_configurations->setDualOperationMode(newOperationMode);
} else if (newOperationMode == DUAL_OPERATION_MODE_SYNC) {
m_earlyDualOperationMode = newOperationMode;
CLOGD("[R%d] stanby mode trigger start, modeChange(%d)",
request->getKey(), isNeedModeChange);
ret = m_setStandbyModeTrigger(flagFinishFactoryStart, newOperationMode, oldOperationMode, isNeedModeChange, &isTriggered);
if (ret != NO_ERROR) {
CLOGE("Set Standby mode(false) fail! ret(%d)", ret);
} else {
if (isTriggered) {
/*
* This variable will be used in case of situation that
* "Early sensorStandby off" is finished too fast
* before the request to trigger it is used in m_createPreviewFrameFunc().
*/
m_earlyTriggerRequestKey = request->getKey();
}
}
/* Clearing essentialRequestList */
m_latestRequestListLock.lock();
m_essentialRequestList.clear();
m_latestRequestListLock.unlock();
}
}
if (isNeedModeChange == true) {
if (m_dualCaptureLockCount > 0) {
m_dualCaptureLockCount--;
}
m_configurations->decreaseDualOperationModeLockCount();
}
}
return ret;
}
status_t ExynosCamera::m_setStandbyModeTrigger(bool flagFinishFactoryStart,
enum DUAL_OPERATION_MODE newDualOperationMode,
enum DUAL_OPERATION_MODE oldDualOperationMode,
bool isNeedModeChange,
bool *isTriggered)
{
ExynosCameraAutoTimer autoTimer(__FUNCTION__);
status_t ret = NO_ERROR;
bool masterSensorStandby = false; /* target */
bool slaveSensorStandby = false; /* target */
bool supportMasterSensorStandby;
bool supportSlaveSensorStandby;
bool isMasterSensorStandby;
bool isSlaveSensorStandby;
dual_standby_state_t masterStandbyState;
dual_standby_state_t slaveStandbyState;
dual_standby_trigger_t masterDualStandbyTrigger = DUAL_STANDBY_TRIGGER_NONE;
dual_standby_trigger_t slaveDualStandbyTrigger = DUAL_STANDBY_TRIGGER_NONE;
if (isTriggered == NULL) {
CLOGE("isTriggerd is NULL");
return INVALID_OPERATION;
}
*isTriggered = false;
if (flagFinishFactoryStart == false) {
CLOGD("Not yet finishing startFactoryThread(dualOperationMode(%d -> %d))",
newDualOperationMode, oldDualOperationMode);
return ret;
}
/* master */
supportMasterSensorStandby = m_parameters[m_cameraId]->isSupportedFunction(SUPPORTED_HW_FUNCTION_SENSOR_STANDBY);
masterStandbyState = m_parameters[m_cameraId]->getStandbyState();
isMasterSensorStandby = (masterStandbyState >= DUAL_STANDBY_STATE_OFF) ? false : true;
/* slave */
supportSlaveSensorStandby = m_parameters[m_cameraIds[1]]->isSupportedFunction(SUPPORTED_HW_FUNCTION_SENSOR_STANDBY);
slaveStandbyState = m_parameters[m_cameraIds[1]]->getStandbyState();
isSlaveSensorStandby = (slaveStandbyState >= DUAL_STANDBY_STATE_OFF) ? false : true;
switch (oldDualOperationMode) {
case DUAL_OPERATION_MODE_MASTER:
switch (newDualOperationMode) {
case DUAL_OPERATION_MODE_SLAVE:
masterSensorStandby = true; /* off */
slaveSensorStandby = false; /* on */
break;
case DUAL_OPERATION_MODE_SYNC:
masterSensorStandby = false; /* on */
slaveSensorStandby = false; /* on */
break;
default:
CLOGE("invalid trasition of dualOperationMode");
break;
}
break;
case DUAL_OPERATION_MODE_SLAVE:
switch (newDualOperationMode) {
case DUAL_OPERATION_MODE_MASTER:
masterSensorStandby = false; /* on */
slaveSensorStandby = true; /* off */
break;
case DUAL_OPERATION_MODE_SYNC:
masterSensorStandby = false; /* on */
slaveSensorStandby = false; /* on */
break;
default:
CLOGE("invalid trasition of dualOperationMode");
break;
}
break;
case DUAL_OPERATION_MODE_SYNC:
switch (newDualOperationMode) {
case DUAL_OPERATION_MODE_MASTER:
masterSensorStandby = false; /* on */
slaveSensorStandby = true; /* off */
break;
case DUAL_OPERATION_MODE_SLAVE:
masterSensorStandby = true; /* off */
slaveSensorStandby = false; /* on */
break;
default:
CLOGE("invalid trasition of dualOperationMode");
break;
}
break;
default:
CLOG_ASSERT("wrong dual operationMode(%d)", oldDualOperationMode);
break;
}
/* master */
if (masterSensorStandby != isMasterSensorStandby) {
if (!supportMasterSensorStandby) {
/* poststandby case */
if (masterSensorStandby == true) {
m_parameters[m_cameraId]->setStandbyState(DUAL_STANDBY_STATE_ON);
} else {
m_parameters[m_cameraId]->setStandbyState(DUAL_STANDBY_STATE_OFF);
}
} else {
/* sensorstandby case */
masterDualStandbyTrigger = masterSensorStandby ? DUAL_STANDBY_TRIGGER_MASTER_ON : DUAL_STANDBY_TRIGGER_MASTER_OFF;
}
}
/* slave */
if (slaveSensorStandby != isSlaveSensorStandby) {
if (!supportSlaveSensorStandby) {
/* poststandby case */
if (slaveSensorStandby == true) {
m_parameters[m_cameraIds[1]]->setStandbyState(DUAL_STANDBY_STATE_ON);
} else {
m_parameters[m_cameraIds[1]]->setStandbyState(DUAL_STANDBY_STATE_OFF);
}
} else {
/* sensorstandby case */
slaveDualStandbyTrigger = slaveSensorStandby ? DUAL_STANDBY_TRIGGER_SLAVE_ON : DUAL_STANDBY_TRIGGER_SLAVE_OFF;
/* slave shot sync thread */
if (slaveDualStandbyTrigger == DUAL_STANDBY_TRIGGER_SLAVE_OFF) {
if (m_slaveMainThread->isRunning() == false)
m_slaveMainThread->run(PRIORITY_URGENT_DISPLAY);
}
}
}
CLOGD("dualOperationMode(%d -> %d) M[%d](%d, %d, %d) S[%d](%d, %d, %d)",
oldDualOperationMode, newDualOperationMode,
masterDualStandbyTrigger,
masterSensorStandby, isMasterSensorStandby, supportMasterSensorStandby,
slaveDualStandbyTrigger,
slaveSensorStandby, isSlaveSensorStandby, supportSlaveSensorStandby);
/*
* ordering
* Master standby off -> Slave standby off -> Slave standby on -> Master standby on
*/
if (slaveDualStandbyTrigger == DUAL_STANDBY_TRIGGER_SLAVE_OFF) {
m_parameters[m_cameraIds[1]]->setStandbyState(DUAL_STANDBY_STATE_OFF_READY);
m_dualStandbyTriggerQ->pushProcessQ(&slaveDualStandbyTrigger);
*isTriggered = true;
}
if (masterDualStandbyTrigger == DUAL_STANDBY_TRIGGER_MASTER_OFF) {
m_parameters[m_cameraId]->setStandbyState(DUAL_STANDBY_STATE_OFF_READY);
m_dualStandbyTriggerQ->pushProcessQ(&masterDualStandbyTrigger);
*isTriggered = true;
}
if (isNeedModeChange && masterDualStandbyTrigger == DUAL_STANDBY_TRIGGER_MASTER_ON) {
m_parameters[m_cameraId]->setStandbyState(DUAL_STANDBY_STATE_ON_READY);
m_dualStandbyTriggerQ->pushProcessQ(&masterDualStandbyTrigger);
*isTriggered = true;
}
if (isNeedModeChange && slaveDualStandbyTrigger == DUAL_STANDBY_TRIGGER_SLAVE_ON) {
m_parameters[m_cameraIds[1]]->setStandbyState(DUAL_STANDBY_STATE_ON_READY);
m_dualStandbyTriggerQ->pushProcessQ(&slaveDualStandbyTrigger);
*isTriggered = true;
}
if ((masterDualStandbyTrigger != DUAL_STANDBY_TRIGGER_NONE ||
slaveDualStandbyTrigger != DUAL_STANDBY_TRIGGER_NONE)
|| (m_dualStandbyTriggerQ->getSizeOfProcessQ() > 0 &&
m_dualStandbyThread->isRunning() == false)) {
m_dualStandbyThread->run(PRIORITY_URGENT_DISPLAY);
}
return ret;
}
bool ExynosCamera::m_dualStandbyThreadFunc(void)
{
ExynosCameraAutoTimer autoTimer(__FUNCTION__);
status_t ret = NO_ERROR;
bool standby;
bool isNeedPrepare;
dual_standby_trigger_t dualStandbyTrigger;
ExynosCameraFrameFactory *factory;
enum DUAL_OPERATION_MODE dualOperationMode = DUAL_OPERATION_MODE_NONE;
frame_type_t prepareFrameType;
ret = m_dualStandbyTriggerQ->waitAndPopProcessQ(&dualStandbyTrigger);
if (ret == TIMED_OUT) {
CLOGW("Time-out to wait m_dualStandbyTriggerQ");
goto THREAD_EXIT;
} else if (ret != NO_ERROR) {
CLOGE("Failed to waitAndPopProcessQ for m_dualStandbyTriggerQ");
goto THREAD_EXIT;
}
if (m_getState() != EXYNOS_CAMERA_STATE_RUN) {
CLOGE("state is not RUN!!(%d)", m_getState());
goto THREAD_EXIT;
}
/* default stream-off */
standby = true;
isNeedPrepare = false;
CLOGI("dualStandbyTriggerQ(%d) prepare(%d) trigger(%d)",
m_dualStandbyTriggerQ->getSizeOfProcessQ(), m_prepareFrameCount, dualStandbyTrigger);
switch (dualStandbyTrigger) {
case DUAL_STANDBY_TRIGGER_MASTER_OFF:
isNeedPrepare = true;
standby = false;
dualOperationMode = DUAL_OPERATION_MODE_MASTER;
prepareFrameType = FRAME_TYPE_TRANSITION;
/* fall through */
case DUAL_STANDBY_TRIGGER_MASTER_ON:
factory = m_frameFactory[FRAME_FACTORY_TYPE_CAPTURE_PREVIEW];
break;
case DUAL_STANDBY_TRIGGER_SLAVE_OFF:
isNeedPrepare = true;
standby = false;
dualOperationMode = DUAL_OPERATION_MODE_SLAVE;
prepareFrameType = FRAME_TYPE_TRANSITION_SLAVE;
/* fall through */
case DUAL_STANDBY_TRIGGER_SLAVE_ON:
factory = m_frameFactory[FRAME_FACTORY_TYPE_PREVIEW_DUAL];
break;
default:
CLOG_ASSERT("invalid trigger(%d)", dualStandbyTrigger);
break;
}
if (standby == false) {
uint32_t pipeId = PIPE_3AA;
/* wait for real finish */
enum SENSOR_STANDBY_STATE state = factory->getSensorStandbyState(pipeId);
int retryCount = 50; /* maximum 100ms(1frame) * 5 */
while (state != SENSOR_STANDBY_ON && retryCount > 0) {
usleep(10000); /* 10ms */
retryCount--;
CLOGW("waiting for previous standby off(%d) retry(%d)!!", state, retryCount);
state = factory->getSensorStandbyState(pipeId);
}
}
if (isNeedPrepare == true) {
for (int i = 0; i < m_prepareFrameCount; i++) {
ret = m_createInternalFrameFunc(NULL, false, REQ_SYNC_NONE, prepareFrameType);
if (ret != NO_ERROR) {
CLOGE("Failed to createFrameFunc for preparing frame. prepareCount %d/%d",
i, m_prepareFrameCount);
}
}
}
ret = factory->sensorStandby(standby);
if (ret != NO_ERROR) {
CLOGE("sensorStandby(%s) fail! ret(%d)", (standby?"On":"Off"), ret);
} else {
switch (dualStandbyTrigger) {
case DUAL_STANDBY_TRIGGER_MASTER_OFF:
m_parameters[m_cameraId]->setStandbyState(DUAL_STANDBY_STATE_OFF);
break;
case DUAL_STANDBY_TRIGGER_MASTER_ON:
m_parameters[m_cameraId]->setStandbyState(DUAL_STANDBY_STATE_ON);
break;
case DUAL_STANDBY_TRIGGER_SLAVE_OFF:
m_parameters[m_cameraIds[1]]->setStandbyState(DUAL_STANDBY_STATE_OFF);
break;
case DUAL_STANDBY_TRIGGER_SLAVE_ON:
m_parameters[m_cameraIds[1]]->setStandbyState(DUAL_STANDBY_STATE_ON);
break;
default:
break;
}
CLOGI("dualStandbyTriggerQ(%d) prepare(%d) trigger(%d) standby(M:%d, S:%d)",
m_dualStandbyTriggerQ->getSizeOfProcessQ(), m_prepareFrameCount, dualStandbyTrigger,
m_parameters[m_cameraId]->getStandbyState(),
m_parameters[m_cameraIds[1]]->getStandbyState());
}
THREAD_EXIT:
if (m_dualStandbyTriggerQ->getSizeOfProcessQ() > 0) {
CLOGI("run again. dualStandbyTriggerQ size %d", m_dualStandbyTriggerQ->getSizeOfProcessQ());
return true;
} else {
CLOGI("Complete to dualStandbyTriggerQ");
return false;
}
return ret;
}
#endif
#ifdef MONITOR_LOG_SYNC
uint32_t ExynosCamera::m_getSyncLogId(void)
{
return ++cameraSyncLogId;
}
#endif
bool ExynosCamera::m_monitorThreadFunc(void)
{
CLOGV("");
int *threadState;
uint64_t *timeInterval;
int *pipeCountRenew, resultCountRenew;
int ret = NO_ERROR;
int loopCount = 0;
int dtpStatus = 0;
int pipeIdFlite = m_getBayerPipeId();
int pipeIdErrorCheck = 0;
uint32_t checkStreamCount = 1;
frame_type_t frameType = FRAME_TYPE_PREVIEW;
frame_handle_components_t components;
ExynosCameraFrameFactory *factory = NULL;
/* 1. MONITOR_THREAD_INTERVAL (0.2s)*/
for (loopCount = 0; loopCount < MONITOR_THREAD_INTERVAL; loopCount += (MONITOR_THREAD_INTERVAL / 20)) {
if (m_getState() == EXYNOS_CAMERA_STATE_FLUSH) {
CLOGI("Flush is in progress");
return false;
}
usleep(MONITOR_THREAD_INTERVAL / 20);
}
m_framefactoryCreateThread->join();
#ifdef USE_DUAL_CAMERA
if (m_configurations->getMode(CONFIGURATION_DUAL_MODE) == true
&& m_configurations->getDualOperationMode() == DUAL_OPERATION_MODE_SYNC) {
checkStreamCount = 2;
}
#endif
for (uint32_t i = 1; i <= checkStreamCount; i++) {
switch (i) {
#ifdef USE_DUAL_CAMERA
case 2:
frameType = FRAME_TYPE_PREVIEW_SLAVE;
break;
#endif
case 1:
default:
#ifdef USE_DUAL_CAMERA
if (m_configurations->getMode(CONFIGURATION_DUAL_MODE) == true
&& m_configurations->getDualOperationMode() == DUAL_OPERATION_MODE_SLAVE) {
frameType = FRAME_TYPE_PREVIEW_SLAVE;
} else
#endif
{
frameType = FRAME_TYPE_PREVIEW;
}
break;
}
getFrameHandleComponents(frameType, &components);
factory = components.previewFactory;
if (factory == NULL) {
CLOGE("previewFrameFactory is NULL. Skip monitoring.");
return false;
}
if (factory->isCreated() == false) {
CLOGE("previewFrameFactory is not Created. Skip monitoring.");
return false;
}
bool flag3aaIspM2M = (components.parameters->getHwConnectionMode(PIPE_3AA, PIPE_ISP) == HW_CONNECTION_MODE_M2M);
bool flagIspMcscM2M = (components.parameters->getHwConnectionMode(PIPE_ISP, PIPE_MCSC) == HW_CONNECTION_MODE_M2M);
/* 2. Select Error check pipe ID (of last output node) */
if (flagIspMcscM2M == true
&& IS_OUTPUT_NODE(factory, PIPE_MCSC) == true) {
pipeIdErrorCheck = PIPE_MCSC;
} else if (flag3aaIspM2M == true
&& IS_OUTPUT_NODE(factory, PIPE_ISP) == true) {
pipeIdErrorCheck = PIPE_ISP;
} else {
pipeIdErrorCheck = PIPE_3AA;
}
if (factory->checkPipeThreadRunning(pipeIdErrorCheck) == false) {
CLOGW("pipe(%d) is not running.. Skip monitoring.", pipeIdErrorCheck);
return false;
}
/* 3. Monitor sync log output */
#ifdef MONITOR_LOG_SYNC
uint32_t pipeIdLogSync = PIPE_3AA;
/* If it is not front camera in PIP and sensor pipe is running, do sync log */
if (factory->checkPipeThreadRunning(pipeIdLogSync)
&& !(getCameraId() == CAMERA_ID_FRONT && m_configurations->getMode(CONFIGURATION_PIP_MODE))) {
if (!(m_syncLogDuration % MONITOR_LOG_SYNC_INTERVAL)) {
uint32_t syncLogId = m_getSyncLogId();
CLOGI("@FIMC_IS_SYNC %d", syncLogId);
factory->syncLog(pipeIdLogSync, syncLogId);
}
m_syncLogDuration++;
}
#endif
/* 4. DTP status check */
factory->getControl(V4L2_CID_IS_G_DTPSTATUS, &dtpStatus, pipeIdFlite);
if (dtpStatus == 1) {
CLOGE("DTP Detected. dtpStatus(%d)", dtpStatus);
dump();
/* Once this error is returned by some method, or if notify() is called with ERROR_DEVICE,
* only the close() method can be called successfully. */
m_requestMgr->notifyDeviceError();
ret = m_transitState(EXYNOS_CAMERA_STATE_ERROR);
if (ret != NO_ERROR) {
CLOGE("Failed to transitState into ERROR. ret %d", ret);
}
if (m_configurations->getSamsungCamera() == true) {
ret = factory->setControl(V4L2_CID_IS_CAMERA_TYPE, IS_COLD_RESET, PIPE_3AA);
if (ret < 0) {
CLOGE("PIPE_3AA V4L2_CID_IS_CAMERA_TYPE fail, ret(%d)", ret);
}
}
#ifdef SENSOR_OVERFLOW_CHECK
android_printAssert(NULL, LOG_TAG, "killed by itself");
#endif
return false;
}
/* 5. ESD check */
if (m_streamManager->findStream(HAL_STREAM_ID_PREVIEW) == true) {
factory->getThreadState(&threadState, pipeIdErrorCheck);
factory->getThreadRenew(&pipeCountRenew, pipeIdErrorCheck);
if ((*threadState == ERROR_POLLING_DETECTED) || (*pipeCountRenew > ERROR_DQ_BLOCKED_COUNT)) {
CLOGE("ESD Detected. threadState(%d) pipeCountRenew(%d)", *threadState, *pipeCountRenew);
goto ERROR;
}
CLOGV("Thread Renew Count [%d]", *pipeCountRenew);
factory->incThreadRenew(pipeIdErrorCheck);
}
/* 6. Result Callback Error check */
if (m_getState() == EXYNOS_CAMERA_STATE_RUN) {
resultCountRenew = m_requestMgr->getResultRenew();
if (resultCountRenew > ERROR_RESULT_DALAY_COUNT) {
CLOGE("Device Error Detected. Probably there was not result callback about %.2f seconds. resultCountRenew(%d)",
(float)MONITOR_THREAD_INTERVAL / 1000000 * (float)ERROR_RESULT_DALAY_COUNT, resultCountRenew);
m_requestMgr->dump();
goto ERROR;
}
CLOGV("Result Renew Count [%d]", resultCountRenew);
m_requestMgr->incResultRenew();
} else {
m_requestMgr->resetResultRenew();
}
factory->getThreadInterval(&timeInterval, pipeIdErrorCheck);
CLOGV("Thread IntervalTime [%ju]", *timeInterval);
}
return true;
ERROR:
dump();
/* Once this error is returned by some method, or if notify() is called with ERROR_DEVICE,
* only the close() method can be called successfully. */
m_requestMgr->notifyDeviceError();
ret = m_transitState(EXYNOS_CAMERA_STATE_ERROR);
if (ret != NO_ERROR) {
CLOGE("Failed to transitState into ERROR. ret %d", ret);
}
if (m_configurations->getSamsungCamera() == true) {
ret = factory->setControl(V4L2_CID_IS_CAMERA_TYPE, IS_COLD_RESET, PIPE_3AA);
if (ret < 0) {
CLOGE("PIPE_3AA V4L2_CID_IS_CAMERA_TYPE fail, ret(%d)", ret);
}
}
return false;
}
#ifdef BUFFER_DUMP
bool ExynosCamera::m_dumpThreadFunc(void)
{
char filePath[70];
int imagePlaneCount = -1;
status_t ret = NO_ERROR;
buffer_dump_info_t bufDumpInfo;
ret = m_dumpBufferQ->waitAndPopProcessQ(&bufDumpInfo);
if (ret == TIMED_OUT) {
CLOGW("Time-out to wait dumpBufferQ");
goto THREAD_EXIT;
} else if (ret != NO_ERROR) {
CLOGE("Failed to waitAndPopProcessQ for dumpBufferQ");
goto THREAD_EXIT;
}
memset(filePath, 0, sizeof(filePath));
snprintf(filePath, sizeof(filePath), "/data/media/0/%s_CAM%d_F%d_%c%c%c%c_%dx%d.img",
bufDumpInfo.name,
m_cameraId,
bufDumpInfo.frameCount,
v4l2Format2Char(bufDumpInfo.format, 0),
v4l2Format2Char(bufDumpInfo.format, 1),
v4l2Format2Char(bufDumpInfo.format, 2),
v4l2Format2Char(bufDumpInfo.format, 3),
bufDumpInfo.width, bufDumpInfo.height);
imagePlaneCount = bufDumpInfo.buffer.planeCount - 1;
switch (imagePlaneCount) {
case 2:
if (bufDumpInfo.buffer.addr[1] == NULL) {
android_printAssert(NULL, LOG_TAG, "[CAM_ID(%d)][%s]-ASSERT(%s[%d]):[F%d B%d P1]%s_Buffer do NOT have virtual address",
m_cameraId, m_name, __FUNCTION__, __LINE__,
bufDumpInfo.frameCount, bufDumpInfo.buffer.index, bufDumpInfo.name);
goto THREAD_EXIT;
}
case 1:
if (bufDumpInfo.buffer.addr[0] == NULL) {
android_printAssert(NULL, LOG_TAG, "[CAM_ID(%d)][%s]-ASSERT(%s[%d]):[F%d B%d P0]%s_Buffer do NOT have virtual address",
m_cameraId, m_name, __FUNCTION__, __LINE__,
bufDumpInfo.frameCount, bufDumpInfo.buffer.index, bufDumpInfo.name);
goto THREAD_EXIT;
}
default:
break;
}
if (imagePlaneCount > 1) {
ret = dumpToFile2plane((char *)filePath,
bufDumpInfo.buffer.addr[0], bufDumpInfo.buffer.addr[1],
bufDumpInfo.buffer.size[0], bufDumpInfo.buffer.size[1]);
} else {
ret = dumpToFile((char *)filePath, bufDumpInfo.buffer.addr[0], bufDumpInfo.buffer.size[0]);
}
if (ret == false) {
CLOGE("[F%d B%d]Failed to dumpToFile. FilePath %s size %d/%d",
bufDumpInfo.frameCount, bufDumpInfo.buffer.index, filePath,
bufDumpInfo.buffer.size[0], bufDumpInfo.buffer.size[1]);
goto THREAD_EXIT;
}
THREAD_EXIT:
if (bufDumpInfo.buffer.index > -1) {
m_bufferSupplier->putBuffer(bufDumpInfo.buffer);
}
if (m_dumpBufferQ->getSizeOfProcessQ() > 0) {
CLOGI("run again. dumpBufferQ size %d",
m_dumpBufferQ->getSizeOfProcessQ());
return true;
} else {
CLOGI("Complete to dumpFrame.");
return false;
}
}
#endif
status_t ExynosCamera::m_transitState(ExynosCamera::exynos_camera_state_t state)
{
int ret = NO_ERROR;
Mutex::Autolock lock(m_stateLock);
CLOGV("State transition. curState %d newState %d", m_state, state);
if (state == EXYNOS_CAMERA_STATE_ERROR) {
CLOGE("Exynos camera state is ERROR! The device close of framework must be called.");
}
switch (m_state) {
case EXYNOS_CAMERA_STATE_OPEN:
if (state != EXYNOS_CAMERA_STATE_INITIALIZE
&& state != EXYNOS_CAMERA_STATE_ERROR) {
ret = INVALID_OPERATION;
goto ERR_EXIT;
}
break;
case EXYNOS_CAMERA_STATE_INITIALIZE:
if (state != EXYNOS_CAMERA_STATE_CONFIGURED
&& state != EXYNOS_CAMERA_STATE_FLUSH
&& state != EXYNOS_CAMERA_STATE_ERROR) {
/* GED Camera appliction calls flush() directly after calling initialize(). */
ret = INVALID_OPERATION;
goto ERR_EXIT;
}
break;
case EXYNOS_CAMERA_STATE_CONFIGURED:
if (state != EXYNOS_CAMERA_STATE_CONFIGURED
&& state != EXYNOS_CAMERA_STATE_START
&& state != EXYNOS_CAMERA_STATE_FLUSH
&& state != EXYNOS_CAMERA_STATE_ERROR) {
ret = INVALID_OPERATION;
goto ERR_EXIT;
}
break;
case EXYNOS_CAMERA_STATE_START:
if (state == EXYNOS_CAMERA_STATE_FLUSH) {
/* When FLUSH state is requested on START state, it must wait state to transit to RUN.
* On FLUSH state, Frame factory will be stopped.
* On START state, Frame factory will be run.
* They must be done sequencially
*/
/* HACK
* The original retryCount is 10 (1s), : int retryCount = 10;
* Due to the sensor entry time issues, it has increased to 30 (3s).
*/
int retryCount = 30;
while (m_state == EXYNOS_CAMERA_STATE_START && retryCount-- > 0) {
CLOGI("Wait to RUN state");
m_stateLock.unlock();
/* Sleep 100ms */
usleep(100000);
m_stateLock.lock();
}
if (retryCount < 0 && m_state == EXYNOS_CAMERA_STATE_START) {
android_printAssert(NULL, LOG_TAG,
"ASSERT(%s):Failed to wait EXYNOS_CAMERA_RUN state. curState %d newState %d",
__FUNCTION__, m_state, state);
}
} else if (state != EXYNOS_CAMERA_STATE_RUN
&& state != EXYNOS_CAMERA_STATE_ERROR) {
ret = INVALID_OPERATION;
goto ERR_EXIT;
}
break;
case EXYNOS_CAMERA_STATE_RUN:
if (state != EXYNOS_CAMERA_STATE_FLUSH
&& state != EXYNOS_CAMERA_STATE_ERROR) {
ret = INVALID_OPERATION;
goto ERR_EXIT;
}
break;
case EXYNOS_CAMERA_STATE_FLUSH:
if (state != EXYNOS_CAMERA_STATE_CONFIGURED
&& state != EXYNOS_CAMERA_STATE_ERROR) {
ret = INVALID_OPERATION;
goto ERR_EXIT;
}
break;
case EXYNOS_CAMERA_STATE_ERROR:
if (state != EXYNOS_CAMERA_STATE_ERROR) {
/*
* Camera HAL device ops functions that have a return value will all return -ENODEV / NULL
* in case of a serious error.
* This means the device cannot continue operation, and must be closed by the framework.
*/
ret = NO_INIT;
goto ERR_EXIT;
}
break;
default:
CLOGW("Invalid curState %d maxValue %d", state, EXYNOS_CAMERA_STATE_MAX);
ret = INVALID_OPERATION;
goto ERR_EXIT;
}
m_state = state;
return NO_ERROR;
ERR_EXIT:
CLOGE("Invalid state transition. curState %d newState %d", m_state, state);
return ret;
}
ExynosCamera::exynos_camera_state_t ExynosCamera::m_getState(void)
{
Mutex::Autolock lock(m_stateLock);
return m_state;
}
status_t ExynosCamera::m_checkRestartStream(ExynosCameraRequestSP_sprt_t request)
{
status_t ret = NO_ERROR;
bool restart = m_configurations->getRestartStream();
if (restart) {
CLOGD("Internal restart stream request[R%d]",
request->getKey());
ret = m_restartStreamInternal();
if (ret != NO_ERROR) {
CLOGE("m_restartStreamInternal failed [%d]", ret);
return ret;
}
m_requestMgr->registerToServiceList(request);
m_configurations->setRestartStream(false);
if (m_configurations->getMode(CONFIGURATION_OBTE_MODE) == true) {
m_monitorThread->requestExitAndWait();
ret = m_frameFactory[FRAME_FACTORY_TYPE_CAPTURE_PREVIEW]->destroy();
ret = m_frameFactory[FRAME_FACTORY_TYPE_REPROCESSING]->destroy();
m_configurations->setMode(CONFIGURATION_OBTE_STREAM_CHANGING, false);
ret = m_frameFactory[FRAME_FACTORY_TYPE_CAPTURE_PREVIEW]->create();
ret = m_frameFactory[FRAME_FACTORY_TYPE_REPROCESSING]->create();
}
}
return ret;
}
#ifdef FPS_CHECK
void ExynosCamera::m_debugFpsCheck(enum pipeline pipeId)
{
uint32_t debugMaxPipeNum = sizeof(m_debugFpsCount);
uint32_t id = pipeId % debugMaxPipeNum;
uint32_t debugStartCount = 1, debugEndCount = 30;
m_debugFpsCount[id]++;
if (m_debugFpsCount[id] == debugStartCount) {
m_debugFpsTimer[id].start();
}
if (m_debugFpsCount[id] == debugStartCount + debugEndCount) {
m_debugFpsTimer[id].stop();
long long durationTime = m_debugFpsTimer[id].durationMsecs();
CLOGI("FPS_CHECK(id:%d), duration %lld / 30 = %lld ms. %lld fps",
pipeId, durationTime, durationTime / debugEndCount, 1000 / (durationTime / debugEndCount));
m_debugFpsCount[id] = 0;
}
}
#endif
#if defined(USE_RAW_REVERSE_PROCESSING) && defined(USE_SW_RAW_REVERSE_PROCESSING)
bool ExynosCamera::m_reverseProcessingBayerThreadFunc(void)
{
ExynosCameraAutoTimer autoTimer(__FUNCTION__);
status_t ret = NO_ERROR;
bool loop = false;
int dstPos = -1;
int leaderPipeId = PIPE_3AA_REPROCESSING;
entity_buffer_state_t bufferState = ENTITY_BUFFER_STATE_INVALID;
ExynosCameraRequestSP_sprt_t request = NULL;
ExynosCameraFrameSP_sptr_t frame = NULL;
ExynosCameraBuffer dstBuffer;
ExynosCameraBuffer serviceBuffer;
frame_handle_components_t components;
CLOGV("Wait reverseProcessingBayerQ");
ret = m_reverseProcessingBayerQ->waitAndPopProcessQ(&frame);
if (ret == TIMED_OUT) {
CLOGV("Wait timeout to reverseProcessingBayerQ");
loop = true;
goto p_err;
} else if (ret != NO_ERROR) {
CLOGE("Failed to waitAndPopProcessQ to reverseProcessingBayerQ");
goto p_err;
} else if (frame == NULL) {
CLOGE("Frame is NULL");
goto p_err;
}
request = m_requestMgr->getRunningRequest(frame->getFrameCount());
if (request == NULL) {
CLOGE("[F%d]Failed to get request.", frame->getFrameCount());
return INVALID_OPERATION;
}
getFrameHandleComponents((enum FRAME_TYPE)frame->getFrameType(), &components);
dstPos = components.reprocessingFactory->getNodeType(PIPE_3AC_REPROCESSING);
ret = frame->getDstBuffer(leaderPipeId, &dstBuffer, dstPos);
if (ret != NO_ERROR || dstBuffer.index < 0) {
CLOGE("[F%d B%d]Failed to getDstBuffer. pos %d. ret %d",
frame->getFrameCount(), dstBuffer.index, dstPos, ret);
goto p_err;
}
ret = frame->getDstBufferState(leaderPipeId, &bufferState, dstPos);
if (ret != NO_ERROR) {
CLOGE("[F%d B%d]Failed to getDstBufferState. pos %d. ret %d",
frame->getFrameCount(), dstBuffer.index, dstPos, ret);
goto p_err;
}
if (bufferState == ENTITY_BUFFER_STATE_ERROR) {
CLOGE("[R%d F%d B%d]Invalid RAW buffer state. bufferState %d",
request->getKey(), frame->getFrameCount(), dstBuffer.index, bufferState);
request->setStreamBufferStatus(HAL_STREAM_ID_RAW, CAMERA3_BUFFER_STATUS_ERROR);
goto p_err;
}
/* HACK: get service buffer backuped by output node index */
ret = frame->getDstBuffer(leaderPipeId, &serviceBuffer, OUTPUT_NODE_1);
if (ret != NO_ERROR || serviceBuffer.index < 0) {
CLOGE("[F%d B%d]Failed to getDstBuffer for serviceBuffer. pos %d. ret %d",
frame->getFrameCount(), serviceBuffer.index, OUTPUT_NODE_1, ret);
return ret;
}
/* reverse the raw buffer */
ret = m_reverseProcessingBayer(frame, &dstBuffer, &serviceBuffer);
if (ret != NO_ERROR) {
CLOGE("[F%d B%d]Failed m_reverseProcessingBayer %d",
frame->getFrameCount(), dstBuffer.index, ret);
}
ret = m_bufferSupplier->putBuffer(dstBuffer);
if (ret != NO_ERROR) {
CLOGE("[F%d B%d]Failed to putBuffer for bayerBuffer. ret %d",
frame->getFrameCount(), dstBuffer.index, ret);
}
ret = m_sendRawStreamResult(request, &serviceBuffer);
if (ret != NO_ERROR) {
CLOGE("[F%d B%d]Failed to sendRawStreamResult. ret %d",
frame->getFrameCount(), dstBuffer.index, ret);
}
p_err:
return loop;
}
#endif
#ifdef SUPPORT_HW_GDC
bool ExynosCamera::m_gdcThreadFunc(void)
{
#ifdef DEBUG
ExynosCameraAutoTimer autoTimer(__FUNCTION__);
#endif
status_t ret = NO_ERROR;
bool loop = true;
int outputPortId = -1;
int srcPipeId = -1;
int srcNodeIndex = -1;
int dstPipeId = -1;
int srcFmt = -1;
int dstFmt = -1;
ExynosRect gdcSrcRect[2];
ExynosRect gdcDstRect;
ExynosCameraBuffer gdcSrcBuf;
ExynosCameraBuffer gdcDstBuf;
ExynosCameraFrameSP_sptr_t frame = NULL;
frame_handle_components_t components;
struct camera2_stream *meta = NULL;
camera2_node_group bcropNodeGroupInfo;
int perframeInfoIndex = -1;
outputPortId = m_streamManager->getOutputPortId(HAL_STREAM_ID_VIDEO);
if (outputPortId < 0) {
CLOGE("There is NO VIDEO stream");
goto exit_thread_loop;
}
CLOGV("Wait gdcQ");
ret = m_gdcQ->waitAndPopProcessQ(&frame);
if (ret == TIMED_OUT) {
CLOGW("Wait timeout to gdcQ");
goto retry_thread_loop;
} else if (ret != NO_ERROR) {
CLOGE("Failed to waitAndPopProcessQ to gdcQ");
goto retry_thread_loop;
} else if (frame == NULL) {
CLOGE("Frame is NULL");
goto retry_thread_loop;
} else {
getFrameHandleComponents((enum FRAME_TYPE)frame->getFrameType(), &components);
ExynosCameraFrameFactory *factory = components.previewFactory;
bool flag3aaIspM2M = (components.parameters->getHwConnectionMode(PIPE_3AA, PIPE_ISP) == HW_CONNECTION_MODE_M2M);
bool flagIspMcscM2M = (components.parameters->getHwConnectionMode(PIPE_ISP, PIPE_MCSC) == HW_CONNECTION_MODE_M2M);
if (flagIspMcscM2M == true
&& IS_OUTPUT_NODE(factory, PIPE_MCSC) == true) {
srcPipeId = PIPE_MCSC;
} else if (flag3aaIspM2M == true
&& IS_OUTPUT_NODE(factory, PIPE_ISP) == true) {
srcPipeId = PIPE_ISP;
} else {
srcPipeId = PIPE_3AA;
}
srcNodeIndex = factory->getNodeType(PIPE_MCSC0 + outputPortId);
dstPipeId = PIPE_GDC;
srcFmt = m_configurations->getYuvFormat(outputPortId);
dstFmt = m_configurations->getYuvFormat(outputPortId);
/* Set Source Rect */
ret = frame->getDstBuffer(srcPipeId, &gdcSrcBuf, srcNodeIndex);
if (ret != NO_ERROR) {
CLOGE("[F%d]Failed to getDstBuffer. pipeId %d nodeIndex %d ret %d",
frame->getFrameCount(),
srcPipeId, srcNodeIndex, ret);
goto retry_thread_loop;
}
meta = (struct camera2_stream *)gdcSrcBuf.addr[gdcSrcBuf.getMetaPlaneIndex()];
if (meta == NULL) {
CLOGE("[F%d B%d]meta is NULL. pipeId %d nodeIndex %d",
frame->getFrameCount(), gdcSrcBuf.index,
srcPipeId, srcNodeIndex);
goto retry_thread_loop;
}
gdcSrcRect[0].x = meta->output_crop_region[0];
gdcSrcRect[0].y = meta->output_crop_region[1];
gdcSrcRect[0].w = meta->output_crop_region[2];
gdcSrcRect[0].h = meta->output_crop_region[3];
gdcSrcRect[0].fullW = meta->output_crop_region[2];
gdcSrcRect[0].fullH = meta->output_crop_region[3];
gdcSrcRect[0].colorFormat = srcFmt;
/* Set Bcrop Rect */
perframeInfoIndex = (components.parameters->getHwConnectionMode(PIPE_FLITE, PIPE_3AA) == HW_CONNECTION_MODE_M2M) ? PERFRAME_INFO_3AA : PERFRAME_INFO_FLITE;
frame->getNodeGroupInfo(&bcropNodeGroupInfo, perframeInfoIndex);
components.parameters->getMaxSensorSize(&gdcSrcRect[1].fullW, &gdcSrcRect[1].fullH);
gdcSrcRect[1].x = bcropNodeGroupInfo.leader.input.cropRegion[0];
gdcSrcRect[1].y = bcropNodeGroupInfo.leader.input.cropRegion[1];
gdcSrcRect[1].w = bcropNodeGroupInfo.leader.input.cropRegion[2];
gdcSrcRect[1].h = bcropNodeGroupInfo.leader.input.cropRegion[3];
gdcSrcRect[1].colorFormat = srcFmt;
/* Set Destination Rect */
gdcDstRect.x = 0;
gdcDstRect.y = 0;
gdcDstRect.w = gdcSrcRect[0].w;
gdcDstRect.h = gdcSrcRect[0].h;
gdcDstRect.fullW = gdcSrcRect[0].fullW;
gdcDstRect.fullH = gdcSrcRect[0].fullH;
gdcDstRect.colorFormat = dstFmt;
for (int i = 0; i < 2; i++) {
ret = frame->setSrcRect(dstPipeId, gdcSrcRect[i], i);
if (ret != NO_ERROR) {
CLOGE("[F%d]Failed to setSrcRect. pipeId %d index %d ret %d",
frame->getFrameCount(), dstPipeId, i, ret);
goto retry_thread_loop;
}
}
ret = frame->setDstRect(dstPipeId, gdcDstRect);
if (ret != NO_ERROR) {
CLOGE("[F%d]Failed to setDstRect. pipeId %d ret %d",
frame->getFrameCount(), dstPipeId, ret);
goto retry_thread_loop;
}
ret = m_setSrcBuffer(dstPipeId, frame, &gdcSrcBuf);
if (ret != NO_ERROR) {
CLOGE("[F%d B%d]Failed to setSrcBuffer. pipeId %d ret %d",
frame->getFrameCount(), gdcSrcBuf.index,
dstPipeId, ret);
goto retry_thread_loop;
}
factory->setOutputFrameQToPipe(m_pipeFrameDoneQ[dstPipeId], dstPipeId);
factory->pushFrameToPipe(frame, dstPipeId);
}
return true;
retry_thread_loop:
if (m_gdcQ->getSizeOfProcessQ() > 0) {
return true;
}
exit_thread_loop:
return false;
}
#endif
int ExynosCamera::m_getMcscLeaderPipeId(ExynosCameraFrameFactory *factory)
{
uint32_t pipeId = -1;
if (factory == NULL) {
CLOGE("frame Factory is NULL");
/* TODO: doing exception handling */
return -1;
}
uint32_t cameraId = (uint32_t)factory->getCameraId();
bool flag3aaIspM2M = (m_parameters[cameraId]->getHwConnectionMode(PIPE_3AA_REPROCESSING, PIPE_ISP_REPROCESSING) == HW_CONNECTION_MODE_M2M);
bool flagIspMcscM2M = (m_parameters[cameraId]->getHwConnectionMode(PIPE_ISP_REPROCESSING, PIPE_MCSC_REPROCESSING) == HW_CONNECTION_MODE_M2M);
if (flagIspMcscM2M == true
&& IS_OUTPUT_NODE(factory, PIPE_MCSC_REPROCESSING) == true) {
pipeId = PIPE_MCSC_REPROCESSING;
} else if (flag3aaIspM2M == true
&& IS_OUTPUT_NODE(factory, PIPE_ISP_REPROCESSING) == true) {
pipeId = PIPE_ISP_REPROCESSING;
} else {
pipeId = PIPE_3AA_REPROCESSING;
}
return pipeId;
}
void ExynosCamera::getFrameHandleComponents(frame_type_t frameType, frame_handle_components_t *components)
{
switch (frameType) {
#ifdef USE_DUAL_CAMERA
case FRAME_TYPE_PREVIEW_SLAVE:
case FRAME_TYPE_PREVIEW_DUAL_SLAVE:
case FRAME_TYPE_REPROCESSING_DUAL_SLAVE:
case FRAME_TYPE_INTERNAL_SLAVE:
case FRAME_TYPE_REPROCESSING_SLAVE:
case FRAME_TYPE_TRANSITION_SLAVE:
components->previewFactory = m_frameFactory[FRAME_FACTORY_TYPE_PREVIEW_DUAL];
components->reprocessingFactory = m_frameFactory[FRAME_FACTORY_TYPE_REPROCESSING_DUAL];
components->parameters = m_parameters[m_cameraIds[1]];
components->activityControl = m_activityControl[m_cameraIds[1]];
components->captureSelector = m_captureSelector[m_cameraIds[1]];
components->currentCameraId = m_cameraIds[1];
break;
/* TODO: MUST consider JPEG_REPROCESSING in case of DUAL scenario */
#endif
case FRAME_TYPE_JPEG_REPROCESSING:
components->previewFactory = m_frameFactory[FRAME_FACTORY_TYPE_CAPTURE_PREVIEW];
components->reprocessingFactory = m_frameFactory[FRAME_FACTORY_TYPE_JPEG_REPROCESSING];
components->parameters = m_parameters[m_cameraId];
components->activityControl = m_activityControl[m_cameraId];
components->captureSelector = m_captureSelector[m_cameraId];
components->currentCameraId = m_cameraId;
break;
default:
components->previewFactory = m_frameFactory[FRAME_FACTORY_TYPE_CAPTURE_PREVIEW];
components->reprocessingFactory = m_frameFactory[FRAME_FACTORY_TYPE_REPROCESSING];
components->parameters = m_parameters[m_cameraId];
components->activityControl = m_activityControl[m_cameraId];
components->captureSelector = m_captureSelector[m_cameraId];
components->currentCameraId = m_cameraId;
break;
}
}
status_t ExynosCamera::m_updateFDAEMetadata(ExynosCameraFrameSP_sptr_t frame)
{
status_t ret = NO_ERROR;
ExynosCameraFrameFactory *factory = NULL;
camera2_shot_ext frameShotExt;
fdae_info_t fdaeInfo;
struct v4l2_ext_control extCtrl;
struct v4l2_ext_controls extCtrls;
ret = frame->getMetaData(&frameShotExt);
if (ret != NO_ERROR) {
CLOGE("[F%d]Failed to getMetaData. ret %d",
frame->getFrameCount(), ret);
return ret;
}
memset(&fdaeInfo, 0x00, sizeof(fdaeInfo));
memset(&extCtrl, 0x00, sizeof(extCtrl));
memset(&extCtrls, 0x00, sizeof(extCtrls));
factory = m_frameFactory[FRAME_FACTORY_TYPE_CAPTURE_PREVIEW];
fdaeInfo.frameCount = frameShotExt.shot.dm.request.frameCount;
for (int index = 0; index < NUM_OF_DETECTED_FACES; index++) {
if (frameShotExt.hfd.faceIds[index] > 0) {
fdaeInfo.id[index] = frameShotExt.hfd.faceIds[index];
fdaeInfo.score[index] = frameShotExt.hfd.score[index];
fdaeInfo.rect[index][X1] = frameShotExt.hfd.faceRectangles[index][X1];
fdaeInfo.rect[index][Y1] = frameShotExt.hfd.faceRectangles[index][Y1];
fdaeInfo.rect[index][X2] = frameShotExt.hfd.faceRectangles[index][X2];
fdaeInfo.rect[index][Y2] = frameShotExt.hfd.faceRectangles[index][Y2];
fdaeInfo.isRot[index] = frameShotExt.hfd.is_rot[index];
fdaeInfo.rot[index] = frameShotExt.hfd.rot[index];
fdaeInfo.faceNum += 1;
CLOGV("[F%d(%d)]id %d score %d rect %d,%d %dx%d isRot %d rot %d",
frame->getFrameCount(),
fdaeInfo.frameCount,
fdaeInfo.id[index],
fdaeInfo.score[index],
fdaeInfo.rect[index][X1],
fdaeInfo.rect[index][Y1],
fdaeInfo.rect[index][X2],
fdaeInfo.rect[index][Y2],
fdaeInfo.isRot[index],
fdaeInfo.rot[index]);
}
}
CLOGV("[F%d(%d)]setExtControl for FDAE. FaceNum %d",
frame->getFrameCount(), fdaeInfo.frameCount, fdaeInfo.faceNum);
extCtrl.id = V4L2_CID_IS_FDAE;
extCtrl.ptr = &fdaeInfo;
extCtrls.ctrl_class = V4L2_CTRL_CLASS_CAMERA;
extCtrls.count = 1;
extCtrls.controls = &extCtrl;
ret = factory->setExtControl(&extCtrls, PIPE_VRA);
if (ret != NO_ERROR) {
CLOGE("[F%d]Failed to setExtControl(V4L2_CID_IS_FDAE). ret %d",
frame->getFrameCount(), ret);
}
return ret;
}
void ExynosCamera::m_adjustSlave3AARegion(frame_handle_components_t *components, ExynosCameraFrameSP_sptr_t frame)
{
status_t ret = NO_ERROR;
camera2_shot_ext frameShotExt;
ExynosRect masterHwSensorSize;
ExynosRect masterHwBcropSize;
ExynosRect slaveHwSensorSize;
ExynosRect slaveHwBcropSize;
float scaleRatioW = 0.0f, scaleRatioH = 0.0f;
uint32_t *region = NULL;
ret = frame->getMetaData(&frameShotExt);
if (ret != NO_ERROR) {
CLOGE("[F%d]Failed to getMetaData. ret %d",
frame->getFrameCount(), ret);
return;
}
m_parameters[m_cameraId]->getPreviewBayerCropSize(&masterHwSensorSize, &masterHwBcropSize);
components->parameters->getPreviewBayerCropSize(&slaveHwSensorSize, &slaveHwBcropSize);
CLOGV("[F%d T%d]MasterBcrop %d,%d %dx%d(%d) SlaveBcrop %d,%d %dx%d(%d)",
frame->getFrameCount(), frame->getFrameType(),
masterHwBcropSize.x, masterHwBcropSize.y, masterHwBcropSize.w, masterHwBcropSize.h,
SIZE_RATIO(masterHwBcropSize.w, masterHwBcropSize.h),
slaveHwBcropSize.x, slaveHwBcropSize.y, slaveHwBcropSize.w, slaveHwBcropSize.h,
SIZE_RATIO(slaveHwBcropSize.w, slaveHwBcropSize.h));
/* Scale up the 3AA region
to adjust into the 3AA input size of slave sensor stream
*/
scaleRatioW = (float) slaveHwBcropSize.w / (float) masterHwBcropSize.w;
scaleRatioH = (float) slaveHwBcropSize.h / (float) masterHwBcropSize.h;
for (int i = 0; i < 3; i++) {
switch (i) {
case 0:
region = frameShotExt.shot.ctl.aa.afRegions;
break;
case 1:
region = frameShotExt.shot.ctl.aa.aeRegions;
break;
case 2:
region = frameShotExt.shot.ctl.aa.awbRegions;
break;
default:
continue;
}
region[0] = (uint32_t) (((float) region[0]) * scaleRatioW);
region[1] = (uint32_t) (((float) region[1]) * scaleRatioH);
region[2] = (uint32_t) (((float) region[2]) * scaleRatioW);
region[3] = (uint32_t) (((float) region[3]) * scaleRatioH);
/* Adjust the boundary of HW bcrop region */
/* Bottom-right */
if (region[0] > (uint32_t)slaveHwBcropSize.w) region[0] = (uint32_t)slaveHwBcropSize.w;
if (region[1] > (uint32_t)slaveHwBcropSize.h) region[1] = (uint32_t)slaveHwBcropSize.h;
if (region[2] > (uint32_t)slaveHwBcropSize.w) region[2] = (uint32_t)slaveHwBcropSize.w;
if (region[3] > (uint32_t)slaveHwBcropSize.h) region[3] = (uint32_t)slaveHwBcropSize.h;
}
ret = frame->setMetaData(&frameShotExt);
if (ret != NO_ERROR) {
CLOGE("[F%d]Failed to setMetaData. ret %d", frame->getFrameCount(), ret);
return;
}
}
#ifdef USE_DUAL_CAMERA
status_t ExynosCamera::m_updateSizeBeforeDualFusion(ExynosCameraFrameSP_sptr_t frame, int pipeId)
{
status_t ret = NO_ERROR;
frame_handle_components_t components;
getFrameHandleComponents((enum FRAME_TYPE)frame->getFrameType(), &components);
int pipeId_next = PIPE_FUSION;
int previewOutputPortId = m_streamManager->getOutputPortId(HAL_STREAM_ID_PREVIEW);
int previewFormat = m_configurations->getYuvFormat(previewOutputPortId);
ExynosCameraBuffer buffer;
if (m_configurations->getDualPreviewMode() == DUAL_PREVIEW_MODE_SW) {
///////////////////////
// set Src(WIDE) Rect
/*
* use pipeId_next, not pipeId.
* because, pipeId is changed in somewhere.
*/
buffer.index = -2;
ret = frame->getSrcBuffer(pipeId_next, &buffer);
if(buffer.index < 0) {
CLOGE("Invalid buffer index(%d), framecount(%d), pipeId(%d)",
buffer.index, frame->getFrameCount(), pipeId_next);
} else {
ExynosRect rect = convertingBufferDst2Rect(&buffer, previewFormat);
ret = frame->setSrcRect(pipeId_next, rect, OUTPUT_NODE_1);
if(ret != NO_ERROR) {
CLOGE("setSrcRect fail, pipeId(%d), ret(%d)", pipeId_next, ret);
}
}
///////////////////////
// set Src(TELE) Rect
CLOGV("frame->getFrameType() : %d", frame->getFrameType());
switch (frame->getFrameType()) {
case FRAME_TYPE_PREVIEW_DUAL_MASTER:
case FRAME_TYPE_PREVIEW_DUAL_SLAVE:
case FRAME_TYPE_REPROCESSING_DUAL_MASTER:
case FRAME_TYPE_REPROCESSING_DUAL_SLAVE:
buffer.index = -2;
ret = frame->getDstBuffer(pipeId, &buffer);
if (buffer.index < 0) {
CLOGE("Invalid buffer index(%d), framecount(%d), pipeId(%d)",
buffer.index, frame->getFrameCount(), pipeId);
} else {
ExynosRect rect = convertingBufferDst2Rect(&buffer, previewFormat);
ret = frame->setSrcRect(pipeId_next, rect, OUTPUT_NODE_2);
if(ret != NO_ERROR) {
CLOGE("setSrcRect fail, pipeId(%d), ret(%d)", pipeId_next, ret);
}
}
break;
default:
break;
}
}
///////////////////////
// set Dst Rect
ExynosRect dstRect;
int width, height;
components.parameters->getSize(HW_INFO_HW_YUV_SIZE, (uint32_t *)&width, (uint32_t *)&height, previewOutputPortId);
dstRect.x = 0;
dstRect.y = 0;
dstRect.w = width;
dstRect.h = height;
dstRect.fullW = width;
dstRect.fullH = height;
dstRect.colorFormat = previewFormat;
ret = frame->setDstRect(pipeId_next, dstRect);
if (ret != NO_ERROR) {
CLOGE("setDstRect(Pipe:%d) failed, Fcount(%d), ret(%d)",
pipeId_next, frame->getFrameCount(), ret);
}
return ret;
}
#endif
#ifdef SUPPORT_ME
status_t ExynosCamera::m_handleMeBuffer(ExynosCameraFrameSP_sptr_t frame, int mePos, const int meLeaderPipeId)
{
int leaderPipeId = -1;
ExynosCameraFrameEntity* entity = NULL;
bool bError = false;
ExynosCameraBuffer buffer;
entity_buffer_state_t bufferState = ENTITY_BUFFER_STATE_INVALID;
int dstPos = mePos;
status_t ret = NO_ERROR;
if (frame->getRequest(PIPE_ME) == false) {
frame->setRequest(PIPE_GMV, false);
return NO_ERROR;
}
/* 1. verify pipeId including ME */
if (meLeaderPipeId < 0) {
entity = frame->getFrameDoneFirstEntity();
if (entity == NULL) {
CLOGE("current entity is NULL, HAL-frameCount(%d)",
frame->getFrameCount());
/* TODO: doing exception handling */
return INVALID_OPERATION;
}
leaderPipeId = entity->getPipeId();
} else {
leaderPipeId = meLeaderPipeId;
}
if (m_parameters[m_cameraId]->getLeaderPipeOfMe() != leaderPipeId) {
return NO_ERROR;
}
/* 2. handling ME buffer*/
ret = frame->getDstBuffer(leaderPipeId, &buffer, dstPos);
if (ret != NO_ERROR || buffer.index < 0) {
CLOGE("[F%d B%d]Failed to getDstBuffer for PIPE_ME. ret %d",
frame->getFrameCount(), buffer.index, ret);
bError = true;
}
ret = frame->getDstBufferState(leaderPipeId, &bufferState, dstPos);
if (ret != NO_ERROR) {
CLOGE("[F%d P%d]Failed to getDstBufferState for PIPE_ME",
frame->getFrameCount(), leaderPipeId);
bError = true;
}
if (buffer.index >= 0 && bufferState == ENTITY_BUFFER_STATE_COMPLETE) {
/* In this case only, the me tag can be appendedd to the frame */
if (frame->getRawStateInSelector() == FRAME_STATE_IN_SELECTOR_PUSHED) {
ret = frame->addSelectorTag(m_captureSelector[m_cameraId]->getId(), leaderPipeId, dstPos, false);
if (ret != NO_ERROR) {
CLOGE("[F%d B%d]Failed to addSelectorTag. pipeId %d, dstPos %d, ret %d",
frame->getFrameCount(), buffer.index, leaderPipeId, dstPos, ret);
bError = true;
}
} else {
/* Don't release me buffer in order to support use case for ME */
//bError = true;
}
if (frame->getRequest(PIPE_GMV) == true) {
ret = m_setupEntity(PIPE_GMV, frame, &buffer, NULL);
if (ret != NO_ERROR) {
CLOGE("[F%d B%d]Failed to setSrcBuffer to PIPE_GMV. ret %d",
frame->getFrameCount(), buffer.index, ret);
bError = true;
}
}
} else {
CLOGE("[F%d B%d]Invalid buffer. pipeId %d",
frame->getFrameCount(), buffer.index, leaderPipeId);
bError = true;
}
/* 3. error case */
if (bError == true) {
ret = frame->setDstBufferState(leaderPipeId, ENTITY_BUFFER_STATE_ERROR, dstPos);
if (ret != NO_ERROR) {
CLOGE("[F%d P%d]Failed to setDstBufferState with ERROR for PIPE_ME",
frame->getFrameCount(), leaderPipeId);
}
if (buffer.index >= 0) {
ret = m_bufferSupplier->putBuffer(buffer);
if (ret != NO_ERROR) {
CLOGE("[F%d B%d]Failed to putBuffer for ME. ret %d",
frame->getFrameCount(), buffer.index, ret);
}
}
}
return ret;
}
#endif
bool ExynosCamera::previewStreamFunc(ExynosCameraFrameSP_sptr_t newFrame,int pipeId)
{
return m_previewStreamFunc(newFrame, pipeId);
}
ExynosCameraStreamThread::ExynosCameraStreamThread(ExynosCamera* cameraObj, const char* name, int pipeId)
: ExynosCameraThread<ExynosCameraStreamThread>(this, &ExynosCameraStreamThread::m_streamThreadFunc, name)
{
m_mainCamera = cameraObj;
m_frameDoneQ = NULL;
m_pipeId = pipeId;
}
ExynosCameraStreamThread::~ExynosCameraStreamThread()
{
}
frame_queue_t* ExynosCameraStreamThread::getFrameDoneQ()
{
return m_frameDoneQ;
}
void ExynosCameraStreamThread::setFrameDoneQ(frame_queue_t* frameDoneQ)
{
m_frameDoneQ = frameDoneQ;
}
bool ExynosCameraStreamThread::m_streamThreadFunc(void)
{
status_t ret = 0;
ExynosCameraFrameSP_sptr_t newFrame = NULL;
if(m_frameDoneQ == NULL) {
ALOGE("frameDoneQ is NULL");
return false;
}
ret = m_frameDoneQ->waitAndPopProcessQ(&newFrame);
if (ret < 0) {
/* TODO: We need to make timeout duration depends on FPS */
if (ret == TIMED_OUT) {
/* CLOGW("wait timeout"); */
} else {
ALOGE("wait and pop fail, ret(%d)", ret);
/* TODO: doing exception handling */
}
return true;
}
return m_mainCamera->previewStreamFunc(newFrame, m_pipeId);
}
bool ExynosCamera::m_bayerStreamThreadFunc(void)
{
status_t ret = 0;
ExynosCameraFrameSP_sptr_t frame = NULL;
ExynosCameraFrameEntity *entity = NULL;
ExynosCameraBuffer srcBuffer;
ExynosCameraBuffer buffer;
ExynosCameraFrameFactory *factory;
ExynosCameraRequestSP_sprt_t request = NULL;
entity_buffer_state_t bufferState = ENTITY_BUFFER_STATE_INVALID;
int pipeId = -1;
ret = m_bayerStreamQ->waitAndPopProcessQ(&frame);
if (ret != NO_ERROR) {
/* TODO: We need to make timeout duration depends on FPS */
if (ret == TIMED_OUT) {
CLOGW("wait timeout");
} else {
CLOGE("Failed to wait&pop m_bayerStreamQ, ret(%d)", ret);
/* TODO: doing exception handling */
}
goto FUNC_EXIT;
}
if (frame == NULL) {
CLOGE("frame is NULL");
goto FUNC_EXIT;
} else if (m_getState() == EXYNOS_CAMERA_STATE_FLUSH) {
CLOGD("[F%d]Flush is in progress.", frame->getFrameCount());
goto FUNC_EXIT;
}
if (frame->getFrameType() != FRAME_TYPE_INTERNAL) {
if (frame->getFrameType() == FRAME_TYPE_JPEG_REPROCESSING)
factory = m_frameFactory[FRAME_FACTORY_TYPE_JPEG_REPROCESSING];
else
factory = m_frameFactory[FRAME_FACTORY_TYPE_REPROCESSING];
request = m_requestMgr->getRunningRequest(frame->getFrameCount());
}
entity = frame->getFrameDoneEntity();
if (entity == NULL) {
CLOGE("Current entity is NULL");
/* TODO: doing exception handling */
goto FUNC_EXIT;
}
pipeId = entity->getPipeId();
CLOG_PERFRAME(PATH, m_cameraId, m_name, frame.get(), nullptr, frame->getRequestKey(), "pipeId(%d)", pipeId);
CLOGD("[F%d T%d]Bayer Processing done. entityID %d",
frame->getFrameCount(), frame->getFrameType(), pipeId);
switch (pipeId) {
case PIPE_LLS_REPROCESSING:
/* get source buffer */
ret = frame->getSrcBuffer(entity->getPipeId(), &srcBuffer);
if (ret != NO_ERROR || srcBuffer.index < 0) {
CLOGE("[F%d B%d]Failed to getSrcBuffer. pipeId %d, ret %d",
frame->getFrameCount(), srcBuffer.index, entity->getPipeId(), ret);
ret = INVALID_OPERATION;
goto FUNC_EXIT;
}
ret = frame->getSrcBufferState(entity->getPipeId(), &bufferState);
if (ret < 0) {
CLOGE("getSrcBufferState fail, pipeId(%d), ret(%d)",
entity->getPipeId(), ret);
goto FUNC_EXIT;
}
if (bufferState == ENTITY_BUFFER_STATE_ERROR) {
CLOGE("Src buffer state is error index(%d), framecount(%d), pipeId(%d)",
srcBuffer.index, frame->getFrameCount(), entity->getPipeId());
ret = INVALID_OPERATION;
goto FUNC_EXIT;
}
/*
* if the frame is not internal frame, move the dst buffer
* to source position for reprocessing
*/
if (frame->getFrameType() != FRAME_TYPE_INTERNAL) {
/* get dst buffer */
ret = frame->getDstBuffer(entity->getPipeId(), &buffer);
if (ret != NO_ERROR || buffer.index < 0) {
CLOGE("[F%d B%d]Failed to getDstBuffer. pipeId %d, ret %d",
frame->getFrameCount(), buffer.index, entity->getPipeId(), ret);
ret = INVALID_OPERATION;
goto FUNC_EXIT;
}
ret = frame->getDstBufferState(entity->getPipeId(), &bufferState);
if (ret < 0) {
CLOGE("getDstBufferState fail, pipeId(%d), ret(%d)", entity->getPipeId(), ret);
goto FUNC_EXIT;
}
if (bufferState == ENTITY_BUFFER_STATE_ERROR) {
CLOGE("Dst buffer state is error index(%d), framecount(%d), pipeId(%d)",
buffer.index, frame->getFrameCount(), entity->getPipeId());
ret = INVALID_OPERATION;
goto FUNC_EXIT;
}
/* memcpy meta data to dst buf from src buf */
memcpy((struct camera2_shot_ext *)srcBuffer.addr[srcBuffer.getMetaPlaneIndex()],
(struct camera2_shot_ext *)buffer.addr[buffer.getMetaPlaneIndex()],
sizeof(struct camera2_shot_ext));
/* cache clean */
if (m_ionClient >= 0) {
for (int i = 0; i < buffer.getMetaPlaneIndex(); i++)
exynos_ion_sync_fd(m_ionClient, buffer.fd[i]);
}
m_setSrcBuffer(PIPE_ISP_REPROCESSING, frame, &buffer);
if (ret < 0) {
CLOGE("[F%d B%d]Failed to setSrcBuffer. pipeId %d ret %d",
frame->getFrameCount(), buffer.index,
PIPE_ISP_REPROCESSING, ret);
goto FUNC_EXIT;
}
}
/* release source buffer */
if (srcBuffer.index >= 0) {
ret = m_releaseSelectorTagBuffers(frame);
if (ret < 0) {
CLOGE("Failed to releaseSelectorTagBuffers. frameCount %d ret %d",
frame->getFrameCount(), ret);
goto FUNC_EXIT;
}
}
/* frame complete for internal frame */
if (frame->getFrameType() == FRAME_TYPE_INTERNAL) {
frame->setFrameState(FRAME_STATE_COMPLETE);
goto FUNC_EXIT;
}
break;
default:
CLOGE("Invalid pipeId %d", entity->getPipeId());
break;
}
ret = frame->setEntityState(pipeId, ENTITY_STATE_COMPLETE);
if (ret < 0) {
CLOGE("setEntityState fail, pipeId(%d), state(%d), ret(%d)",
entity->getPipeId(), ENTITY_STATE_COMPLETE, ret);
return ret;
}
m_captureQ->pushProcessQ(&frame);
FUNC_EXIT:
if (frame != NULL && frame->isComplete() == true && m_getState() != EXYNOS_CAMERA_STATE_FLUSH) {
/* error case */
if (frame->getFrameType() != FRAME_TYPE_INTERNAL && ret < 0) {
ret = m_sendNotifyError(request, EXYNOS_REQUEST_RESULT::ERROR_REQUEST);
if (ret != NO_ERROR) {
CLOGE("[F%d B%d] sendNotifyError fail. ret %d",
frame->getFrameCount(), buffer.index, ret);
}
}
if (frame->getPipeIdForResultUpdate(ExynosCameraFrame::RESULT_UPDATE_TYPE_ALL) == pipeId
&& (frame->isReadyForResultUpdate(ExynosCameraFrame::RESULT_UPDATE_TYPE_ALL) == true)) {
struct camera2_shot_ext resultShot;
ExynosCameraRequestSP_sprt_t request = NULL;
ret = frame->getMetaData(&resultShot);
if (ret != NO_ERROR) {
CLOGE("[F%d]Failed to getMetaData. ret %d", frame->getFrameCount(), ret);
}
request = m_requestMgr->getRunningRequest(frame->getFrameCount());
if (request == NULL) {
CLOGE("getRequest failed ");
return INVALID_OPERATION;
}
ret = m_updateResultShot(request, &resultShot);
if (ret != NO_ERROR) {
CLOGE("[F%d(%d)]Failed to m_updateResultShot. ret %d",
frame->getFrameCount(), resultShot.shot.dm.request.frameCount, ret);
}
ret = m_sendMeta(request, EXYNOS_REQUEST_RESULT::CALLBACK_ALL_RESULT);
if (ret != NO_ERROR) {
CLOGE("[F%d]Failed to sendMeta. ret %d", frame->getFrameCount(), ret);
}
}
List<ExynosCameraFrameSP_sptr_t> *list = NULL;
Mutex *listLock = NULL;
list = &m_captureProcessList;
listLock = &m_captureProcessLock;
// TODO:decide proper position
CLOGD("frame complete. framecount %d", frame->getFrameCount());
ret = m_removeFrameFromList(list, listLock, frame);
if (ret < 0) {
CLOGE("remove frame from processList fail, ret(%d)", ret);
}
frame = NULL;
}
{
Mutex::Autolock l(m_captureProcessLock);
if (m_captureProcessList.size() > 0)
return true;
else
return false;
}
}
status_t ExynosCamera::m_selectBayerHandler(uint32_t pipeID, ExynosCameraFrameSP_sptr_t frame, ExynosCameraBuffer *bayerBuffer,__unused ExynosCameraFrameSP_sptr_t bayerFrame, ExynosCameraFrameFactory *factory)
{
status_t ret = NO_ERROR;
buffer_manager_tag_t bufTag;
ExynosCameraBuffer dstBuffer;
bool needBayerProcessingThread = false;
camera2_stream *shot_stream = NULL;
ExynosRect cropRect;
/* dstbuffer setting */
switch (pipeID) {
case PIPE_LLS_REPROCESSING:
#ifdef SUPPORT_ME
{
/* ME buffer setting */
int meSrcPipeId = m_parameters[m_cameraId]->getLeaderPipeOfMe();
int dstPos = m_frameFactory[FRAME_FACTORY_TYPE_CAPTURE_PREVIEW]->getNodeType(PIPE_ME);
ExynosCameraBuffer meBuffer;
bayerFrame->getDstBuffer(meSrcPipeId, &meBuffer, dstPos);
if (meBuffer.index < 0) {
CLOGE("getDstBuffer fail, pipeId(%d), dstPos(%d) ret(%d)",
meSrcPipeId, dstPos, ret);
} else {
/* move to buffer position and set */
ret = frame->setSrcBuffer(pipeID, meBuffer, OUTPUT_NODE_2);
if (ret < 0) {
CLOGE("[F%d B%d]Failed to setSrcBuffer. pipeId %d ret %d",
frame->getFrameCount(), meBuffer.index, pipeID, ret);
}
frame->addSelectorTag(m_captureSelector[m_cameraId]->getId(),
pipeID, OUTPUT_NODE_2, true /* isSrc */);
}
}
#endif
/* bayer buffer setting */
shot_stream = (camera2_stream *)bayerBuffer->addr[bayerBuffer->getMetaPlaneIndex()];
cropRect.x = shot_stream->output_crop_region[0];
cropRect.y = shot_stream->output_crop_region[1];
cropRect.w = shot_stream->output_crop_region[2];
cropRect.h = shot_stream->output_crop_region[3];
cropRect.fullW = shot_stream->output_crop_region[2];
cropRect.fullH = shot_stream->output_crop_region[3];
cropRect.colorFormat = m_parameters[m_cameraId]->getBayerFormat(PIPE_ISP_REPROCESSING);
ret = frame->setSrcRect(pipeID, cropRect);
if (ret < 0)
CLOGE("[F%d]Failed to setSrcRect. ret %d", frame->getFrameCount(), ret);
ret = frame->setDstRect(pipeID, cropRect);
if (ret < 0)
CLOGE("[F%d]Failed to setDstRect. ret %d", frame->getFrameCount(), ret);
/* getting dst buffer in last frame */
if (frame->getFrameType() != FRAME_TYPE_INTERNAL
#ifdef USE_LLS_REPROCESSING
&& frame->getFrameIndex() == (m_parameters[m_cameraId]->getLLSCaptureCount())
#endif
) {
bufTag.pipeId[0] = pipeID;
bufTag.managerType = BUFFER_MANAGER_ION_TYPE;
ret = m_bufferSupplier->getBuffer(bufTag, &dstBuffer);
if (ret < 0 || dstBuffer.index < 0) {
CLOGE("[F%d B%d]Failed to get dstBuffer. ret %d",
frame->getFrameCount(), dstBuffer.index, ret);
}
} else {
frame->setDstBufferState(pipeID, ENTITY_BUFFER_STATE_NOREQ);
if (ret < 0)
CLOGE("[F%d]Failed to set dstBuffer state. ret %d", frame->getFrameCount(), ret);
}
break;
default:
break;
}
ret = m_setupEntity(pipeID, frame, bayerBuffer, dstBuffer.index < 0 ? NULL : &dstBuffer);
if (ret < 0) {
CLOGE("setupEntity fail, bayerPipeId(%d), ret(%d)",
pipeID, ret);
goto CLEAN;
}
/* add selectorTag to release all buffers after done of these buffers */
frame->addSelectorTag(m_captureSelector[m_cameraId]->getId(),
pipeID, OUTPUT_NODE_1, true /* isSrc */);
/* queing for different path */
switch (pipeID) {
case PIPE_LLS_REPROCESSING:
factory->setOutputFrameQToPipe(m_bayerStreamQ, pipeID);
factory->pushFrameToPipe(frame, pipeID);
needBayerProcessingThread = true;
break;
default:
m_captureQ->pushProcessQ(&frame);
break;
}
if (needBayerProcessingThread == true &&
m_bayerStreamThread != NULL && m_bayerStreamThread->isRunning() == false) {
m_bayerStreamThread->run();
CLOGI("Initiate bayerStreamThread (%d)", m_bayerStreamThread->getTid());
} else {
CLOGI("bayerStreamThread (%d, %d, run:%d)",
needBayerProcessingThread, m_bayerStreamThread != NULL,
m_bayerStreamThread->isRunning());
}
CLEAN:
return ret;
}
}; /* namespace android */