blob: 5ca25852ea7db741b1824d79f7db4fecdb90c601 [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"
namespace android {
#ifdef MONITOR_LOG_SYNC
uint32_t ExynosCamera::cameraSyncLogId = 0;
#endif
ExynosCamera::ExynosCamera(int cameraId,
camera_metadata_t **info,
#ifndef USE_DUAL_CAMERA
__unused
#endif
uint32_t numOfSensors):
m_requestMgr(NULL),
m_streamManager(NULL),
m_activityControl(NULL)
{
//BUILD_DATE();
m_cameraOriginId = cameraId;
if (m_cameraOriginId == CAMERA_ID_SECURE) {
m_cameraIds[0] = CAMERA_ID_FRONT;
m_scenario = SCENARIO_SECURE;
} else {
m_cameraIds[0] = m_cameraOriginId;
m_scenario = SCENARIO_NORMAL;
}
m_cameraId = m_cameraIds[0];
#ifdef USE_DUAL_CAMERA
if (numOfSensors >= 2) {
switch (m_cameraOriginId) {
case CAMERA_ID_BACK_0:
m_cameraIds[1] = CAMERA_ID_BACK_1;
m_scenario = SCENARIO_DUAL_CAMERA;
break;
case CAMERA_ID_FRONT_0:
m_cameraIds[1] = CAMERA_ID_FRONT_1;
m_scenario = SCENARIO_DUAL_CAMERA;
break;
default:
break;
}
CLOGI("Dual cameara enabled! CameraId (%d & %d)", m_cameraIds[0], m_cameraIds[1]);
}
#endif
switch (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)", cameraId);
break;
}
/* 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_captureZslSelector = NULL;
m_vendorSpecificPreConstructor(m_cameraId);
/* Create related classes */
switch (m_scenario) {
case SCENARIO_SECURE:
m_parameters[m_cameraId] = new ExynosCameraParameters(m_cameraOriginId);
break;
#ifdef USE_DUAL_CAMERA
case SCENARIO_DUAL_CAMERA:
m_parameters[m_cameraIds[1]] = new ExynosCameraParameters(m_cameraIds[1]);
/* No break: m_parameters[0] is same with normal */
#endif
case SCENARIO_NORMAL:
default:
m_parameters[m_cameraId] = new ExynosCameraParameters(m_cameraId);
break;
}
m_activityControl = m_parameters[m_cameraId]->getActivityControl();
m_metadataConverter = new ExynosCameraMetadataConverter(m_cameraOriginId, m_parameters[m_cameraId]);
m_requestMgr = new ExynosCameraRequestManager(m_cameraOriginId, m_parameters[m_cameraId]);
m_requestMgr->setMetaDataConverter(m_metadataConverter);
/* Create managers */
m_createManagers();
/* Create threads */
m_createThreads();
/* Create queue for preview path. If you want to control pipeDone in ExynosCamera, try to create frame queue here */
m_shotDoneQ = new ExynosCameraList<uint32_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;
}
}
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 USE_DUAL_CAMERA
if (m_scenario == SCENARIO_DUAL_CAMERA) {
m_dualShotDoneQ = new ExynosCameraList<uint32_t>();
m_pipeFrameDoneQ[PIPE_DCP] = new frame_queue_t;
m_pipeFrameDoneQ[PIPE_SYNC] = new frame_queue_t;
m_pipeFrameDoneQ[PIPE_FUSION] = new frame_queue_t;
m_dualTransitionCount = DUAL_TRANSITION_FRAME_COUNT;
} else {
m_dualShotDoneQ = NULL;
m_pipeFrameDoneQ[PIPE_SYNC] = NULL;
m_pipeFrameDoneQ[PIPE_FUSION] = NULL;
m_dualTransitionCount = 0;
}
#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_shotDoneQ->setWaitTime(4000000000);
m_frameFactoryQ = new framefactory3_queue_t;
m_selectBayerQ = new frame_queue_t();
m_captureQ = new frame_queue_t(m_captureThread);
#ifdef SUPPORT_HW_GDC
m_gdcQ = new frame_queue_t(m_gdcThread);
#endif
/* construct static meta data information */
if (ExynosCameraMetadataConverter::constructStaticInfo(m_cameraOriginId, info))
CLOGE("Create static meta data failed!!");
m_metadataConverter->setStaticInfo(m_cameraOriginId, *info);
m_streamManager->setYuvStreamMaxCount(m_parameters[m_cameraId]->getYuvStreamMaxNum());
m_setFrameManager();
m_setConfigInform();
/* init infomation of fd orientation*/
m_parameters[m_cameraId]->setDeviceOrientation(0);
ExynosCameraActivityUCTL *uctlMgr = m_activityControl->getUCTLMgr();
if (uctlMgr != NULL) {
uctlMgr->setDeviceRotation(m_parameters[m_cameraId]->getFdOrientation());
}
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_firstRequestFrameNumber = 0;
m_internalFrameCount = 1;
m_isNeedRequestFrame = false;
m_currentPreviewShot = new struct camera2_shot_ext;
memset(m_currentPreviewShot, 0x00, sizeof(struct camera2_shot_ext));
m_currentCaptureShot = new struct camera2_shot_ext;
memset(m_currentCaptureShot, 0x00, sizeof(struct camera2_shot_ext));
#ifdef MONITOR_LOG_SYNC
m_syncLogDuration = 0;
#endif
m_lastFrametime = 0;
#ifdef YUV_DUMP
m_dumpFrameQ = new frame_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_needDynamicBayerCount = 0;
m_flagFirstPreviewTimerOn = false;
/* 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 */
exynosConfig.info[CONFIG_MODE::NORMAL].bufInfo.num_fastaestable_buffer = NUM_FASTAESTABLE_BUFFERS;
exynosConfig.info[CONFIG_MODE::NORMAL].bufInfo.num_sensor_buffers = NUM_SENSOR_BUFFERS;
exynosConfig.info[CONFIG_MODE::NORMAL].bufInfo.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.reprocessing_bayer_hold_count = REPROCESSING_BAYER_HOLD_COUNT;
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;
#ifdef USE_DUAL_CAMERA
exynosConfig.info[CONFIG_MODE::NORMAL].bufInfo.num_preview_buffers = VIDEO_MAX_FRAME - NUM_FUSION_BUFFERS;
#else
exynosConfig.info[CONFIG_MODE::NORMAL].bufInfo.num_preview_buffers = VIDEO_MAX_FRAME;
#endif
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 */
exynosConfig.info[CONFIG_MODE::NORMAL].bufInfo.num_request_raw_buffers = NUM_REQUEST_RAW_BUFFER;
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_jpeg_buffers = NUM_REQUEST_JPEG_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 */
exynosConfig.info[CONFIG_MODE::HIGHSPEED_60].bufInfo.num_fastaestable_buffer = NUM_FASTAESTABLE_BUFFERS;
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.reprocessing_bayer_hold_count = REPROCESSING_BAYER_HOLD_COUNT;
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 */
exynosConfig.info[CONFIG_MODE::HIGHSPEED_60].bufInfo.num_request_raw_buffers = NUM_REQUEST_RAW_BUFFER;
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_jpeg_buffers = NUM_REQUEST_JPEG_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.reprocessing_bayer_hold_count = REPROCESSING_BAYER_HOLD_COUNT;
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_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_jpeg_buffers = FPS120_NUM_REQUEST_JPEG_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.reprocessing_bayer_hold_count = REPROCESSING_BAYER_HOLD_COUNT;
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_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_jpeg_buffers = FPS240_NUM_REQUEST_JPEG_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;
#endif
m_parameters[m_cameraId]->setConfig(&exynosConfig);
#ifdef USE_DUAL_CAMERA
if (m_scenario == SCENARIO_DUAL_CAMERA
&& m_parameters[m_cameraIds[1]] != NULL) {
m_parameters[m_cameraIds[1]]->setConfig(&exynosConfig);
}
#endif
m_exynosconfig = m_parameters[m_cameraId]->getConfig();
return NO_ERROR;
}
status_t ExynosCamera::m_checkStreamInfo(void)
{
status_t ret = NO_ERROR;
/* Check PIP Mode Limitation
* Max number of YUV stream for each device: 1
* Max size of YUV stream: FHD(1080p)
* Each limitation is defined at config.h
*/
if (m_parameters[m_cameraId]->getPIPMode() == true) {
int yuvStreamCount = m_streamManager->getYuvStreamCount();
int maxYuvW = 0, maxYuvH = 0;
m_parameters[m_cameraId]->getMaxYuvSize(&maxYuvW, &maxYuvH);
if (yuvStreamCount > PIP_CAMERA_MAX_YUV_STREAM
|| maxYuvH > PIP_CAMERA_MAX_YUV_HEIGHT
|| (maxYuvW * maxYuvH) > PIP_CAMERA_MAX_YUV_SIZE) {
CLOGW("PIP mode NOT support this configuration. " \
"YUVStreamCount %d MaxYUVSize %dx%d",
yuvStreamCount, maxYuvW, maxYuvH);
ret = BAD_VALUE;
}
}
return ret;
}
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 mainCameraThread(this, &ExynosCamera::m_previewStreamBayerPipeThreadFunc, "PreviewBayerThread");
CLOGD("Bayer Preview stream thread created");
m_previewStream3AAThread = new mainCameraThread(this, &ExynosCamera::m_previewStream3AAPipeThreadFunc, "Preview3AAThread");
CLOGD("3AA Preview stream thread created");
m_previewStreamISPThread = new mainCameraThread(this, &ExynosCamera::m_previewStreamISPPipeThreadFunc, "PreviewISPThread");
CLOGD("ISP Preview stream thread created");
m_previewStreamMCSCThread = new mainCameraThread(this, &ExynosCamera::m_previewStreamMCSCPipeThreadFunc, "PreviewMCSCThread");
CLOGD("MCSC Preview stream thread created");
#ifdef SUPPORT_HW_GDC
m_previewStreamGDCThread = new mainCameraThread(this, &ExynosCamera::m_previewStreamGDCPipeThreadFunc, "PreviewGDCThread");
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_CAMERA) {
m_previewStreamDCPThread = new mainCameraThread(this, &ExynosCamera::m_previewStreamDCPPipeThreadFunc, "PreviewDCPThread");
CLOGD("DCP Preview stream thread created");
m_dualMainThread = new mainCameraThread(this, &ExynosCamera::m_dualMainThreadFunc, "m_dualMainThreadFunc");
CLOGD("Dual Main 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");
}
#endif
m_selectBayerThread = new mainCameraThread(this, &ExynosCamera::m_selectBayerThreadFunc, "SelectBayerThreadFunc");
CLOGD("SelectBayerThread 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");
#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 YUV_DUMP
m_dumpThread = new mainCameraThread(this, &ExynosCamera::m_dumpThreadFunc, "m_dumpThreadFunc");
CLOGD("DumpThread created");
#endif
m_vendorCreateThreads();
}
ExynosCamera::~ExynosCamera()
{
this->release();
}
void ExynosCamera::release()
{
CLOGI("-IN-");
m_vendorSpecificPreDestructor();
if (m_bufferSupplier != NULL) {
delete m_bufferSupplier;
m_bufferSupplier = NULL;
}
if (m_ionAllocator != NULL) {
delete m_ionAllocator;
m_ionAllocator = NULL;
}
if (m_shotDoneQ != NULL) {
delete m_shotDoneQ;
m_shotDoneQ = NULL;
}
#ifdef USE_DUAL_CAMERA
if (m_dualShotDoneQ != NULL) {
delete m_dualShotDoneQ;
m_dualShotDoneQ = 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_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;
}
#ifdef SUPPORT_HW_GDC
if (m_gdcQ != NULL) {
delete m_gdcQ;
m_gdcQ = NULL;
}
#endif
#ifdef YUV_DUMP
if (m_dumpFrameQ != NULL) {
delete m_dumpFrameQ;
m_dumpFrameQ = 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_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_currentPreviewShot != NULL) {
delete m_currentPreviewShot;
m_currentPreviewShot = NULL;
}
if (m_currentCaptureShot != NULL) {
delete m_currentCaptureShot;
m_currentCaptureShot = NULL;
}
if (m_ionClient >= 0) {
exynos_ion_close(m_ionClient);
m_ionClient = -1;
}
// TODO: clean up
// m_resultBufferVectorSet
// m_processList
// m_postProcessList
// m_pipeFrameDoneQ
m_vendorSpecificDestructor();
/* 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_parameters[m_cameraId], m_bufferSupplier, m_frameMgr);
ret = m_captureSelector[m_cameraId]->setFrameHoldCount(REPROCESSING_BAYER_HOLD_COUNT);
if (ret < 0) {
CLOGE("m_captureSelector[%d] setFrameHoldCount(%d) is fail",
m_cameraId, REPROCESSING_BAYER_HOLD_COUNT);
}
}
#ifdef USE_DUAL_CAMERA
if (m_parameters[m_cameraId]->getDualMode() == true
&& m_captureSelector[m_cameraIds[1]] == NULL) {
m_captureSelector[m_cameraIds[1]] = new ExynosCameraFrameSelector(m_cameraIds[1], 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_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::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 -ENODEV;
}
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;
}
int ExynosCamera::getCameraIdOrigin() const
{
return m_cameraOriginId;
}
status_t ExynosCamera::setPIPMode(bool enabled)
{
if (m_parameters[m_cameraId] == NULL) {
CLOGE("m_parameters[m_cameraId] is NULL");
return INVALID_OPERATION;
}
m_parameters[m_cameraId]->setPIPMode(enabled);
return NO_ERROR;
}
bool ExynosCamera::getAvailablePIPMode(void)
{
exynos_camera_state_t state = m_getState();
if (state == EXYNOS_CAMERA_STATE_CONFIGURED
|| state == EXYNOS_CAMERA_STATE_START
|| state == EXYNOS_CAMERA_STATE_RUN) {
return false;
} else {
return true;
}
}
#ifdef USE_DUAL_CAMERA
status_t ExynosCamera::setDualMode(bool enabled)
{
if (m_parameters[m_cameraId] == NULL) {
CLOGE("m_parameters[m_cameraId] is NULL");
return INVALID_OPERATION;
}
m_parameters[m_cameraId]->setDualMode(enabled);
if (m_parameters[m_cameraIds[1]] != NULL) {
m_parameters[m_cameraIds[1]]->setDualMode(enabled);
}
return NO_ERROR;
}
bool ExynosCamera::getDualMode(void)
{
if (m_parameters[m_cameraId] == NULL) {
CLOGE("m_parameters[m_cameraId] is NULL");
return false;
}
return m_parameters[m_cameraId]->getDualMode();
}
#endif
bool ExynosCamera::m_mainPreviewThreadFunc(void)
{
status_t ret = NO_ERROR;
if (m_getState() != EXYNOS_CAMERA_STATE_RUN) {
CLOGI("Wait to run FrameFactory");
usleep(1);
return true;
}
if (m_parameters[m_cameraId]->getVisionMode() == false) {
ret = m_createPreviewFrameFunc(REQ_SYNC_WITH_3AA);
} else {
ret = m_createVisionFrameFunc(REQ_SYNC_WITH_3AA);
}
if (ret != NO_ERROR) {
CLOGE("Failed to createPreviewFrameFunc. Shotdone");
}
return true;
}
bool ExynosCamera::m_mainCaptureThreadFunc(void)
{
status_t ret = NO_ERROR;
if (m_getState() != EXYNOS_CAMERA_STATE_RUN) {
CLOGI("Wait to run FrameFactory");
usleep(1);
return true;
}
ret = m_createCaptureFrameFunc();
if (ret != NO_ERROR) {
CLOGE("Failed to createCaptureFrameFunc. Shotdone");
}
if (m_getSizeFromRequestList(&m_requestCaptureWaitingList, &m_requestCaptureWaitingLock) > 0) {
return true;
} else {
return false;
}
}
#ifdef USE_DUAL_CAMERA
bool ExynosCamera::m_dualMainThreadFunc(void)
{
uint32_t frameCount = 0;
status_t ret = NO_ERROR;
if (m_getState() != EXYNOS_CAMERA_STATE_RUN) {
CLOGI("Wait to run FrameFactory");
usleep(1);
return true;
}
/* 1. Wait the shot done with the latest framecount */
ret = m_dualShotDoneQ->waitAndPopProcessQ(&frameCount);
if (ret < 0) {
if (ret == TIMED_OUT)
CLOGW("wait timeout");
else
CLOGE("wait and pop fail, ret(%d)", ret);
return true;
}
switch (m_parameters[m_cameraId]->getDualOperationMode()) {
case DUAL_OPERATION_MODE_MASTER:
if (m_parameters[m_cameraId]->isSupportSlaveSensorStandby() == false) {
break;
}
return false;
case DUAL_OPERATION_MODE_SLAVE:
if (m_parameters[m_cameraId]->isSupportMasterSensorStandby() == false) {
break;
}
return false;
case DUAL_OPERATION_MODE_SYNC:
return false;
}
ret = m_createInternalFrameFunc(NULL, REQ_SYNC_NONE, FRAME_TYPE_TRANSITION);
if (ret != NO_ERROR)
CLOGE("Failed to createFrameFunc. Shotdone");
return true;
}
#endif
status_t ExynosCamera::m_createPreviewFrameFunc(enum Request_Sync_Type syncType)
{
status_t ret = NO_ERROR;
ExynosCameraRequestSP_sprt_t request = NULL;
struct camera2_shot_ext *service_shot_ext = NULL;
FrameFactoryList previewFactoryAddrList;
FrameFactoryListIterator factorylistIter;
factory_handler_t frameCreateHandler;
List<ExynosCameraRequestSP_sprt_t>::iterator r;
ExynosCameraFrameFactory *factory = NULL;
frame_type_t frameType = FRAME_TYPE_PREVIEW;
#ifdef USE_DUAL_CAMERA
ExynosCameraFrameFactory *subFactory = NULL;
frame_type_t subFrameType = FRAME_TYPE_PREVIEW;
#endif
uint32_t waitingListSize;
uint32_t requiredRequestCount = -1;
#ifdef DEBUG_STREAM_CONFIGURATIONS
CLOGD("DEBUG_STREAM_CONFIGURATIONS::[R%d] generate request frame", request->getKey());
#endif
m_waitShotDone(syncType);
m_captureResultDoneCondition.signal();
/* 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;
/* 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 {
memcpy(m_currentPreviewShot, service_shot_ext, sizeof(struct camera2_shot_ext));
}
/* 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, waitingListSize);
/* 3. Select the frame creation logic between request frame and internal frame */
if (m_isNeedRequestFrame == true) {
#ifdef USE_DUAL_CAMERA
if (m_parameters[m_cameraId]->getDualMode() == true) {
m_checkDualOperationMode(request);
if (ret != NO_ERROR) {
CLOGE("m_checkDualOperationMode fail! ret(%d)", ret);
}
}
#endif
previewFactoryAddrList.clear();
request->getFactoryAddrList(FRAME_FACTORY_TYPE_CAPTURE_PREVIEW, &previewFactoryAddrList);
m_parameters[m_cameraId]->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_VISION:
frameType = FRAME_TYPE_VISION;
break;
default:
CLOGE("[R%d] Factory type is not available", request->getKey());
break;
}
#ifdef USE_DUAL_CAMERA
if (m_parameters[m_cameraId]->getDualMode() == true) {
enum DUAL_OPERATION_MODE dualOperationMode = m_parameters[m_cameraId]->getDualOperationMode();
switch(factory->getFactoryType()) {
case FRAME_FACTORY_TYPE_CAPTURE_PREVIEW:
if (dualOperationMode == DUAL_OPERATION_MODE_SYNC) {
subFrameType = FRAME_TYPE_PREVIEW_DUAL_SLAVE;
subFactory = m_frameFactory[FRAME_FACTORY_TYPE_PREVIEW_DUAL];
frameCreateHandler = subFactory->getFrameCreateHandler();
(this->*frameCreateHandler)(request, subFactory, subFrameType);
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];
}
break;
default:
CLOGE("[R%d] Factory type is not available", request->getKey());
break;
}
}
#endif
frameCreateHandler = factory->getFrameCreateHandler();
(this->*frameCreateHandler)(request, factory, frameType);
factorylistIter++;
}
} else {
m_createInternalFrameFunc(request, syncType);
#ifdef USE_DUAL_CAMERA
if (m_parameters[m_cameraId]->getDualMode() == true
&& m_parameters[m_cameraId]->getDualOperationMode() == DUAL_OPERATION_MODE_SYNC) {
m_createInternalFrameFunc(request, syncType, FRAME_TYPE_PREVIEW_DUAL_SLAVE);
}
#endif
}
} else {
m_createInternalFrameFunc(NULL, syncType);
#ifdef USE_DUAL_CAMERA
if (m_parameters[m_cameraId]->getDualMode() == true
&& m_parameters[m_cameraId]->getDualOperationMode() == DUAL_OPERATION_MODE_SYNC) {
m_createInternalFrameFunc(NULL, syncType, FRAME_TYPE_PREVIEW_DUAL_SLAVE);
}
#endif
}
previewFactoryAddrList.clear();
return ret;
}
status_t ExynosCamera::m_createVisionFrameFunc(enum Request_Sync_Type syncType)
{
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;
#ifdef DEBUG_STREAM_CONFIGURATIONS
CLOGD("DEBUG_STREAM_CONFIGURATIONS::[R%d] generate request frame", request->getKey());
#endif
m_waitShotDone(syncType);
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 {
memcpy(m_currentPreviewShot, service_shot_ext, sizeof(struct camera2_shot_ext));
}
/* 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:
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, syncType);
}
} else {
m_createInternalFrameFunc(NULL, syncType);
}
visionFactoryAddrList.clear();
return ret;
}
status_t ExynosCamera::m_waitShotDone(enum Request_Sync_Type syncType)
{
status_t ret = NO_ERROR;
uint32_t frameCount = 0;
if (syncType == REQ_SYNC_WITH_3AA && m_shotDoneQ != NULL) {
/* 1. Wait the shot done with the latest framecount */
ret = m_shotDoneQ->waitAndPopProcessQ(&frameCount);
if (ret < 0) {
if (ret == TIMED_OUT)
CLOGW("wait timeout");
else
CLOGE("wait and pop fail, ret(%d)", ret);
return ret;
}
}
return ret;
}
status_t ExynosCamera::m_sendVisionStreamResult(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 VISION */
ret = m_streamManager->getStream(HAL_STREAM_ID_VISION, &stream);
if (ret < 0) {
CLOGE("getStream is failed, from streammanager. Id error:HAL_STREAM_ID_VISION");
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_VISION",
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_VISION",
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_VISION",
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_VISION");
return ret;
}
/* 3. Get the bayer buffer from frame */
streamBuffer->buffer = buffer->handle[0];
/* 4. Get the service buffer handle from buffer manager */
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_VISION);
return ret;
}
/* 5. Update the remained buffer info */
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_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;
CameraMetadata resultMeta;
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();
resultMeta = *(request->getServiceMeta());
request->setRequestUnlock();
requestResult->frame_number = frameNumber;
requestResult->result = resultMeta.release();
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(%llu)", requestKey, (unsigned long long)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;
}
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) {
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) {
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) {
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);
ALOGV("[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 flag = 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_ZSL_OUTPUT);
SET_STREAM_CONFIG_BIT(targetBit, HAL_STREAM_ID_DEPTHMAP);
flag = (COMPARE_STREAM_CONFIG_BIT(streamConfigBit, targetBit) > 0) ? true : false;
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);
flag &= (COMPARE_STREAM_CONFIG_BIT(streamConfigBit, targetBit) == 0) ? true : false;
break;
case FRAME_TYPE_REPROCESSING:
#ifdef USE_DUAL_CAMERA
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);
flag = (COMPARE_STREAM_CONFIG_BIT(streamConfigBit, targetBit) > 0) ? true : false;
break;
case FRAME_TYPE_VISION:
targetBit = 0;
SET_STREAM_CONFIG_BIT(targetBit, HAL_STREAM_ID_VISION);
flag = (COMPARE_STREAM_CONFIG_BIT(streamConfigBit, targetBit) > 0) ? true : false;
break;
default:
CLOGE("[F%d]Unsupported frame type %d", frame->getFrameCount(), frameType);
break;
}
frame->setUpdateResult(flag);
CLOGV("[F%d T%d]%s Result. streamConfig %x",
frame->getFrameCount(),
frame->getFrameType(),
(flag == true) ? "Update" : "Skip",
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)
{
#ifdef DEBUG
ExynosCameraAutoTimer autoTimer(__FUNCTION__);
#endif
bool loop = false;
status_t ret = NO_ERROR;
ExynosCameraFrameFactory *framefactory = NULL;
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");
framefactory->create();
} 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;
/* prepare pipes */
ret = factory->preparePipes();
if (ret < 0) {
CLOGW("Failed to prepare FLITE");
}
/* stream on pipes */
ret = factory->startPipes();
if (ret < 0) {
CLOGE("startPipe fail");
return ret;
}
/* start all thread */
ret = factory->startInitialThreads();
if (ret < 0) {
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) {
ret = m_frameFactory[i]->destroy();
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_setSetfile(void) {
int configMode = m_parameters[m_cameraId]->getConfigMode();
int setfile = 0;
int setfileReprocessing = 0;
int yuvRange = YUV_FULL_RANGE;
int yuvRangeReprocessing = YUV_FULL_RANGE;
uint32_t minFps = 0, maxFps = 0;
switch (configMode) {
case CONFIG_MODE::NORMAL:
m_parameters[m_cameraId]->checkSetfileYuvRange();
/* general */
m_parameters[m_cameraId]->getSetfileYuvRange(false, &setfile, &yuvRange);
/* reprocessing */
m_parameters[m_cameraId]->getSetfileYuvRange(true, &setfileReprocessing, &yuvRangeReprocessing);
break;
case CONFIG_MODE::HIGHSPEED_60:
setfile = ISS_SUB_SCENARIO_FHD_60FPS;
setfileReprocessing = ISS_SUB_SCENARIO_VIDEO_HIGH_SPEED;
yuvRange = YUV_LIMITED_RANGE;
break;
case CONFIG_MODE::HIGHSPEED_120:
setfile = ISS_SUB_SCENARIO_VIDEO_HIGH_SPEED;
setfileReprocessing = ISS_SUB_SCENARIO_VIDEO_HIGH_SPEED;
yuvRange = YUV_LIMITED_RANGE;
break;
case CONFIG_MODE::HIGHSPEED_240:
m_parameters[m_cameraId]->getPreviewFpsRange(&minFps, &maxFps);
if (maxFps == 120) {
setfile = ISS_SUB_SCENARIO_VIDEO_HIGH_SPEED;
} else {
setfile = ISS_SUB_SCENARIO_FHD_240FPS;
}
setfileReprocessing = ISS_SUB_SCENARIO_VIDEO_HIGH_SPEED;
yuvRange = YUV_LIMITED_RANGE;
break;
default:
CLOGE("configMode is abnormal(%d)", configMode);
break;
}
CLOGI("configMode(%d), PIPMode(%d)", configMode, m_parameters[m_cameraId]->getPIPMode());
/* reprocessing */
m_parameters[m_cameraId]->setSetfileYuvRange(true, setfileReprocessing, yuvRangeReprocessing);
/* preview */
m_parameters[m_cameraId]->setSetfileYuvRange(false, setfile, yuvRange);
return NO_ERROR;
}
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;
uint32_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 flagMcscVraM2M = (m_parameters[cameraId]->getHwConnectionMode(PIPE_MCSC, PIPE_VRA) == HW_CONNECTION_MODE_M2M);
#ifdef USE_DUAL_CAMERA
bool flagIspDcpM2M = (m_parameters[cameraId]->getHwConnectionMode(PIPE_ISP, PIPE_DCP) == HW_CONNECTION_MODE_M2M);
bool flagDcpMcscM2M = (m_parameters[cameraId]->getHwConnectionMode(PIPE_DCP, PIPE_MCSC) == HW_CONNECTION_MODE_M2M);
#endif
int flipHorizontal = 0;
enum NODE_TYPE nodeType;
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);
}
/* 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);
pipeId = PIPE_ISP;
}
#ifdef USE_DUAL_CAMERA
if (cameraId == m_cameraId
&& m_parameters[cameraId]->getDualMode() == true
&& m_parameters[cameraId]->getDualPreviewMode() == DUAL_PREVIEW_MODE_HW) {
if (flagIspDcpM2M == 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_DCP;
}
if (flagDcpMcscM2M == 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;
}
} else
#endif
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_parameters[cameraId]->getFlipHorizontal();
nodePipeId = m_streamManager->getOutputPortId(HAL_STREAM_ID_VIDEO);
if (nodePipeId != -1) {
nodePipeId = nodePipeId + PIPE_MCSC0;
nodeType = factory->getNodeType(nodePipeId);
factory->setControl(V4L2_CID_HFLIP, flipHorizontal, pipeId, nodeType);
CLOGD("set FlipHorizontal on preview, FlipHorizontal(%d) Recording pipeId(%d)",
flipHorizontal, nodePipeId);
}
}
if (flagMcscVraM2M == true) {
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
&& m_parameters[cameraId]->getDualMode() == 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 (m_parameters[cameraId]->getDualPreviewMode() == 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;
}
void ExynosCamera::m_updateCropRegion(struct camera2_shot_ext *shot_ext)
{
int sensorMaxW = 0, sensorMaxH = 0;
int cropRegionMinW = 0, cropRegionMinH = 0;
int maxZoom = 0;
m_parameters[m_cameraId]->getMaxSensorSize(&sensorMaxW, &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);
/* 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) shot_ext->shot.ctl.scaler.cropRegion[2]
|| cropRegionMinH > (int) shot_ext->shot.ctl.scaler.cropRegion[3]){
CLOGE("Invalid Crop Size(%d, %d),Change to cropRegionMin(%d, %d)",
shot_ext->shot.ctl.scaler.cropRegion[2],
shot_ext->shot.ctl.scaler.cropRegion[3],
cropRegionMinW, cropRegionMinH);
shot_ext->shot.ctl.scaler.cropRegion[2] = cropRegionMinW;
shot_ext->shot.ctl.scaler.cropRegion[3] = 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) shot_ext->shot.ctl.scaler.cropRegion[2]
|| sensorMaxH < (int)shot_ext->shot.ctl.scaler.cropRegion[3]) {
CLOGE("Invalid Crop Size(%d, %d), sensorMax(%d, %d)",
shot_ext->shot.ctl.scaler.cropRegion[2],
shot_ext->shot.ctl.scaler.cropRegion[3],
sensorMaxW, sensorMaxH);
shot_ext->shot.ctl.scaler.cropRegion[2] = sensorMaxW;
shot_ext->shot.ctl.scaler.cropRegion[3] = sensorMaxH;
}
/* 2. Check the validation of the crop offset.
* Offset coordinate + width or height must be smaller than sensor max size.
*/
if (sensorMaxW < (int) shot_ext->shot.ctl.scaler.cropRegion[0]
+ (int) shot_ext->shot.ctl.scaler.cropRegion[2]) {
CLOGE("Invalid Crop Region, offsetX(%d), width(%d) sensorMaxW(%d)",
shot_ext->shot.ctl.scaler.cropRegion[0],
shot_ext->shot.ctl.scaler.cropRegion[2],
sensorMaxW);
shot_ext->shot.ctl.scaler.cropRegion[0] = sensorMaxW - shot_ext->shot.ctl.scaler.cropRegion[2];
}
if (sensorMaxH < (int) shot_ext->shot.ctl.scaler.cropRegion[1]
+ (int) shot_ext->shot.ctl.scaler.cropRegion[3]) {
CLOGE("Invalid Crop Region, offsetY(%d), height(%d) sensorMaxH(%d)",
shot_ext->shot.ctl.scaler.cropRegion[1],
shot_ext->shot.ctl.scaler.cropRegion[3],
sensorMaxH);
shot_ext->shot.ctl.scaler.cropRegion[1] = sensorMaxH - shot_ext->shot.ctl.scaler.cropRegion[3];
}
m_parameters[m_cameraId]->setCropRegion(
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]);
#ifdef USE_DUAL_CAMERA
if (m_parameters[m_cameraId]->getDualMode() == true) {
ExynosRect slaveRect;
m_parameters[m_cameraIds[1]]->getMaxSensorSize(&sensorMaxW, &sensorMaxH);
slaveRect.x = ALIGN_DOWN(shot_ext->shot.ctl.scaler.cropRegion[0]/DUAL_CAMERA_TELE_RATIO, 2);
slaveRect.y = ALIGN_DOWN(shot_ext->shot.ctl.scaler.cropRegion[1]/DUAL_CAMERA_TELE_RATIO, 2);
slaveRect.w = ALIGN_UP(shot_ext->shot.ctl.scaler.cropRegion[2]*DUAL_CAMERA_TELE_RATIO, 2);
slaveRect.h = ALIGN_UP(shot_ext->shot.ctl.scaler.cropRegion[3]*DUAL_CAMERA_TELE_RATIO, 2);
/* 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 = sensorMaxW - slaveRect.w;
}
if (sensorMaxH < slaveRect.y + slaveRect.h) {
slaveRect.y = sensorMaxH - slaveRect.h;
}
m_parameters[m_cameraIds[1]]->setCropRegion(
slaveRect.x, slaveRect.y, slaveRect.w, slaveRect.h);
}
#endif
}
void ExynosCamera::m_updateFD(struct camera2_shot_ext *shot_ext, enum facedetect_mode fdMode, int dsInputPortId, bool isReprocessing)
{
if (fdMode <= FACEDETECT_MODE_OFF) {
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) {
if (dsInputPortId < MCSC_PORT_MAX) {
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 {
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 % MCSC_PORT_MAX);
}
} else {
//To Do
if (m_parameters[m_cameraId]->getPIPMode() == true && getCameraId() == CAMERA_ID_BACK) {
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 (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;
shot_ext->shot.ctl.stats.faceDetectMode = FACEDETECT_MODE_OFF;
shot_ext->shot.uctl.scalerUd.mcsc_sub_blk_port[INTERFACE_TYPE_DS] = MCSC_PORT_NONE;
}
}
}
}
}
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_parameters[m_cameraId]->checkJpegQuality(shot_ext->shot.ctl.jpeg.quality);
if (ret != NO_ERROR)
CLOGE("Failed to checkJpegQuality. 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]);
ret = m_parameters[m_cameraId]->checkThumbnailQuality(shot_ext->shot.ctl.jpeg.thumbnailQuality);
if (ret != NO_ERROR)
CLOGE("Failed to checkThumbnailQuality. 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);
#ifndef USE_DUAL_CAMERA
ret = m_searchFrameFromList(list, listLock, frameCount, newFrame);
if (ret < 0) {
CLOGE("searchFrameFromList fail");
return INVALID_OPERATION;
}
#endif
if (newFrame == NULL) {
newFrame = factory->createNewFrame(frameCount);
if (newFrame == NULL) {
CLOGE("newFrame is NULL");
return UNKNOWN_ERROR;
}
listLock->lock();
list->push_back(newFrame);
listLock->unlock();
}
newFrame->setHasRequest(true);
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);
#ifndef USE_DUAL_CAMERA
ret = m_searchFrameFromList(list, listLock, frameCount, newFrame);
if (ret < 0) {
CLOGE("searchFrameFromList fail");
return INVALID_OPERATION;
}
#endif
if (newFrame == NULL) {
newFrame = factory->createNewFrame(frameCount, useJpegFlag);
if (newFrame == NULL) {
CLOGE("newFrame is NULL");
return UNKNOWN_ERROR;
}
listLock->lock();
list->push_back(newFrame);
listLock->unlock();
}
newFrame->setHasRequest(true);
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;
ExynosCameraFrameFactory *factory = NULL;
uint32_t pipeId = 0;
int retryCount = 1;
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;
}
CLOGV("[F%d T%d]frame frameCount", frame->getFrameCount(), frame->getFrameType());
pipeId = frame->getFirstEntity()->getPipeId();
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 {
#ifdef USE_DUAL_CAMERA
if (frame->getFrameType() == FRAME_TYPE_REPROCESSING_DUAL_SLAVE) {
factory = m_frameFactory[FRAME_FACTORY_TYPE_REPROCESSING_DUAL];
} else
#endif
{
factory = m_frameFactory[FRAME_FACTORY_TYPE_REPROCESSING];
}
if (factory == NULL) {
CLOGE("frame factory is NULL");
goto FUNC_EXIT;
}
while (factory->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_DUAL_CAMERA
if (frame->getFrameType() == FRAME_TYPE_REPROCESSING_DUAL_MASTER) {
factory->pushFrameToPipe(frame, PIPE_SYNC_REPROCESSING);
} else
#endif
{
factory->pushFrameToPipe(frame, pipeId);
}
/* When enabled SCC capture or pureBayerReprocessing, we need to start bayer pipe thread */
if (m_parameters[m_cameraId]->isReprocessing() == true)
factory->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)
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;
ExynosCameraFrameFactory *factory = m_frameFactory[FRAME_FACTORY_TYPE_CAPTURE_PREVIEW];
int dstPos = factory->getNodeType(PIPE_VC0);
int pipeId = -1;
if (m_parameters[m_cameraId]->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, m_getBayerPipeId(), false, retryCount, dstPos);
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_previewStreamBayerPipeThreadFunc(void)
{
status_t ret = 0;
ExynosCameraFrameSP_sptr_t newFrame = NULL;
ret = m_pipeFrameDoneQ[PIPE_FLITE]->waitAndPopProcessQ(&newFrame);
if (ret < 0) {
/* 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 */
}
return true;
}
return m_previewStreamFunc(newFrame, PIPE_FLITE);
}
bool ExynosCamera::m_previewStream3AAPipeThreadFunc(void)
{
status_t ret = NO_ERROR;
ExynosCameraFrameSP_sptr_t newFrame = NULL;
ret = m_pipeFrameDoneQ[PIPE_3AA]->waitAndPopProcessQ(&newFrame);
if (ret < 0) {
/* TODO: We need to make timeout duration depends on FPS */
if (ret == TIMED_OUT) {
CLOGV("wait timeout");
} else {
CLOGE("wait and pop fail, ret(%d)", ret);
/* TODO: doing exception handling */
}
return true;
}
return m_previewStreamFunc(newFrame, PIPE_3AA);
}
bool ExynosCamera::m_previewStreamISPPipeThreadFunc(void)
{
status_t ret = NO_ERROR;
ExynosCameraFrameSP_sptr_t newFrame = NULL;
ret = m_pipeFrameDoneQ[PIPE_ISP]->waitAndPopProcessQ(&newFrame);
if (ret != NO_ERROR) {
if (ret == TIMED_OUT)
CLOGV("wait timeout");
else
CLOGE("Failed to waitAndPopProcessQ. ret %d", ret);
return true;
}
return m_previewStreamFunc(newFrame, PIPE_ISP);
}
bool ExynosCamera::m_previewStreamMCSCPipeThreadFunc(void)
{
status_t ret = NO_ERROR;
ExynosCameraFrameSP_sptr_t newFrame = NULL;
ret = m_pipeFrameDoneQ[PIPE_MCSC]->waitAndPopProcessQ(&newFrame);
if (ret < 0) {
/* 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 */
}
return true;
}
return m_previewStreamFunc(newFrame, PIPE_MCSC);
}
#ifdef USE_DUAL_CAMERA
bool ExynosCamera::m_previewStreamDCPPipeThreadFunc(void)
{
status_t ret = NO_ERROR;
ExynosCameraFrameSP_sptr_t newFrame = NULL;
ret = m_pipeFrameDoneQ[PIPE_DCP]->waitAndPopProcessQ(&newFrame);
if (ret < 0) {
/* 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 */
}
return true;
}
return m_previewStreamFunc(newFrame, PIPE_DCP);
}
#endif
#ifdef SUPPORT_HW_GDC
bool ExynosCamera::m_previewStreamGDCPipeThreadFunc(void)
{
status_t ret = NO_ERROR;
ExynosCameraFrameSP_sptr_t newFrame = NULL;
ret = m_pipeFrameDoneQ[PIPE_GDC]->waitAndPopProcessQ(&newFrame);
if (ret < 0) {
/* 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 */
}
return true;
}
return m_previewStreamFunc(newFrame, PIPE_GDC);
}
#endif
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_VRA]->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) {
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) {
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)
{
int ret;
if (m_parameters[m_cameraId]->getVisionMode() == false) {
ret = m_setBuffers();
} else {
ret = m_setVisionBuffers();
}
if (ret < 0) {
CLOGE("m_setBuffers failed");
m_bufferSupplier->deinit();
return false;
}
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)
{
status_t ret = OK;
CLOGV("m_pushServiceRequest frameCnt(%d)", request_in->frame_number);
req = m_requestMgr->registerToServiceList(request_in);
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;
factory = m_frameFactory[FRAME_FACTORY_TYPE_REPROCESSING];
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;
}
#ifdef USE_DUAL_CAMERA
if (m_parameters[m_cameraId]->getDualMode() == 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_startPictureBufferThreadFunc(void)
{
int ret = 0;
if (m_parameters[m_cameraId]->isReprocessing() == true) {
ret = m_setReprocessingBuffer();
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,
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 {
frameCount = m_internalFrameCount++;
hasReques = false;
}
CLOGV("(%d)", frameCount);
#ifndef USE_DUAL_CAMERA
ret = m_searchFrameFromList(list, listLock, frameCount, newFrame);
if (ret < 0) {
CLOGE("searchFrameFromList fail");
return INVALID_OPERATION;
}
#endif
if (newFrame == NULL) {
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_INTERNAL */
ret = newFrame->setFrameInfo(m_parameters[m_cameraId], frameCount, FRAME_TYPE_INTERNAL);
if (ret != NO_ERROR) {
CLOGE("Failed to setFrameInfo with INTERNAL. frameCount %d", frameCount);
return ret;
}
newFrame->setHasRequest(hasReques);
return ret;
}
#ifdef USE_DUAL_CAMERA
status_t ExynosCamera::m_generateTransitionFrame(ExynosCameraFrameFactory *factory, List<ExynosCameraFrameSP_sptr_t> *list,
Mutex *listLock, ExynosCameraFrameSP_dptr_t newFrame)
{
status_t ret = NO_ERROR;
newFrame = NULL;
uint32_t frameCount = m_internalFrameCount;
bool hasReques = false;
frameCount = m_internalFrameCount;
CLOGV("(%d)", frameCount);
#ifndef USE_DUAL_CAMERA
ret = m_searchFrameFromList(list, listLock, frameCount, newFrame);
if (ret < 0) {
CLOGE("searchFrameFromList fail");
return INVALID_OPERATION;
}
#endif
if (newFrame == NULL) {
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_parameters[m_cameraId], frameCount, FRAME_TYPE_TRANSITION);
if (ret != NO_ERROR) {
CLOGE("Failed to setFrameInfo with INTERNAL. frameCount %d", frameCount);
return ret;
}
newFrame->setHasRequest(hasReques);
return ret;
}
status_t ExynosCamera::m_checkDualOperationMode(ExynosCameraRequestSP_sprt_t request)
{
status_t ret = NO_ERROR;
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_parameters[m_cameraId]->getDualOperationMode();
struct CameraMetaParameters *metaParameters = request->getMetaParameters();
float zoomRatio = metaParameters->m_zoomRatio;
m_parameters[m_cameraIds[1]]->setZoomRatio(zoomRatio);
if (zoomRatio == 1.0f) {
newOperationMode = DUAL_OPERATION_MODE_MASTER;
} else if (zoomRatio > 2.0f) {
newOperationMode = DUAL_OPERATION_MODE_SLAVE;
} else {
newOperationMode = DUAL_OPERATION_MODE_SYNC;
}
newOperationMode = DUAL_OPERATION_MODE_SYNC;
if (oldOperationMode == DUAL_OPERATION_MODE_SYNC
&& m_dualTransitionCount > 0) {
m_dualTransitionCount--;
return NO_ERROR;
}
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;
}
m_parameters[m_cameraId]->setDualOperationMode(newOperationMode);
if (newOperationMode == DUAL_OPERATION_MODE_SYNC) {
m_dualTransitionCount = 30;
ret = m_setStandbyMode(false);
if (ret != NO_ERROR) {
CLOGE("Set Standby mode(false) fail! ret(%d)", ret);
}
} else {
ret = m_setStandbyMode(true);
if (ret != NO_ERROR) {
CLOGE("Set Standby mode(true) fail! ret(%d)", ret);
}
}
}
return ret;
}
status_t ExynosCamera::m_setStandbyMode(bool standby)
{
ExynosCameraAutoTimer autoTimer(__FUNCTION__);
status_t ret = NO_ERROR;
enum DUAL_OPERATION_MODE dualOperationMode = m_parameters[m_cameraId]->getDualOperationMode();
bool sensorStandby = false;
bool isNeedPrepare = false;
ExynosCameraFrameFactory *factory = NULL;
frame_type_t frameType = FRAME_TYPE_BASE;
switch (dualOperationMode) {
case DUAL_OPERATION_MODE_MASTER:
if (standby == true) {
sensorStandby = m_parameters[m_cameraId]->isSupportSlaveSensorStandby();
factory = m_frameFactory[FRAME_FACTORY_TYPE_PREVIEW_DUAL];
} else {
sensorStandby = m_parameters[m_cameraId]->isSupportMasterSensorStandby();
factory = m_frameFactory[FRAME_FACTORY_TYPE_CAPTURE_PREVIEW];
}
frameType = FRAME_TYPE_TRANSITION;
break;
case DUAL_OPERATION_MODE_SLAVE:
if (standby == true) {
sensorStandby = m_parameters[m_cameraId]->isSupportMasterSensorStandby();
factory = m_frameFactory[FRAME_FACTORY_TYPE_CAPTURE_PREVIEW];
} else {
sensorStandby = m_parameters[m_cameraId]->isSupportSlaveSensorStandby();
factory = m_frameFactory[FRAME_FACTORY_TYPE_PREVIEW_DUAL];
}
frameType = FRAME_TYPE_TRANSITION;
break;
case DUAL_OPERATION_MODE_SYNC:
if (standby == true) {
CLOGE("Invalid standby(true) setting, fail! Dual operation mode(%d)",
dualOperationMode);
return BAD_VALUE;
}
if (m_frameFactory[FRAME_FACTORY_TYPE_CAPTURE_PREVIEW]->isSensorStandby() == true) {
factory = m_frameFactory[FRAME_FACTORY_TYPE_CAPTURE_PREVIEW];
frameType = FRAME_TYPE_INTERNAL;
} else if (m_frameFactory[FRAME_FACTORY_TYPE_PREVIEW_DUAL]->isSensorStandby() == true) {
factory = m_frameFactory[FRAME_FACTORY_TYPE_PREVIEW_DUAL];
frameType = FRAME_TYPE_PREVIEW_DUAL_SLAVE;
}
break;
default:
CLOGE("Invalid dual operation mode(%d)", dualOperationMode);
return INVALID_OPERATION;
break;
}
if (standby == true) {
if (sensorStandby == false) {
/* Goto post standby mode, and prepare Frames */
isNeedPrepare = true;
m_dualShotDoneQ->release();
if (m_dualMainThread->isRunning() == false) {
m_dualMainThread->run(PRIORITY_URGENT_DISPLAY);
}
}
} else {
if (sensorStandby == true) {
/* Wakeup for Sync mode, and prepare Frames */
isNeedPrepare = true;
}
}
if (m_getState() == EXYNOS_CAMERA_STATE_RUN
&& isNeedPrepare == true) {
uint32_t prepare = m_parameters[m_cameraId]->getSensorStandbyDelay();
for (uint32_t i = 0; i < prepare; i++) {
ret = m_createInternalFrameFunc(NULL, REQ_SYNC_NONE, frameType);
if (ret != NO_ERROR) {
CLOGE("Failed to createFrameFunc for preparing frame. prepareCount %d/%d",
i, prepare);
}
}
}
if (sensorStandby == true) {
ret = factory->sensorStandby(standby);
if (ret != NO_ERROR) {
CLOGE("sensorStandby(%s) fail! ret(%d)", (standby?"On":"Off"), ret);
}
}
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;
bool flag3aaIspM2M = (m_parameters[m_cameraId]->getHwConnectionMode(PIPE_3AA, PIPE_ISP) == HW_CONNECTION_MODE_M2M);
bool flagIspMcscM2M = (m_parameters[m_cameraId]->getHwConnectionMode(PIPE_ISP, PIPE_MCSC) == HW_CONNECTION_MODE_M2M);
#ifdef USE_DUAL_CAMERA
bool flagIspDcpM2M = (m_parameters[m_cameraId]->getHwConnectionMode(PIPE_ISP, PIPE_DCP) == HW_CONNECTION_MODE_M2M);
bool flagDcpMcscM2M = (m_parameters[m_cameraId]->getHwConnectionMode(PIPE_DCP, PIPE_MCSC) == HW_CONNECTION_MODE_M2M);
#endif
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();
factory = m_frameFactory[FRAME_FACTORY_TYPE_CAPTURE_PREVIEW];
if (factory == NULL) {
CLOGE("previewFrameFactory is NULL. Skip monitoring.");
return false;
}
/* 2. Select Error check pipe ID (of last output node) */
#ifdef USE_DUAL_CAMERA
if (m_parameters[m_cameraId]->getDualMode() == true
&& m_parameters[m_cameraId]->getDualPreviewMode() == DUAL_PREVIEW_MODE_HW) {
if (flagDcpMcscM2M == true
&& IS_OUTPUT_NODE(factory, PIPE_MCSC) == true) {
pipeIdErrorCheck = PIPE_MCSC;
} else if (flagIspDcpM2M == true
&& IS_OUTPUT_NODE(factory, PIPE_DCP) == true) {
pipeIdErrorCheck = PIPE_DCP;
} else if (flag3aaIspM2M == true
&& IS_OUTPUT_NODE(factory, PIPE_ISP) == true) {
pipeIdErrorCheck = PIPE_ISP;
} else {
pipeIdErrorCheck = PIPE_3AA;
}
} else
#endif
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_parameters[m_cameraId]->getPIPMode())) {
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);
}
#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 [%lld]", (long long)(*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_parameters[m_cameraId]->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 YUV_DUMP
bool ExynosCamera::m_dumpThreadFunc(void)
{
char filePath[70];
int size = -1;
uint32_t pipeId = -1;
uint32_t nodeIndex = -1;
status_t ret = NO_ERROR;
ExynosCameraFrameFactory *factory = NULL;
ExynosCameraFrameSP_sptr_t frame = NULL;
ExynosCameraBuffer buffer;
bool flag3aaIspM2M = (m_parameters[m_cameraId]->getHwConnectionMode(PIPE_3AA_REPROCESSING, PIPE_ISP_REPROCESSING) == HW_CONNECTION_MODE_M2M);
bool flagIspMcscM2M = (m_parameters[m_cameraId]->getHwConnectionMode(PIPE_ISP_REPROCESSING, PIPE_MCSC_REPROCESSING) == HW_CONNECTION_MODE_M2M);
#ifdef USE_DUAL_CAMERA
bool flagIspDcpM2M = (m_parameters[m_cameraId]->getHwConnectionMode(PIPE_ISP_REPROCESSING, PIPE_DCP_REPROCESSING) == HW_CONNECTION_MODE_M2M);
bool flagDcpMcscM2M = (m_parameters[m_cameraId]->getHwConnectionMode(PIPE_DCP_REPROCESSING, PIPE_MCSC_REPROCESSING) == HW_CONNECTION_MODE_M2M);
#endif
ret = m_dumpFrameQ->waitAndPopProcessQ(&frame);
if (ret == TIMED_OUT) {
CLOGW("Time-out to wait dumpFrameQ");
goto THREAD_EXIT;
} else if (ret != NO_ERROR) {
CLOGE("Failed to waitAndPopProcessQ for dumpFrameQ");
goto THREAD_EXIT;
} else if (frame == NULL) {
CLOGE("frame is NULL");
goto THREAD_EXIT;
}
memset(filePath, 0, sizeof(filePath));
snprintf(filePath, sizeof(filePath), "/data/YuvCapture.yuv");
factory = m_frameFactory[FRAME_FACTORY_TYPE_CAPTURE_PREVIEW];
#ifdef USE_DUAL_CAMERA
if (m_parameters[m_cameraId]->getDualMode() == true
&& m_parameters[m_cameraId]->getDualReprocessingMode() == DUAL_REPROCESSING_MODE_HW) {
if (flagDcpMcscM2M == true
&& IS_OUTPUT_NODE(factory, PIPE_MCSC_REPROCESSING) == true) {
pipeId = PIPE_MCSC_REPROCESSING;
} else if (flagIspDcpM2M == true
&& IS_OUTPUT_NODE(factory, PIPE_DCP_REPROCESSING) == true) {
pipeId = PIPE_DCP_REPROCESSING;
} else if (flag3aaIspM2M == true
&& IS_OUTPUT_NODE(factory, PIPE_ISP_REPROCESSING) == true) {
pipeId = PIPE_ISP_REPROCESSING;
} else {
pipeId = PIPE_3AA_REPROCESSING;
}
} else
#endif
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;
}
nodeIndex = factory->getNodeType(PIPE_MCSC3_REPROCESSING);
ret = frame->getDstBuffer(pipeId, &buffer, nodeIndex);
if (ret != NO_ERROR) {
CLOGE("Failed to getDstBuffer. frameCount %d pipeId %d nodeIndex %d",
frame->getFrameCount(), pipeId, nodeIndex);
goto THREAD_EXIT;
}
size = buffer.size[0];
ret = dumpToFile((char *)filePath, buffer.addr[0], size);
if (ret == false) {
CLOGE("Failed to dumpToFile. frameCount %d filePath %s size %d",
frame->getFrameCount(), filePath, size);
goto THREAD_EXIT;
}
THREAD_EXIT:
if (m_dumpFrameQ->getSizeOfProcessQ() > 0) {
CLOGI("run again. dumpFrameQ size %d",
m_dumpFrameQ->getSizeOfProcessQ());
return true;
} else {
CLOGI("Complete to dumpFrame. frameCount %d",
frame->getFrameCount());
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) {
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),
* Due to the sensor entry time issues, it has increased to 150 (15s).
* int retryCount = 10;
*/
int retryCount = 150;
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_parameters[m_cameraId]->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_parameters[m_cameraId]->setRestartStream(false);
}
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
#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;
ExynosCameraFrameFactory *factory = m_frameFactory[FRAME_FACTORY_TYPE_CAPTURE_PREVIEW];
struct camera2_stream *meta = NULL;
camera2_node_group bcropNodeGroupInfo;
int perframeInfoIndex = -1;
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);
#ifdef USE_DUAL_CAMERA
bool flagIspDcpM2M = (m_parameters[cameraId]->getHwConnectionMode(PIPE_ISP, PIPE_DCP) == HW_CONNECTION_MODE_M2M);
bool flagDcpMcscM2M = (m_parameters[cameraId]->getHwConnectionMode(PIPE_DCP, PIPE_MCSC) == HW_CONNECTION_MODE_M2M);
#endif
outputPortId = m_streamManager->getOutputPortId(HAL_STREAM_ID_VIDEO);
if (outputPortId < 0) {
CLOGE("There is NO VIDEO stream");
goto exit_thread_loop;
}
#ifdef USE_DUAL_CAMERA
if (m_parameters[m_cameraId]->getDualMode() == true
&& m_parameters[m_cameraId]->getDualPreviewMode() == DUAL_PREVIEW_MODE_HW) {
if (flagDcpMcscM2M == true
&& IS_OUTPUT_NODE(factory, PIPE_MCSC) == true) {
srcPipeId = PIPE_MCSC;
} else if (flagIspDcpM2M == true
&& IS_OUTPUT_NODE(factory, PIPE_DCP) == true) {
srcPipeId = PIPE_DCP;
} else if (flag3aaIspM2M == true
&& IS_OUTPUT_NODE(factory, PIPE_ISP) == true) {
srcPipeId = PIPE_ISP;
} else {
srcPipeId = PIPE_3AA;
}
} else
#endif
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;
}
srcPipeId = (m_parameters[m_cameraId]->getHwConnectionMode(PIPE_3AA, PIPE_ISP) == HW_CONNECTION_MODE_M2M) ? PIPE_ISP : PIPE_3AA;
srcNodeIndex = factory->getNodeType(PIPE_MCSC0 + outputPortId);
dstPipeId = PIPE_GDC;
srcFmt = m_parameters[m_cameraId]->getYuvFormat(outputPortId);
dstFmt = m_parameters[m_cameraId]->getYuvFormat(outputPortId);
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;
}
/* 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 = (m_parameters[m_cameraId]->getHwConnectionMode(PIPE_FLITE, PIPE_3AA) == HW_CONNECTION_MODE_M2M) ? PERFRAME_INFO_3AA : PERFRAME_INFO_FLITE;
frame->getNodeGroupInfo(&bcropNodeGroupInfo, perframeInfoIndex);
m_parameters[m_cameraId]->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
}; /* namespace android */