blob: afbcb38b09b8c406a7d7bf0de2e50917c7794861 [file] [log] [blame]
/*
**
** Copyright 2013, Samsung Electronics Co. LTD
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
/* #define LOG_NDEBUG 0 */
#define LOG_TAG "ExynosCamera"
#include <cutils/log.h>
#include "ExynosCamera.h"
namespace android {
#ifdef MONITOR_LOG_SYNC
uint32_t ExynosCamera::cameraSyncLogId = 0;
#endif
ExynosCamera::ExynosCamera(int cameraId, __unused camera_device_t *dev)
{
BUILD_DATE();
checkAndroidVersion();
m_cameraId = cameraId;
m_dev = dev;
initialize();
}
void ExynosCamera::initialize()
{
CLOGI("INFO(%s[%d]): -IN-", __FUNCTION__, __LINE__);
int ret = 0;
ExynosCameraActivityUCTL *uctlMgr = NULL;
memset(m_name, 0x00, sizeof(m_name));
m_use_companion = isCompanion(m_cameraId);
m_cameraSensorId = getSensorId(m_cameraId);
if (m_cameraId != CAMERA_ID_SECURE)
m_vendorSpecificPreConstructor(m_cameraId, m_dev);
/* Create Main Threads */
m_createThreads();
m_parameters = new ExynosCamera1Parameters(m_cameraId, m_use_companion);
CLOGD("DEBUG(%s):Parameters(Id=%d) created", __FUNCTION__, m_cameraId);
if (m_cameraId == CAMERA_ID_SECURE) {
m_cameraHiddenId = m_cameraId;
m_cameraId = CAMERA_ID_FRONT;
} else {
m_cameraHiddenId = -1;
}
m_exynosCameraActivityControl = m_parameters->getActivityControl();
/* Frame factories */
m_previewFrameFactory = NULL;
m_reprocessingFrameFactory = NULL;
m_visionFrameFactory= NULL;
/* Memory allocator */
m_ionAllocator = NULL;
m_grAllocator = NULL;
m_mhbAllocator = NULL;
/* Frame manager */
m_frameMgr = NULL;
/* Main Buffer */
/* Bayer buffer: Output buffer of Flite or 3AC */
m_createInternalBufferManager(&m_bayerBufferMgr, "BAYER_BUF");
#ifdef DEBUG_RAWDUMP
/* Flite buffer: Output buffer of Flite for DEBUG_RAWDUMP on Single chain */
if (m_parameters->getUsePureBayerReprocessing() == false)
m_createInternalBufferManager(&m_fliteBufferMgr, "FLITE_BUF");
#endif
/* 3AA buffer: Input buffer of 3AS */
m_createInternalBufferManager(&m_3aaBufferMgr, "3AS_IN_BUF");
/* ISP buffer: Hand-shaking buffer of 3AA-ISP */
m_createInternalBufferManager(&m_ispBufferMgr, "3AP_OUT_BUF");
/* HWDIS buffer: Hand-shaking buffer of ISP-TPU or ISP-MCSC */
m_createInternalBufferManager(&m_hwDisBufferMgr, "ISP_OUT_BUF");
#ifdef SUPPORT_DEPTH_MAP
m_createInternalBufferManager(&m_depthMapBufferMgr, "DEPTH_MAP_BUF");
#endif
/* Reprocessing Buffer */
/* ISP-Re buffer: Hand-shaking buffer of reprocessing 3AA-ISP */
m_createInternalBufferManager(&m_ispReprocessingBufferMgr, "ISP_RE_BUF");
/* SCC-Re buffer: Output buffer of reprocessing ISP(MCSC) */
m_createInternalBufferManager(&m_sccReprocessingBufferMgr, "MCSC_RE_BUF");
/* Thumbnail buffer: Output buffer of reprocessing ISP(MCSC) */
m_createInternalBufferManager(&m_thumbnailBufferMgr, "THUMBNAIL_BUF");
/* Capture Buffer */
/* SCC buffer: Output buffer of preview ISP(MCSC) */
m_createInternalBufferManager(&m_sccBufferMgr, "SCC_BUF");
/* GSC buffer: Output buffer of external scaler */
m_createInternalBufferManager(&m_gscBufferMgr, "GSC_BUF");
/* GSC buffer: Output buffer of JPEG */
m_createInternalBufferManager(&m_jpegBufferMgr, "JPEG_BUF");
/* Magic shot Buffer */
m_createInternalBufferManager(&m_postPictureBufferMgr, "POSTPICTURE_GSC_BUF");
/* Preview Buffer */
/* SCP buffer: Output buffer of MCSC0(Preview) */
m_scpBufferMgr = NULL;
/* Preview CB buffer: Output buffer of MCSC1(Preview CB) */
m_createInternalBufferManager(&m_previewCallbackBufferMgr, "PREVIEW_CB_BUF");
/* High resolution CB buffer: Output buffer of Reprocessing CB */
m_createInternalBufferManager(&m_highResolutionCallbackBufferMgr, "HIGH_RESOLUTION_CB_BUF");
m_fdCallbackHeap = NULL;
/* Recording Buffer */
m_recordingCallbackHeap = NULL;
/* Recording buffer: Output buffer of MCSC2(Preview) */
m_createInternalBufferManager(&m_recordingBufferMgr, "RECORDING_BUF");
/* Highspeed dzoom Buffer */
m_createInternalBufferManager(&m_zoomScalerBufferMgr, "DZOOM_SCALER_BUF");
#ifdef BOARD_CAMERA_USES_DUAL_CAMERA
/* fusion preview buffer */
m_createInternalBufferManager(&m_fusionBufferMgr, "FUSION_BUF");
#endif
/* Thumbnail scaling Buffer */
m_createInternalBufferManager(&m_thumbnailGscBufferMgr, "THUMBNAIL_GSC_BUF");
/* Create Internal Queue */
for(int i = 0 ; i < MAX_NUM_PIPES ; i++ ) {
m_mainSetupQ[i] = new frame_queue_t;
m_mainSetupQ[i]->setWaitTime(550000000);
}
m_pipeFrameDoneQ = new frame_queue_t;
m_pipeFrameDoneQ->setWaitTime(550000000);
m_dstIspReprocessingQ = new frame_queue_t;
m_dstIspReprocessingQ->setWaitTime(20000000);
m_dstSccReprocessingQ = new frame_queue_t;
m_dstSccReprocessingQ->setWaitTime(50000000);
m_dstGscReprocessingQ = new frame_queue_t;
m_dstGscReprocessingQ->setWaitTime(500000000);
m_zoomPreviwWithCscQ = new frame_queue_t;
#ifdef BOARD_CAMERA_USES_DUAL_CAMERA
m_fusionQ = new frame_queue_t;
#endif
m_dstPostPictureGscQ = new frame_queue_t;
m_dstPostPictureGscQ->setWaitTime(2000000000);
m_dstJpegReprocessingQ = new frame_queue_t;
m_dstJpegReprocessingQ->setWaitTime(500000000);
m_pipeFrameVisionDoneQ = new frame_queue_t;
m_pipeFrameVisionDoneQ->setWaitTime(2000000000);
m_facedetectQ = new frame_queue_t;
m_facedetectQ->setWaitTime(550000000);
m_autoFocusContinousQ.setWaitTime(550000000);
m_previewQ = new frame_queue_t;
m_previewQ->setWaitTime(550000000);
m_previewCallbackGscFrameDoneQ = new frame_queue_t;
m_recordingQ = new frame_queue_t;
m_recordingQ->setWaitTime(550000000);
m_postPictureQ = new frame_queue_t(m_postPictureThread);
m_highResolutionCallbackQ = new frame_queue_t(m_highResolutionCallbackThread);
m_highResolutionCallbackQ->setWaitTime(550000000);
m_jpegCallbackQ = new frame_queue_t;
m_jpegCallbackQ->setWaitTime(1000000000);
m_postviewCallbackQ = new postview_callback_queue_t;
m_postviewCallbackQ->setWaitTime(2000000000);
m_thumbnailCallbackQ = new thumbnail_callback_queue_t;
m_thumbnailCallbackQ->setWaitTime(1000000000);
m_ThumbnailPostCallbackQ = new frame_queue_t;
m_ThumbnailPostCallbackQ->setWaitTime(2000000000);
#ifdef SUPPORT_DEPTH_MAP
m_depthCallbackQ = new depth_callback_queue_t;
m_depthCallbackQ->setWaitTime(50000000);
#endif
for (int threadNum = JPEG_SAVE_THREAD0; threadNum < JPEG_SAVE_THREAD_MAX_COUNT; threadNum++) {
m_jpegSaveQ[threadNum] = new frame_queue_t;
m_jpegSaveQ[threadNum]->setWaitTime(2000000000);
m_burst[threadNum] = false;
m_running[threadNum] = false;
}
/* Initialize menber variable */
memset(&m_frameMetadata, 0, sizeof(camera_frame_metadata_t));
memset(m_faces, 0, sizeof(camera_face_t) * NUM_OF_DETECTED_FACES);
memset(&m_notifyCb, 0, sizeof(camera_notify_callback));
memset(&m_dataCb, 0, sizeof(camera_data_callback));;
memset(&m_dataCbTimestamp, 0, sizeof(camera_data_timestamp_callback));
memset(&m_getMemoryCb, 0, sizeof(camera_request_memory));
m_previewWindow = NULL;
m_exitAutoFocusThread = false;
m_autoFocusRunning = false;
m_previewEnabled = false;
m_pictureEnabled = false;
m_recordingEnabled = false;
m_zslPictureEnabled = false;
m_flagStartFaceDetection = false;
m_flagLLSStart = false;
m_flagLightCondition = false;
m_fdThreshold = 0;
m_captureSelector = NULL;
m_sccCaptureSelector = NULL;
m_autoFocusType = 0;
m_hdrEnabled = false;
m_hdrSkipedFcount = 0;
m_doCscRecording = true;
m_recordingBufferCount = NUM_RECORDING_BUFFERS;
m_frameSkipCount = 0;
m_isZSLCaptureOn = false;
m_isSuccessedBufferAllocation = false;
m_fdFrameSkipCount = 0;
m_fliteFrameCount = 0;
m_3aa_ispFrameCount = 0;
m_ispFrameCount = 0;
m_sccFrameCount = 0;
m_scpFrameCount = 0;
m_displayPreviewToggle = 0;
m_isTryStopFlash = false;
m_curMinFps = 0;
m_visionFps = 0;
m_visionAe = 0;
m_hackForAlignment = 0;
#ifdef FPS_CHECK
for (int i = 0; i < DEBUG_MAX_PIPE_NUM; i++)
m_debugFpsCount[i] = 0;
#endif
m_stopBurstShot = false;
m_disablePreviewCB = false;
m_checkFirstFrameLux = false;
m_callbackCookie = NULL;
m_callbackState = 0;
m_callbackStateOld = 0;
m_callbackMonitorCount = 0;
m_highResolutionCallbackRunning = false;
m_skipReprocessing = false;
m_isFirstStart = true;
m_parameters->setIsFirstStartFlag(m_isFirstStart);
m_lastRecordingTimeStamp = 0;
m_recordingStartTimeStamp = 0;
m_recordingFrameSkipCount = 0;
m_exynosconfig = NULL;
/* HACK Reset Preview Flag*/
m_resetPreview = false;
m_dynamicSccCount = 0;
m_previewBufferCount = NUM_PREVIEW_BUFFERS;
m_faceDetected = false;
m_flagThreadStop= false;
m_isNeedAllocPictureBuffer = false;
m_longExposureRemainCount = 0;
m_stopLongExposure = false;
m_cancelPicture = false;
m_longExposureCaptureState = LONG_EXPOSURE_PREVIEW;
#ifdef BURST_CAPTURE
m_isCancelBurstCapture = false;
m_burstCaptureCallbackCount = 0;
m_burstSaveTimerTime = 0;
m_burstDuration = 0;
m_burstInitFirst = false;
m_burstRealloc = false;
m_burstShutterLocation = 0;
#endif
#ifdef FIRST_PREVIEW_TIME_CHECK
m_flagFirstPreviewTimerOn = false;
#endif
/* init infomation of fd orientation*/
m_parameters->setDeviceOrientation(0);
uctlMgr = m_exynosCameraActivityControl->getUCTLMgr();
if (uctlMgr != NULL)
uctlMgr->setDeviceRotation(m_parameters->getFdOrientation());
#ifdef MONITOR_LOG_SYNC
m_syncLogDuration = 0;
#endif
#ifdef CAMERA_FAST_ENTRANCE_V1
m_fastEntrance = false;
m_isFirstParametersSet = false;
#endif
m_tempshot = new struct camera2_shot_ext;
m_fdmeta_shot = new struct camera2_shot_ext;
m_meta_shot = new struct camera2_shot_ext;
m_picture_meta_shot = new struct camera2_shot;
m_ionClient = ion_open();
if (m_ionClient < 0) {
ALOGE("ERR(%s):m_ionClient ion_open() fail", __func__);
m_ionClient = -1;
}
/* ExynosConfig setting */
m_setConfigInform();
/* Frame manager setting */
m_setFrameManager();
/* Initialize Frame factory */
m_initFrameFactory();
/* Construct vendor */
m_vendorSpecificConstructor(m_cameraId, m_dev);
CLOGI("INFO(%s[%d]): -OUT-", __FUNCTION__, __LINE__);
}
ExynosCamera::~ExynosCamera()
{
this->release();
}
void ExynosCamera::release()
{
CLOGI("INFO(%s[%d]): -IN-", __FUNCTION__, __LINE__);
int ret = 0;
#ifdef CAMERA_FAST_ENTRANCE_V1
if (m_fastenAeThread != NULL) {
CLOGI("INFO(%s[%d]): wait m_fastenAeThread", __FUNCTION__, __LINE__);
m_fastenAeThread->requestExitAndWait();
CLOGI("INFO(%s[%d]): wait m_fastenAeThread end", __FUNCTION__, __LINE__);
} else {
CLOGI("INFO(%s[%d]):m_fastenAeThread is NULL", __FUNCTION__, __LINE__);
}
#endif
m_stopCompanion();
if (m_frameMgr != NULL) {
m_frameMgr->stop();
}
/* release all framefactory */
m_deinitFrameFactory();
if (m_parameters != NULL) {
delete m_parameters;
m_parameters = NULL;
CLOGD("DEBUG(%s):Parameters(Id=%d) destroyed", __FUNCTION__, m_cameraId);
}
/* free all buffers */
m_releaseBuffers();
if (m_ionClient >= 0) {
ion_close(m_ionClient);
m_ionClient = -1;
}
if (m_ionAllocator != NULL) {
delete m_ionAllocator;
m_ionAllocator = NULL;
}
if (m_grAllocator != NULL) {
delete m_grAllocator;
m_grAllocator = NULL;
}
if (m_mhbAllocator != NULL) {
delete m_mhbAllocator;
m_mhbAllocator = NULL;
}
if (m_pipeFrameDoneQ != NULL) {
delete m_pipeFrameDoneQ;
m_pipeFrameDoneQ = NULL;
}
if (m_zoomPreviwWithCscQ != NULL) {
delete m_zoomPreviwWithCscQ;
m_zoomPreviwWithCscQ = NULL;
}
#ifdef BOARD_CAMERA_USES_DUAL_CAMERA
if (m_fusionQ != NULL) {
delete m_fusionQ;
m_fusionQ = NULL;
}
#endif
/* vision */
if (m_pipeFrameVisionDoneQ != NULL) {
delete m_pipeFrameVisionDoneQ;
m_pipeFrameVisionDoneQ = NULL;
}
if (m_dstIspReprocessingQ != NULL) {
delete m_dstIspReprocessingQ;
m_dstIspReprocessingQ = NULL;
}
if (m_dstSccReprocessingQ != NULL) {
delete m_dstSccReprocessingQ;
m_dstSccReprocessingQ = NULL;
}
if (m_dstGscReprocessingQ != NULL) {
delete m_dstGscReprocessingQ;
m_dstGscReprocessingQ = NULL;
}
if (m_dstPostPictureGscQ != NULL) {
delete m_dstPostPictureGscQ;
m_dstPostPictureGscQ = NULL;
}
if (m_dstJpegReprocessingQ != NULL) {
delete m_dstJpegReprocessingQ;
m_dstJpegReprocessingQ = NULL;
}
if (m_postPictureQ != NULL) {
delete m_postPictureQ;
m_postPictureQ = NULL;
}
if (m_jpegCallbackQ != NULL) {
delete m_jpegCallbackQ;
m_jpegCallbackQ = NULL;
}
if (m_yuvCallbackQ != NULL) {
delete m_yuvCallbackQ;
m_yuvCallbackQ = NULL;
}
if (m_postviewCallbackQ != NULL) {
delete m_postviewCallbackQ;
m_postviewCallbackQ = NULL;
}
#ifdef SUPPORT_DEPTH_MAP
if (m_depthCallbackQ != NULL) {
delete m_depthCallbackQ;
m_depthCallbackQ = NULL;
}
#endif
if (m_thumbnailCallbackQ != NULL) {
delete m_thumbnailCallbackQ;
m_thumbnailCallbackQ = NULL;
}
if (m_ThumbnailPostCallbackQ != NULL) {
delete m_ThumbnailPostCallbackQ;
m_ThumbnailPostCallbackQ = NULL;
}
if (m_facedetectQ != NULL) {
delete m_facedetectQ;
m_facedetectQ = NULL;
}
if (m_previewQ != NULL) {
delete m_previewQ;
m_previewQ = NULL;
}
for(int i = 0 ; i < MAX_NUM_PIPES ; i++ ) {
if (m_mainSetupQ[i] != NULL) {
delete m_mainSetupQ[i];
m_mainSetupQ[i] = NULL;
}
}
if (m_previewCallbackGscFrameDoneQ != NULL) {
delete m_previewCallbackGscFrameDoneQ;
m_previewCallbackGscFrameDoneQ = NULL;
}
if (m_recordingQ != NULL) {
delete m_recordingQ;
m_recordingQ = NULL;
}
for (int threadNum = JPEG_SAVE_THREAD0; threadNum < JPEG_SAVE_THREAD_MAX_COUNT; threadNum++) {
if (m_jpegSaveQ[threadNum] != NULL) {
delete m_jpegSaveQ[threadNum];
m_jpegSaveQ[threadNum] = NULL;
}
}
if (m_highResolutionCallbackQ != NULL) {
delete m_highResolutionCallbackQ;
m_highResolutionCallbackQ = NULL;
}
if (m_bayerBufferMgr != NULL) {
delete m_bayerBufferMgr;
m_bayerBufferMgr = NULL;
CLOGD("DEBUG(%s):BufferManager(bayerBufferMgr) destroyed", __FUNCTION__);
}
#ifdef DEBUG_RAWDUMP
if (m_fliteBufferMgr != NULL) {
delete m_fliteBufferMgr;
m_fliteBufferMgr = NULL;
CLOGD("DEBUG(%s):BufferManager(fliteBufferMgr) destroyed", __FUNCTION__);
}
#endif
#ifdef SUPPORT_DEPTH_MAP
if (m_depthMapBufferMgr != NULL) {
delete m_depthMapBufferMgr;
m_depthMapBufferMgr = NULL;
CLOGD("DEBUG(%s):BufferManager(m_depthMapBufferMgr) destroyed", __FUNCTION__);
}
#endif
#ifdef DEBUG_RAWDUMP
if (m_fliteBufferMgr != NULL) {
delete m_fliteBufferMgr;
m_fliteBufferMgr = NULL;
CLOGD("DEBUG(%s):BufferManager(fliteBufferMgr) destroyed", __FUNCTION__);
}
#endif
if (m_3aaBufferMgr != NULL) {
delete m_3aaBufferMgr;
m_3aaBufferMgr = NULL;
CLOGD("DEBUG(%s):BufferManager(3aaBufferMgr) destroyed", __FUNCTION__);
}
if (m_ispBufferMgr != NULL) {
delete m_ispBufferMgr;
m_ispBufferMgr = NULL;
CLOGD("DEBUG(%s):BufferManager(ispBufferMgr) destroyed", __FUNCTION__);
}
if (m_hwDisBufferMgr != NULL) {
delete m_hwDisBufferMgr;
m_hwDisBufferMgr = NULL;
CLOGD("DEBUG(%s):BufferManager(m_hwDisBufferMgr) destroyed", __FUNCTION__);
}
if (m_scpBufferMgr != NULL) {
delete m_scpBufferMgr;
m_scpBufferMgr = NULL;
CLOGD("DEBUG(%s):BufferManager(scpBufferMgr) destroyed", __FUNCTION__);
}
if (m_zoomScalerBufferMgr != NULL) {
delete m_zoomScalerBufferMgr;
m_zoomScalerBufferMgr = NULL;
CLOGD("DEBUG(%s):BufferManager(m_zoomScalerBufferMgr) destroyed", __FUNCTION__);
}
#ifdef BOARD_CAMERA_USES_DUAL_CAMERA
if (m_fusionBufferMgr != NULL) {
delete m_fusionBufferMgr;
m_fusionBufferMgr = NULL;
CLOGD("DEBUG(%s):BufferManager(m_fusionBufferMgr) destroyed", __FUNCTION__);
}
#endif
if (m_ispReprocessingBufferMgr != NULL) {
delete m_ispReprocessingBufferMgr;
m_ispReprocessingBufferMgr = NULL;
CLOGD("DEBUG(%s):BufferManager(ispReprocessingBufferMgr) destroyed", __FUNCTION__);
}
if (m_sccReprocessingBufferMgr != NULL) {
delete m_sccReprocessingBufferMgr;
m_sccReprocessingBufferMgr = NULL;
CLOGD("DEBUG(%s):BufferManager(sccReprocessingBufferMgr) destroyed", __FUNCTION__);
}
if (m_thumbnailBufferMgr != NULL) {
delete m_thumbnailBufferMgr;
m_thumbnailBufferMgr = NULL;
CLOGD("DEBUG(%s):BufferManager(sccReprocessingBufferMgr) destroyed", __FUNCTION__);
}
if (m_sccBufferMgr != NULL) {
delete m_sccBufferMgr;
m_sccBufferMgr = NULL;
CLOGD("DEBUG(%s):BufferManager(sccBufferMgr) destroyed", __FUNCTION__);
}
if (m_gscBufferMgr != NULL) {
delete m_gscBufferMgr;
m_gscBufferMgr = NULL;
CLOGD("DEBUG(%s):BufferManager(gscBufferMgr) destroyed", __FUNCTION__);
}
if (m_jpegBufferMgr != NULL) {
delete m_jpegBufferMgr;
m_jpegBufferMgr = NULL;
CLOGD("DEBUG(%s):BufferManager(jpegBufferMgr) destroyed", __FUNCTION__);
}
if (m_previewCallbackBufferMgr != NULL) {
delete m_previewCallbackBufferMgr;
m_previewCallbackBufferMgr = NULL;
CLOGD("DEBUG(%s):BufferManager(previewCallbackBufferMgr) destroyed", __FUNCTION__);
}
if (m_highResolutionCallbackBufferMgr != NULL) {
delete m_highResolutionCallbackBufferMgr;
m_highResolutionCallbackBufferMgr = NULL;
CLOGD("DEBUG(%s):BufferManager(m_highResolutionCallbackBufferMgr) destroyed", __FUNCTION__);
}
if (m_recordingBufferMgr != NULL) {
delete m_recordingBufferMgr;
m_recordingBufferMgr = NULL;
CLOGD("DEBUG(%s):BufferManager(recordingBufferMgr) destroyed", __FUNCTION__);
}
if (m_captureSelector != NULL) {
delete m_captureSelector;
m_captureSelector = NULL;
}
if (m_sccCaptureSelector != NULL) {
delete m_sccCaptureSelector;
m_sccCaptureSelector = NULL;
}
if (m_recordingCallbackHeap != NULL) {
m_recordingCallbackHeap->release(m_recordingCallbackHeap);
delete m_recordingCallbackHeap;
m_recordingCallbackHeap = NULL;
CLOGD("DEBUG(%s):BufferManager(recordingCallbackHeap) destroyed", __FUNCTION__);
}
m_isFirstStart = true;
m_previewBufferCount = NUM_PREVIEW_BUFFERS;
if (m_frameMgr != NULL) {
delete m_frameMgr;
m_frameMgr = NULL;
}
if (m_tempshot != NULL) {
delete m_tempshot;
m_tempshot = NULL;
}
if (m_fdmeta_shot != NULL) {
delete m_fdmeta_shot;
m_fdmeta_shot = NULL;
}
if (m_meta_shot != NULL) {
delete m_meta_shot;
m_meta_shot = NULL;
}
if (m_picture_meta_shot != NULL) {
delete m_picture_meta_shot;
m_picture_meta_shot = NULL;
}
m_vendorSpecificDestructor();
CLOGI("INFO(%s[%d]): -OUT-", __FUNCTION__, __LINE__);
}
int ExynosCamera::getCameraId() const
{
if (m_cameraHiddenId != -1)
return m_cameraHiddenId;
else
return m_cameraId;
}
int ExynosCamera::getCameraIdInternal() const
{
return m_cameraId;
}
bool ExynosCamera::previewEnabled()
{
bool ret = false;
/* in scalable mode, we should controll out state */
if (m_parameters != NULL &&
(m_parameters->getScalableSensorMode() == true) &&
(m_scalableSensorMgr.getMode() == EXYNOS_CAMERA_SCALABLE_CHANGING))
ret = true;
else
ret = m_previewEnabled;
CLOGI("INFO(%s[%d]):m_previewEnabled=%d",
__FUNCTION__, __LINE__, (int)ret);
return ret;
}
bool ExynosCamera::recordingEnabled()
{
bool ret = m_getRecordingEnabled();
CLOGI("INFO(%s[%d]):m_recordingEnabled=%d",
__FUNCTION__, __LINE__, (int)ret);
return ret;
}
status_t ExynosCamera::autoFocus()
{
CLOGI("INFO(%s[%d])", __FUNCTION__, __LINE__);
if (m_parameters != NULL) {
if (m_parameters->getVisionMode() == true) {
CLOGW("WRN(%s[%d]): Vision mode does not support", __FUNCTION__, __LINE__);
android_printAssert(NULL, LOG_TAG, "Cannot support this operation");
return INVALID_OPERATION;
}
}
if (m_previewEnabled == false) {
CLOGE("ERR(%s[%d]): preview is not enabled", __FUNCTION__, __LINE__);
return INVALID_OPERATION;
}
if (m_autoFocusRunning == false) {
m_autoFocusType = AUTO_FOCUS_SERVICE;
m_autoFocusThread->requestExitAndWait();
m_autoFocusThread->run(PRIORITY_DEFAULT);
} else {
CLOGW("WRN(%s[%d]): auto focus is inprogressing", __FUNCTION__, __LINE__);
}
#if 0 // not used.
if (m_parameters != NULL) {
if (m_parameters->getFocusMode() == FOCUS_MODE_AUTO) {
CLOGI("INFO(%s[%d]) ae awb lock", __FUNCTION__, __LINE__);
m_parameters->m_setAutoExposureLock(true);
m_parameters->m_setAutoWhiteBalanceLock(true);
}
}
#endif
return NO_ERROR;
}
CameraParameters ExynosCamera::getParameters() const
{
CLOGI("INFO(%s[%d])", __FUNCTION__, __LINE__);
return m_parameters->getParameters();
}
void ExynosCamera::setCallbacks(
camera_notify_callback notify_cb,
camera_data_callback data_cb,
camera_data_timestamp_callback data_cb_timestamp,
camera_request_memory get_memory,
void *user)
{
CLOGI("INFO(%s[%d]): -IN-", __FUNCTION__, __LINE__);
int ret = 0;
m_notifyCb = notify_cb;
m_dataCb = data_cb;
m_dataCbTimestamp = data_cb_timestamp;
m_getMemoryCb = get_memory;
m_callbackCookie = user;
if (m_mhbAllocator == NULL)
m_mhbAllocator = new ExynosCameraMHBAllocator();
ret = m_mhbAllocator->init(get_memory);
if (ret < 0) {
CLOGE("ERR(%s[%d]:m_mhbAllocator init failed", __FUNCTION__, __LINE__);
}
}
status_t ExynosCamera::setDualMode(bool enabled)
{
if (m_parameters == NULL) {
CLOGE("ERR(%s[%d]):m_parameters is NULL", __FUNCTION__, __LINE__);
return INVALID_OPERATION;
}
m_parameters->setDualMode(enabled);
return NO_ERROR;
}
void ExynosCamera::enableMsgType(int32_t msgType)
{
if (m_parameters) {
CLOGV("INFO(%s[%d]): enable Msg (%x)", __FUNCTION__, __LINE__, msgType);
m_parameters->enableMsgType(msgType);
}
}
void ExynosCamera::disableMsgType(int32_t msgType)
{
if (m_parameters) {
CLOGV("INFO(%s[%d]): disable Msg (%x)", __FUNCTION__, __LINE__, msgType);
m_parameters->disableMsgType(msgType);
}
}
bool ExynosCamera::msgTypeEnabled(int32_t msgType)
{
bool isEnabled = false;
if (m_parameters) {
CLOGV("INFO(%s[%d]): Msg type enabled (%x)", __FUNCTION__, __LINE__, msgType);
isEnabled = m_parameters->msgTypeEnabled(msgType);
}
return isEnabled;
}
status_t ExynosCamera::dump(__unused int fd)
{
CLOGI("INFO(%s[%d]):", __FUNCTION__, __LINE__);
m_dump();
return NO_ERROR;
}
status_t ExynosCamera::storeMetaDataInBuffers(__unused bool enable)
{
CLOGI("INFO(%s[%d])", __FUNCTION__, __LINE__);
return OK;
}
bool ExynosCamera::m_mainThreadFunc(void)
{
status_t ret = NO_ERROR;
int index = 0;
ExynosCameraFrame *newFrame = NULL;
if (m_previewEnabled == false) {
CLOGD("DEBUG(%s[%d]):Preview is stopped, thread stop", __FUNCTION__, __LINE__);
return false;
}
ret = m_pipeFrameDoneQ->waitAndPopProcessQ(&newFrame);
if (m_flagThreadStop == true) {
CLOGI("INFO(%s[%d]):m_flagThreadStop(%d)", __FUNCTION__, __LINE__, m_flagThreadStop);
return false;
}
if (ret != NO_ERROR) {
/* TODO: We need to make timeout duration depends on FPS */
if (ret == TIMED_OUT)
CLOGW("WARN(%s[%d]):Wait timeout", __FUNCTION__, __LINE__);
else
CLOGE("ERR(%s[%d]):Wait and pop fail, ret(%d)", __FUNCTION__, __LINE__, ret);
return true;
}
if (newFrame == NULL) {
CLOGE("ERR(%s[%d]):newFrame is NULL", __FUNCTION__, __LINE__);
return true;
}
/* HACK Reset Preview Flag*/
#if 0
if (m_parameters->getRestartPreview() == true) {
m_resetPreview = true;
ret = m_restartPreviewInternal();
m_resetPreview = false;
CLOGE("INFO(%s[%d]) m_resetPreview(%d)", __FUNCTION__, __LINE__, m_resetPreview);
if (ret < 0)
CLOGE("(%s[%d]): restart preview internal fail", __FUNCTION__, __LINE__);
return true;
}
#endif
ret = m_handlePreviewFrame(newFrame);
if (ret != NO_ERROR) {
CLOGE("ERR(%s[%d]):handle preview frame fail, ret(%d)",
__FUNCTION__, __LINE__, ret);
return ret;
}
/* Below code block is moved to m_handlePreviewFrame() and m_handlePreviewFrameFront() functions
* because we want to delete the frame as soon as the setFrameState(FRAME_STATE_COMPLETE) is called.
* Otherwise, some other thread might be executed between "setFrameState(FRAME_STATE_COMPLETE)" and
* "delete frame" statements and might delete the same frame. This would cause the second "delete frame"
* (trying to delete the same frame) to behave abnormally since that frame is already deleted.
*/
#if 0
/* Don't use this lock */
m_frameFliteDeleteBetweenPreviewReprocessing.lock();
if (newFrame->isComplete() == true) {
ret = m_removeFrameFromList(&m_processList, newFrame);
if (ret < 0) {
CLOGE("ERR(%s[%d]):remove frame from processList fail, ret(%d)", __FUNCTION__, __LINE__, ret);
}
if (newFrame->getFrameLockState() == false)
{
delete newFrame;
newFrame = NULL;
}
}
m_frameFliteDeleteBetweenPreviewReprocessing.unlock();
#endif
/*
* HACK
* By using MCpipe. we don't use seperated pipe_scc.
* so, we will not meet inputFrameQ's fail issue.
*/
/* m_checkFpsAndUpdatePipeWaitTime(); */
return true;
}
bool ExynosCamera::m_mainThreadQSetupFLITE(void)
{
#ifdef DEBUG
ExynosCameraAutoTimer autoTimer(__FUNCTION__);
#endif
status_t ret = NO_ERROR;
bool loop = true;
int pipeId = PIPE_FLITE;
ExynosCameraBuffer buffer;
ExynosCameraFrame *frame = NULL;
ExynosCameraFrame *newframe = NULL;
CLOGV("INFO(%s[%d]):Wait previewCancelQ", __FUNCTION__, __LINE__);
ret = m_mainSetupQ[INDEX(pipeId)]->waitAndPopProcessQ(&frame);
if (m_flagThreadStop == true) {
CLOGI("INFO(%s[%d]):m_flagThreadStop(%d)", __FUNCTION__, __LINE__, m_flagThreadStop);
goto func_exit;
}
if (ret != NO_ERROR) {
if (ret == TIMED_OUT)
CLOGW("WARN(%s[%d]):Wait timeout", __FUNCTION__, __LINE__);
else
CLOGE("ERR(%s[%d]):Wait and pop fail, ret(%d)", __FUNCTION__, __LINE__, ret);
goto func_exit;
}
if (frame == NULL) {
CLOGE("ERR(%s[%d]):frame is NULL", __FUNCTION__, __LINE__);
goto func_exit;
}
if (m_bayerBufferMgr->getNumOfAvailableBuffer() > 0) {
ret = m_generateFrame(m_fliteFrameCount, &newframe);
if (ret != NO_ERROR) {
CLOGE("ERR(%s[%d]):generateFrame fail", __FUNCTION__, __LINE__);
goto func_exit;
}
if (newframe == NULL) {
CLOGE("ERR(%s[%d]):frame is NULL", __FUNCTION__, __LINE__);
goto func_exit;
}
ret = m_setupEntity(pipeId, newframe);
if (ret != NO_ERROR) {
CLOGE("ERR(%s[%d]):setupEntity fail", __FUNCTION__, __LINE__);
}
ret = newframe->getDstBuffer(pipeId, &buffer);
if (ret != NO_ERROR)
CLOGE("ERR(%s[%d]):getDstBuffer fail, ret(%d)", __FUNCTION__, __LINE__, ret);
m_previewFrameFactory->pushFrameToPipe(&newframe, pipeId);
m_fliteFrameCount++;
}
func_exit:
if (frame != NULL) {
frame->decRef();
m_frameMgr->deleteFrame(frame);;
frame = NULL;
}
return loop;
}
bool ExynosCamera::m_mainThreadQSetup3AA(void)
{
#ifdef DEBUG
ExynosCameraAutoTimer autoTimer(__FUNCTION__);
#endif
status_t ret = NO_ERROR;
bool loop = true;
int bayerPipeId = PIPE_FLITE;
int pipeId = PIPE_3AA;
ExynosCameraBuffer buffer;
ExynosCameraFrame *frame = NULL;
ExynosCameraFrame *newframe = NULL;
CLOGV("INFO(%s[%d]):Wait previewCancelQ", __FUNCTION__, __LINE__);
ret = m_mainSetupQ[INDEX(pipeId)]->waitAndPopProcessQ(&frame);
if (m_flagThreadStop == true) {
CLOGI("INFO(%s[%d]):m_flagThreadStop(%d)", __FUNCTION__, __LINE__, m_flagThreadStop);
goto func_exit;
}
if (ret != NO_ERROR) {
if (ret == TIMED_OUT)
CLOGW("WARN(%s[%d]):Wait timeout", __FUNCTION__, __LINE__);
else
CLOGE("ERR(%s[%d]):Wait and pop fail, ret(%d)", __FUNCTION__, __LINE__, ret);
goto func_exit;
}
if (frame == NULL) {
CLOGE("ERR(%s[%d]):frame is NULL", __FUNCTION__, __LINE__);
goto func_exit;
}
ret = frame->getSrcBuffer(pipeId, &buffer);
if (ret != NO_ERROR) {
CLOGE("ERR(%s[%d]):getSrcBuffer fail, pipeId(%d), ret(%d)",
__FUNCTION__, __LINE__, pipeId, ret);
goto func_exit;
}
if (buffer.index >= 0) {
ret = m_putBuffers(m_3aaBufferMgr, buffer.index);
if (ret != NO_ERROR) {
CLOGE("ERR(%s[%d]):put Buffer fail", __FUNCTION__, __LINE__);
}
}
if (m_parameters->isUseEarlyFrameReturn() == true) {
frame->decRef();
m_frameMgr->deleteFrame(frame);
} else {
m_pipeFrameDoneQ->pushProcessQ(&frame);
}
ret = m_generateFrame(m_3aa_ispFrameCount, &newframe);
if (ret != NO_ERROR) {
CLOGE("ERR(%s[%d]):generateFrame fail", __FUNCTION__, __LINE__);
goto func_exit;
}
if (newframe == NULL) {
CLOGE("ERR(%s[%d]):frame is NULL", __FUNCTION__, __LINE__);
goto func_exit;
}
ret = m_setupEntity(pipeId, newframe);
if (ret != NO_ERROR)
CLOGE("ERR(%s[%d]):setupEntity fail", __FUNCTION__, __LINE__);
m_previewFrameFactory->pushFrameToPipe(&newframe, pipeId);
m_3aa_ispFrameCount++;
/* Push frame to pure bayer pipe when pure always mode */
if (m_parameters->getReprocessingBayerMode() == REPROCESSING_BAYER_MODE_PURE_ALWAYS_ON
&& m_parameters->getIntelligentMode() != 1) {
int minBayerFrameNum = m_exynosconfig->current->bufInfo.init_bayer_buffers;
int min3AAFrameNum = m_exynosconfig->current->pipeInfo.prepare[PIPE_3AA];
/*
* Generate frame and sync FLITE, 3AA frame count.
* We must considering FLITE, 3AA initialized buffer count gap.
* (min3AAFrame count - minBayerFrameNum) is calculation of initialized buffer count gap.
* FLITE count > 3AA count : Skip frame generation.
* FLITE count <= 3AA count : Generate frame while FLITE count == 3AA count.
*/
while ((int)m_3aa_ispFrameCount - (int)m_fliteFrameCount > min3AAFrameNum - minBayerFrameNum) {
ret = m_generateFrame(m_fliteFrameCount, &newframe);
if (ret != NO_ERROR) {
CLOGE("ERR(%s[%d]):generateFrame fail", __FUNCTION__, __LINE__);
goto func_exit;
}
if (newframe == NULL) {
CLOGE("ERR(%s[%d]):frame is NULL", __FUNCTION__, __LINE__);
goto func_exit;
}
/* Wait tha bayer buffer to be returned to avoid that
bayer buffer is skipped to queue. */
int retryCount = 10; /* 1 msec x 10 = 10 msec */
while (m_bayerBufferMgr->getNumOfAvailableBuffer() <= 0
&& retryCount-- > 0) {
usleep(1000);
}
if (m_bayerBufferMgr->getNumOfAvailableBuffer() > 0) {
ret = m_setupEntity(bayerPipeId, newframe);
if (ret != NO_ERROR) {
CLOGE("ERR(%s[%d]):setupEntity fail", __FUNCTION__, __LINE__);
}
#ifdef SUPPORT_DEPTH_MAP
if (newframe->getRequest(PIPE_VC1) == true) {
if (m_depthMapBufferMgr != NULL
&& m_depthMapBufferMgr->getNumOfAvailableBuffer() > 0) {
int bufIndex = -1;
ret = m_depthMapBufferMgr->getBuffer(&bufIndex, EXYNOS_CAMERA_BUFFER_POSITION_IN_HAL, &buffer);
if (ret == NO_ERROR && bufIndex >= 0) {
ret = newframe->setDstBufferState(PIPE_FLITE, ENTITY_BUFFER_STATE_REQUESTED, CAPTURE_NODE_2);
if (ret == NO_ERROR) {
ret = newframe->setDstBuffer(PIPE_FLITE, buffer, CAPTURE_NODE_2);
if (ret != NO_ERROR) {
CLOGE("ERR(%s[%d]):Failed to setDstBuffer. PIPE_FLITE, CAPTURE_NODE_2",
__FUNCTION__, __LINE__);
newframe->setRequest(PIPE_VC1, false);
}
} else {
CLOGE("ERR(%s[%d]):Failed to setDstBufferState with REQUESTED. PIPE_FLITE, CAPTURE_NODE_2",
__FUNCTION__, __LINE__);
newframe->setRequest(PIPE_VC1, false);
}
} else {
CLOGW("WARN(%s[%d]):Failed to get DepthMap buffer. ret %d bufferIndex %d",
__FUNCTION__, __LINE__, ret, bufIndex);
newframe->setRequest(PIPE_VC1, false);
}
} else {
CLOGW("WARN(%s[%d]):Failed to get DepthyMap buffer. m_depthMapBufferMgr %p availableBuffercount %d",
__FUNCTION__, __LINE__,
m_depthMapBufferMgr,
m_depthMapBufferMgr->getNumOfAvailableBuffer());
newframe->setRequest(PIPE_VC1, false);
}
}
#endif
m_previewFrameFactory->pushFrameToPipe(&newframe, bayerPipeId);
} else {
int numRequestPipe = (int)(newframe->getNumRequestPipe());
numRequestPipe--;
if (numRequestPipe < 0)
numRequestPipe = 0;
newframe->setNumRequestPipe(numRequestPipe);
}
m_fliteFrameCount++;
}
}
func_exit:
return loop;
}
bool ExynosCamera::m_zoomPreviwWithCscThreadFunc(void)
{
#ifdef DEBUG
ExynosCameraAutoTimer autoTimer(__FUNCTION__);
#endif
int ret = 0;
bool loop = true;
int32_t previewFormat = 0;
ExynosRect srcRect, dstRect;
ExynosCameraBuffer srcBuf;
ExynosCameraBuffer dstBuf;
uint32_t *output = NULL;
struct camera2_stream *meta = NULL;
ExynosCameraBufferManager *srcBufMgr = NULL;
ExynosCameraBufferManager *dstBufMgr = NULL;
ExynosCameraFrameEntity *entity = NULL;
int previewH, previewW;
int bufIndex = -1;
int waitCount = 0;
int scpNodeIndex = -1;
int srcNodeIndex = -1;
int srcFmt = -1;
int pipeId = -1;
int gscPipe = -1;
ExynosCameraFrame *frame = NULL;
int32_t status = 0;
frame_queue_t *pipeFrameDoneQ = NULL;
entity_buffer_state_t state = ENTITY_BUFFER_STATE_NOREQ;
CLOGV("INFO(%s[%d]):wait zoomPreviwWithCscQThreadFunc", __FUNCTION__, __LINE__);
status = m_zoomPreviwWithCscQ->waitAndPopProcessQ(&frame);
if (m_flagThreadStop == true) {
CLOGI("INFO(%s[%d]):m_flagThreadStop(%d)", __FUNCTION__, __LINE__, m_flagThreadStop);
return false;
}
if (status < 0) {
/* TODO: We need to make timeout duration depends on FPS */
if (status == TIMED_OUT) {
CLOGW("WARN(%s):wait timeout", __FUNCTION__);
} else {
CLOGE("ERR(%s):wait and pop fail, ret(%d)", __FUNCTION__, ret);
/* TODO: doing exception handling */
}
return true;
}
if (frame == NULL) {
CLOGE("ERR(%s[%d]):frame is NULL, retry", __FUNCTION__, __LINE__);
return true;
}
pipeFrameDoneQ = m_pipeFrameDoneQ;
previewFormat = m_parameters->getHwPreviewFormat();
m_parameters->getHwPreviewSize(&previewW, &previewH);
/* get Scaler src Buffer Node Index*/
if ((m_parameters->getDualMode() == true) &&
(getCameraIdInternal() == CAMERA_ID_FRONT || getCameraIdInternal() == CAMERA_ID_BACK_1)) {
pipeId = PIPE_3AA;
#ifdef USE_GSC_FOR_PREVIEW
gscPipe = PIPE_GSC;
#else
gscPipe = PIPE_GSC_VIDEO;
#endif
srcNodeIndex = m_previewFrameFactory->getNodeType(PIPE_ISPC);
srcFmt = m_parameters->getHWVdisFormat();
scpNodeIndex = m_previewFrameFactory->getNodeType(PIPE_SCP);
srcBufMgr = m_sccBufferMgr;
#ifdef BOARD_CAMERA_USES_DUAL_CAMERA
if (m_parameters->isFusionEnabled() == true)
dstBufMgr = m_fusionBufferMgr;
else
#endif
dstBufMgr = m_scpBufferMgr;
} else {
pipeId = PIPE_ISP;
#ifdef USE_GSC_FOR_PREVIEW
gscPipe = PIPE_GSC;
#else
gscPipe = PIPE_GSC_VIDEO;
#endif
srcNodeIndex = m_previewFrameFactory->getNodeType(PIPE_SCP);
srcFmt = m_parameters->getHwPreviewFormat();
scpNodeIndex = m_previewFrameFactory->getNodeType(PIPE_SCP);
srcBufMgr = m_zoomScalerBufferMgr;
#ifdef BOARD_CAMERA_USES_DUAL_CAMERA
if (m_parameters->isFusionEnabled() == true)
dstBufMgr = m_fusionBufferMgr;
else
#endif
dstBufMgr = m_scpBufferMgr;
}
ret = frame->getDstBufferState(pipeId, &state, srcNodeIndex);
if (ret < 0 || state != ENTITY_BUFFER_STATE_COMPLETE) {
CLOGE("ERR(%s[%d]):getDstBufferState fail, pipeId(%d), state(%d) frame(%d)",
__FUNCTION__, __LINE__, pipeId, state, frame->getFrameCount());
ret = INVALID_OPERATION;
goto func_exit;
}
/* get scaler source buffer */
srcBuf.index = -1;
ret = frame->getDstBuffer(pipeId, &srcBuf, srcNodeIndex);
if (ret != NO_ERROR) {
CLOGE("ERR(%s[%d]):getDstBuffer fail, pipeId(%d), ret(%d) frame(%d)",
__FUNCTION__, __LINE__, pipeId, ret, frame->getFrameCount());
ret = INVALID_OPERATION;
goto func_exit;
}
/* getMetadata to get buffer size */
meta = (struct camera2_stream*)srcBuf.addr[srcBuf.planeCount-1];
if (meta == NULL) {
CLOGE("ERR(%s[%d]):meta is NULL, pipeId(%d), ret(%d) frame(%d)",
__FUNCTION__, __LINE__, gscPipe, ret, frame->getFrameCount());
ret = INVALID_OPERATION;
goto func_exit;
}
output = meta->output_crop_region;
dstBuf.index = -2;
bufIndex = -1;
ret = dstBufMgr->getBuffer(&bufIndex, EXYNOS_CAMERA_BUFFER_POSITION_IN_HAL, &dstBuf);
if (ret != NO_ERROR) {
CLOGE("ERR(%s[%d]):Buffer manager getBuffer fail, frame(%d), ret(%d)",
__FUNCTION__, __LINE__, frame->getFrameCount(), ret);
goto func_exit;
}
/* csc and scaling */
srcRect.x = 0;
srcRect.y = 0;
srcRect.w = output[2];
srcRect.h = output[3];
srcRect.fullW = output[2];
srcRect.fullH = output[3];
srcRect.colorFormat = srcFmt;
dstRect.x = 0;
dstRect.y = 0;
dstRect.w = previewW;
dstRect.h = previewH;
dstRect.fullW = previewW;
dstRect.fullH = previewH;
dstRect.colorFormat = previewFormat;
if ((m_parameters->getDualMode() == true) &&
(getCameraIdInternal() == CAMERA_ID_FRONT || getCameraIdInternal() == CAMERA_ID_BACK_1)) {
/* dual front scenario use 3aa bayer crop */
} else {
m_parameters->calcPreviewDzoomCropSize(&srcRect, &dstRect);
}
ret = frame->setSrcRect(gscPipe, srcRect);
ret = frame->setDstRect(gscPipe, dstRect);
CLOGV("DEBUG(%s[%d]):do zoomPreviw with CSC : srcBuf(%d) dstBuf(%d) (%d, %d, %d, %d) format(%d) actual(%x) -> \
(%d, %d, %d, %d) format(%d) actual(%x)", __FUNCTION__, __LINE__,
srcBuf.index, dstBuf.index, srcRect.x, srcRect.y, srcRect.w, srcRect.h, srcFmt,
V4L2_PIX_2_HAL_PIXEL_FORMAT(srcFmt), dstRect.x, dstRect.y, dstRect.w, dstRect.h,
previewFormat, V4L2_PIX_2_HAL_PIXEL_FORMAT(previewFormat));
ret = m_setupEntity(gscPipe, frame, &srcBuf, &dstBuf);
if (ret < 0) {
CLOGE("ERR(%s[%d]):setupEntity fail, pipeId(%d), ret(%d) frame(%d)",
__FUNCTION__, __LINE__, gscPipe, ret, frame->getFrameCount());
ret = INVALID_OPERATION;
goto func_exit;
}
m_previewFrameFactory->setOutputFrameQToPipe(pipeFrameDoneQ, gscPipe);
m_previewFrameFactory->pushFrameToPipe(&frame, gscPipe);
CLOGV("DEBUG(%s[%d]):--OUT--", __FUNCTION__, __LINE__);
return loop;
func_exit:
CLOGE("ERR(%s[%d]):do zoomPreviw with CSC failed frame(%d) ret(%d) src(%d) dst(%d)",
__FUNCTION__, __LINE__, frame->getFrameCount(), ret, srcBuf.index, dstBuf.index);
dstBuf.index = -1;
ret = frame->getDstBuffer(gscPipe, &dstBuf);
if (ret != NO_ERROR) {
CLOGE("ERR(%s[%d]):getDstBuffer fail, pipeId(%d), ret(%d) frame(%d)",
__FUNCTION__, __LINE__, gscPipe, ret, frame->getFrameCount());
}
if (dstBuf.index >= 0)
dstBufMgr->cancelBuffer(dstBuf.index);
/* msc with ndone frame, in order to frame order*/
CLOGE("ERR(%s[%d]): zoom with scaler getbuffer failed , use MSC for NDONE frame(%d)",
__FUNCTION__, __LINE__, frame->getFrameCount());
frame->setSrcBufferState(gscPipe, ENTITY_BUFFER_STATE_ERROR);
m_previewFrameFactory->setOutputFrameQToPipe(pipeFrameDoneQ, gscPipe);
m_previewFrameFactory->pushFrameToPipe(&frame, gscPipe);
CLOGV("DEBUG(%s[%d]):--OUT--", __FUNCTION__, __LINE__);
return INVALID_OPERATION;
}
#ifdef BOARD_CAMERA_USES_DUAL_CAMERA
bool ExynosCamera::m_fusionThreadFunc(void)
{
#ifdef DEBUG
ExynosCameraAutoTimer autoTimer(__FUNCTION__);
#endif
int ret = 0;
bool loop = true;
int32_t previewFormat = 0;
ExynosRect srcRect, dstRect;
ExynosCameraBuffer srcBuf;
ExynosCameraBuffer dstBuf;
uint32_t *output = NULL;
struct camera2_stream *meta = NULL;
ExynosCameraBufferManager *srcBufMgr = NULL;
ExynosCameraBufferManager *dstBufMgr = NULL;
int previewH, previewW;
int bufIndex = -1;
int waitCount = 0;
int srcNodeIndex = -1;
int srcPipeId = -1;
int dstPipeId = PIPE_FUSION;
ExynosCameraFrame *frame = NULL;
int32_t status = 0;
frame_queue_t *pipeFrameDoneQ = NULL;
entity_buffer_state_t state = ENTITY_BUFFER_STATE_NOREQ;
ExynosRect fusionSrcRect;
ExynosRect fusionDstRect;
CLOGV("INFO(%s[%d]):wait %s", __FUNCTION__, __LINE__, __FUNCTION__);
status = m_fusionQ->waitAndPopProcessQ(&frame);
if (m_flagThreadStop == true) {
CLOGI("INFO(%s[%d]):m_flagThreadStop(%d)", __FUNCTION__, __LINE__, m_flagThreadStop);
return false;
}
if (status < 0) {
/* TODO: We need to make timeout duration depends on FPS */
if (status == TIMED_OUT) {
CLOGW("WARN(%s):wait timeout", __FUNCTION__);
} else {
CLOGE("ERR(%s):wait and pop fail, ret(%d)", __FUNCTION__, ret);
/* TODO: doing exception handling */
}
return true;
}
if (frame == NULL) {
CLOGE("ERR(%s[%d]):frame is NULL, retry", __FUNCTION__, __LINE__);
return true;
}
pipeFrameDoneQ = m_pipeFrameDoneQ;
previewFormat = m_parameters->getHwPreviewFormat();
m_parameters->getHwPreviewSize(&previewW, &previewH);
///////////////////////////////////////////
// src buffer
if (m_parameters->getZoomPreviewWIthScaler()== true) {
srcPipeId = PIPE_GSC;
srcNodeIndex = 0;
} else {
srcPipeId = PIPE_3AA;
if (m_parameters->is3aaIspOtf() == false)
srcPipeId = PIPE_ISP;
if (m_parameters->getTpuEnabledMode() == true && m_parameters->isIspTpuOtf() == false)
srcPipeId = PIPE_TPU;
if (m_parameters->isIspMcscOtf() == false && m_parameters->isTpuMcscOtf() == false)
srcPipeId = PIPE_MCSC;
srcNodeIndex = m_previewFrameFactory->getNodeType(PIPE_MCSC0);
}
srcBufMgr = m_fusionBufferMgr;
/* gscaler give always ENTITY_BUFFER_STATE_READY */
/*
ret = frame->getDstBufferState(srcPipeId, &state, srcNodeIndex);
if (ret < 0 || state != ENTITY_BUFFER_STATE_COMPLETE) {
CLOGE("ERR(%s[%d]):getDstBufferState fail, srcPipeId(%d), state(%d) frame(%d)",__FUNCTION__, __LINE__, srcPipeId, state, frame->getFrameCount());
goto func_exit;
}
*/
if (frame->getFrameState() == FRAME_STATE_SKIPPED) {
CLOGE("ERR(%s[%d]):frame->getFrameState() == FRAME_STATE_SKIPPED. so, skip fusion. srcPipeId(%d), frame(%d)",
__FUNCTION__, __LINE__, srcPipeId, frame->getFrameCount());
goto func_exit;
}
srcBuf.index = -1;
ret = frame->getDstBuffer(srcPipeId, &srcBuf, srcNodeIndex);
if (ret != NO_ERROR) {
CLOGE("ERR(%s[%d]):getDstBuffer fail, srcPipeId(%d), ret(%d) frame(%d)",__FUNCTION__, __LINE__, srcPipeId, ret, frame->getFrameCount());
goto func_exit;
}
///////////////////////////////////////////
// dst buffer
dstPipeId = PIPE_FUSION;
dstBufMgr = m_scpBufferMgr;
dstBuf.index = -2;
bufIndex = -1;
ret = dstBufMgr->getBuffer(&bufIndex, EXYNOS_CAMERA_BUFFER_POSITION_IN_HAL, &dstBuf);
if (ret != NO_ERROR) {
CLOGE("ERR(%s[%d]):Buffer manager getBuffer fail, frame(%d), ret(%d)",
__FUNCTION__, __LINE__, frame->getFrameCount(), ret);
goto func_exit;
}
/* getMetadata to get buffer size */
meta = (struct camera2_stream*)srcBuf.addr[srcBuf.planeCount - 1];
if (meta == NULL) {
CLOGE("ERR(%s[%d]):meta is NULL, skip fuision. srcPipeId(%d), ret(%d) frame(%d)", __FUNCTION__, __LINE__, srcPipeId, ret, frame->getFrameCount());
goto func_exit;
}
output = meta->output_crop_region;
/* csc and scaling */
srcRect.x = 0;
srcRect.y = 0;
srcRect.w = output[2];
srcRect.h = output[3];
srcRect.fullW = output[2];
srcRect.fullH = output[3];
srcRect.colorFormat = previewFormat;
ret = frame->setSrcRect(dstPipeId, srcRect);
if (m_parameters->getFusionSize(previewW, previewH, &fusionSrcRect, &fusionDstRect) != NO_ERROR) {
CLOGE("ERR(%s[%d]):getFusionSize(%d, %d) fail", __FUNCTION__, __LINE__, previewW, previewH);
return loop;
}
dstRect = fusionDstRect;
ret = frame->setDstRect(dstPipeId, dstRect);
CLOGV("DEBUG(%s[%d]):do fusion : srcBuf(%d)(%d, %d, %d, %d) format(%d) actual(%x) -> dstBuf(%d)(%d, %d, %d, %d) format(%d) actual(%x)",
__FUNCTION__, __LINE__,
srcBuf.index, srcRect.x, srcRect.y, srcRect.w, srcRect.h, srcRect.colorFormat, V4L2_PIX_2_HAL_PIXEL_FORMAT(srcRect.colorFormat),
dstBuf.index, dstRect.x, dstRect.y, dstRect.w, dstRect.h, dstRect.colorFormat, V4L2_PIX_2_HAL_PIXEL_FORMAT(dstRect.colorFormat));
ret = m_setupEntity(dstPipeId, frame, &srcBuf, &dstBuf);
if (ret != NO_ERROR) {
CLOGE("ERR(%s[%d]):setupEntity fail, srcPipeId(%d), ret(%d) frame(%d)", __FUNCTION__, __LINE__, dstPipeId, ret, frame->getFrameCount());
goto func_exit;
}
m_previewFrameFactory->setOutputFrameQToPipe(pipeFrameDoneQ, dstPipeId);
m_previewFrameFactory->pushFrameToPipe(&frame, dstPipeId);
CLOGV("DEBUG(%s[%d]):--OUT--", __FUNCTION__, __LINE__);
return loop;
func_exit:
CLOGE("ERR(%s[%d]):do fusion fail frame(%d) ret(%d) src(%d) dst(%d)", __FUNCTION__, __LINE__, frame->getFrameCount(), ret, srcBuf.index, dstBuf.index);
ret = m_putFrameBuffer(frame, srcPipeId, SRC_BUFFER_DIRECTION);
if (ret != NO_ERROR) {
CLOGE("ERR(%s[%d]):m_putFrameBuffer(frame(%d), pipeId(%d), SRC_BUFFER_DIRECTION) fail",
__FUNCTION__, __LINE__, frame->getFrameCount(), srcPipeId);
}
ret = m_putFrameBuffer(frame, srcPipeId, DST_BUFFER_DIRECTION);
if (ret != NO_ERROR) {
CLOGE("ERR(%s[%d]):m_putFrameBuffer(frame(%d), pipeId(%d), DST_BUFFER_DIRECTION) fail",
__FUNCTION__, __LINE__, frame->getFrameCount(), srcPipeId);
}
/* NDONE frame */
frame->setEntityState(dstPipeId, ENTITY_STATE_FRAME_SKIP);
frame->setSrcBufferState(dstPipeId, ENTITY_BUFFER_STATE_ERROR);
m_previewFrameFactory->setOutputFrameQToPipe(pipeFrameDoneQ, dstPipeId);
m_previewFrameFactory->pushFrameToPipe(&frame, dstPipeId);
CLOGV("DEBUG(%s[%d]):--OUT--", __FUNCTION__, __LINE__);
return loop;
}
#endif
bool ExynosCamera::m_setBuffersThreadFunc(void)
{
int ret = 0;
ret = m_setBuffers();
if (ret < 0) {
CLOGE("ERR(%s[%d]):m_setBuffers failed, releaseBuffer", __FUNCTION__, __LINE__);
/* TODO: Need release buffers and error exit */
m_releaseBuffers();
m_isSuccessedBufferAllocation = false;
return false;
}
m_isSuccessedBufferAllocation = true;
return false;
}
bool ExynosCamera::m_startPictureInternalThreadFunc(void)
{
int ret = 0;
ret = m_startPictureInternal();
if (ret < 0) {
CLOGE("ERR(%s[%d]):m_startPictureInternal failed", __FUNCTION__, __LINE__);
/* TODO: Need release buffers and error exit */
return false;
}
return false;
}
bool ExynosCamera::m_startPictureBufferThreadFunc(void)
{
int ret = 0;
ret = m_setPictureBuffer();
if (ret < 0) {
CLOGE("ERR(%s[%d]):m_setPictureBuffer failed", __FUNCTION__, __LINE__);
/* TODO: Need release buffers and error exit */
return false;
}
return false;
}
#ifdef CAMERA_FAST_ENTRANCE_V1
bool ExynosCamera::m_fastenAeThreadFunc(void)
{
CLOGI("INFO(%s[%d]):", __FUNCTION__, __LINE__);
ExynosCameraAutoTimer autoTimer(__FUNCTION__);
status_t ret = NO_ERROR;
int32_t skipFrameCount = INITIAL_SKIP_FRAME;
m_fastenAeThreadResult = 0;
/* frame manager start */
m_frameMgr->start();
/*
* This is for updating parameter value at once.
* This must be just before making factory
*/
m_parameters->updateTpuParameters();
if (m_previewFrameFactory->isCreated() == false) {
#if defined(SAMSUNG_EEPROM)
if (m_use_companion == false
&& isEEprom(getCameraIdInternal()) == true) {
if (m_eepromThread != NULL) {
CLOGD("DEBUG(%s[%d]):eepromThread join.....", __FUNCTION__, __LINE__);
m_eepromThread->join();
} else {
CLOGD("DEBUG(%s[%d]): eepromThread is NULL.", __FUNCTION__, __LINE__);
}
m_parameters->setRomReadThreadDone(true);
CLOGD("DEBUG(%s[%d]):eepromThread joined", __FUNCTION__, __LINE__);
}
#endif /* SAMSUNG_EEPROM */
#ifdef SAMSUNG_COMPANION
if (m_use_companion == true) {
ret = m_previewFrameFactory->precreate();
if (ret != NO_ERROR) {
CLOGE("ERR(%s[%d]):m_previewFrameFactory->precreate() failed", __FUNCTION__, __LINE__);
goto err;
}
m_waitCompanionThreadEnd();
#ifdef SAMSUNG_COMPANION
m_parameters->setRomReadThreadDone(true);
#endif
ret = m_previewFrameFactory->postcreate();
if (ret != NO_ERROR) {
CLOGE("ERR(%s[%d]):m_previewFrameFactory->postcreate() failed", __FUNCTION__, __LINE__);
goto err;
}
} else {
ret = m_previewFrameFactory->create();
if (ret != NO_ERROR) {
CLOGE("ERR(%s[%d]):m_previewFrameFactory->create() failed", __FUNCTION__, __LINE__);
goto err;
}
}
#else
ret = m_previewFrameFactory->create();
if (ret != NO_ERROR) {
CLOGE("ERR(%s[%d]):m_previewFrameFactory->create() failed", __FUNCTION__, __LINE__);
goto err;
}
#endif /* SAMSUNG_COMPANION */
CLOGD("DEBUG(%s):FrameFactory(previewFrameFactory) created", __FUNCTION__);
}
#ifdef USE_QOS_SETTING
ret = m_previewFrameFactory->setControl(V4L2_CID_IS_DVFS_CLUSTER1, BIG_CORE_MAX_LOCK, PIPE_3AA);
if (ret != NO_ERROR)
CLOGE("ERR(%s[%d]):V4L2_CID_IS_DVFS_CLUSTER1 setControl fail, ret(%d)", __FUNCTION__, __LINE__, ret);
#endif
if (m_parameters->getUseFastenAeStable() == true
&& m_parameters->getDualMode() == false
&& m_isFirstStart == true) {
ret = m_fastenAeStable();
if (ret != NO_ERROR) {
CLOGE("ERR(%s[%d]):m_fastenAeStable() failed", __FUNCTION__, __LINE__);
goto err;
} else {
skipFrameCount = 0;
m_parameters->setUseFastenAeStable(false);
}
}
#ifdef USE_FADE_IN_ENTRANCE
if (m_parameters->getUseFastenAeStable() == true) {
CLOGE("ERR(%s[%d]):consistency in skipFrameCount might be broken by FASTEN_AE and FADE_IN", __FUNCTION__, __LINE__);
}
#endif
m_parameters->setFrameSkipCount(skipFrameCount);
m_fdFrameSkipCount = 0;
/* one shot */
return false;
err:
m_fastenAeThreadResult = ret;
#ifdef SAMSUNG_COMPANION
if (m_use_companion == true)
m_waitCompanionThreadEnd();
#endif
#if defined(SAMSUNG_EEPROM)
if (m_use_companion == false
&& isEEprom(getCameraIdInternal()) == true) {
if (m_eepromThread != NULL)
m_eepromThread->join();
else
CLOGD("DEBUG(%s): eepromThread is NULL.", __FUNCTION__);
}
#endif
return false;
}
status_t ExynosCamera::m_waitFastenAeThreadEnd(void)
{
ExynosCameraDurationTimer timer;
timer.start();
if(m_fastEntrance == true) {
if (m_fastenAeThread != NULL) {
m_fastenAeThread->join();
} else {
CLOGI("INFO(%s[%d]):m_fastenAeThread is NULL", __FUNCTION__, __LINE__);
}
}
timer.stop();
CLOGD("DEBUG(%s[%d]):fastenAeThread waiting time : duration time(%5d msec)", __FUNCTION__, __LINE__, (int)timer.durationMsecs());
CLOGD("DEBUG(%s[%d]):fastenAeThread join", __FUNCTION__, __LINE__);
return NO_ERROR;
}
#endif
bool ExynosCamera::m_prePictureThreadFunc(void)
{
bool loop = false;
bool isProcessed = true;
ExynosCameraDurationTimer m_burstPrePictureTimer;
uint64_t m_burstPrePictureTimerTime;
uint64_t burstWaitingTime;
status_t ret = NO_ERROR;
uint64_t seriesShotDuration = m_parameters->getSeriesShotDuration();
m_burstPrePictureTimer.start();
if (m_parameters->isReprocessing())
loop = m_reprocessingPrePictureInternal();
else
loop = m_prePictureInternal(&isProcessed);
m_burstPrePictureTimer.stop();
m_burstPrePictureTimerTime = m_burstPrePictureTimer.durationUsecs();
if(isProcessed && loop && seriesShotDuration > 0 && m_burstPrePictureTimerTime < seriesShotDuration) {
CLOGD("DEBUG(%s[%d]): The time between shots is too short(%lld)us. Extended to (%lld)us"
, __FUNCTION__, __LINE__, m_burstPrePictureTimerTime, seriesShotDuration);
burstWaitingTime = seriesShotDuration - m_burstPrePictureTimerTime;
usleep(burstWaitingTime);
}
return loop;
}
#if 0
bool ExynosCamera::m_highResolutionCallbackThreadFunc(void)
{
ExynosCameraAutoTimer autoTimer(__FUNCTION__);
CLOGI("INFO(%s[%d]):", __FUNCTION__, __LINE__);
int ret = 0;
int loop = false;
int retryCountGSC = 4;
ExynosCameraFrame *newFrame = NULL;
camera2_stream *shot_stream = NULL;
ExynosCameraBuffer sccReprocessingBuffer;
ExynosCameraBuffer highResolutionCbBuffer;
int cbPreviewW = 0, cbPreviewH = 0;
int previewFormat = 0;
ExynosRect srcRect, dstRect;
m_parameters->getPreviewSize(&cbPreviewW, &cbPreviewH);
previewFormat = m_parameters->getPreviewFormat();
int pipeId_scc = 0;
int pipeId_gsc = 0;
unsigned int planeSize[EXYNOS_CAMERA_BUFFER_MAX_PLANES] = {0};
unsigned int bytesPerLine[EXYNOS_CAMERA_BUFFER_MAX_PLANES] = {0};
int planeCount = getYuvPlaneCount(previewFormat);
int minBufferCount = 1;
int maxBufferCount = 1;
int buffer_idx = getShotBufferIdex();
sccReprocessingBuffer.index = -2;
highResolutionCbBuffer.index = -2;
pipeId_scc = (m_parameters->isOwnScc(getCameraIdInternal()) == true) ? PIPE_SCC_REPROCESSING : PIPE_ISP_REPROCESSING;
pipeId_gsc = PIPE_GSC_REPROCESSING;
exynos_camera_buffer_type_t type = EXYNOS_CAMERA_BUFFER_ION_CACHED_TYPE;
buffer_manager_allocation_mode_t allocMode = BUFFER_MANAGER_ALLOCATION_ONDEMAND;
if (m_parameters->getHighResolutionCallbackMode() == false &&
m_highResolutionCallbackRunning == false) {
CLOGD("DEBUG(%s[%d]): High Resolution Callback Stop", __FUNCTION__, __LINE__);
goto CLEAN;
}
ret = getYuvPlaneSize(previewFormat, planeSize, cbPreviewW, cbPreviewH);
if (ret < 0) {
CLOGE("ERR(%s[%d]): BAD value, format(%x), size(%dx%d)",
__FUNCTION__, __LINE__, previewFormat, cbPreviewW, cbPreviewH);
return ret;
}
/* wait SCC */
CLOGV("INFO(%s[%d]):wait SCC output", __FUNCTION__, __LINE__);
ret = m_highResolutionCallbackQ->waitAndPopProcessQ(&newFrame);
if (m_flagThreadStop == true) {
CLOGI("INFO(%s[%d]):m_flagThreadStop(%d)", __FUNCTION__, __LINE__, m_flagThreadStop);
goto CLEAN;
}
if (ret < 0) {
CLOGE("ERR(%s[%d]):wait and pop fail, ret(%d)", __FUNCTION__, __LINE__, ret);
// TODO: doing exception handling
goto CLEAN;
}
if (newFrame == NULL) {
CLOGE("ERR(%s[%d]):newFrame is NULL", __FUNCTION__, __LINE__);
goto CLEAN;
}
ret = newFrame->setEntityState(pipeId_scc, ENTITY_STATE_COMPLETE);
if (ret < 0) {
CLOGE("ERR(%s[%d]):setEntityState(ENTITY_STATE_PROCESSING) fail, pipeId(%d), ret(%d)", __FUNCTION__, __LINE__, pipeId_scc, ret);
return ret;
}
CLOGV("INFO(%s[%d]):SCC output done", __FUNCTION__, __LINE__);
if (m_parameters->msgTypeEnabled(CAMERA_MSG_PREVIEW_FRAME)) {
/* get GSC src buffer */
ret = newFrame->getDstBuffer(pipeId_scc, &sccReprocessingBuffer, m_reprocessingFrameFactory->getNodeType(PIPE_SCC_REPROCESSING));
if (ret < 0) {
CLOGE("ERR(%s[%d]):getDstBuffer fail, pipeId(%d), ret(%d)",
__FUNCTION__, __LINE__, pipeId_scc, ret);
goto CLEAN;
}
shot_stream = (struct camera2_stream *)(sccReprocessingBuffer.addr[buffer_idx]);
if (shot_stream == NULL) {
CLOGE("ERR(%s[%d]):shot_stream is NULL. buffer(%d)",
__FUNCTION__, __LINE__, sccReprocessingBuffer.index);
goto CLEAN;
}
/* alloc GSC buffer */
if (m_highResolutionCallbackBufferMgr->isAllocated() == false) {
ret = m_allocBuffers(m_highResolutionCallbackBufferMgr, planeCount, planeSize, bytesPerLine, minBufferCount, maxBufferCount, type, allocMode, false, false);
if (ret < 0) {
CLOGE("ERR(%s[%d]):m_highResolutionCallbackBufferMgr m_allocBuffers(minBufferCount=%d, maxBufferCount=%d) fail",
__FUNCTION__, __LINE__, minBufferCount, maxBufferCount);
return ret;
}
}
/* get GSC dst buffer */
int bufIndex = -2;
m_highResolutionCallbackBufferMgr->getBuffer(&bufIndex, EXYNOS_CAMERA_BUFFER_POSITION_IN_HAL, &highResolutionCbBuffer);
/* get preview callback heap */
camera_memory_t *previewCallbackHeap = NULL;
previewCallbackHeap = m_getMemoryCb(highResolutionCbBuffer.fd[0], highResolutionCbBuffer.size[0], 1, m_callbackCookie);
if (!previewCallbackHeap || previewCallbackHeap->data == MAP_FAILED) {
CLOGE("ERR(%s[%d]):m_getMemoryCb(%d) fail", __FUNCTION__, __LINE__, highResolutionCbBuffer.size[0]);
goto CLEAN;
}
ret = m_setCallbackBufferInfo(&highResolutionCbBuffer, (char *)previewCallbackHeap->data);
if (ret < 0) {
CLOGE("ERR(%s[%d]): setCallbackBufferInfo fail, ret(%d)", __FUNCTION__, __LINE__, ret);
goto CLEAN;
}
/* set src/dst rect */
srcRect.x = shot_stream->output_crop_region[0];
srcRect.y = shot_stream->output_crop_region[1];
srcRect.w = shot_stream->output_crop_region[2];
srcRect.h = shot_stream->output_crop_region[3];
ret = m_calcHighResolutionPreviewGSCRect(&srcRect, &dstRect);
ret = newFrame->setSrcRect(pipeId_gsc, &srcRect);
ret = newFrame->setDstRect(pipeId_gsc, &dstRect);
CLOGV("DEBUG(%s[%d]):srcRect x : %d, y : %d, w : %d, h : %d", __FUNCTION__, __LINE__, srcRect.x, srcRect.y, srcRect.w, srcRect.h);
CLOGV("DEBUG(%s[%d]):dstRect x : %d, y : %d, w : %d, h : %d", __FUNCTION__, __LINE__, dstRect.x, dstRect.y, dstRect.w, dstRect.h);
ret = m_setupEntity(pipeId_gsc, newFrame, &sccReprocessingBuffer, &highResolutionCbBuffer);
if (ret < 0) {
CLOGE("ERR(%s[%d]):setupEntity fail, pipeId(%d), ret(%d)",
__FUNCTION__, __LINE__, pipeId_gsc, ret);
goto CLEAN;
}
/* push frame to GSC pipe */
m_pictureFrameFactory->setOutputFrameQToPipe(m_dstGscReprocessingQ, pipeId_gsc);
m_pictureFrameFactory->pushFrameToPipe(&newFrame, pipeId_gsc);
/* wait GSC for high resolution preview callback */
CLOGI("INFO(%s[%d]):wait GSC output", __FUNCTION__, __LINE__);
while (retryCountGSC > 0) {
ret = m_dstGscReprocessingQ->waitAndPopProcessQ(&newFrame);
if (ret == TIMED_OUT) {
CLOGW("WRN(%s)(%d):wait and pop timeout, ret(%d)", __FUNCTION__, __LINE__, ret);
m_pictureFrameFactory->startThread(pipeId_gsc);
} else if (ret < 0) {
CLOGE("ERR(%s)(%d):wait and pop fail, ret(%d)", __FUNCTION__, __LINE__, ret);
/* TODO: doing exception handling */
goto CLEAN;
} else {
break;
}
retryCountGSC--;
}
if (newFrame == NULL) {
CLOGE("ERR(%s):newFrame is NULL", __FUNCTION__);
goto CLEAN;
}
CLOGI("INFO(%s[%d]):GSC output done", __FUNCTION__, __LINE__);
/* put SCC buffer */
ret = newFrame->getDstBuffer(pipeId_scc, &sccReprocessingBuffer, m_reprocessingFrameFactory->getNodeType(PIPE_SCC_REPROCESSING));
if (ret < 0) {
CLOGE("ERR(%s[%d]):getDstBuffer fail, pipeId(%d), ret(%d)", __FUNCTION__, __LINE__, pipeId_scc, ret);
goto CLEAN;
}
ret = m_putBuffers(m_sccReprocessingBufferMgr, sccReprocessingBuffer.index);
CLOGV("DEBUG(%s[%d]):high resolution preview callback", __FUNCTION__, __LINE__);
if (m_parameters->msgTypeEnabled(CAMERA_MSG_PREVIEW_FRAME)) {
setBit(&m_callbackState, CALLBACK_STATE_PREVIEW_FRAME, false);
m_dataCb(CAMERA_MSG_PREVIEW_FRAME, previewCallbackHeap, 0, NULL, m_callbackCookie);
clearBit(&m_callbackState, CALLBACK_STATE_PREVIEW_FRAME, false);
}
previewCallbackHeap->release(previewCallbackHeap);
/* put high resolution callback buffer */
ret = m_putBuffers(m_highResolutionCallbackBufferMgr, highResolutionCbBuffer.index);
if (ret < 0) {
CLOGE("ERR(%s[%d]):m_putBuffers fail, pipeId(%d), ret(%d)", __FUNCTION__, __LINE__, pipeId_gsc, ret);
goto CLEAN;
}
if (newFrame != NULL) {
newFrame->frameUnlock();
ret = m_removeFrameFromList(&m_postProcessList, newFrame);
if (ret < 0) {
CLOGE("ERR(%s[%d]):remove frame from processList fail, ret(%d)", __FUNCTION__, __LINE__, ret);
}
CLOGD("DEBUG(%s[%d]): Reprocessing frame delete(%d)", __FUNCTION__, __LINE__, newFrame->getFrameCount());
newFrame->decRef();
m_frameMgr->deleteFrame(newFrame);
newFrame = NULL;
}
} else {
CLOGD("DEBUG(%s[%d]): Preview callback message disabled, skip callback", __FUNCTION__, __LINE__);
/* put SCC buffer */
ret = newFrame->getDstBuffer(pipeId_scc, &sccReprocessingBuffer, m_reprocessingFrameFactory->getNodeType(PIPE_SCC_REPROCESSING));
if (ret < 0) {
CLOGE("ERR(%s[%d]):getDstBuffer fail, pipeId(%d), ret(%d)", __FUNCTION__, __LINE__, pipeId_scc, ret);
goto CLEAN;
}
ret = m_putBuffers(m_sccReprocessingBufferMgr, sccReprocessingBuffer.index);
}
if(m_flagThreadStop != true) {
if (m_highResolutionCallbackQ->getSizeOfProcessQ() > 0 ||
m_parameters->getHighResolutionCallbackMode() == true) {
CLOGD("DEBUG(%s[%d]):highResolutionCallbackQ size(%d), highResolutionCallbackMode(%s), start again",
__FUNCTION__, __LINE__,
m_highResolutionCallbackQ->getSizeOfProcessQ(),
(m_parameters->getHighResolutionCallbackMode() == true)? "TRUE" : "FALSE");
loop = true;
}
}
CLOGI("INFO(%s[%d]):high resolution callback thread complete, loop(%d)", __FUNCTION__, __LINE__, loop);
/* one shot */
return loop;
CLEAN:
if (sccReprocessingBuffer.index != -2)
ret = m_putBuffers(m_sccReprocessingBufferMgr, sccReprocessingBuffer.index);
if (highResolutionCbBuffer.index != -2)
m_putBuffers(m_highResolutionCallbackBufferMgr, highResolutionCbBuffer.index);
if (newFrame != NULL) {
newFrame->printEntity();
newFrame->frameUnlock();
ret = m_removeFrameFromList(&m_postProcessList, newFrame);
if (ret < 0) {
CLOGE("ERR(%s[%d]):remove frame from processList fail, ret(%d)", __FUNCTION__, __LINE__, ret);
}
ret = m_deleteFrame(&newFrame);
if (ret < 0) {
CLOGE("ERR(%s[%d]):m_deleteFrame fail, ret(%d)", __FUNCTION__, __LINE__, ret);
}
}
if(m_flagThreadStop != true) {
if (m_highResolutionCallbackQ->getSizeOfProcessQ() > 0 ||
m_parameters->getHighResolutionCallbackMode() == true) {
CLOGD("DEBUG(%s[%d]):highResolutionCallbackQ size(%d), highResolutionCallbackMode(%s), start again",
__FUNCTION__, __LINE__,
m_highResolutionCallbackQ->getSizeOfProcessQ(),
(m_parameters->getHighResolutionCallbackMode() == true)? "TRUE" : "FALSE");
loop = true;
}
}
CLOGI("INFO(%s[%d]):high resolution callback thread fail, loop(%d)", __FUNCTION__, __LINE__, loop);
/* one shot */
return loop;
}
#endif
bool ExynosCamera::m_highResolutionCallbackThreadFunc(void)
{
ExynosCameraAutoTimer autoTimer(__FUNCTION__);
CLOGI("INFO(%s[%d]):", __FUNCTION__, __LINE__);
int ret = 0;
int loop = false;
int retryCountGSC = 4;
ExynosCameraFrame *newFrame = NULL;
camera2_stream *shot_stream = NULL;
ExynosCameraBuffer reprocessingDstBuffer;
int cbPreviewW = 0, cbPreviewH = 0;
int previewFormat = 0;
ExynosRect srcRect, dstRect;
m_parameters->getPreviewSize(&cbPreviewW, &cbPreviewH);
previewFormat = m_parameters->getPreviewFormat();
int pipeReprocessingSrc = 0;
int pipeReprocessingDst = 0;
unsigned int planeSize[EXYNOS_CAMERA_BUFFER_MAX_PLANES] = {0};
unsigned int bytesPerLine[EXYNOS_CAMERA_BUFFER_MAX_PLANES] = {0};
int planeCount = getYuvPlaneCount(previewFormat);
int minBufferCount = 1;
int maxBufferCount = 1;
int buffer_idx = m_getShotBufferIdex();
ExynosCameraBufferManager *bufferMgr = NULL;
reprocessingDstBuffer.index = -2;
pipeReprocessingSrc = m_parameters->isReprocessing3aaIspOTF() == true ? PIPE_3AA_REPROCESSING : PIPE_ISP_REPROCESSING;
pipeReprocessingDst = PIPE_MCSC2_REPROCESSING;
exynos_camera_buffer_type_t type = EXYNOS_CAMERA_BUFFER_ION_CACHED_TYPE;
buffer_manager_allocation_mode_t allocMode = BUFFER_MANAGER_ALLOCATION_ONDEMAND;
if (m_parameters->getHighResolutionCallbackMode() == false &&
m_highResolutionCallbackRunning == false) {
CLOGD("DEBUG(%s[%d]): High Resolution Callback Stop", __FUNCTION__, __LINE__);
goto CLEAN;
}
ret = getYuvPlaneSize(previewFormat, planeSize, cbPreviewW, cbPreviewH);
if (ret < 0) {
CLOGE("ERR(%s[%d]): BAD value, format(%x), size(%dx%d)",
__FUNCTION__, __LINE__, previewFormat, cbPreviewW, cbPreviewH);
return ret;
}
ret = m_getBufferManager(pipeReprocessingDst, &bufferMgr, DST_BUFFER_DIRECTION);
if (ret < 0) {
CLOGE("ERR(%s[%d]):getBufferManager(SRC) fail, pipeId(%d), ret(%d)",
__FUNCTION__, __LINE__, pipeReprocessingDst, ret);
return ret;
}
/* wait MCSC2 */
CLOGW("INFO(%s[%d]):wait MCSC2 output", __FUNCTION__, __LINE__);
ret = m_highResolutionCallbackQ->waitAndPopProcessQ(&newFrame);
if (m_flagThreadStop == true) {
CLOGI("INFO(%s[%d]):m_flagThreadStop(%d)", __FUNCTION__, __LINE__, m_flagThreadStop);
goto CLEAN;
}
if (ret < 0) {
CLOGE("ERR(%s[%d]):wait and pop fail, ret(%d)", __FUNCTION__, __LINE__, ret);
// TODO: doing exception handling
goto CLEAN;
}
if (newFrame == NULL) {
CLOGE("ERR(%s[%d]):newFrame is NULL", __FUNCTION__, __LINE__);
goto CLEAN;
}
ret = newFrame->setEntityState(pipeReprocessingSrc, ENTITY_STATE_COMPLETE);
if (ret < 0) {
CLOGE("ERR(%s[%d]):setEntityState(ENTITY_STATE_PROCESSING) fail, pipeId(%d), ret(%d)",
__FUNCTION__, __LINE__, pipeReprocessingSrc, ret);
return ret;
}
CLOGW("INFO(%s[%d]):MCSC2 output done", __FUNCTION__, __LINE__);
if (m_parameters->msgTypeEnabled(CAMERA_MSG_PREVIEW_FRAME)) {
ret = newFrame->getDstBuffer(pipeReprocessingSrc, &reprocessingDstBuffer,
m_reprocessingFrameFactory->getNodeType(pipeReprocessingDst));
if (ret < 0 || reprocessingDstBuffer.index < 0) {
CLOGE("ERR(%s[%d]):getDstBuffer fail, pipeReprocessingDst(%d), ret(%d)",
__FUNCTION__, __LINE__, pipeReprocessingDst, ret);
goto CLEAN;
}
/* get preview callback heap */
camera_memory_t *previewCallbackHeap = NULL;
previewCallbackHeap = m_getMemoryCb(reprocessingDstBuffer.fd[0], reprocessingDstBuffer.size[0], 1, m_callbackCookie);
if (!previewCallbackHeap || previewCallbackHeap->data == MAP_FAILED) {
CLOGE("ERR(%s[%d]):m_getMemoryCb(%d) fail", __FUNCTION__, __LINE__, reprocessingDstBuffer.size[0]);
goto CLEAN;
}
CLOGV("DEBUG(%s[%d]):high resolution preview callback", __FUNCTION__, __LINE__);
if (m_parameters->msgTypeEnabled(CAMERA_MSG_PREVIEW_FRAME)) {
setBit(&m_callbackState, CALLBACK_STATE_PREVIEW_FRAME, false);
m_dataCb(CAMERA_MSG_PREVIEW_FRAME, previewCallbackHeap, 0, NULL, m_callbackCookie);
clearBit(&m_callbackState, CALLBACK_STATE_PREVIEW_FRAME, false);
}
previewCallbackHeap->release(previewCallbackHeap);
ret = m_putBuffers(bufferMgr, reprocessingDstBuffer.index);
if (ret < 0) {
CLOGE("ERR(%s[%d]):m_putBuffers fail, pipeReprocessingDst(%d), ret(%d)",
__FUNCTION__, __LINE__, pipeReprocessingDst, ret);
goto CLEAN;
}
} else {
CLOGD("DEBUG(%s[%d]): Preview callback message disabled, skip callback", __FUNCTION__, __LINE__);
ret = newFrame->getDstBuffer(pipeReprocessingSrc, &reprocessingDstBuffer,
m_reprocessingFrameFactory->getNodeType(pipeReprocessingDst));
if (ret < 0) {
CLOGE("ERR(%s[%d]):getDstBuffer fail, pipeReprocessingDst(%d), ret(%d)",
__FUNCTION__, __LINE__, pipeReprocessingDst, ret);
goto CLEAN;
}
ret = m_putBuffers(bufferMgr, reprocessingDstBuffer.index);
if (ret < 0) {
CLOGE("ERR(%s[%d]):m_putBuffers fail, pipeReprocessingDst(%d), ret(%d)",
__FUNCTION__, __LINE__, pipeReprocessingDst, ret);
goto CLEAN;
}
}
if (newFrame != NULL) {
newFrame->frameUnlock();
CLOGD("DEBUG(%s[%d]): Reprocessing frame delete(%d)", __FUNCTION__, __LINE__, newFrame->getFrameCount());
newFrame->decRef();
m_frameMgr->deleteFrame(newFrame);
newFrame = NULL;
}
if(m_flagThreadStop != true) {
if (m_highResolutionCallbackQ->getSizeOfProcessQ() > 0 ||
m_parameters->getHighResolutionCallbackMode() == true) {
CLOGD("DEBUG(%s[%d]):highResolutionCallbackQ size(%d), highResolutionCallbackMode(%s), start again",
__FUNCTION__, __LINE__,
m_highResolutionCallbackQ->getSizeOfProcessQ(),
(m_parameters->getHighResolutionCallbackMode() == true)? "TRUE" : "FALSE");
loop = true;
}
}
CLOGI("INFO(%s[%d]):high resolution callback thread complete, loop(%d)", __FUNCTION__, __LINE__, loop);
/* one shot */
return loop;
CLEAN:
if (reprocessingDstBuffer.index != -2) {
ret = m_putBuffers(bufferMgr, reprocessingDstBuffer.index);
if (ret < 0) {
CLOGE("ERR(%s[%d]):m_putBuffers fail, pipeReprocessingDst(%d), ret(%d)",
__FUNCTION__, __LINE__, pipeReprocessingDst, ret);
goto CLEAN;
}
}
if (newFrame != NULL) {
newFrame->printEntity();
newFrame->frameUnlock();
ret = m_deleteFrame(&newFrame);
if (ret < 0) {
CLOGE("ERR(%s[%d]):m_deleteFrame fail, ret(%d)", __FUNCTION__, __LINE__, ret);
}
}
if(m_flagThreadStop != true) {
if (m_highResolutionCallbackQ->getSizeOfProcessQ() > 0 ||
m_parameters->getHighResolutionCallbackMode() == true) {
CLOGD("DEBUG(%s[%d]):highResolutionCallbackQ size(%d), highResolutionCallbackMode(%s), start again",
__FUNCTION__, __LINE__,
m_highResolutionCallbackQ->getSizeOfProcessQ(),
(m_parameters->getHighResolutionCallbackMode() == true)? "TRUE" : "FALSE");
loop = true;
}
}
CLOGI("INFO(%s[%d]):high resolution callback thread fail, loop(%d)", __FUNCTION__, __LINE__, loop);
/* one shot */
return loop;
}
bool ExynosCamera::m_facedetectThreadFunc(void)
{
int32_t status = 0;
bool loop = true;
int index = 0;
int count = 0;
ExynosCameraFrame *newFrame = NULL;
uint32_t frameCnt = 0;
#ifdef SUPPORT_DEPTH_MAP
ExynosCameraBuffer depthMapBuffer;
depthMapBuffer.index = -2;
uint32_t pipeId = PIPE_VC1;
int ret = 0;
#endif
if (m_previewEnabled == false) {
CLOGD("DEBUG(%s):preview is stopped, thread stop", __FUNCTION__);
loop = false;
goto func_exit;
}
status = m_facedetectQ->waitAndPopProcessQ(&newFrame);
if (m_flagThreadStop == true) {
CLOGI("INFO(%s[%d]):m_flagThreadStop(%d) m_flagStartFaceDetection(%d)", __FUNCTION__, __LINE__, m_flagThreadStop, m_flagStartFaceDetection);
loop = false;
goto func_exit;
}
if (status < 0) {
if (status == TIMED_OUT) {
/* Face Detection time out is not meaningful */
} else {
/* TODO: doing exception handling */
CLOGE("ERR(%s):wait and pop fail, status(%d)", __FUNCTION__, status);
}
goto func_exit;
}
#ifdef SUPPORT_DEPTH_MAP
if (m_parameters->getDepthCallbackOnPreview()) {
status = m_depthCallbackQ->waitAndPopProcessQ(&depthMapBuffer);
if (status < 0) {
if (status == TIMED_OUT) {
/* Face Detection time out is not meaningful */
CLOGE("ERR(%s):m_depthCallbackQ time out, status(%d)", __FUNCTION__, status);
} else {
/* TODO: doing exception handling */
CLOGE("ERR(%s):wait and pop fail, status(%d)", __FUNCTION__, status);
}
}
if (depthMapBuffer.index != -2) {
newFrame->setRequest(pipeId, true);
ret = newFrame->setDstBuffer(pipeId, depthMapBuffer);
if (ret != NO_ERROR) {
CLOGE("ERR(%s[%d]):Failed to get DepthMap buffer", __FUNCTION__, __LINE__);
}
}
}
#endif
count = m_facedetectQ->getSizeOfProcessQ();
if (count >= MAX_FACEDETECT_THREADQ_SIZE) {
if (newFrame != NULL) {
CLOGE("ERR(%s[%d]):m_facedetectQ skipped QSize(%d) frame(%d)",
__FUNCTION__, __LINE__, count, newFrame->getFrameCount());
#ifdef SUPPORT_DEPTH_MAP
if (newFrame->getRequest(pipeId) == true) {
depthMapBuffer.index = -2;
ret = newFrame->getDstBuffer(pipeId, &depthMapBuffer);
if (ret != NO_ERROR) {
CLOGE("ERR(%s[%d]):Failed to get DepthMap buffer", __FUNCTION__, __LINE__);
}
ret = m_putBuffers(m_depthMapBufferMgr, depthMapBuffer.index);
if (ret != NO_ERROR) {
CLOGE("ERR(%s[%d]):Failed to put DepthMap buffer to bufferMgr",
__FUNCTION__, __LINE__);
}
}
#endif
newFrame->decRef();
m_frameMgr->deleteFrame(newFrame);
newFrame = NULL;
}
for (int i = 0 ; i < count-1 ; i++) {
m_facedetectQ->popProcessQ(&newFrame);
if (newFrame != NULL) {
#ifdef SUPPORT_DEPTH_MAP
if (newFrame->getRequest(pipeId) == true) {
depthMapBuffer.index = -2;
ret = newFrame->getDstBuffer(pipeId, &depthMapBuffer);
if (ret != NO_ERROR) {
CLOGE("ERR(%s[%d]):Failed to get DepthMap buffer", __FUNCTION__, __LINE__);
}
ret = m_putBuffers(m_depthMapBufferMgr, depthMapBuffer.index);
if (ret != NO_ERROR) {
CLOGE("ERR(%s[%d]):Failed to put DepthMap buffer to bufferMgr",
__FUNCTION__, __LINE__);
}
}
#endif
newFrame->decRef();
m_frameMgr->deleteFrame(newFrame);
newFrame = NULL;
}
}
m_facedetectQ->popProcessQ(&newFrame);
}
if (newFrame != NULL) {
status = m_doFdCallbackFunc(newFrame);
if (status < 0) {
#ifdef SUPPORT_DEPTH_MAP
if (newFrame->getRequest(pipeId) == true) {
depthMapBuffer.index = -2;
ret = newFrame->getDstBuffer(pipeId, &depthMapBuffer);
if (ret != NO_ERROR) {
CLOGE("ERR(%s[%d]):Failed to get DepthMap buffer", __FUNCTION__, __LINE__);
}
ret = m_putBuffers(m_depthMapBufferMgr, depthMapBuffer.index);
if (ret != NO_ERROR) {
CLOGE("ERR(%s[%d]):Failed to put DepthMap buffer to bufferMgr",
__FUNCTION__, __LINE__);
}
}
#endif
CLOGE("ERR(%s[%d]) m_doFdCallbackFunc failed(%d).", __FUNCTION__, __LINE__, status);
}
}
if (m_facedetectQ->getSizeOfProcessQ() > 0) {
loop = true;
}
if (newFrame != NULL) {
newFrame->decRef();
m_frameMgr->deleteFrame(newFrame);
newFrame = NULL;
}
func_exit:
return loop;
}
void ExynosCamera::m_createThreads(void)
{
m_mainThread = new mainCameraThread(this, &ExynosCamera::m_mainThreadFunc, "ExynosCameraThread", PRIORITY_URGENT_DISPLAY);
CLOGV("DEBUG(%s):mainThread created", __FUNCTION__);
m_previewThread = new mainCameraThread(this, &ExynosCamera::m_previewThreadFunc, "previewThread", PRIORITY_DISPLAY);
CLOGV("DEBUG(%s):previewThread created", __FUNCTION__);
/*
* In here, we cannot know single, dual scenario.
* So, make all threads.
*/
/* if (m_parameters->isFlite3aaOtf() == true) { */
if (1) {
m_mainSetupQThread[INDEX(PIPE_FLITE)] = new mainCameraThread(this, &ExynosCamera::m_mainThreadQSetupFLITE, "mainThreadQSetupFLITE", PRIORITY_URGENT_DISPLAY);
CLOGV("DEBUG(%s):mainThreadQSetupFLITEThread created", __FUNCTION__);
/* Change 3AA_ISP, 3AC, SCP to ISP */
/*
m_mainSetupQThread[INDEX(PIPE_3AC)] = new mainCameraThread(this, &ExynosCamera::m_mainThreadQSetup3AC, "mainThreadQSetup3AC", PRIORITY_URGENT_DISPLAY);
CLOGD("DEBUG(%s):mainThreadQSetup3ACThread created", __FUNCTION__);
m_mainSetupQThread[INDEX(PIPE_3AA_ISP)] = new mainCameraThread(this, &ExynosCamera::m_mainThreadQSetup3AA_ISP, "mainThreadQSetup3AA_ISP", PRIORITY_URGENT_DISPLAY);
CLOGD("DEBUG(%s):mainThreadQSetup3AA_ISPThread created", __FUNCTION__);
m_mainSetupQThread[INDEX(PIPE_ISP)] = new mainCameraThread(this, &ExynosCamera::m_mainThreadQSetupISP, "mainThreadQSetupISP", PRIORITY_URGENT_DISPLAY);
CLOGD("DEBUG(%s):mainThreadQSetupISPThread created", __FUNCTION__);
m_mainSetupQThread[INDEX(PIPE_SCP)] = new mainCameraThread(this, &ExynosCamera::m_mainThreadQSetupSCP, "mainThreadQSetupSCP", PRIORITY_URGENT_DISPLAY);
CLOGD("DEBUG(%s):mainThreadQSetupSCPThread created", __FUNCTION__);
*/
m_mainSetupQThread[INDEX(PIPE_3AA)] = new mainCameraThread(this, &ExynosCamera::m_mainThreadQSetup3AA, "mainThreadQSetup3AA", PRIORITY_URGENT_DISPLAY);
CLOGV("DEBUG(%s):mainThreadQSetup3AAThread created", __FUNCTION__);
}
m_setBuffersThread = new mainCameraThread(this, &ExynosCamera::m_setBuffersThreadFunc, "setBuffersThread");
CLOGV("DEBUG(%s):setBuffersThread created", __FUNCTION__);
m_startPictureInternalThread = new mainCameraThread(this, &ExynosCamera::m_startPictureInternalThreadFunc, "startPictureInternalThread");
CLOGV("DEBUG(%s):startPictureInternalThread created", __FUNCTION__);
m_startPictureBufferThread = new mainCameraThread(this, &ExynosCamera::m_startPictureBufferThreadFunc, "startPictureBufferThread");
CLOGV("DEBUG(%s):startPictureBufferThread created", __FUNCTION__);
m_prePictureThread = new mainCameraThread(this, &ExynosCamera::m_prePictureThreadFunc, "prePictureThread");
CLOGV("DEBUG(%s):prePictureThread created", __FUNCTION__);
m_pictureThread = new mainCameraThread(this, &ExynosCamera::m_pictureThreadFunc, "PictureThread");
CLOGV("DEBUG(%s):pictureThread created", __FUNCTION__);
m_postPictureThread = new mainCameraThread(this, &ExynosCamera::m_postPictureThreadFunc, "postPictureThread");
CLOGV("DEBUG(%s):postPictureThread created", __FUNCTION__);
m_recordingThread = new mainCameraThread(this, &ExynosCamera::m_recordingThreadFunc, "recordingThread");
CLOGV("DEBUG(%s):recordingThread created", __FUNCTION__);
m_autoFocusThread = new mainCameraThread(this, &ExynosCamera::m_autoFocusThreadFunc, "AutoFocusThread");
CLOGV("DEBUG(%s):autoFocusThread created", __FUNCTION__);
m_autoFocusContinousThread = new mainCameraThread(this, &ExynosCamera::m_autoFocusContinousThreadFunc, "AutoFocusContinousThread");
CLOGV("DEBUG(%s):autoFocusContinousThread created", __FUNCTION__);
m_facedetectThread = new mainCameraThread(this, &ExynosCamera::m_facedetectThreadFunc, "FaceDetectThread");
CLOGV("DEBUG(%s):FaceDetectThread created", __FUNCTION__);
m_monitorThread = new mainCameraThread(this, &ExynosCamera::m_monitorThreadFunc, "monitorThread");
CLOGV("DEBUG(%s):monitorThread created", __FUNCTION__);
m_jpegCallbackThread = new mainCameraThread(this, &ExynosCamera::m_jpegCallbackThreadFunc, "jpegCallbackThread");
CLOGV("DEBUG(%s):jpegCallbackThread created", __FUNCTION__);
m_zoomPreviwWithCscThread = new mainCameraThread(this, &ExynosCamera::m_zoomPreviwWithCscThreadFunc, "zoomPreviwWithCscQThread");
CLOGV("DEBUG(%s):zoomPreviwWithCscQThread created", __FUNCTION__);
#ifdef BOARD_CAMERA_USES_DUAL_CAMERA
m_fusionThread = new mainCameraThread(this, &ExynosCamera::m_fusionThreadFunc, "fusionThread");
CLOGD("DEBUG(%s):m_fusionThread created", __FUNCTION__);
#endif
/* saveThread */
char threadName[20];
for (int threadNum = JPEG_SAVE_THREAD0; threadNum < JPEG_SAVE_THREAD_MAX_COUNT; threadNum++) {
snprintf(threadName, sizeof(threadName), "jpegSaveThread%d", threadNum);
m_jpegSaveThread[threadNum] = new mainCameraThread(this, &ExynosCamera::m_jpegSaveThreadFunc, threadName);
CLOGV("DEBUG(%s):%s created", __FUNCTION__, threadName);
}
/* high resolution preview callback Thread */
m_highResolutionCallbackThread = new mainCameraThread(this, &ExynosCamera::m_highResolutionCallbackThreadFunc, "m_highResolutionCallbackThread");
CLOGV("DEBUG(%s):highResolutionCallbackThread created", __FUNCTION__);
/* Shutter callback */
m_shutterCallbackThread = new mainCameraThread(this, &ExynosCamera::m_shutterCallbackThreadFunc, "shutterCallbackThread");
CLOGV("DEBUG(%s):shutterCallbackThread created", __FUNCTION__);
#ifdef CAMERA_FAST_ENTRANCE_V1
m_fastenAeThread = new mainCameraThread(this, &ExynosCamera::m_fastenAeThreadFunc, "fastenAeThread", PRIORITY_URGENT_DISPLAY);
CLOGV("DEBUG(%s):m_fastenAeThread created", __FUNCTION__);
#endif
}
status_t ExynosCamera::m_setConfigInform() {
struct ExynosConfigInfo exynosConfig;
memset((void *)&exynosConfig, 0x00, sizeof(exynosConfig));
exynosConfig.mode = CONFIG_MODE::NORMAL;
exynosConfig.info[CONFIG_MODE::NORMAL].bufInfo.num_sensor_buffers = (getCameraIdInternal() == CAMERA_ID_BACK) ? NUM_SENSOR_BUFFERS : FRONT_NUM_SENSOR_BUFFERS;
exynosConfig.info[CONFIG_MODE::NORMAL].bufInfo.num_bayer_buffers = (getCameraIdInternal() == CAMERA_ID_BACK) ? NUM_BAYER_BUFFERS : FRONT_NUM_BAYER_BUFFERS;
exynosConfig.info[CONFIG_MODE::NORMAL].bufInfo.init_bayer_buffers = INIT_BAYER_BUFFERS;
exynosConfig.info[CONFIG_MODE::NORMAL].bufInfo.num_3aa_buffers = (getCameraIdInternal() == CAMERA_ID_BACK) ? NUM_3AA_BUFFERS : FRONT_NUM_3AA_BUFFERS;
exynosConfig.info[CONFIG_MODE::NORMAL].bufInfo.num_hwdis_buffers = NUM_HW_DIS_BUFFERS;
exynosConfig.info[CONFIG_MODE::NORMAL].bufInfo.num_preview_buffers = NUM_PREVIEW_BUFFERS;
exynosConfig.info[CONFIG_MODE::NORMAL].bufInfo.num_picture_buffers = (getCameraIdInternal() == CAMERA_ID_BACK) ? NUM_PICTURE_BUFFERS : FRONT_NUM_PICTURE_BUFFERS;
exynosConfig.info[CONFIG_MODE::NORMAL].bufInfo.num_reprocessing_buffers = NUM_REPROCESSING_BUFFERS;
exynosConfig.info[CONFIG_MODE::NORMAL].bufInfo.num_recording_buffers = NUM_RECORDING_BUFFERS;
exynosConfig.info[CONFIG_MODE::NORMAL].bufInfo.num_fastaestable_buffer = INITIAL_SKIP_FRAME;
exynosConfig.info[CONFIG_MODE::NORMAL].bufInfo.reprocessing_bayer_hold_count = REPROCESSING_BAYER_HOLD_COUNT;
exynosConfig.info[CONFIG_MODE::NORMAL].bufInfo.preview_buffer_margin = NUM_PREVIEW_BUFFERS_MARGIN;
exynosConfig.info[CONFIG_MODE::NORMAL].bufInfo.num_hiding_mode_buffers = NUM_HIDING_BUFFER_COUNT;
exynosConfig.info[CONFIG_MODE::NORMAL].pipeInfo.prepare[PIPE_FLITE] = (getCameraIdInternal() == CAMERA_ID_BACK) ? PIPE_FLITE_PREPARE_COUNT : PIPE_FLITE_FRONT_PREPARE_COUNT;
exynosConfig.info[CONFIG_MODE::NORMAL].pipeInfo.prepare[PIPE_3AC] = PIPE_3AC_PREPARE_COUNT;
exynosConfig.info[CONFIG_MODE::NORMAL].pipeInfo.prepare[PIPE_3AA] = PIPE_3AA_ISP_PREPARE_COUNT;
exynosConfig.info[CONFIG_MODE::NORMAL].pipeInfo.prepare[PIPE_3AA_ISP] = PIPE_3AA_ISP_PREPARE_COUNT;
exynosConfig.info[CONFIG_MODE::NORMAL].pipeInfo.prepare[PIPE_ISP] = PIPE_ISP_PREPARE_COUNT;
exynosConfig.info[CONFIG_MODE::NORMAL].pipeInfo.prepare[PIPE_ISPC] = (getCameraIdInternal() == CAMERA_ID_BACK) ? PIPE_3AA_ISP_PREPARE_COUNT : PIPE_FLITE_FRONT_PREPARE_COUNT;
exynosConfig.info[CONFIG_MODE::NORMAL].pipeInfo.prepare[PIPE_SCC] = (getCameraIdInternal() == CAMERA_ID_BACK) ? PIPE_3AA_ISP_PREPARE_COUNT : PIPE_FLITE_FRONT_PREPARE_COUNT;
exynosConfig.info[CONFIG_MODE::NORMAL].pipeInfo.prepare[PIPE_SCP] = (getCameraIdInternal() == CAMERA_ID_BACK) ? PIPE_SCP_PREPARE_COUNT : PIPE_SCP_FRONT_PREPARE_COUNT;
/* reprocessing */
exynosConfig.info[CONFIG_MODE::NORMAL].pipeInfo.prepare[PIPE_SCP_REPROCESSING] = PIPE_SCP_REPROCESSING_PREPARE_COUNT;
exynosConfig.info[CONFIG_MODE::NORMAL].pipeInfo.prepare[PIPE_ISPC_REPROCESSING] = PIPE_SCC_REPROCESSING_PREPARE_COUNT;
exynosConfig.info[CONFIG_MODE::NORMAL].pipeInfo.prepare[PIPE_SCC_REPROCESSING] = PIPE_SCC_REPROCESSING_PREPARE_COUNT;
#if (USE_HIGHSPEED_RECORDING)
/* Config HIGH_SPEED 60 buffer & pipe info */
exynosConfig.info[CONFIG_MODE::HIGHSPEED_60].bufInfo.num_sensor_buffers = (getCameraIdInternal() == CAMERA_ID_BACK) ? FPS60_NUM_NUM_SENSOR_BUFFERS : FPS60_FRONT_NUM_SENSOR_BUFFERS;
exynosConfig.info[CONFIG_MODE::HIGHSPEED_60].bufInfo.num_bayer_buffers = (getCameraIdInternal() == CAMERA_ID_BACK) ? FPS60_NUM_NUM_BAYER_BUFFERS : FPS60_FRONT_NUM_BAYER_BUFFERS;
exynosConfig.info[CONFIG_MODE::HIGHSPEED_60].bufInfo.init_bayer_buffers = FPS60_NUM_NUM_BAYER_BUFFERS;
exynosConfig.info[CONFIG_MODE::HIGHSPEED_60].bufInfo.num_3aa_buffers = FPS60_NUM_NUM_BAYER_BUFFERS;
exynosConfig.info[CONFIG_MODE::HIGHSPEED_60].bufInfo.num_hwdis_buffers = FPS60_NUM_HW_DIS_BUFFERS;
exynosConfig.info[CONFIG_MODE::HIGHSPEED_60].bufInfo.num_preview_buffers = FPS60_NUM_PREVIEW_BUFFERS;
exynosConfig.info[CONFIG_MODE::HIGHSPEED_60].bufInfo.num_picture_buffers = (getCameraIdInternal() == CAMERA_ID_BACK) ? FPS60_NUM_PICTURE_BUFFERS : FPS60_FRONT_NUM_PICTURE_BUFFERS;
exynosConfig.info[CONFIG_MODE::HIGHSPEED_60].bufInfo.num_reprocessing_buffers = FPS60_NUM_REPROCESSING_BUFFERS;
exynosConfig.info[CONFIG_MODE::HIGHSPEED_60].bufInfo.num_recording_buffers = FPS60_NUM_RECORDING_BUFFERS;
exynosConfig.info[CONFIG_MODE::HIGHSPEED_60].bufInfo.num_fastaestable_buffer = FPS60_INITIAL_SKIP_FRAME;
exynosConfig.info[CONFIG_MODE::HIGHSPEED_60].bufInfo.reprocessing_bayer_hold_count = FPS60_REPROCESSING_BAYER_HOLD_COUNT;
exynosConfig.info[CONFIG_MODE::HIGHSPEED_60].bufInfo.preview_buffer_margin = FPS60_NUM_PREVIEW_BUFFERS_MARGIN;
exynosConfig.info[CONFIG_MODE::HIGHSPEED_60].bufInfo.num_hiding_mode_buffers = FPS60_NUM_HIDING_BUFFER_COUNT;
exynosConfig.info[CONFIG_MODE::HIGHSPEED_60].pipeInfo.prepare[PIPE_FLITE] = FPS60_PIPE_FLITE_PREPARE_COUNT;
exynosConfig.info[CONFIG_MODE::HIGHSPEED_60].pipeInfo.prepare[PIPE_3AC] = FPS60_PIPE_3AC_PREPARE_COUNT;
exynosConfig.info[CONFIG_MODE::HIGHSPEED_60].pipeInfo.prepare[PIPE_3AA] = FPS60_PIPE_3AA_ISP_PREPARE_COUNT;
exynosConfig.info[CONFIG_MODE::HIGHSPEED_60].pipeInfo.prepare[PIPE_3AA_ISP] = FPS60_PIPE_3AA_ISP_PREPARE_COUNT;
exynosConfig.info[CONFIG_MODE::HIGHSPEED_60].pipeInfo.prepare[PIPE_SCP] = FPS60_PIPE_SCP_PREPARE_COUNT;
exynosConfig.info[CONFIG_MODE::HIGHSPEED_60].pipeInfo.prepare[PIPE_SCP_REPROCESSING] = FPS60_PIPE_SCP_REPROCESSING_PREPARE_COUNT;
/* Config HIGH_SPEED 120 buffer & pipe info */
exynosConfig.info[CONFIG_MODE::HIGHSPEED_120].bufInfo.num_sensor_buffers = (getCameraIdInternal() == CAMERA_ID_BACK) ? FPS120_NUM_NUM_SENSOR_BUFFERS : FPS120_FRONT_NUM_SENSOR_BUFFERS;
exynosConfig.info[CONFIG_MODE::HIGHSPEED_120].bufInfo.num_bayer_buffers = (getCameraIdInternal() == CAMERA_ID_BACK) ? FPS120_NUM_NUM_BAYER_BUFFERS : FPS120_FRONT_NUM_BAYER_BUFFERS;
exynosConfig.info[CONFIG_MODE::HIGHSPEED_120].bufInfo.init_bayer_buffers = FPS120_NUM_NUM_BAYER_BUFFERS;
exynosConfig.info[CONFIG_MODE::HIGHSPEED_120].bufInfo.num_3aa_buffers = FPS120_NUM_NUM_BAYER_BUFFERS;
exynosConfig.info[CONFIG_MODE::HIGHSPEED_120].bufInfo.num_hwdis_buffers = FPS120_NUM_HW_DIS_BUFFERS;
exynosConfig.info[CONFIG_MODE::HIGHSPEED_120].bufInfo.num_preview_buffers = FPS120_NUM_PREVIEW_BUFFERS;
exynosConfig.info[CONFIG_MODE::HIGHSPEED_120].bufInfo.num_picture_buffers = (getCameraIdInternal() == CAMERA_ID_BACK) ? FPS120_NUM_PICTURE_BUFFERS : FPS120_FRONT_NUM_PICTURE_BUFFERS;
exynosConfig.info[CONFIG_MODE::HIGHSPEED_120].bufInfo.num_reprocessing_buffers = FPS120_NUM_REPROCESSING_BUFFERS;
exynosConfig.info[CONFIG_MODE::HIGHSPEED_120].bufInfo.num_recording_buffers = FPS120_NUM_RECORDING_BUFFERS;
exynosConfig.info[CONFIG_MODE::HIGHSPEED_120].bufInfo.num_fastaestable_buffer = FPS120_INITIAL_SKIP_FRAME;
exynosConfig.info[CONFIG_MODE::HIGHSPEED_120].bufInfo.reprocessing_bayer_hold_count = FPS120_REPROCESSING_BAYER_HOLD_COUNT;
exynosConfig.info[CONFIG_MODE::HIGHSPEED_120].bufInfo.preview_buffer_margin = FPS120_NUM_PREVIEW_BUFFERS_MARGIN;
exynosConfig.info[CONFIG_MODE::HIGHSPEED_120].bufInfo.num_hiding_mode_buffers = FPS120_NUM_HIDING_BUFFER_COUNT;
exynosConfig.info[CONFIG_MODE::HIGHSPEED_120].pipeInfo.prepare[PIPE_FLITE] = FPS120_PIPE_FLITE_PREPARE_COUNT;
exynosConfig.info[CONFIG_MODE::HIGHSPEED_120].pipeInfo.prepare[PIPE_3AC] = FPS120_PIPE_3AC_PREPARE_COUNT;
exynosConfig.info[CONFIG_MODE::HIGHSPEED_120].pipeInfo.prepare[PIPE_3AA] = FPS120_PIPE_3AA_ISP_PREPARE_COUNT;
exynosConfig.info[CONFIG_MODE::HIGHSPEED_120].pipeInfo.prepare[PIPE_3AA_ISP] = FPS120_PIPE_3AA_ISP_PREPARE_COUNT;
exynosConfig.info[CONFIG_MODE::HIGHSPEED_120].pipeInfo.prepare[PIPE_SCP] = FPS120_PIPE_SCP_PREPARE_COUNT;
exynosConfig.info[CONFIG_MODE::HIGHSPEED_120].pipeInfo.prepare[PIPE_SCP_REPROCESSING] = FPS120_PIPE_SCP_REPROCESSING_PREPARE_COUNT;
/* Config HIGH_SPEED 240 buffer & pipe info */
exynosConfig.info[CONFIG_MODE::HIGHSPEED_240].bufInfo.num_sensor_buffers = (getCameraIdInternal() == CAMERA_ID_BACK) ? FPS240_NUM_NUM_SENSOR_BUFFERS : FPS240_FRONT_NUM_SENSOR_BUFFERS;
exynosConfig.info[CONFIG_MODE::HIGHSPEED_240].bufInfo.num_bayer_buffers = (getCameraIdInternal() == CAMERA_ID_BACK) ? FPS240_NUM_NUM_BAYER_BUFFERS : FPS240_FRONT_NUM_BAYER_BUFFERS;
exynosConfig.info[CONFIG_MODE::HIGHSPEED_240].bufInfo.init_bayer_buffers = FPS240_INIT_BAYER_BUFFERS;
exynosConfig.info[CONFIG_MODE::HIGHSPEED_240].bufInfo.num_3aa_buffers = FPS240_NUM_NUM_BAYER_BUFFERS;
exynosConfig.info[CONFIG_MODE::HIGHSPEED_240].bufInfo.num_hwdis_buffers = FPS240_NUM_HW_DIS_BUFFERS;
exynosConfig.info[CONFIG_MODE::HIGHSPEED_240].bufInfo.num_preview_buffers = FPS240_NUM_PREVIEW_BUFFERS;
exynosConfig.info[CONFIG_MODE::HIGHSPEED_240].bufInfo.num_picture_buffers = (getCameraIdInternal() == CAMERA_ID_BACK) ? FPS240_NUM_PICTURE_BUFFERS : FPS240_FRONT_NUM_PICTURE_BUFFERS;
exynosConfig.info[CONFIG_MODE::HIGHSPEED_240].bufInfo.num_reprocessing_buffers = FPS240_NUM_REPROCESSING_BUFFERS;
exynosConfig.info[CONFIG_MODE::HIGHSPEED_240].bufInfo.num_recording_buffers = FPS240_NUM_RECORDING_BUFFERS;
exynosConfig.info[CONFIG_MODE::HIGHSPEED_240].bufInfo.num_fastaestable_buffer = FPS240_INITIAL_SKIP_FRAME;
exynosConfig.info[CONFIG_MODE::HIGHSPEED_240].bufInfo.reprocessing_bayer_hold_count = FPS240_REPROCESSING_BAYER_HOLD_COUNT;
exynosConfig.info[CONFIG_MODE::HIGHSPEED_240].bufInfo.preview_buffer_margin = FPS240_NUM_PREVIEW_BUFFERS_MARGIN;
exynosConfig.info[CONFIG_MODE::HIGHSPEED_240].bufInfo.num_hiding_mode_buffers = FPS240_NUM_HIDING_BUFFER_COUNT;
exynosConfig.info[CONFIG_MODE::HIGHSPEED_240].pipeInfo.prepare[PIPE_FLITE] = FPS240_PIPE_FLITE_PREPARE_COUNT;
exynosConfig.info[CONFIG_MODE::HIGHSPEED_240].pipeInfo.prepare[PIPE_3AC] = FPS240_PIPE_3AC_PREPARE_COUNT;
exynosConfig.info[CONFIG_MODE::HIGHSPEED_240].pipeInfo.prepare[PIPE_3AA] = FPS240_PIPE_3AA_ISP_PREPARE_COUNT;
exynosConfig.info[CONFIG_MODE::HIGHSPEED_240].pipeInfo.prepare[PIPE_3AA_ISP] = FPS240_PIPE_3AA_ISP_PREPARE_COUNT;
exynosConfig.info[CONFIG_MODE::HIGHSPEED_240].pipeInfo.prepare[PIPE_SCP] = FPS240_PIPE_SCP_PREPARE_COUNT;
exynosConfig.info[CONFIG_MODE::HIGHSPEED_240].pipeInfo.prepare[PIPE_SCP_REPROCESSING] = FPS240_PIPE_SCP_REPROCESSING_PREPARE_COUNT;
#endif
m_parameters->setConfig(&exynosConfig);
m_exynosconfig = m_parameters->getConfig();
return NO_ERROR;
}
status_t ExynosCamera::m_setFrameManager()
{
sp<FrameWorker> worker;
m_frameMgr = new ExynosCameraFrameManager("FRAME MANAGER", m_cameraId, FRAMEMGR_OPER::SLIENT, 100, 150);
worker = new CreateWorker("CREATE FRAME WORKER", m_cameraId, FRAMEMGR_OPER::SLIENT, 200);
m_frameMgr->setWorker(FRAMEMGR_WORKER::CREATE, worker);
worker = new DeleteWorker("DELETE FRAME WORKER", m_cameraId, FRAMEMGR_OPER::SLIENT);
m_frameMgr->setWorker(FRAMEMGR_WORKER::DELETE, worker);
sp<KeyBox> key = new KeyBox("FRAME KEYBOX", m_cameraId);
m_frameMgr->setKeybox(key);
return NO_ERROR;
}
status_t ExynosCamera::m_initFrameFactory(void)
{
CLOGI("INFO(%s[%d]): -IN-", __FUNCTION__, __LINE__);
ExynosCameraAutoTimer autoTimer(__FUNCTION__);
status_t ret = NO_ERROR;
m_previewFrameFactory = NULL;
m_pictureFrameFactory = NULL;
m_reprocessingFrameFactory = NULL;
m_visionFrameFactory = NULL;
/*
* new all FrameFactories.
* because this called on open(). so we don't know current scenario
*/
m_previewFrameFactory = new ExynosCameraFrameFactoryPreview(m_cameraId, m_parameters);
m_previewFrameFactory->setFrameManager(m_frameMgr);
m_reprocessingFrameFactory = new ExynosCameraFrameReprocessingFactory(m_cameraId, m_parameters);
m_reprocessingFrameFactory->setFrameManager(m_frameMgr);
CLOGI("INFO(%s[%d]): -OUT-", __FUNCTION__, __LINE__);
return ret;
}
status_t ExynosCamera::m_deinitFrameFactory(void)
{
CLOGI("INFO(%s[%d]): -IN-", __FUNCTION__, __LINE__);
ExynosCameraAutoTimer autoTimer(__FUNCTION__);
status_t ret = NO_ERROR;
if (m_previewFrameFactory != NULL
&& m_previewFrameFactory->isCreated() == true) {
ret = m_previewFrameFactory->destroy();
if (ret != NO_ERROR)
CLOGE("ERR(%s[%d]):m_previewFrameFactory destroy fail", __FUNCTION__, __LINE__);
}
if (m_reprocessingFrameFactory != NULL
&& m_reprocessingFrameFactory->isCreated() == true) {
ret = m_reprocessingFrameFactory->destroy();
if (ret != NO_ERROR)
CLOGE("ERR(%s[%d]):m_reprocessingFrameFactory destroy fail", __FUNCTION__, __LINE__);
}
if (m_visionFrameFactory != NULL
&& m_visionFrameFactory->isCreated() == true) {
ret = m_visionFrameFactory->destroy();
if (ret != NO_ERROR)
CLOGE("ERR(%s[%d]):m_visionFrameFactory destroy fail", __FUNCTION__, __LINE__);
}
SAFE_DELETE(m_previewFrameFactory);
CLOGD("DEBUG(%s[%d]):m_previewFrameFactory destroyed", __FUNCTION__, __LINE__);
SAFE_DELETE(m_reprocessingFrameFactory);
CLOGD("DEBUG(%s[%d]):m_reprocessingFrameFactory destroyed", __FUNCTION__, __LINE__);
/*
COUTION: m_pictureFrameFactory is only a pointer, just refer preview or reprocessing frame factory's instance.
So, this pointer shuld be set null when camera HAL is deinitializing.
*/
m_pictureFrameFactory = NULL;
CLOGD("DEBUG(%s[%d]):m_pictureFrameFactory destroyed", __FUNCTION__, __LINE__);
SAFE_DELETE(m_visionFrameFactory);
CLOGD("DEBUG(%s[%d]):m_visionFrameFactory destroyed", __FUNCTION__, __LINE__);
CLOGI("INFO(%s[%d]): -OUT-", __FUNCTION__, __LINE__);
return NO_ERROR;
}
status_t ExynosCamera::m_setBuffers(void)
{
ExynosCameraAutoTimer autoTimer(__FUNCTION__);
CLOGI("INFO(%s[%d]):alloc buffer - camera ID: %d",
__FUNCTION__, __LINE__, m_cameraId);
status_t ret = NO_ERROR;
unsigned int bytesPerLine[EXYNOS_CAMERA_BUFFER_MAX_PLANES] = {0};
unsigned int planeSize[EXYNOS_CAMERA_BUFFER_MAX_PLANES] = {0};
int hwPreviewW = 0, hwPreviewH = 0, hwPreviewFormat = 0;
int hwPictureW = 0, hwPictureH = 0;
int ispBufferW = 0, ispBufferH = 0;
int tpuBufferW = 0, tpuBufferH = 0;
int previewMaxW = 0, previewMaxH = 0;
int pictureMaxW = 0, pictureMaxH = 0;
int sensorMaxW = 0, sensorMaxH = 0;
ExynosRect bdsRect;
unsigned int bpp = 0;
unsigned int planeCount = 1;
int maxBufferCount = 1;
int bayerFormat = m_parameters->getBayerFormat(PIPE_FLITE);
exynos_camera_buffer_type_t type = EXYNOS_CAMERA_BUFFER_ION_NONCACHED_TYPE;
buffer_manager_allocation_mode_t allocMode = BUFFER_MANAGER_ALLOCATION_ATONCE;
bool needMmap = false;
if (m_parameters->getReallocBuffer() == true) {
/* skip to free and reallocate buffers : flite / 3aa / isp / ispReprocessing */
m_releasebuffersForRealloc();
}
m_parameters->getPreviewBdsSize(&bdsRect, false);
m_parameters->getHwPreviewSize(&hwPreviewW, &hwPreviewH);
CLOGI("INFO(%s[%d]):HW Preview width x height = %dx%d",
__FUNCTION__, __LINE__, hwPreviewW, hwPreviewH);
m_parameters->getHwPictureSize(&hwPictureW, &hwPictureH);
CLOGI("INFO(%s[%d]):HW Picture width x height = %dx%d",
__FUNCTION__, __LINE__, hwPictureW, hwPictureH);
m_parameters->getMaxPictureSize(&pictureMaxW, &pictureMaxH);
CLOGI("INFO(%s[%d]):Picture MAX width x height = %dx%d",
__FUNCTION__, __LINE__, pictureMaxW, pictureMaxH);
if (m_parameters->getHighSpeedRecording() == true) {
m_parameters->getHwSensorSize(&sensorMaxW, &sensorMaxH);
CLOGI("INFO(%s[%d]):HW Sensor(HighSpeed) MAX width x height = %dx%d",
__FUNCTION__, __LINE__, sensorMaxW, sensorMaxH);
m_parameters->getHwPreviewSize(&previewMaxW, &previewMaxH);
CLOGI("INFO(%s[%d]):HW Preview(HighSpeed) MAX width x height = %dx%d",
__FUNCTION__, __LINE__, previewMaxW, previewMaxH);
} else {
m_parameters->getMaxSensorSize(&sensorMaxW, &sensorMaxH);
CLOGI("INFO(%s[%d]):Sensor MAX width x height = %dx%d",
__FUNCTION__, __LINE__, sensorMaxW, sensorMaxH);
m_parameters->getMaxPreviewSize(&previewMaxW, &previewMaxH);
CLOGI("INFO(%s[%d]):Preview MAX width x height = %dx%d",
__FUNCTION__, __LINE__, previewMaxW, previewMaxH);
}
hwPreviewFormat = m_parameters->getHwPreviewFormat();
#ifdef BOARD_CAMERA_USES_DUAL_CAMERA
ExynosRect fusionSrcRect;
ExynosRect fusionDstRect;
if (m_parameters->isFusionEnabled() == true) {
ret = m_parameters->getFusionSize(hwPreviewW, hwPreviewH, &fusionSrcRect, &fusionDstRect);
if (ret != NO_ERROR) {
CLOGE("ERR(%s[%d]):getFusionSize(%d, %d)) fail", __FUNCTION__, __LINE__, hwPreviewW, hwPreviewH);
return ret;
}
CLOGI("(%s):Fusion src width x height = %dx%d", __FUNCTION__, fusionSrcRect.w, fusionDstRect.h);
CLOGI("(%s):Fusion dst width x height = %dx%d", __FUNCTION__, fusionDstRect.w, fusionDstRect.h);
}
#endif
#if (SUPPORT_BACK_HW_VDIS || SUPPORT_FRONT_HW_VDIS)
/*
* we cannot expect TPU on or not, when open() api.
* so extract memory TPU size
*/
int w = 0, h = 0;
m_parameters->calcNormalToTpuSize(previewMaxW, previewMaxH, &w, &h);
if (ret != NO_ERROR) {
CLOGE("ERR(%s[%d]):Hw vdis buffer calulation fail src(%d x %d) dst(%d x %d)",__FUNCTION__, __LINE__, previewMaxW, previewMaxH, w, h);
}
previewMaxW = w;
previewMaxH = h;
CLOGI("(%s): TPU based Preview MAX width x height = %dx%d", __FUNCTION__, previewMaxW, previewMaxH);
#endif
/* Depth map buffer */
#ifdef SUPPORT_DEPTH_MAP
if (m_parameters->getUseDepthMap()) {
int depthMapW = 0, depthMapH = 0;
ret = m_parameters->getDepthMapSize(&depthMapW, &depthMapH);
if (ret != NO_ERROR) {
ALOGE("ERR(%s[%d]):Failed to getDepthMapSize.", __FUNCTION__, __LINE__);
return ret;
} else {
CLOGI("INFO(%s[%d]):Depth Map Size width x height = %dx%d",
__FUNCTION__, __LINE__, depthMapW, depthMapH);
}
bayerFormat = DEPTH_MAP_FORMAT;
bytesPerLine[0] = getBayerLineSize(depthMapW, bayerFormat);
planeSize[0] = getBayerPlaneSize(depthMapW, depthMapH, bayerFormat);
planeCount = 2;
maxBufferCount = NUM_DEPTHMAP_BUFFERS;
needMmap = true;
type = EXYNOS_CAMERA_BUFFER_ION_CACHED_TYPE;
ret = m_allocBuffers(m_depthMapBufferMgr,
planeCount, planeSize, bytesPerLine,
maxBufferCount, maxBufferCount,
type, true, needMmap);
if (ret != NO_ERROR) {
CLOGE("ERR(%s[%d]):Failed to allocate Depth Map Buffers. bufferCount %d",
__FUNCTION__, __LINE__, maxBufferCount);
return ret;
}
CLOGI("INFO(%s[%d]):m_allocBuffers(DepthMap Buffer) %d x %d,\
planeSize(%d), planeCount(%d), maxBufferCount(%d)",
__FUNCTION__, __LINE__, depthMapW, depthMapH,
planeSize[0], planeCount, maxBufferCount);
}
#endif
/* 3AA source(for shot) Buffer */
planeCount = 2;
planeSize[0] = 32 * 64 * 2;
maxBufferCount = m_exynosconfig->current->bufInfo.num_3aa_buffers;
type = EXYNOS_CAMERA_BUFFER_ION_NONCACHED_TYPE;
ret = m_allocBuffers(m_3aaBufferMgr, planeCount, planeSize, bytesPerLine, maxBufferCount, true, false);
if (ret != NO_ERROR) {
CLOGE("ERR(%s[%d]):m_3aaBufferMgr m_allocBuffers(bufferCount=%d) fail",
__FUNCTION__, __LINE__, maxBufferCount);
return ret;
}
/* 3AP to ISP Buffer */
if (m_parameters->is3aaIspOtf() == false
#ifdef USE_3AA_ISP_BUFFER_HIDING_MODE
|| (USE_3AA_ISP_BUFFER_HIDING_MODE == true
&& (m_cameraId == CAMERA_ID_BACK
|| m_parameters->getDualMode() == false))
#endif
) {
#if defined (USE_ISP_BUFFER_SIZE_TO_BDS)
ispBufferW = bdsRect.w;
ispBufferH = bdsRect.h;
#else
ispBufferW = previewMaxW;
ispBufferH = previewMaxH;
#endif
bayerFormat = m_parameters->getBayerFormat(PIPE_3AP);
bytesPerLine[0] = getBayerLineSize(ispBufferW, bayerFormat);
planeSize[0] = getBayerPlaneSize(ispBufferW, ispBufferH, bayerFormat);
planeCount = 2;
#ifdef USE_3AA_ISP_BUFFER_HIDING_MODE
if (USE_3AA_ISP_BUFFER_HIDING_MODE == true
&& m_parameters->is3aaIspOtf() == true
&& (m_cameraId == CAMERA_ID_BACK
|| m_parameters->getDualMode() == false))
maxBufferCount = m_exynosconfig->current->bufInfo.num_hiding_mode_buffers;
else
#endif
maxBufferCount = m_exynosconfig->current->bufInfo.num_3aa_buffers;
#ifdef RESERVED_MEMORY_ENABLE
if (getCameraIdInternal() == CAMERA_ID_BACK) {
type = EXYNOS_CAMERA_BUFFER_ION_RESERVED_TYPE;
if(m_parameters->getUHDRecordingMode() == true)
m_ispBufferMgr->setContigBufCount(RESERVED_NUM_ISP_BUFFERS_ON_UHD);
else
m_ispBufferMgr->setContigBufCount(RESERVED_NUM_ISP_BUFFERS);
} else if (m_parameters->getDualMode() == false) {
type = EXYNOS_CAMERA_BUFFER_ION_RESERVED_TYPE;
if(m_parameters->getUHDRecordingMode() == true)
m_ispBufferMgr->setContigBufCount(FRONT_RESERVED_NUM_ISP_BUFFERS_ON_UHD);
else
m_ispBufferMgr->setContigBufCount(FRONT_RESERVED_NUM_ISP_BUFFERS);
} else
#endif
type = EXYNOS_CAMERA_BUFFER_ION_NONCACHED_TYPE;
ret = m_allocBuffers(m_ispBufferMgr, planeCount, planeSize, bytesPerLine, maxBufferCount, maxBufferCount, type, true, false);
if (ret != NO_ERROR) {
CLOGE("ERR(%s[%d]):m_ispBufferMgr m_allocBuffers(bufferCount=%d) fail",
__FUNCTION__, __LINE__, maxBufferCount);
return ret;
}
memset(&bytesPerLine, 0, sizeof(unsigned int) * EXYNOS_CAMERA_BUFFER_MAX_PLANES);
CLOGI("INFO(%s[%d]):m_allocBuffers(ISP Buffer) %d x %d, planeSize(%d), planeCount(%d), maxBufferCount(%d)",
__FUNCTION__, __LINE__, ispBufferW, ispBufferH, planeSize[0], planeCount, maxBufferCount);
}
/* ISP to TPU(MCSC) Buffer */
if ((m_parameters->isIspTpuOtf() == false && m_parameters->isIspMcscOtf() == false)
#ifdef USE_ISP_TPU_BUFFER_HIDING_MODE
|| (USE_ISP_TPU_BUFFER_HIDING_MODE == true
&& m_parameters->isIspTpuOtf() == true
&& (m_cameraId == CAMERA_ID_BACK
|| m_parameters->getDualMode() == false))
#endif
#ifdef USE_ISP_MCSC_BUFFER_HIDING_MODE
|| (USE_ISP_MCSC_BUFFER_HIDING_MODE == true
&& m_parameters->isIspMcscOtf() == true
&& (m_cameraId == CAMERA_ID_BACK
|| m_parameters->getDualMode() == false))
#endif
) {
int ispDmaOutAlignW = CAMERA_16PX_ALIGN;
int ispDmaOutAlignH = 1;
if (m_parameters->getTpuEnabledMode() == true) {
ispDmaOutAlignW = CAMERA_TPU_CHUNK_ALIGN_W;
ispDmaOutAlignH = CAMERA_TPU_CHUNK_ALIGN_H;
}
#if defined (USE_ISP_BUFFER_SIZE_TO_BDS)
tpuBufferW = bdsRect.w;
tpuBufferH = bdsRect.h;
#else
tpuBufferW = previewMaxW;
tpuBufferH = previewMaxH;
#endif
planeCount = 2;
bytesPerLine[0] = ROUND_UP((tpuBufferW * 2), ispDmaOutAlignW);
planeSize[0] = bytesPerLine[0] * ROUND_UP(tpuBufferH, ispDmaOutAlignH);
#ifdef USE_ISP_TPU_BUFFER_HIDING_MODE
if (USE_ISP_TPU_BUFFER_HIDING_MODE == true
&& m_parameters->isIspTpuOtf() == true
&& (m_cameraId == CAMERA_ID_BACK
|| m_parameters->getDualMode() == false))
maxBufferCount = m_exynosconfig->current->bufInfo.num_hiding_mode_buffers;
else
#endif
#ifdef USE_ISP_MCSC_BUFFER_HIDING_MODE
if (USE_ISP_MCSC_BUFFER_HIDING_MODE == true
&& m_parameters->isIspMcscOtf() == true
&& (m_cameraId == CAMERA_ID_BACK
|| m_parameters->getDualMode() == false))
maxBufferCount = m_exynosconfig->current->bufInfo.num_hiding_mode_buffers;
else
#endif
maxBufferCount = m_exynosconfig->current->bufInfo.num_hwdis_buffers;
#ifdef RESERVED_MEMORY_ENABLE
if (getCameraIdInternal() == CAMERA_ID_BACK) {
type = EXYNOS_CAMERA_BUFFER_ION_RESERVED_TYPE;
if(m_parameters->getUHDRecordingMode() == true)
m_hwDisBufferMgr->setContigBufCount(RESERVED_NUM_ISP_BUFFERS_ON_UHD);
else
m_hwDisBufferMgr->setContigBufCount(RESERVED_NUM_ISP_BUFFERS);
} else if (m_parameters->getDualMode() == false) {
type = EXYNOS_CAMERA_BUFFER_ION_RESERVED_TYPE;
if(m_parameters->getUHDRecordingMode() == true)
m_hwDisBufferMgr->setContigBufCount(FRONT_RESERVED_NUM_ISP_BUFFERS_ON_UHD);
else
m_hwDisBufferMgr->setContigBufCount(FRONT_RESERVED_NUM_ISP_BUFFERS);
} else
#endif
type = EXYNOS_CAMERA_BUFFER_ION_NONCACHED_TYPE;
ret = m_allocBuffers(m_hwDisBufferMgr, planeCount, planeSize, bytesPerLine, maxBufferCount, maxBufferCount, type, true, false);
if (ret != NO_ERROR) {
CLOGE("ERR(%s[%d]):m_hwDisBufferMgr m_allocBuffers(bufferCount=%d) fail",
__FUNCTION__, __LINE__, maxBufferCount);
return ret;
}
#ifdef CAMERA_PACKED_BAYER_ENABLE
memset(&bytesPerLine, 0, sizeof(unsigned int) * EXYNOS_CAMERA_BUFFER_MAX_PLANES);
#endif
CLOGI("INFO(%s[%d]):m_allocBuffers(hwDis Buffer) %d x %d, planeSize(%d), planeCount(%d), maxBufferCount(%d)",
__FUNCTION__, __LINE__, tpuBufferW, tpuBufferH, planeSize[0], planeCount, maxBufferCount);
}
/* Preview(MCSC0) Buffer */
memset(planeSize, 0, sizeof(planeSize));
ret = getYuvFormatInfo(hwPreviewFormat, &bpp, &planeCount);
if (ret < 0) {
CLOGE("ERR(%s[%d]):getYuvFormatInfo(hwPreviewFormat(%x)) fail",
__FUNCTION__, __LINE__, hwPreviewFormat);
return INVALID_OPERATION;
}
// for meta
planeCount += 1;
if(m_parameters->increaseMaxBufferOfPreview() == true)
maxBufferCount = m_parameters->getPreviewBufferCount();
else
maxBufferCount = m_exynosconfig->current->bufInfo.num_preview_buffers;
if (m_previewWindow == NULL)
needMmap = true;
else
needMmap = false;
#ifdef BOARD_CAMERA_USES_DUAL_CAMERA
if (m_parameters->isFusionEnabled() == true) {
// hack for debugging
needMmap = true;
ret = getYuvPlaneSize(hwPreviewFormat, planeSize, fusionDstRect.w, fusionDstRect.h);
if (ret < 0) {
CLOGE("ERR(%s[%d]):getYuvPlaneSize(hwPreviewFormat(%x), fusionDstRect(%d x %d)) fail",
__FUNCTION__, __LINE__, hwPreviewFormat, fusionDstRect.w, fusionDstRect.h);
return INVALID_OPERATION;
}
ret = m_allocBuffers(m_scpBufferMgr, planeCount, planeSize, bytesPerLine, maxBufferCount, true,
fusionDstRect.w, fusionDstRect.h, fusionDstRect.w, m_parameters->convertingHalPreviewFormat(hwPreviewFormat, YUV_LIMITED_RANGE),
needMmap);
} else
#endif
{
ret = getYuvPlaneSize(hwPreviewFormat, planeSize, hwPreviewW, hwPreviewH);
if (ret < 0) {
CLOGE("ERR(%s[%d]):getYuvPlaneSize(hwPreviewFormat(%x), hwPreview(%d x %d)) fail",
__FUNCTION__, __LINE__, hwPreviewFormat, hwPreviewW, hwPreviewH);
return INVALID_OPERATION;
}
ret = m_allocBuffers(m_scpBufferMgr, planeCount, planeSize, bytesPerLine, maxBufferCount, true, needMmap);
}
if (ret != NO_ERROR) {
CLOGE("ERR(%s[%d]):m_scpBufferMgr m_allocBuffers(bufferCount=%d) fail",
__FUNCTION__, __LINE__, maxBufferCount);
return ret;
}
CLOGI("INFO(%s[%d]):m_allocBuffers(Preview Buffer) %d x %d, planeSize(%d+%d), planeCount(%d), maxBufferCount(%d)",
__FUNCTION__, __LINE__, hwPreviewW, hwPreviewH, planeSize[0], planeSize[1], planeCount, maxBufferCount);
/* for zoom scaling by external scaler */
/*
* only alloc in back case.
* dual's front doesn't need m_zoomScalerBufferMgr, by src(m_sccBufferMgr), dst(m_scpBufferMgr)
*/
if ((m_parameters->getSupportedZoomPreviewWIthScaler()) &&
! ((m_parameters->getDualMode() == true) &&
(getCameraIdInternal() == CAMERA_ID_FRONT || getCameraIdInternal() == CAMERA_ID_BACK_1))) {
int scalerW = hwPreviewW;
int scalerH = hwPreviewH;
#ifdef BOARD_CAMERA_USES_DUAL_CAMERA
if (m_parameters->isFusionEnabled() == true) {
scalerW = fusionSrcRect.w;
scalerH = fusionSrcRect.h;
}
#endif
memset(planeSize, 0, sizeof(planeSize));
ret = getYuvPlaneSize(hwPreviewFormat, planeSize, scalerW, scalerH);
if (ret < 0) {
CLOGE("ERR(%s[%d]):getYuvPlaneSize(hwPreviewFormat(%x), scaler(%d x %d)) fail",
__FUNCTION__, __LINE__, hwPreviewFormat, scalerW, scalerH);
return INVALID_OPERATION;
}
ret = getYuvFormatInfo(hwPreviewFormat, &bpp, &planeCount);
if (ret < 0) {
CLOGE("ERR(%s[%d]):getYuvFormatInfo(hwPreviewFormat(%x)) fail",
__FUNCTION__, __LINE__, hwPreviewFormat);
return INVALID_OPERATION;
}
// for meta
planeCount += 1;
if(m_parameters->increaseMaxBufferOfPreview()){
maxBufferCount = m_parameters->getPreviewBufferCount();
} else {
maxBufferCount = m_exynosconfig->current->bufInfo.num_preview_buffers;
}
bool needMmap = false;
if (m_previewWindow == NULL)
needMmap = true;
#ifdef BOARD_CAMERA_USES_DUAL_CAMERA
if (m_parameters->isFusionEnabled() == true) {
// hack for debugging
needMmap = true;
ret = m_allocBuffers(m_zoomScalerBufferMgr, planeCount, planeSize, bytesPerLine, maxBufferCount, true,
fusionSrcRect.w, fusionSrcRect.h, fusionSrcRect.w, m_parameters->convertingHalPreviewFormat(hwPreviewFormat, YUV_LIMITED_RANGE),
needMmap);
} else
#endif
{
ret = m_allocBuffers(m_zoomScalerBufferMgr, planeCount, planeSize, bytesPerLine, maxBufferCount, true, needMmap);
}
if (ret < 0) {
CLOGE("ERR(%s[%d]):m_scpBufferMgr m_allocBuffers(bufferCount=%d) fail",
__FUNCTION__, __LINE__, maxBufferCount);
return ret;
}
}
#ifdef BOARD_CAMERA_USES_DUAL_CAMERA
if (m_parameters->isFusionEnabled() == true) {
memset(planeSize, 0, sizeof(planeSize));
ret = getYuvPlaneSize(hwPreviewFormat, planeSize, fusionSrcRect.w, fusionSrcRect.h);
if (ret < 0) {
CLOGE("ERR(%s[%d]):getYuvPlaneSize(hwPreviewFormat(%x), fusionSrcRect(%d x %d)) fail",
__FUNCTION__, __LINE__, hwPreviewFormat, fusionSrcRect.w, fusionSrcRect.h);
return INVALID_OPERATION;
}
ret = getYuvFormatInfo(hwPreviewFormat, &bpp, &planeCount);
if (ret < 0) {
CLOGE("ERR(%s[%d]):getYuvFormatInfo(hwPreviewFormat(%x)) fail",
__FUNCTION__, __LINE__, hwPreviewFormat);
return INVALID_OPERATION;
}
// for meta
planeCount += 1;
if (m_parameters->isFlite3aaOtf() == true)
maxBufferCount = m_exynosconfig->current->bufInfo.num_3aa_buffers;
else
maxBufferCount = m_exynosconfig->current->bufInfo.num_bayer_buffers;
bool needMmap = false;
// hack for debugging
needMmap = true;
ret = m_allocBuffers(m_fusionBufferMgr, planeCount, planeSize, bytesPerLine, maxBufferCount, true,
fusionSrcRect.w, fusionSrcRect.h, fusionSrcRect.w, m_parameters->convertingHalPreviewFormat(hwPreviewFormat, YUV_LIMITED_RANGE),
needMmap);
if (ret < 0) {
CLOGE("ERR(%s[%d]):m_fusionBufferMgr m_allocBuffers(bufferCount=%d) fail",
__FUNCTION__, __LINE__, maxBufferCount);
return ret;
}
}
#endif
#ifdef USE_BUFFER_WITH_STRIDE
int stride = m_scpBufferMgr->getBufStride();
if (stride != hwPreviewW) {
CLOGI("INFO(%s[%d]):hwPreviewW(%d), stride(%d)", __FUNCTION__, __LINE__, hwPreviewW, stride);
if (stride == 0) {
/* If the SCP buffer manager is not instance of GrallocExynosCameraBufferManager
(In case of setPreviewWindow(null) is called), return value of setHwPreviewStride()
will be zero. If this value is passed as SCP width to firmware, firmware will
generate PABORT error. */
CLOGW("WARN(%s[%d]):HACK: Invalid stride(%d). It will be replaced as hwPreviewW(%d) value.",
__FUNCTION__, __LINE__, stride, hwPreviewW);
stride = hwPreviewW;
}
}
#endif
#ifdef BOARD_CAMERA_USES_DUAL_CAMERA
if (m_parameters->isFusionEnabled() == true) {
stride = fusionSrcRect.w;
}
#endif
m_parameters->setHwPreviewStride(stride);
/* Do not allocate SCC buffer */
#if 0
if (m_parameters->isSccCapture() == true) {
m_parameters->getHwPictureSize(&hwPictureW, &hwPictureH);
CLOGI("(%s):HW Picture width x height = %dx%d", __FUNCTION__, hwPictureW, hwPictureH);
if (SCC_OUTPUT_COLOR_FMT == V4L2_PIX_FMT_NV21M) {
planeSize[0] = ALIGN_UP(hwPictureW, GSCALER_IMG_ALIGN) * ALIGN_UP(hwPictureH, GSCALER_IMG_ALIGN);
planeSize[1] = ALIGN_UP(hwPictureW, GSCALER_IMG_ALIGN) * ALIGN_UP(hwPictureH, GSCALER_IMG_ALIGN) / 2;
planeCount = 3;
} else if (SCC_OUTPUT_COLOR_FMT == V4L2_PIX_FMT_NV21) {
planeSize[0] = ALIGN_UP(hwPictureW, GSCALER_IMG_ALIGN) * ALIGN_UP(hwPictureH, GSCALER_IMG_ALIGN) * 3 / 2;
planeCount = 2;
} else {
planeSize[0] = ALIGN_UP(hwPictureW, GSCALER_IMG_ALIGN) * ALIGN_UP(hwPictureH, GSCALER_IMG_ALIGN) * 2;
planeCount = 2;
}
/* TO DO : make same num of buffers */
if (m_parameters->isFlite3aaOtf() == true)
maxBufferCount = m_exynosconfig->current->bufInfo.num_picture_buffers;
else
maxBufferCount = m_exynosconfig->current->bufInfo.num_bayer_buffers;
ret = m_allocBuffers(m_sccBufferMgr, planeCount, planeSize, bytesPerLine, maxBufferCount, true, false);
if (ret < 0) {
CLOGE("ERR(%s[%d]):m_sccBufferMgr m_allocBuffers(bufferCount=%d) fail",
__FUNCTION__, __LINE__, maxBufferCount);
return ret;
}
}
#endif
ret = m_setVendorBuffers();
if (ret != NO_ERROR)
CLOGE("ERR(%s[%d]):m_setVendorBuffers fail, ret(%d)",
__FUNCTION__, __LINE__, ret);
ret = m_setPreviewCallbackBuffer();
if (ret != NO_ERROR) {
CLOGE("ERR(%s[%d]):m_setPreviewCallback Buffer fail", __FUNCTION__, __LINE__);
return ret;
}
CLOGI("INFO(%s[%d]):alloc buffer done - camera ID: %d",
__FUNCTION__, __LINE__, m_cameraId);
return NO_ERROR;
}
status_t ExynosCamera::m_setPictureBuffer(void)
{
status_t ret = NO_ERROR;
unsigned int planeSize[EXYNOS_CAMERA_BUFFER_MAX_PLANES] = {0};
unsigned int bytesPerLine[EXYNOS_CAMERA_BUFFER_MAX_PLANES] = {0};
int pictureW = 0, pictureH = 0;
int planeCount = 0;
int minBufferCount = 1;
int maxBufferCount = 1;
int pictureFormat = m_parameters->getHwPictureFormat();
exynos_camera_buffer_type_t type = EXYNOS_CAMERA_BUFFER_ION_NONCACHED_TYPE;
buffer_manager_allocation_mode_t allocMode = BUFFER_MANAGER_ALLOCATION_ONDEMAND;
m_parameters->getMaxPictureSize(&pictureW, &pictureH);
if (m_parameters->needGSCForCapture(getCameraIdInternal()) == true) {
if (pictureFormat == V4L2_PIX_FMT_NV21M) {
planeCount = 2;
planeSize[0] = pictureW * pictureH;
planeSize[1] = pictureW * pictureH / 2;
} else {
planeCount = 1;
planeSize[0] = FRAME_SIZE(V4L2_PIX_2_HAL_PIXEL_FORMAT(pictureFormat), pictureW, pictureH);
}
// Pre-allocate certain amount of buffers enough to fed into 3 JPEG save threads.
if (m_parameters->getSeriesShotCount() > 0)
minBufferCount = NUM_BURST_GSC_JPEG_INIT_BUFFER;
else
minBufferCount = 1;
maxBufferCount = m_exynosconfig->current->bufInfo.num_picture_buffers;
type = EXYNOS_CAMERA_BUFFER_ION_NONCACHED_TYPE;
ret = m_allocBuffers(m_gscBufferMgr, planeCount, planeSize, bytesPerLine,
minBufferCount, maxBufferCount, type, allocMode, false, false);
if (ret != NO_ERROR) {
CLOGE("ERR(%s[%d]):m_gscBufferMgr m_allocBuffers(minBufferCount=%d, maxBufferCount=%d) fail",
__FUNCTION__, __LINE__, minBufferCount, maxBufferCount);
return ret;
}
CLOGI("INFO(%s[%d]):m_allocBuffers(GSC Buffer) %d x %d, planeCount(%d), maxBufferCount(%d)",
__FUNCTION__, __LINE__, pictureW, pictureH, planeCount, maxBufferCount);
}
if (m_hdrEnabled == false) {
planeCount = 1;
planeSize[0] = FRAME_SIZE(V4L2_PIX_2_HAL_PIXEL_FORMAT(pictureFormat), pictureW, pictureH);
// Pre-allocate certain amount of buffers enough to fed into 3 JPEG save threads.
if (m_parameters->getSeriesShotCount() > 0)
minBufferCount = NUM_BURST_GSC_JPEG_INIT_BUFFER;
else
minBufferCount = 1;
maxBufferCount = m_exynosconfig->current->bufInfo.num_picture_buffers;
CLOGD("DEBUG(%s[%d]): jpegBuffer picture(%dx%d) size(%d)", __FUNCTION__, __LINE__, pictureW, pictureH, planeSize[0]);
#ifdef RESERVED_MEMORY_ENABLE
if (getCameraIdInternal() == CAMERA_ID_BACK
#ifdef RESERVED_MEMORY_20M_WORKAROUND
&& m_cameraSensorId != SENSOR_NAME_S5K2T2
#endif
) {
type = EXYNOS_CAMERA_BUFFER_ION_CACHED_RESERVED_TYPE;
if (m_parameters->getUHDRecordingMode() == true) {
m_jpegBufferMgr->setContigBufCount(RESERVED_NUM_JPEG_BUFFERS_ON_UHD);
} else {
m_jpegBufferMgr->setContigBufCount(RESERVED_NUM_JPEG_BUFFERS);
/* alloc at once */
minBufferCount = NUM_BURST_GSC_JPEG_INIT_BUFFER;
}
} else
#endif
type = EXYNOS_CAMERA_BUFFER_ION_CACHED_SYNC_FORCE_TYPE;
ret = m_allocBuffers(m_jpegBufferMgr, planeCount, planeSize, bytesPerLine,
minBufferCount, maxBufferCount, type, allocMode, false, true);
if (ret != NO_ERROR)
CLOGE("ERR(%s:%d):jpegSrcHeapBuffer m_allocBuffers(bufferCount=%d) fail",
__FUNCTION__, __LINE__, NUM_REPROCESSING_BUFFERS);
CLOGI("INFO(%s[%d]):m_allocBuffers(JPEG Buffer) %d x %d, planeCount(%d), maxBufferCount(%d)",
__FUNCTION__, __LINE__, pictureW, pictureH, planeCount, maxBufferCount);
}
ret = m_setVendorPictureBuffer();
if (ret != NO_ERROR)
CLOGE("ERR(%s[%d]):m_setVendorBuffers fail, ret(%d)",
__FUNCTION__, __LINE__, ret);
return ret;
}
status_t ExynosCamera::m_releaseBuffers(void)
{
CLOGI("INFO(%s[%d]):release buffer", __FUNCTION__, __LINE__);
int ret = 0;
if (m_fdCallbackHeap != NULL) {
m_fdCallbackHeap->release(m_fdCallbackHeap);
m_fdCallbackHeap = NULL;
}
if (m_bayerBufferMgr != NULL) {
m_bayerBufferMgr->deinit();
}
#ifdef DEBUG_RAWDUMP
if (m_fliteBufferMgr != NULL) {
m_fliteBufferMgr->deinit();
}
#endif
if (m_3aaBufferMgr != NULL) {
m_3aaBufferMgr->deinit();
}
if (m_ispBufferMgr != NULL) {
m_ispBufferMgr->deinit();
}
if (m_hwDisBufferMgr != NULL) {
m_hwDisBufferMgr->deinit();
}
if (m_scpBufferMgr != NULL) {
m_scpBufferMgr->deinit();
}
#ifdef BOARD_CAMERA_USES_DUAL_CAMERA
if (m_fusionBufferMgr != NULL) {
m_fusionBufferMgr->deinit();
}
#endif
if (m_ispReprocessingBufferMgr != NULL) {
m_ispReprocessingBufferMgr->deinit();
}
if (m_sccReprocessingBufferMgr != NULL) {
m_sccReprocessingBufferMgr->deinit();
}
if (m_thumbnailBufferMgr != NULL) {
m_thumbnailBufferMgr->deinit();
}
if (m_sccBufferMgr != NULL) {
m_sccBufferMgr->deinit();
}
if (m_gscBufferMgr != NULL) {
m_gscBufferMgr->deinit();
}
if (m_postPictureBufferMgr != NULL) {
m_postPictureBufferMgr->deinit();
}
if (m_thumbnailGscBufferMgr != NULL) {
m_thumbnailGscBufferMgr->deinit();
}
if (m_jpegBufferMgr != NULL) {
m_jpegBufferMgr->deinit();
}
if (m_recordingBufferMgr != NULL) {
m_recordingBufferMgr->deinit();
}
if (m_previewCallbackBufferMgr != NULL) {
m_previewCallbackBufferMgr->deinit();
}
if (m_highResolutionCallbackBufferMgr != NULL) {
m_highResolutionCallbackBufferMgr->deinit();
}
ret = m_releaseVendorBuffers();
if (ret != NO_ERROR)
CLOGE("ERR(%s[%d]):m_releaseVendorBuffers fail, ret(%d)",
__FUNCTION__, __LINE__, ret);
CLOGI("INFO(%s[%d]):free buffer done", __FUNCTION__, __LINE__);
return NO_ERROR;
}
bool ExynosCamera::m_startFaceDetection(void)
{
if (m_flagStartFaceDetection == true) {
CLOGD("DEBUG(%s):Face detection already started..", __FUNCTION__);
return true;
}
if (m_parameters->getDualMode() == true
&& getCameraIdInternal() == CAMERA_ID_BACK
) {
CLOGW("WRN(%s[%d]):On dual mode, Face detection disable!", __FUNCTION__, __LINE__);
m_enableFaceDetection(false);
m_flagStartFaceDetection = false;
} else {
/* FD-AE is always on */
#ifdef USE_FD_AE
#else
m_enableFaceDetection(true);
#endif
/* Block FD-AF except for special shot modes */
if(m_parameters->getShotMode() == SHOT_MODE_BEAUTY_FACE ||
m_parameters->getShotMode() == SHOT_MODE_SELFIE_ALARM) {
ExynosCameraActivityAutofocus *autoFocusMgr = m_exynosCameraActivityControl->getAutoFocusMgr();
if (autoFocusMgr->setFaceDetection(true) == false) {
CLOGE("ERR(%s[%d]):setFaceDetection(%d)", __FUNCTION__, __LINE__, true);
} else {
/* restart CAF when FD mode changed */
switch (autoFocusMgr->getAutofocusMode()) {
case ExynosCameraActivityAutofocus::AUTOFOCUS_MODE_CONTINUOUS_PICTURE:
case ExynosCameraActivityAutofocus::AUTOFOCUS_MODE_CONTINUOUS_PICTURE_MACRO:
if (autoFocusMgr->flagAutofocusStart() == true &&
autoFocusMgr->flagLockAutofocus() == false) {
autoFocusMgr->stopAutofocus();
autoFocusMgr->startAutofocus();
}
break;
default:
break;
}
}
}
if (m_facedetectQ->getSizeOfProcessQ() > 0) {
CLOGE("ERR(%s[%d]):startFaceDetection recordingQ(%d)", __FUNCTION__, __LINE__, m_facedetectQ->getSizeOfProcessQ());
m_clearList(m_facedetectQ);
}
m_flagStartFaceDetection = true;
if (m_facedetectThread->isRunning() == false)
m_facedetectThread->run();
}
return true;
}
bool ExynosCamera::m_stopFaceDetection(void)
{
if (m_flagStartFaceDetection == false) {
CLOGD("DEBUG(%s [%d]):Face detection already stopped..", __FUNCTION__, __LINE__);
return true;
}
ExynosCameraActivityAutofocus *autoFocusMgr = m_exynosCameraActivityControl->getAutoFocusMgr();
if (autoFocusMgr->setFaceDetection(false) == false) {
CLOGE("ERR(%s[%d]):setFaceDetection(%d)", __FUNCTION__, __LINE__, false);
} else {
/* restart CAF when FD mode changed */
switch (autoFocusMgr->getAutofocusMode()) {
case ExynosCameraActivityAutofocus::AUTOFOCUS_MODE_CONTINUOUS_PICTURE:
case ExynosCameraActivityAutofocus::AUTOFOCUS_MODE_CONTINUOUS_PICTURE_MACRO:
if (autoFocusMgr->flagAutofocusStart() == true &&
autoFocusMgr->flagLockAutofocus() == false) {
autoFocusMgr->stopAutofocus();
autoFocusMgr->startAutofocus();
}
break;
default:
break;
}
}
/* FD-AE is always on */
#ifdef USE_FD_AE
#else
m_enableFaceDetection(false);
#endif
m_flagStartFaceDetection = false;
return true;
}
status_t ExynosCamera::m_setPreviewCallbackBuffer(void)
{
int ret = 0;
int previewW = 0, previewH = 0;
int previewFormat = 0;
if (m_parameters->getHighResolutionCallbackMode() == true) {
m_parameters->getHwPreviewSize(&previewW, &previewH);
} else {
m_parameters->getPreviewSize(&previewW, &previewH);
}
previewFormat = m_parameters->getPreviewFormat();
unsigned int planeSize[EXYNOS_CAMERA_BUFFER_MAX_PLANES] = {0};
unsigned int bytesPerLine[EXYNOS_CAMERA_BUFFER_MAX_PLANES] = {0};
int bufferCount = 1;
exynos_camera_buffer_type_t type = EXYNOS_CAMERA_BUFFER_ION_CACHED_TYPE;
int planeCount = getYuvPlaneCount(previewFormat);
planeCount++;
#ifdef USE_MCSC1_FOR_PREVIEWCALLBACK
bufferCount = m_parameters->getPreviewBufferCount();
#endif
if (m_previewCallbackBufferMgr == NULL) {
CLOGE("ERR(%s[%d]): m_previewCallbackBufferMgr is NULL", __FUNCTION__, __LINE__);
return INVALID_OPERATION;
}
if (m_previewCallbackBufferMgr->isAllocated() == true) {
if (m_parameters->getRestartPreview() == true) {
CLOGD("DEBUG(%s[%d]): preview size is changed, realloc buffer", __FUNCTION__, __LINE__);
m_previewCallbackBufferMgr->deinit();
} else {
return NO_ERROR;
}
}
ret = getYuvPlaneSize(previewFormat, planeSize, previewW, previewH);
if (ret < 0) {
CLOGE("ERR(%s[%d]): BAD value, format(%x), size(%dx%d)",
__FUNCTION__, __LINE__, previewFormat, previewW, previewH);
return ret;
}
ret = m_allocBuffers(m_previewCallbackBufferMgr,
planeCount,
planeSize,
bytesPerLine,
bufferCount,
bufferCount,
type,
true,
false);
if (ret < 0) {
CLOGE("ERR(%s[%d]):m_previewCallbackBufferMgr m_allocBuffers(bufferCount=%d/%d) fail",
__FUNCTION__, __LINE__, bufferCount, bufferCount);
return ret;
}
CLOGI("INFO(%s[%d]):m_allocBuffers(Preview Callback Buffer) %d x %d, planeSize(%d), planeCount(%d), bufferCount(%d)",
__FUNCTION__, __LINE__, previewW, previewH, planeSize[0], planeCount, bufferCount);
return NO_ERROR;
}
status_t ExynosCamera::m_putBuffers(ExynosCameraBufferManager *bufManager, int bufIndex)
{
status_t ret = NO_ERROR;
if (bufManager != NULL) {
ret = bufManager->putBuffer(bufIndex, EXYNOS_CAMERA_BUFFER_POSITION_NONE);
if (ret != NO_ERROR)
CLOGE("ERR(%s[%d]):Buffer manager putBuffer fail, index(%d), ret(%d)",
__FUNCTION__, __LINE__, bufIndex, ret);
}
return NO_ERROR;
}
status_t ExynosCamera::m_allocBuffers(
ExynosCameraBufferManager *bufManager,
int planeCount,
unsigned int *planeSize,
unsigned int *bytePerLine,
int reqBufCount,
bool createMetaPlane,
bool needMmap)
{
int ret = 0;
ret = m_allocBuffers(
bufManager,
planeCount,
planeSize,
bytePerLine,
reqBufCount,
reqBufCount,
EXYNOS_CAMERA_BUFFER_ION_NONCACHED_TYPE,
BUFFER_MANAGER_ALLOCATION_ATONCE,
createMetaPlane,
needMmap);
if (ret < 0) {
CLOGE("ERR(%s[%d]):m_allocBuffers(reqBufCount=%d) fail",
__FUNCTION__, __LINE__, reqBufCount);
}
return ret;
}
status_t ExynosCamera::m_allocBuffers(
ExynosCameraBufferManager *bufManager,
int planeCount,
unsigned int *planeSize,
unsigned int *bytePerLine,
int minBufCount,
int maxBufCount,
exynos_camera_buffer_type_t type,
bool createMetaPlane,
bool needMmap)
{
int ret = 0;
ret = m_allocBuffers(
bufManager,
planeCount,
planeSize,
bytePerLine,
minBufCount,
maxBufCount,
type,
BUFFER_MANAGER_ALLOCATION_ONDEMAND,
createMetaPlane,
needMmap);
if (ret < 0) {
CLOGE("ERR(%s[%d]):m_allocBuffers(minBufCount=%d, maxBufCount=%d, type=%d) fail",
__FUNCTION__, __LINE__, minBufCount, maxBufCount, type);
}
return ret;
}
status_t ExynosCamera::m_allocBuffers(
ExynosCameraBufferManager *bufManager,
int planeCount,
unsigned int *planeSize,
unsigned int *bytePerLine,
int minBufCount,
int maxBufCount,
exynos_camera_buffer_type_t type,
buffer_manager_allocation_mode_t allocMode,
bool createMetaPlane,
bool needMmap)
{
int ret = 0;
int retryCount = 20; /* 2Sec */
retry_alloc:
CLOGI("INFO(%s[%d]):setInfo(planeCount=%d, minBufCount=%d, maxBufCount=%d, type=%d, allocMode=%d)",
__FUNCTION__, __LINE__, planeCount, minBufCount, maxBufCount, (int)type, (int)allocMode);
ret = bufManager->setInfo(
planeCount,
planeSize,
bytePerLine,
0,
minBufCount,
maxBufCount,
type,
allocMode,
createMetaPlane,
needMmap);
if (ret < 0) {
CLOGE("ERR(%s[%d]):setInfo fail", __FUNCTION__, __LINE__);
goto func_exit;
}
ret = bufManager->alloc();
if (ret < 0) {
if (retryCount != 0
&& (type == EXYNOS_CAMERA_BUFFER_ION_RESERVED_TYPE
|| type == EXYNOS_CAMERA_BUFFER_ION_CACHED_RESERVED_TYPE)) {
CLOGE("ERR(%s[%d]: Alloc fail about reserved memory. retry alloc. (%d)", __FUNCTION__, __LINE__, retryCount);
usleep(100000); /* 100ms */
retryCount--;
goto retry_alloc;
}
CLOGE("ERR(%s[%d]):alloc fail", __FUNCTION__, __LINE__);
goto func_exit;
}
func_exit:
return ret;
}
status_t ExynosCamera::m_allocBuffers(
ExynosCameraBufferManager *bufManager,
int planeCount,
unsigned int *planeSize,
unsigned int *bytePerLine,
int reqBufCount,
bool createMetaPlane,
int width,
int height,
int stride,
int pixelFormat,
bool needMmap)
{
int ret = 0;
CLOGI("INFO(%s[%d]):setInfo(planeCount=%d, minBufCount=%d, maxBufCount=%d, width=%d height=%d stride=%d pixelFormat=%d)",
__FUNCTION__, __LINE__, planeCount, reqBufCount, reqBufCount, width, height, stride, pixelFormat);
ret = bufManager->setInfo(
planeCount,
planeSize,
bytePerLine,
0,
reqBufCount,
reqBufCount,
EXYNOS_CAMERA_BUFFER_ION_CACHED_TYPE,
BUFFER_MANAGER_ALLOCATION_ATONCE,
createMetaPlane,
width,
height,
stride,
pixelFormat,
needMmap);
if (ret < 0) {
CLOGE("ERR(%s[%d]):setInfo fail", __FUNCTION__, __LINE__);
goto func_exit;
}
ret = bufManager->alloc();
if (ret < 0) {
CLOGE("ERR(%s[%d]):alloc fail", __FUNCTION__, __LINE__);
goto func_exit;
}
func_exit:
return ret;
}
int ExynosCamera::m_getShotBufferIdex() const
{
return NUM_PLANES(V4L2_PIX_2_HAL_PIXEL_FORMAT(SCC_OUTPUT_COLOR_FMT));
}
bool ExynosCamera::m_enableFaceDetection(bool toggle)
{
CLOGD("DEBUG(%s[%d]) toggle : %d", __FUNCTION__, __LINE__, toggle);
if (toggle == true) {
m_parameters->setFdEnable(true);
m_parameters->setFdMode(FACEDETECT_MODE_FULL);
} else {
m_parameters->setFdEnable(false);
m_parameters->setFdMode(FACEDETECT_MODE_OFF);
}
memset(&m_frameMetadata, 0, sizeof(camera_frame_metadata_t));
return true;
}
bool ExynosCamera::m_getRecordingEnabled(void)
{
Mutex::Autolock lock(m_recordingStateLock);
return m_recordingEnabled;
}
void ExynosCamera::m_setRecordingEnabled(bool enable)
{
Mutex::Autolock lock(m_recordingStateLock);
m_recordingEnabled = enable;
return;
}
int ExynosCamera::m_calibratePosition(int w, int new_w, int pos)
{
return (float)(pos * new_w) / (float)w;
}
status_t ExynosCamera::m_generateFrame(int32_t frameCount, ExynosCameraFrame **newFrame)
{
Mutex::Autolock lock(m_frameLock);
int ret = 0;
*newFrame = NULL;
if (frameCount >= 0) {
ret = m_searchFrameFromList(&m_processList, frameCount, newFrame);
if (ret < 0) {
CLOGE("ERR(%s[%d]):searchFrameFromList fail", __FUNCTION__, __LINE__);
return INVALID_OPERATION;
}
}
if (*newFrame == NULL) {
*newFrame = m_previewFrameFactory->createNewFrame();
if (*newFrame == NULL) {
CLOGE("ERR(%s):newFrame is NULL", __FUNCTION__);
return UNKNOWN_ERROR;
}
bool flagRequested = false;
if (m_parameters->isOwnScc(getCameraIdInternal()) == true)
flagRequested = (*newFrame)->getRequest(PIPE_SCC);
else
flagRequested = (*newFrame)->getRequest(PIPE_ISPC);
if (flagRequested == true) {
m_dynamicSccCount++;
CLOGV("DEBUG(%s[%d]):dynamicSccCount inc(%d) frameCount(%d)", __FUNCTION__, __LINE__, m_dynamicSccCount, (*newFrame)->getFrameCount());
}
m_processList.push_back(*newFrame);
}
return ret;
}
status_t ExynosCamera::m_setupEntity(
uint32_t pipeId,
ExynosCameraFrame *newFrame,
ExynosCameraBuffer *srcBuf,
ExynosCameraBuffer *dstBuf)
{
int ret = 0;
entity_buffer_state_t entityBufferState;
/* set SRC buffer */
ret = newFrame->getSrcBufferState(pipeId, &entityBufferState);
if (ret < 0) {
CLOGE("ERR(%s[%d]):getSrcBufferState fail, pipeId(%d), ret(%d)", __FUNCTION__, __LINE__, pipeId, ret);
return ret;
}
if (entityBufferState == ENTITY_BUFFER_STATE_REQUESTED) {
ret = m_setSrcBuffer(pipeId, newFrame, srcBuf);
if (ret < 0) {
CLOGE("ERR(%s[%d]):m_setSrcBuffer fail, pipeId(%d), ret(%d)", __FUNCTION__, __LINE__, pipeId, ret);
return ret;
}
}
/* set DST buffer */
ret = newFrame->getDstBufferState(pipeId, &entityBufferState);
if (ret < 0) {
CLOGE("ERR(%s[%d]):getDstBufferState fail, pipeId(%d), ret(%d)", __FUNCTION__, __LINE__, pipeId, ret);
return ret;
}
if (entityBufferState == ENTITY_BUFFER_STATE_REQUESTED) {
ret = m_setDstBuffer(pipeId, newFrame, dstBuf);
if (ret < 0) {
CLOGE("ERR(%s[%d]):m_setDstBuffer fail, pipeId(%d), ret(%d)", __FUNCTION__, __LINE__, pipeId, ret);
return ret;
}
}
ret = newFrame->setEntityState(pipeId, ENTITY_STATE_PROCESSING);
if (ret < 0) {
CLOGE("ERR(%s[%d]):setEntityState(ENTITY_STATE_PROCESSING) fail, pipeId(%d), ret(%d)", __FUNCTION__, __LINE__, pipeId, ret);
return ret;
}
return NO_ERROR;
}
status_t ExynosCamera::m_setSrcBuffer(
uint32_t pipeId,
ExynosCameraFrame *newFrame,
ExynosCameraBuffer *buffer)
{
int ret = 0;
int bufIndex = -1;
ExynosCameraBufferManager *bufferMgr = NULL;
ExynosCameraBuffer srcBuf;
if (buffer == NULL) {
buffer = &srcBuf;
ret = m_getBufferManager(pipeId, &bufferMgr, SRC_BUFFER_DIRECTION);
if (ret < 0) {
CLOGE("ERR(%s[%d]):getBufferManager(SRC) fail, pipeId(%d), ret(%d)", __FUNCTION__, __LINE__, pipeId, ret);
return ret;
}
if (bufferMgr == NULL) {
CLOGE("ERR(%s[%d]):buffer manager is NULL, pipeId(%d)", __FUNCTION__, __LINE__, pipeId);
return BAD_VALUE;
}
/* get buffers */
ret = bufferMgr->getBuffer(&bufIndex, EXYNOS_CAMERA_BUFFER_POSITION_IN_HAL, buffer);
if (ret < 0) {
CLOGE("ERR(%s[%d]):getBuffer fail, pipeId(%d), frameCount(%d), ret(%d)",
__FUNCTION__, __LINE__, pipeId, newFrame->getFrameCount(), ret);
bufferMgr->dump();
return ret;
}
}
/* set buffers */
ret = newFrame->setSrcBuffer(pipeId, *buffer);
if (ret < 0) {
CLOGE("ERR(%s[%d]):setSrcBuffer fail, pipeId(%d), ret(%d)", __FUNCTION__, __LINE__, pipeId, ret);
return ret;
}
return NO_ERROR;
}
status_t ExynosCamera::m_setDstBuffer(
uint32_t pipeId,
ExynosCameraFrame *newFrame,
ExynosCameraBuffer *buffer)
{
int ret = 0;
int bufIndex = -1;
ExynosCameraBufferManager *bufferMgr = NULL;
ExynosCameraBuffer dstBuf;
if (buffer == NULL) {
buffer = &dstBuf;
ret = m_getBufferManager(pipeId, &bufferMgr, DST_BUFFER_DIRECTION);
if (ret < 0) {
CLOGE("ERR(%s[%d]):getBufferManager(DST) fail, pipeId(%d), ret(%d)", __FUNCTION__, __LINE__, pipeId, ret);
return ret;
}
if (bufferMgr == NULL) {
CLOGE("ERR(%s[%d]):buffer manager is NULL, pipeId(%d)", __FUNCTION__, __LINE__, pipeId);
return BAD_VALUE;
}
/* get buffers */
ret = bufferMgr->getBuffer(&bufIndex, EXYNOS_CAMERA_BUFFER_POSITION_IN_HAL, buffer);
if (ret < 0) {
ExynosCameraFrameEntity *curEntity = newFrame->searchEntityByPipeId(pipeId);
if (curEntity != NULL) {
if (curEntity->getBufType() == ENTITY_BUFFER_DELIVERY) {
CLOGV("DEBUG(%s[%d]): pipe(%d) buffer is empty for delivery", __FUNCTION__, __LINE__, pipeId);
buffer->index = -1;
} else {
CLOGE("ERR(%s[%d]):getBuffer fail, pipeId(%d), frameCount(%d), ret(%d)",
__FUNCTION__, __LINE__, pipeId, newFrame->getFrameCount(), ret);
return ret;
}
} else {
CLOGE("ERR(%s[%d]):curEntity is NULL, pipeId(%d)", __FUNCTION__, __LINE__, pipeId);
return ret;
}
}
}
/* set buffers */
ret = newFrame->setDstBuffer(pipeId, *buffer);
if (ret < 0) {
CLOGE("ERR(%s[%d]):setDstBuffer fail, pipeId(%d), ret(%d)", __FUNCTION__, __LINE__, pipeId, ret);
return ret;
}
return NO_ERROR;
}
status_t ExynosCamera::m_generateFrameReprocessing(ExynosCameraFrame **newFrame)
{
Mutex::Autolock lock(m_frameLock);
int ret = 0;
struct ExynosCameraBuffer tempBuffer;
int bufIndex = -1;
/* 1. Make Frame */
*newFrame = m_reprocessingFrameFactory->createNewFrame();
if (*newFrame == NULL) {
CLOGE("ERR(%s):newFrame is NULL", __FUNCTION__);
return UNKNOWN_ERROR;
}
return NO_ERROR;
}
status_t ExynosCamera::m_setCallbackBufferInfo(ExynosCameraBuffer *callbackBuf, char *baseAddr)
{
/*
* If it is not 16-aligend, shrink down it as 16 align. ex) 1080 -> 1072
* But, memory is set on Android format. so, not aligned area will be black.
*/
int dst_width = 0, dst_height = 0, dst_crop_width = 0, dst_crop_height = 0;
int dst_format = m_parameters->getPreviewFormat();
m_parameters->getPreviewSize(&dst_width, &dst_height);
dst_crop_width = dst_width;
dst_crop_height = dst_height;
if (dst_format == V4L2_PIX_FMT_NV21 ||
dst_format == V4L2_PIX_FMT_NV21M) {
callbackBuf->size[0] = (dst_width * dst_height);
callbackBuf->size[1] = (dst_width * dst_height) / 2;
callbackBuf->addr[0] = baseAddr;
callbackBuf->addr[1] = callbackBuf->addr[0] + callbackBuf->size[0];
} else if (dst_format == V4L2_PIX_FMT_YVU420 ||
dst_format == V4L2_PIX_FMT_YVU420M) {
callbackBuf->size[0] = dst_width * dst_height;
callbackBuf->size[1] = dst_width / 2 * dst_height / 2;
callbackBuf->size[2] = callbackBuf->size[1];
callbackBuf->addr[0] = baseAddr;
callbackBuf->addr[1] = callbackBuf->addr[0] + callbackBuf->size[0];
callbackBuf->addr[2] = callbackBuf->addr[1] + callbackBuf->size[1];
}
CLOGV("DEBUG(%s): dst_size(%dx%d), dst_crop_size(%dx%d)", __FUNCTION__, dst_width, dst_height, dst_crop_width, dst_crop_height);
return NO_ERROR;
}
status_t ExynosCamera::m_syncPrviewWithCSC(int32_t pipeId, int32_t gscPipe, ExynosCameraFrame *frame)
{
#ifdef DEBUG
ExynosCameraAutoTimer autoTimer(__FUNCTION__);
#endif
int32_t previewFormat = 0;
status_t ret = NO_ERROR;
ExynosRect srcRect, dstRect;
ExynosCameraBuffer srcBuf;
ExynosCameraBuffer dstBuf;
uint32_t *output = NULL;
struct camera2_stream *meta = NULL;
ExynosCameraBufferManager *srcBufMgr = NULL;
ExynosCameraBufferManager *dstBufMgr = NULL;
int previewH, previewW;
int bufIndex = -1;
int waitCount = 0;
int srcNodeIndex = -1;
int dstNodeIndex = -1;
int scpNodeIndex = -1;
int srcFmt = -1;
entity_buffer_state_t state = ENTITY_BUFFER_STATE_NOREQ;
/* copy metadata src to dst*/
if ((m_parameters->getDualMode() == true) &&
(getCameraIdInternal() == CAMERA_ID_FRONT || getCameraIdInternal() == CAMERA_ID_BACK_1)) {
srcNodeIndex = m_previewFrameFactory->getNodeType(PIPE_ISPC);
dstNodeIndex = 0;
#ifdef BOARD_CAMERA_USES_DUAL_CAMERA
if (m_parameters->isFusionEnabled() == true)
scpNodeIndex = 0;
else
#endif
scpNodeIndex = m_previewFrameFactory->getNodeType(PIPE_SCP);
srcBufMgr = m_sccBufferMgr;
m_getBufferManager(gscPipe, &dstBufMgr, DST_BUFFER_DIRECTION);
} else {
srcNodeIndex = m_previewFrameFactory->getNodeType(PIPE_SCP);
dstNodeIndex = 0;
#ifdef BOARD_CAMERA_USES_DUAL_CAMERA
if (m_parameters->isFusionEnabled() == true)
scpNodeIndex = 0;
else
#endif
scpNodeIndex = m_previewFrameFactory->getNodeType(PIPE_SCP);
srcBufMgr = m_zoomScalerBufferMgr;
m_getBufferManager(gscPipe, &dstBufMgr, DST_BUFFER_DIRECTION);
}
state = ENTITY_BUFFER_STATE_NOREQ;
ret = frame->getSrcBufferState(gscPipe, &state);
if( ret < 0 || state == ENTITY_BUFFER_STATE_ERROR) {
CLOGE("ERR(%s[%d]):getSrcBufferState fail, pipeId(%d), entityState(%d) frame(%d)",__FUNCTION__, __LINE__, gscPipe, state, frame->getFrameCount());
ret = INVALID_OPERATION;
goto func_exit;
}
srcBuf.index = -1;
dstBuf.index = -1;
ret = frame->getSrcBuffer(gscPipe, &srcBuf);
if (ret != NO_ERROR) {
CLOGE("ERR(%s[%d]):getSrcBuffer fail, pipeId(%d), ret(%d) frame(%d)",__FUNCTION__, __LINE__, pipeId, ret, frame->getFrameCount());
ret = INVALID_OPERATION;
goto func_exit;
}
ret = frame->getDstBuffer(gscPipe, &dstBuf, dstNodeIndex);
if (ret != NO_ERROR) {
CLOGE("ERR(%s[%d]):getDstBuffer fail, pipeId(%d), ret(%d) frame(%d)",__FUNCTION__, __LINE__, pipeId, ret, frame->getFrameCount());
ret = INVALID_OPERATION;
goto func_exit;
}
memcpy(dstBuf.addr[dstBuf.planeCount-1],srcBuf.addr[srcBuf.planeCount-1], sizeof(struct camera2_stream));
if ((m_parameters->getDualMode() == true) &&
(getCameraIdInternal() == CAMERA_ID_FRONT || getCameraIdInternal() == CAMERA_ID_BACK_1)) {
/* dual front scenario use ispc buffer for capture, frameSelector ownership for buffer */
} else {
if (srcBuf.index >= 0 )
srcBufMgr->cancelBuffer(srcBuf.index);
}
ret = frame->setDstBufferState(pipeId, ENTITY_BUFFER_STATE_REQUESTED, scpNodeIndex);
if (ret != NO_ERROR) {
CLOGE("ERR(%s[%d]):setdst Buffer state failed(%d) frame(%d)", __FUNCTION__, __LINE__, ret, frame->getFrameCount());
ret = INVALID_OPERATION;
goto func_exit;
}
ret = frame->setDstBuffer(pipeId, dstBuf, scpNodeIndex);
if (ret != NO_ERROR) {
CLOGE("ERR(%s[%d]):setdst Buffer failed(%d) frame(%d)", __FUNCTION__, __LINE__, ret, frame->getFrameCount());
ret = INVALID_OPERATION;
goto func_exit;
}
ret = frame->setDstBufferState(pipeId, ENTITY_BUFFER_STATE_COMPLETE, scpNodeIndex);
if (ret != NO_ERROR) {
CLOGE("ERR(%s[%d]):setdst Buffer state failed(%d) frame(%d)", __FUNCTION__, __LINE__, ret, frame->getFrameCount());
ret = INVALID_OPERATION;
goto func_exit;
}
ret = frame->setDstBufferState(pipeId, ENTITY_BUFFER_STATE_COMPLETE);
if (ret != NO_ERROR) {
CLOGE("ERR(%s[%d]):setdst Buffer failed(%d) frame(%d)", __FUNCTION__, __LINE__, ret, frame->getFrameCount());
ret = INVALID_OPERATION;
goto func_exit;
}
CLOGV("DEBUG(%s[%d]): syncPrviewWithCSC done(%d)", __FUNCTION__, __LINE__, ret);
return ret;
func_exit:
CLOGE("ERR(%s[%d]): sync with csc failed frame(%d) ret(%d) src(%d) dst(%d)", __FUNCTION__, __LINE__, frame->getFrameCount(), ret, srcBuf.index, dstBuf.index);
srcBuf.index = -1;
dstBuf.index = -1;
/* 1. return buffer pipe done. */
ret = frame->getDstBuffer(pipeId, &srcBuf, srcNodeIndex);
if (ret != NO_ERROR) {
CLOGE("ERR(%s[%d]):getSrcBuffer fail, pipeId(%d), ret(%d) frame(%d)",__FUNCTION__, __LINE__, pipeId, ret, frame->getFrameCount());
}
/* 2. do not return buffer dual front case, frameselector ownershipt for the buffer */
if ((m_parameters->getDualMode() == true) &&
(getCameraIdInternal() == CAMERA_ID_FRONT || getCameraIdInternal() == CAMERA_ID_BACK_1)) {
/* dual front scenario use ispc buffer for capture, frameSelector ownership for buffer */
} else {
if (srcBuf.index >= 0)
srcBufMgr->cancelBuffer(srcBuf.index);
}
/* 3. if the gsc dst buffer available, return the buffer. */
ret = frame->getDstBuffer(gscPipe, &dstBuf, dstNodeIndex);
if (ret != NO_ERROR) {
CLOGE("ERR(%s[%d]):getDstBuffer fail, pipeId(%d), ret(%d) frame(%d)",__FUNCTION__, __LINE__, pipeId, ret, frame->getFrameCount());
}
if (dstBuf.index >= 0)
dstBufMgr->cancelBuffer(dstBuf.index);
/* 4. change buffer state error for error handlering */
/* 1)dst buffer state : 0( putbuffer ndone for mcpipe ) */
/* 2)dst buffer state : scp node index ( getbuffer ndone for mcpipe ) */
frame->setDstBufferState(pipeId, ENTITY_BUFFER_STATE_ERROR, scpNodeIndex);
frame->setDstBufferState(pipeId, ENTITY_BUFFER_STATE_ERROR);
return INVALID_OPERATION;
}
/*
* pIsProcessed : out parameter
* true if the frame is properly handled.
* false if frame processing is failed or there is no frame to process
*/
bool ExynosCamera::m_prePictureInternal(bool* pIsProcessed)
{
ExynosCameraAutoTimer autoTimer(__FUNCTION__);
CLOGI("DEBUG(%s[%d]):", __FUNCTION__, __LINE__);
int ret = 0;
bool loop = false;
ExynosCameraFrame *newFrame = NULL;
camera2_shot_ext *shot_ext = NULL;
ExynosCameraBuffer fliteReprocessingBuffer;
ExynosCameraBuffer ispReprocessingBuffer;
int pipeId = 0;
int bufPipeId = 0;
bool isSrc = false;
int retryCount = 3;
if (m_hdrEnabled)
retryCount = 15;
if (m_parameters->isOwnScc(getCameraIdInternal()) == true) {
bufPipeId = PIPE_SCC;
} else {
bufPipeId = PIPE_ISPC;
}
if (m_parameters->is3aaIspOtf() == true) {
pipeId = PIPE_3AA;
} else {
pipeId = PIPE_ISP;
}
int postProcessQSize = m_postPictureQ->getSizeOfProcessQ();
if (postProcessQSize > 2) {
CLOGW("DEBUG(%s[%d]): post picture is delayed(stacked %d frames), skip", __FUNCTION__, __LINE__, postProcessQSize);
usleep(WAITING_TIME);
goto CLEAN;
}
newFrame = m_sccCaptureSelector->selectFrames(m_reprocessingCounter.getCount(), pipeId, isSrc, retryCount, m_pictureFrameFactory->getNodeType(bufPipeId));
if (newFrame == NULL) {
CLOGE("ERR(%s[%d]):newFrame is NULL", __FUNCTION__, __LINE__);
goto CLEAN;
}
newFrame->frameLock();
CLOGI("DEBUG(%s[%d]):Frame Count (%d)", __FUNCTION__, __LINE__, newFrame->getFrameCount());
#ifdef BOARD_CAMERA_USES_DUAL_CAMERA
// update for capture meta data.
if (m_parameters->isFusionEnabled() == true) {
struct camera2_shot_ext temp_shot_ext;
newFrame->getMetaData(&temp_shot_ext);
if (m_parameters->setFusionInfo(&temp_shot_ext) != NO_ERROR) {
CLOGE("DEBUG(%s[%d]):m_parameters->setFusionInfo() fail", __FUNCTION__, __LINE__);
}
}
#endif
m_postProcessList.push_back(newFrame);
if ((m_parameters->getHighResolutionCallbackMode() == true) &&
(m_highResolutionCallbackRunning == true)) {
m_highResolutionCallbackQ->pushProcessQ(&newFrame);
} else {
m_dstSccReprocessingQ->pushProcessQ(&newFrame);
}
m_reprocessingCounter.decCount();
CLOGI("INFO(%s[%d]):prePicture complete, remaining count(%d)", __FUNCTION__, __LINE__, m_reprocessingCounter.getCount());
if (m_hdrEnabled) {
ExynosCameraActivitySpecialCapture *m_sCaptureMgr;
m_sCaptureMgr = m_exynosCameraActivityControl->getSpecialCaptureMgr();
if (m_reprocessingCounter.getCount() == 0)
m_sCaptureMgr->setCaptureStep(ExynosCameraActivitySpecialCapture::SCAPTURE_STEP_OFF);
}
if ((m_parameters->getHighResolutionCallbackMode() == true) &&
(m_highResolutionCallbackRunning == true))
loop = true;
if (m_reprocessingCounter.getCount() > 0) {
loop = true;
}
*pIsProcessed = true;
return loop;
CLEAN:
if (m_hdrEnabled) {
ExynosCameraActivitySpecialCapture *m_sCaptureMgr;
m_sCaptureMgr = m_exynosCameraActivityControl->getSpecialCaptureMgr();
if (m_reprocessingCounter.getCount() == 0)
m_sCaptureMgr->setCaptureStep(ExynosCameraActivitySpecialCapture::SCAPTURE_STEP_OFF);
}
if (m_reprocessingCounter.getCount() > 0)
loop = true;
CLOGI("INFO(%s[%d]): prePicture fail, remaining count(%d)", __FUNCTION__, __LINE__, m_reprocessingCounter.getCount());
*pIsProcessed = false; // Notify failure
return loop;
}
status_t ExynosCamera::m_getAvailableRecordingCallbackHeapIndex(int *index)
{
if (m_recordingBufferCount <= 0 || m_recordingBufferCount > MAX_BUFFERS) {
CLOGE("ERR(%s[%d]):Invalid recordingBufferCount %d",
__FUNCTION__, __LINE__,
m_recordingBufferCount);
return INVALID_OPERATION;
} else if (m_recordingCallbackHeap == NULL) {
CLOGE("ERR(%s[%d]):RecordingCallbackHeap is NULL",
__FUNCTION__, __LINE__);
return INVALID_OPERATION;
}
Mutex::Autolock aLock(m_recordingCallbackHeapAvailableLock);
for (int i = 0; i < m_recordingBufferCount; i++) {
if (m_recordingCallbackHeapAvailable[i] == true) {
CLOGV("DEBUG(%s[%d]):Found recordingCallbackHeapIndex %d",
__FUNCTION__, __LINE__, i);
*index = i;
m_recordingCallbackHeapAvailable[i] = false;
return NO_ERROR;
}
}
CLOGW("WARN(%s[%d]):There is no available recordingCallbackHeapIndex",
__FUNCTION__, __LINE__);
return INVALID_OPERATION;
}
status_t ExynosCamera::m_releaseRecordingCallbackHeap(struct VideoNativeHandleMetadata *addr)
{
struct VideoNativeHandleMetadata *baseAddr = NULL;
int recordingCallbackHeapIndex = -1;
if (addr == NULL) {
CLOGE("ERR(%s[%d]):Addr is NULL",
__FUNCTION__, __LINE__);
return BAD_VALUE;
} else if (m_recordingCallbackHeap == NULL) {
CLOGE("ERR(%s[%d]):RecordingCallbackHeap is NULL",
__FUNCTION__, __LINE__);
return INVALID_OPERATION;
}
/* Calculate the recordingCallbackHeap index base on address offest. */
baseAddr = (struct VideoNativeHandleMetadata *) m_recordingCallbackHeap->data;
recordingCallbackHeapIndex = (int) (addr - baseAddr);
Mutex::Autolock aLock(m_recordingCallbackHeapAvailableLock);
if (recordingCallbackHeapIndex < 0 || recordingCallbackHeapIndex >= m_recordingBufferCount) {
CLOGE("ERR(%s[%d]):Invalid index %d. base %p addr %p offset %d",
__FUNCTION__, __LINE__,
recordingCallbackHeapIndex,
baseAddr,
addr,
(int) (addr - baseAddr));
return INVALID_OPERATION;
} else if (m_recordingCallbackHeapAvailable[recordingCallbackHeapIndex] == true) {
CLOGW("WARN(%s[%d]):Already available index %d. base %p addr %p offset %d",
__FUNCTION__, __LINE__,
recordingCallbackHeapIndex,
baseAddr,
addr,
(int) (addr - baseAddr));
}
CLOGV("DEBUG(%s[%d]):Release recordingCallbackHeapIndex %d.",
__FUNCTION__, __LINE__, recordingCallbackHeapIndex);
m_recordingCallbackHeapAvailable[recordingCallbackHeapIndex] = true;
return NO_ERROR;
}
status_t ExynosCamera::m_releaseRecordingBuffer(int bufIndex)
{
status_t ret = NO_ERROR;
if (bufIndex < 0 || bufIndex >= (int)m_recordingBufferCount) {
CLOGE("ERR(%s):Out of Index! (Max: %d, Index: %d)", __FUNCTION__, m_recordingBufferCount, bufIndex);
ret = INVALID_OPERATION;
goto func_exit;
}
ret = m_putBuffers(m_recordingBufferMgr, bufIndex);
if (ret < 0) {
CLOGE("ERR(%s[%d]):put Buffer fail", __FUNCTION__, __LINE__);
}
func_exit:
return ret;
}
status_t ExynosCamera::m_calcPreviewGSCRect(ExynosRect *srcRect, ExynosRect *dstRect)
{
return m_parameters->calcPreviewGSCRect(srcRect, dstRect);
}
status_t ExynosCamera::m_calcHighResolutionPreviewGSCRect(ExynosRect *srcRect, ExynosRect *dstRect)
{
return m_parameters->calcHighResolutionPreviewGSCRect(srcRect, dstRect);
}
status_t ExynosCamera::m_calcRecordingGSCRect(ExynosRect *srcRect, ExynosRect *dstRect)
{
return m_parameters->calcRecordingGSCRect(srcRect, dstRect);
}
status_t ExynosCamera::m_calcPictureRect(ExynosRect *srcRect, ExynosRect *dstRect)
{
return m_parameters->calcPictureRect(srcRect, dstRect);
}
status_t ExynosCamera::m_calcPictureRect(int originW, int originH, ExynosRect *srcRect, ExynosRect *dstRect)
{
return m_parameters->calcPictureRect(originW, originH, srcRect, dstRect);
}
status_t ExynosCamera::m_searchFrameFromList(List<ExynosCameraFrame *> *list, uint32_t frameCount, ExynosCameraFrame **frame)
{
Mutex::Autolock lock(m_searchframeLock);
int ret = 0;
ExynosCameraFrame *curFrame = NULL;
List<ExynosCameraFrame *>::iterator r;
if (list->empty()) {
CLOGD("DEBUG(%s[%d]):list is empty", __FUNCTION__, __LINE__);
return NO_ERROR;
}
r = list->begin()++;
do {
curFrame = *r;
if (curFrame == NULL) {
CLOGE("ERR(%s):curFrame is empty", __FUNCTION__);
return INVALID_OPERATION;
}
if (frameCount == curFrame->getFrameCount()) {
CLOGV("DEBUG(%s):frame count match: expected(%d)", __FUNCTION__, frameCount);
*frame = curFrame;
return NO_ERROR;
}
r++;
} while (r != list->end());
CLOGV("DEBUG(%s[%d]):Cannot find match frame, frameCount(%d)", __FUNCTION__, __LINE__, frameCount);
return NO_ERROR;
}
status_t ExynosCamera::m_removeFrameFromList(List<ExynosCameraFrame *> *list, ExynosCameraFrame *frame)
{
Mutex::Autolock lock(m_searchframeLock);
int ret = 0;
ExynosCameraFrame *curFrame = NULL;
int frameCount = 0;
int curFrameCount = 0;
List<ExynosCameraFrame *>::iterator r;
if (frame == NULL) {
CLOGE("ERR(%s):frame is NULL", __FUNCTION__);
return BAD_VALUE;
}
if (list->empty()) {
CLOGD("DEBUG(%s):list is empty", __FUNCTION__);
return NO_ERROR;
}
frameCount = frame->getFrameCount();
r = list->begin()++;
do {
curFrame = *r;
if (curFrame == NULL) {
CLOGE("ERR(%s):curFrame is empty", __FUNCTION__);
return INVALID_OPERATION;
}
curFrameCount = curFrame->getFrameCount();
if (frameCount == curFrameCount) {
CLOGV("DEBUG(%s):frame count match: expected(%d), current(%d)", __FUNCTION__, frameCount, curFrameCount);
list->erase(r);
return NO_ERROR;
}
CLOGW("WARN(%s):frame count mismatch: expected(%d), current(%d)", __FUNCTION__, frameCount, curFrameCount);
#if 0
curFrame->printEntity();
#else
curFrame->printNotDoneEntity();
#endif
r++;
} while (r != list->end());
CLOGE("ERR(%s):Cannot find match frame!!!", __FUNCTION__);
return INVALID_OPERATION;
}
status_t ExynosCamera::m_deleteFrame(ExynosCameraFrame **frame)
{
status_t ret = NO_ERROR;
/* put lock using this frame */
Mutex::Autolock lock(m_searchframeLock);
if (*frame == NULL) {
CLOGE("ERR(%s[%d]):frame == NULL. so, fail", __FUNCTION__, __LINE__);
return BAD_VALUE;
}
if ((*frame)->getFrameLockState() == false) {
if ((*frame)->isComplete() == true) {
CLOGD("DEBUG(%s[%d]): Reprocessing frame delete(%d)", __FUNCTION__, __LINE__, (*frame)->getFrameCount());
(*frame)->decRef();
m_frameMgr->deleteFrame(*frame);
}
}
return NO_ERROR;
}
status_t ExynosCamera::m_clearList(List<ExynosCameraFrame *> *list)
{
Mutex::Autolock lock(m_searchframeLock);
int ret = 0;
ExynosCameraFrame *curFrame = NULL;
List<ExynosCameraFrame *>::iterator r;
CLOGD("DEBUG(%s):remaining frame(%zu), we remove them all", __FUNCTION__, list->size());
while (!list->empty()) {
r = list->begin()++;
curFrame = *r;
if (curFrame != NULL) {
CLOGV("DEBUG(%s):remove frame count %d", __FUNCTION__, curFrame->getFrameCount() );
curFrame->decRef();
m_frameMgr->deleteFrame(curFrame);
curFrame = NULL;
}
list->erase(r);
}
CLOGD("DEBUG(%s):EXIT ", __FUNCTION__);
return NO_ERROR;
}
status_t ExynosCamera::m_clearList(frame_queue_t *queue)
{
Mutex::Autolock lock(m_searchframeLock);
int ret = 0;
ExynosCameraFrame *curFrame = NULL;
CLOGD("DEBUG(%s):remaining frame(%d), we remove them all", __FUNCTION__, queue->getSizeOfProcessQ());
while (0 < queue->getSizeOfProcessQ()) {
queue->popProcessQ(&curFrame);
if (curFrame != NULL) {
CLOGV("DEBUG(%s):remove frame count %d", __FUNCTION__, curFrame->getFrameCount() );
curFrame->decRef();
m_frameMgr->deleteFrame(curFrame);
curFrame = NULL;
}
}
CLOGD("DEBUG(%s):EXIT ", __FUNCTION__);
return NO_ERROR;
}
status_t ExynosCamera::m_clearFrameQ(frame_queue_t *frameQ, uint32_t pipeId, uint32_t direction) {
ExynosCameraFrame *newFrame = NULL;
ExynosCameraFrameEntity *entity = NULL;
ExynosCameraBuffer deleteSccBuffer;
ExynosCameraBufferManager *bufferMgr = NULL;
int ret = NO_ERROR;
if (frameQ == NULL) {
CLOGE("ERR(%s[%d]):frameQ is NULL.", __FUNCTION__, __LINE__);
return INVALID_OPERATION;
}
CLOGI("INFO(%s[%d]): IN... frameQSize(%d)", __FUNCTION__, __LINE__, frameQ->getSizeOfProcessQ());
while (0 < frameQ->getSizeOfProcessQ()) {
ret = frameQ->popProcessQ(&newFrame);
if (ret < 0) {
CLOGE("ERR(%s[%d]):wait and pop fail, ret(%d)", __FUNCTION__, __LINE__, ret);
continue;
}
if (newFrame == NULL) {
CLOGE("ERR(%s[%d]):newFrame is NULL", __FUNCTION__, __LINE__);
ret = INVALID_OPERATION;
continue;
}
if (direction == SRC_BUFFER_DIRECTION) {
ret = newFrame->getSrcBuffer(pipeId, &deleteSccBuffer);
} else {
if(m_previewFrameFactory == NULL) {
return INVALID_OPERATION;
}
ret = newFrame->getDstBuffer(pipeId, &deleteSccBuffer, m_previewFrameFactory->getNodeType(pipeId));
}
if (ret < 0) {
CLOGE("ERR(%s[%d]):getSrcBuffer fail, pipeId(%d), ret(%d)", __FUNCTION__, __LINE__, pipeId, ret);
continue;
}
ret = m_getBufferManager(pipeId, &bufferMgr, direction);
if (ret < 0)
CLOGE("ERR(%s[%d]):getBufferManager(SRC) fail, pipeId(%d), ret(%d)", __FUNCTION__, __LINE__, pipeId, ret);
/* put SCC buffer */
CLOGD("DEBUG(%s)(%d):m_putBuffer by clearjpegthread(dstSccRe), index(%d)", __FUNCTION__, __LINE__, deleteSccBuffer.index);
ret = m_putBuffers(bufferMgr, deleteSccBuffer.index);
if (ret < 0)
CLOGE("ERR(%s[%d]):bufferMgr->putBuffers() fail, pipeId(%d), ret(%d)", __FUNCTION__, __LINE__, pipeId, ret);
}
return ret;
}
status_t ExynosCamera::m_printFrameList(List<ExynosCameraFrame *> *list)
{
int ret = 0;
ExynosCameraFrame *curFrame = NULL;
List<ExynosCameraFrame *>::iterator r;
CLOGD("++++++++++++++++++++++++++++++++++++++++++++++++++++++++++");
CLOGD("\t remaining frame count(%zu)", list->size());
r = list->begin()++;
do {
curFrame = *r;
if (curFrame != NULL) {
CLOGI("\t hal frame count %d", curFrame->getFrameCount() );
curFrame->printEntity();
}
r++;
} while (r != list->end());
CLOGD("----------------------------------------------------------------------------");
return NO_ERROR;
}
status_t ExynosCamera::m_createIonAllocator(ExynosCameraIonAllocator **allocator)
{
status_t ret = NO_ERROR;
int retry = 0;
do {
retry++;
CLOGI("INFO(%s[%d]):try(%d) to create IonAllocator", __FUNCTION__, __LINE__, retry);
*allocator = new ExynosCameraIonAllocator();
ret = (*allocator)->init(false);
if (ret < 0)
CLOGE("ERR(%s[%d]):create IonAllocator fail (retryCount=%d)", __FUNCTION__, __LINE__, retry);
else {
CLOGD("DEBUG(%s[%d]):m_createIonAllocator success (allocator=%p)", __FUNCTION__, __LINE__, *allocator);
break;
}
} while (ret < 0 && retry < 3);
if (ret < 0 && retry >=3) {
CLOGE("ERR(%s[%d]):create IonAllocator fail (retryCount=%d)", __FUNCTION__, __LINE__, retry);
ret = INVALID_OPERATION;
}
return ret;
}
status_t ExynosCamera::m_createInternalBufferManager(ExynosCameraBufferManager **bufferManager, const char *name)
{
return m_createBufferManager(bufferManager, name, BUFFER_MANAGER_ION_TYPE);
}
status_t ExynosCamera::m_createBufferManager(
ExynosCameraBufferManager **bufferManager,
const char *name,
buffer_manager_type type)
{
status_t ret = NO_ERROR;
if (m_ionAllocator == NULL) {
ret = m_createIonAllocator(&m_ionAllocator);
if (ret < 0)
CLOGE("ERR(%s[%d]):m_createIonAllocator fail", __FUNCTION__, __LINE__);
else
CLOGD("DEBUG(%s[%d]):m_createIonAllocator success", __FUNCTION__, __LINE__);
}
*bufferManager = ExynosCameraBufferManager::createBufferManager(type);
(*bufferManager)->create(name, m_cameraId, m_ionAllocator);
CLOGV("DEBUG(%s):BufferManager(%s) created", __FUNCTION__, name);
return ret;
}
status_t ExynosCamera::m_checkThreadState(int *threadState, int *countRenew)
{
int ret = NO_ERROR;
if ((*threadState == ERROR_POLLING_DETECTED) || (*countRenew > ERROR_DQ_BLOCKED_COUNT)) {
CLOGW("WRN(%s[%d]:SCP DQ Timeout! State:[%d], Duration:%d msec", __FUNCTION__, __LINE__, *threadState, (*countRenew)*(MONITOR_THREAD_INTERVAL/1000));
ret = false;
} else {
CLOGV("[%s] (%d) (%d)", __FUNCTION__, __LINE__, *threadState);
ret = NO_ERROR;
}
return ret;
}
status_t ExynosCamera::m_checkThreadInterval(uint32_t pipeId, uint32_t pipeInterval, int *threadState)
{
uint64_t *threadInterval;
int ret = NO_ERROR;
m_previewFrameFactory->getThreadInterval(&threadInterval, pipeId);
if (*threadInterval > pipeInterval) {
CLOGW("WRN(%s[%d]:Pipe(%d) Thread Interval [%lld msec], State:[%d]", __FUNCTION__, __LINE__, pipeId, (*threadInterval)/1000, *threadState);
ret = false;
} else {
CLOGV("Thread IntervalTime [%lld]", *threadInterval);
CLOGV("Thread Renew state [%d]", *threadState);
ret = NO_ERROR;
}
return ret;
}
#ifdef MONITOR_LOG_SYNC
uint32_t ExynosCamera::m_getSyncLogId(void)
{
return ++cameraSyncLogId;
}
#endif
void ExynosCamera::m_dump(void)
{
CLOGI("INFO(%s[%d]):", __FUNCTION__, __LINE__);
m_printExynosCameraInfo(__FUNCTION__);
if (m_previewFrameFactory != NULL)
m_previewFrameFactory->dump();
if (m_bayerBufferMgr != NULL)
m_bayerBufferMgr->dump();
#ifdef DEBUG_RAWDUMP
if (m_parameters->getUsePureBayerReprocessing() == false) {
if (m_fliteBufferMgr != NULL)
m_fliteBufferMgr->dump();
}
#endif
if (m_3aaBufferMgr != NULL)
m_3aaBufferMgr->dump();
if (m_ispBufferMgr != NULL)
m_ispBufferMgr->dump();
if (m_hwDisBufferMgr != NULL)
m_hwDisBufferMgr->dump();
if (m_scpBufferMgr != NULL)
m_scpBufferMgr->dump();
#ifdef BOARD_CAMERA_USES_DUAL_CAMERA
if (m_fusionBufferMgr != NULL)
m_fusionBufferMgr->dump();
#endif
if (m_ispReprocessingBufferMgr != NULL)
m_ispReprocessingBufferMgr->dump();
if (m_sccReprocessingBufferMgr != NULL)
m_sccReprocessingBufferMgr->dump();
if (m_thumbnailBufferMgr != NULL)
m_thumbnailBufferMgr->dump();
if (m_sccBufferMgr != NULL)
m_sccBufferMgr->dump();
if (m_gscBufferMgr != NULL)
m_gscBufferMgr->dump();
m_dumpVendor();
return;
}
uint32_t ExynosCamera::m_getBayerPipeId(void)
{
uint32_t pipeId = 0;
if (m_parameters->getUsePureBayerReprocessing() == true) {
pipeId = PIPE_FLITE;
} else {
pipeId = PIPE_3AA;
}
return pipeId;
}
void ExynosCamera::m_debugFpsCheck(__unused uint32_t pipeId)
{
#ifdef FPS_CHECK
uint32_t id = pipeId % DEBUG_MAX_PIPE_NUM;
m_debugFpsCount[id]++;
if (m_debugFpsCount[id] == 1) {
m_debugFpsTimer[id].start();
}
if (m_debugFpsCount[id] == 31) {
m_debugFpsTimer[id].stop();
long long durationTime = m_debugFpsTimer[id].durationMsecs();
CLOGI("INFO(%s[%d]): FPS_CHECK(id:%d), duration %lld / 30 = %lld ms. %lld fps",
__FUNCTION__, __LINE__, pipeId, durationTime, durationTime / 30, 1000 / (durationTime / 30));
m_debugFpsCount[id] = 0;
}
#endif
}
status_t ExynosCamera::m_convertingStreamToShotExt(ExynosCameraBuffer *buffer, struct camera2_node_output *outputInfo)
{
/* TODO: HACK: Will be removed, this is driver's job */
status_t ret = NO_ERROR;
int bayerFrameCount = 0;
camera2_shot_ext *shot_ext = NULL;
camera2_stream *shot_stream = NULL;
shot_stream = (struct camera2_stream *)buffer->addr[buffer->planeCount-1];
bayerFrameCount = shot_stream->fcount;
outputInfo->cropRegion[0] = shot_stream->output_crop_region[0];
outputInfo->cropRegion[1] = shot_stream->output_crop_region[1];
outputInfo->cropRegion[2] = shot_stream->output_crop_region[2];
outputInfo->cropRegion[3] = shot_stream->output_crop_region[3];
memset(buffer->addr[buffer->planeCount-1], 0x0, sizeof(struct camera2_shot_ext));
shot_ext = (struct camera2_shot_ext *)buffer->addr[buffer->planeCount-1];
shot_ext->shot.dm.request.frameCount = bayerFrameCount;
return ret;
}
status_t ExynosCamera::m_checkBufferAvailable(uint32_t pipeId, ExynosCameraBufferManager *bufferMgr)
{
status_t ret = TIMED_OUT;
int retry = 0;
do {
ret = -1;
retry++;
if (bufferMgr->getNumOfAvailableBuffer() > 0) {
ret = OK;
} else {
/* wait available ISP buffer */
usleep(WAITING_TIME);
}
if (retry % 10 == 0)
CLOGW("WRAN(%s[%d]):retry(%d) setupEntity for pipeId(%d)", __FUNCTION__, __LINE__, retry, pipeId);
} while(ret < 0 && retry < (TOTAL_WAITING_TIME/WAITING_TIME) && m_stopBurstShot == false);
return ret;
}
status_t ExynosCamera::m_boostDynamicCapture(void)
{
status_t ret = NO_ERROR;
#if 0 /* TODO: need to implementation for bayer */
uint32_t pipeId = (m_parameters->isOwnScc(getCameraIdInternal()) == true) ? PIPE_SCC : PIPE_ISPC;
uint32_t size = m_processList.size();
ExynosCameraFrame *curFrame = NULL;
List<ExynosCameraFrame *>::iterator r;
camera2_node_group node_group_info_isp;
if (m_processList.empty()) {
CLOGD("DEBUG(%s[%d]):m_processList is empty", __FUNCTION__, __LINE__);
return NO_ERROR;
}
CLOGD("DEBUG(%s[%d]):m_processList size(%d)", __FUNCTION__, __LINE__, m_processList.size());
r = m_processList.end();
for (unsigned int i = 0; i < 3; i++) {
r--;
if (r == m_processList.begin())
break;
}
curFrame = *r;
if (curFrame == NULL) {
CLOGE("ERR(%s):curFrame is empty", __FUNCTION__);
return INVALID_OPERATION;
}
if (curFrame->getRequest(pipeId) == true) {
CLOGD("DEBUG(%s[%d]): Boosting dynamic capture is not need", __FUNCTION__, __LINE__);
return NO_ERROR;
}
CLOGI("INFO(%s[%d]): boosting dynamic capture (frameCount: %d)", __FUNCTION__, __LINE__, curFrame->getFrameCount());
/* For ISP */
curFrame->getNodeGroupInfo(&node_group_info_isp, PERFRAME_INFO_ISP);
m_updateBoostDynamicCaptureSize(&node_group_info_isp);
curFrame->storeNodeGroupInfo(&node_group_info_isp, PERFRAME_INFO_ISP);
curFrame->setRequest(pipeId, true);
curFrame->setNumRequestPipe(curFrame->getNumRequestPipe() + 1);
ret = curFrame->setEntityState(pipeId, ENTITY_STATE_REWORK);
if (ret < 0) {
CLOGE("ERR(%s[%d]):setEntityState fail, pipeId(%d), state(%d), ret(%d)",
__FUNCTION__, __LINE__, pipeId, ENTITY_STATE_REWORK, ret);
return ret;
}
m_previewFrameFactory->pushFrameToPipe(&curFrame, pipeId);
m_dynamicSccCount++;
CLOGV("DEBUG(%s[%d]): dynamicSccCount inc(%d) frameCount(%d)", __FUNCTION__, __LINE__, m_dynamicSccCount, curFrame->getFrameCount());
#endif
return ret;
}
bool ExynosCamera::m_checkCameraSavingPath(char *dir, char* srcPath, char *dstPath, int dstSize)
{
int ret = false;
int funcRet = false;
struct dirent **items = NULL;
struct stat fstat;
int item_count, i;
char ChangeDirPath[CAMERA_FILE_PATH_SIZE] = {'\0',};
memset(dstPath, 0, dstSize);
// Check access path
if (srcPath && dstSize > (int)strlen(srcPath)) {
strncpy(dstPath, srcPath, dstSize - 1);
} else {
CLOGW("WARN(%s[%d])Parameter srcPath is NULL. Change to Default Path", __FUNCTION__, __LINE__);
snprintf(dstPath, dstSize, "%s/DCIM/Camera/", dir);
}
if (access(dstPath, 0)==0) {
CLOGW("WARN(%s[%d]) success access dir = %s", __FUNCTION__, __LINE__, dstPath);
return true;
}
CLOGW("WARN(%s[%d]) can't find dir = %s", __FUNCTION__, __LINE__, m_burstSavePath);
// If directory cant't access, then search "DCIM/Camera" folder in current directory
int iitems = scandir(dir, &items, NULL, alphasort);
for (int i = 0; i < iitems; i++) {
// Search only dcim directory
funcRet = lstat(items[i]->d_name, &fstat);
if ((fstat.st_mode & S_IFDIR) == S_IFDIR) {
if (!strcmp(items[i]->d_name, ".") || !strcmp(items[i]->d_name, ".."))
continue;
if (strcasecmp(items[i]->d_name, "DCIM")==0) {
sprintf(ChangeDirPath, "%s/%s", dir, items[i]->d_name);
int jitems = scandir(ChangeDirPath, &items, NULL, alphasort);
for (int j = 0; j < jitems; j++) {
// Search only camera directory
funcRet = lstat(items[j]->d_name, &fstat);
if ((fstat.st_mode & S_IFDIR) == S_IFDIR) {
if (!strcmp(items[j]->d_name, ".") || !strcmp(items[j]->d_name, ".."))
continue;
if (strcasecmp(items[j]->d_name, "CAMERA")==0) {
sprintf(dstPath, "%s/%s/", ChangeDirPath, items[j]->d_name);
CLOGW("WARN(%s[%d]) change save path = %s", __FUNCTION__, __LINE__, dstPath);
j = jitems;
ret = true;
break;
}
}
}
i = iitems;
break;
}
}
}
if (items != NULL) {
free(items);
}
return ret;
}
bool ExynosCamera::m_FileSaveFunc(char *filePath, ExynosCameraBuffer *SaveBuf)
{
int fd = -1;
int nw, cnt = 0;
uint32_t written = 0;
char *data;
fd = open(filePath, O_RDWR | O_CREAT, 0664);
if (fd < 0) {
CLOGD("DEBUG(%s[%d]):failed to create file [%s]: %s",
__FUNCTION__, __LINE__, filePath, strerror(errno));
goto SAVE_ERR;
}
data = SaveBuf->addr[0];
CLOGD("DEBUG(%s[%d]):(%s)file write start)", __FUNCTION__, __LINE__, filePath);
while (written < SaveBuf->size[0]) {
nw = ::write(fd, (const char *)(data) + written, SaveBuf->size[0] - written);
if (nw < 0) {
CLOGD("DEBUG(%s[%d]):failed to write file [%s]: %s",
__FUNCTION__, __LINE__, filePath, strerror(errno));
break;
}
written += nw;
cnt++;
}
CLOGD("DEBUG(%s[%d]):(%s)file write end)", __FUNCTION__, __LINE__, filePath);
if (fd > 0)
::close(fd);
if (chmod(filePath, 0664) < 0) {
CLOGE("failed chmod [%s]", filePath);
}
if (chown(filePath, AID_MEDIA, AID_MEDIA_RW) < 0) {
CLOGE("failed chown [%s] user(%d), group(%d)", filePath, AID_MEDIA, AID_MEDIA_RW);
}
return true;
SAVE_ERR:
return false;
}
bool ExynosCamera::m_FileSaveFunc(char *filePath, char *saveBuf, unsigned int size)
{
int fd = -1;
int nw, cnt = 0;
uint32_t written = 0;
fd = open(filePath, O_RDWR | O_CREAT, 0664);
if (fd < 0) {
CLOGD("DEBUG(%s[%d]):failed to create file [%s]: %s",
__FUNCTION__, __LINE__, filePath, strerror(errno));
goto SAVE_ERR;
}
CLOGD("DEBUG(%s[%d]):(%s)file write start)", __FUNCTION__, __LINE__, filePath);
while (written < size) {
nw = ::write(fd, (const char *)(saveBuf) + written, size - written);
if (nw < 0) {
CLOGD("DEBUG(%s[%d]):failed to write file [%s]: %s",
__FUNCTION__, __LINE__, filePath, strerror(errno));
break;
}
written += nw;
cnt++;
}
CLOGD("DEBUG(%s[%d]):(%s)file write end)", __FUNCTION__, __LINE__, filePath);
if (fd > 0)
::close(fd);
if (chmod(filePath, 0664) < 0) {
CLOGE("failed chmod [%s]", filePath);
}
if (chown(filePath, AID_MEDIA, AID_MEDIA_RW) < 0) {
CLOGE("failed chown [%s] user(%d), group(%d)", filePath, AID_MEDIA, AID_MEDIA_RW);
}
return true;
SAVE_ERR:
return false;
}
void ExynosCamera::m_updateBoostDynamicCaptureSize(__unused camera2_node_group *node_group_info)
{
#if 0 /* TODO: need to implementation for bayer */
ExynosRect sensorSize;
ExynosRect bayerCropSize;
node_group_info->capture[PERFRAME_BACK_SCC_POS].request = 1;
m_parameters->getPreviewBayerCropSize(&sensorSize, &bayerCropSize);
node_group_info->leader.input.cropRegion[0] = bayerCropSize.x;
node_group_info->leader.input.cropRegion[1] = bayerCropSize.y;
node_group_info->leader.input.cropRegion[2] = bayerCropSize.w;
node_group_info->leader.input.cropRegion[3] = bayerCropSize.h;
node_group_info->leader.output.cropRegion[0] = 0;
node_group_info->leader.output.cropRegion[1] = 0;
node_group_info->leader.output.cropRegion[2] = node_group_info->leader.input.cropRegion[2];
node_group_info->leader.output.cropRegion[3] = node_group_info->leader.input.cropRegion[3];
/* Capture 0 : SCC - [scaling] */
node_group_info->capture[PERFRAME_BACK_SCC_POS].input.cropRegion[0] = node_group_info->leader.output.cropRegion[0];
node_group_info->capture[PERFRAME_BACK_SCC_POS].input.cropRegion[1] = node_group_info->leader.output.cropRegion[1];
node_group_info->capture[PERFRAME_BACK_SCC_POS].input.cropRegion[2] = node_group_info->leader.output.cropRegion[2];
node_group_info->capture[PERFRAME_BACK_SCC_POS].input.cropRegion[3] = node_group_info->leader.output.cropRegion[3];
node_group_info->capture[PERFRAME_BACK_SCC_POS].output.cropRegion[0] = node_group_info->capture[PERFRAME_BACK_SCC_POS].input.cropRegion[0];
node_group_info->capture[PERFRAME_BACK_SCC_POS].output.cropRegion[1] = node_group_info->capture[PERFRAME_BACK_SCC_POS].input.cropRegion[1];
node_group_info->capture[PERFRAME_BACK_SCC_POS].output.cropRegion[2] = node_group_info->capture[PERFRAME_BACK_SCC_POS].input.cropRegion[2];
node_group_info->capture[PERFRAME_BACK_SCC_POS].output.cropRegion[3] = node_group_info->capture[PERFRAME_BACK_SCC_POS].input.cropRegion[3];
/* Capture 1 : SCP - [scaling] */
node_group_info->capture[PERFRAME_BACK_SCP_POS].input.cropRegion[0] = node_group_info->leader.output.cropRegion[0];
node_group_info->capture[PERFRAME_BACK_SCP_POS].input.cropRegion[1] = node_group_info->leader.output.cropRegion[1];
node_group_info->capture[PERFRAME_BACK_SCP_POS].input.cropRegion[2] = node_group_info->leader.output.cropRegion[2];
node_group_info->capture[PERFRAME_BACK_SCP_POS].input.cropRegion[3] = node_group_info->leader.output.cropRegion[3];
#endif
return;
}
void ExynosCamera::m_checkFpsAndUpdatePipeWaitTime(void)
{
uint32_t curMinFps = 0;
uint32_t curMaxFps = 0;
frame_queue_t *inputFrameQ = NULL;
m_parameters->getPreviewFpsRange(&curMinFps, &curMaxFps);
if (m_curMinFps != curMinFps) {
CLOGD("DEBUG(%s[%d]):(%d)(%d)", __FUNCTION__, __LINE__, curMinFps, curMaxFps);
enum pipeline pipe = (m_parameters->isOwnScc(getCameraIdInternal()) == true) ? PIPE_SCC : PIPE_ISPC;
m_previewFrameFactory->getInputFrameQToPipe(&inputFrameQ, pipe);
/* 100ms * (30 / 15 fps) = 200ms */
/* 100ms * (30 / 30 fps) = 100ms */
/* 100ms * (30 / 10 fps) = 300ms */
if (inputFrameQ != NULL && curMinFps != 0)
inputFrameQ->setWaitTime(((100000000 / curMinFps) * 30));
}
m_curMinFps = curMinFps;
return;
}
void ExynosCamera::m_printExynosCameraInfo(const char *funcName)
{
int w = 0;
int h = 0;
ExynosRect srcRect, dstRect;
CLOGD("DEBUG(%s[%d]):===================================================", __FUNCTION__, __LINE__);
CLOGD("DEBUG(%s[%d]):============= ExynosCameraInfo call by %s", __FUNCTION__, __LINE__, funcName);
CLOGD("DEBUG(%s[%d]):===================================================", __FUNCTION__, __LINE__);
CLOGD("DEBUG(%s[%d]):============= Scenario ============================", __FUNCTION__, __LINE__);
CLOGD("DEBUG(%s[%d]):= getCameraId : %d", __FUNCTION__, __LINE__, m_parameters->getCameraId());
CLOGD("DEBUG(%s[%d]):= getDualMode : %d", __FUNCTION__, __LINE__, m_parameters->getDualMode());
CLOGD("DEBUG(%s[%d]):= getScalableSensorMode : %d", __FUNCTION__, __LINE__, m_parameters->getScalableSensorMode());
CLOGD("DEBUG(%s[%d]):= getRecordingHint : %d", __FUNCTION__, __LINE__, m_parameters->getRecordingHint());
CLOGD("DEBUG(%s[%d]):= getEffectRecordingHint : %d", __FUNCTION__, __LINE__, m_parameters->getEffectRecordingHint());
CLOGD("DEBUG(%s[%d]):= getDualRecordingHint : %d", __FUNCTION__, __LINE__, m_parameters->getDualRecordingHint());
CLOGD("DEBUG(%s[%d]):= getAdaptiveCSCRecording : %d", __FUNCTION__, __LINE__, m_parameters->getAdaptiveCSCRecording());
CLOGD("DEBUG(%s[%d]):= doCscRecording : %d", __FUNCTION__, __LINE__, m_parameters->doCscRecording());
CLOGD("DEBUG(%s[%d]):= needGSCForCapture : %d", __FUNCTION__, __LINE__, m_parameters->needGSCForCapture(getCameraIdInternal()));
CLOGD("DEBUG(%s[%d]):= getShotMode : %d", __FUNCTION__, __LINE__, m_parameters->getShotMode());
CLOGD("DEBUG(%s[%d]):= getTpuEnabledMode : %d", __FUNCTION__, __LINE__, m_parameters->getTpuEnabledMode());
CLOGD("DEBUG(%s[%d]):= getHWVdisMode : %d", __FUNCTION__, __LINE__, m_parameters->getHWVdisMode());
CLOGD("DEBUG(%s[%d]):= get3dnrMode : %d", __FUNCTION__, __LINE__, m_parameters->get3dnrMode());
CLOGD("DEBUG(%s[%d]):============= Internal setting ====================", __FUNCTION__, __LINE__);
CLOGD("DEBUG(%s[%d]):= isFlite3aaOtf : %d", __FUNCTION__, __LINE__, m_parameters->isFlite3aaOtf());
CLOGD("DEBUG(%s[%d]):= is3aaIspOtf : %d", __FUNCTION__, __LINE__, m_parameters->is3aaIspOtf());
CLOGD("DEBUG(%s[%d]):= isReprocessing : %d", __FUNCTION__, __LINE__, m_parameters->isReprocessing());
CLOGD("DEBUG(%s[%d]):= isReprocessing3aaIspOTF : %d", __FUNCTION__, __LINE__, m_parameters->isReprocessing3aaIspOTF());
CLOGD("DEBUG(%s[%d]):= getUsePureBayerReprocessing : %d", __FUNCTION__, __LINE__, m_parameters->getUsePureBayerReprocessing());
int reprocessingBayerMode = m_parameters->getReprocessingBayerMode();
switch(reprocessingBayerMode) {
case REPROCESSING_BAYER_MODE_NONE:
CLOGD("DEBUG(%s[%d]):= getReprocessingBayerMode : REPROCESSING_BAYER_MODE_NONE", __FUNCTION__, __LINE__);
break;
case REPROCESSING_BAYER_MODE_PURE_ALWAYS_ON:
CLOGD("DEBUG(%s[%d]):= getReprocessingBayerMode : REPROCESSING_BAYER_MODE_PURE_ALWAYS_ON", __FUNCTION__, __LINE__);
break;
case REPROCESSING_BAYER_MODE_DIRTY_ALWAYS_ON:
CLOGD("DEBUG(%s[%d]):= getReprocessingBayerMode : REPROCESSING_BAYER_MODE_DIRTY_ALWAYS_ON", __FUNCTION__, __LINE__);
break;
case REPROCESSING_BAYER_MODE_PURE_DYNAMIC:
CLOGD("DEBUG(%s[%d]):= getReprocessingBayerMode : REPROCESSING_BAYER_MODE_PURE_DYNAMIC", __FUNCTION__, __LINE__);
break;
case REPROCESSING_BAYER_MODE_DIRTY_DYNAMIC:
CLOGD("DEBUG(%s[%d]):= getReprocessingBayerMode : REPROCESSING_BAYER_MODE_DIRTY_DYNAMIC", __FUNCTION__, __LINE__);
break;
default:
CLOGD("DEBUG(%s[%d]):= getReprocessingBayerMode : unexpected mode %d", __FUNCTION__, __LINE__, reprocessingBayerMode);
break;
}
CLOGD("DEBUG(%s[%d]):= isSccCapture : %d", __FUNCTION__, __LINE__, m_parameters->isSccCapture());
#ifdef BOARD_CAMERA_USES_DUAL_CAMERA
CLOGD("DEBUG(%s[%d]):= getDualCameraMode : %d", __FUNCTION__, __LINE__, m_parameters->getDualCameraMode());
CLOGD("DEBUG(%s[%d]):= isFusionEnabled : %d", __FUNCTION__, __LINE__, m_parameters->isFusionEnabled());
#endif
CLOGD("DEBUG(%s[%d]):============= size setting =======================", __FUNCTION__, __LINE__);
m_parameters->getMaxSensorSize(&w, &h);
CLOGD("DEBUG(%s[%d]):= getMaxSensorSize : %d x %d", __FUNCTION__, __LINE__, w, h);
m_parameters->getHwSensorSize(&w, &h);
CLOGD("DEBUG(%s[%d]):= getHwSensorSize : %d x %d", __FUNCTION__, __LINE__, w, h);
m_parameters->getBnsSize(&w, &h);
CLOGD("DEBUG(%s[%d]):= getBnsSize : %d x %d", __FUNCTION__, __LINE__, w, h);
m_parameters->getPreviewBayerCropSize(&srcRect, &dstRect);
CLOGD("DEBUG(%s[%d]):= getPreviewBayerCropSize : (%d, %d, %d, %d) -> (%d, %d, %d, %d)", __FUNCTION__, __LINE__,
srcRect.x, srcRect.y, srcRect.w, srcRect.h,
dstRect.x, dstRect.y, dstRect.w, dstRect.h);
m_parameters->getPreviewBdsSize(&dstRect);
CLOGD("DEBUG(%s[%d]):= getPreviewBdsSize : (%d, %d, %d, %d)", __FUNCTION__, __LINE__,
dstRect.x, dstRect.y, dstRect.w, dstRect.h);
m_parameters->getHwPreviewSize(&w, &h);
CLOGD("DEBUG(%s[%d]):= getHwPreviewSize : %d x %d", __FUNCTION__, __LINE__, w, h);
#ifdef BOARD_CAMERA_USES_DUAL_CAMERA
if (m_parameters->isFusionEnabled() == true) {
ExynosRect fusionSrcRect;
ExynosRect fusionDstRect;
// we need to calculate with set by app.
m_parameters->getPreviewSize(&w, &h);
m_parameters->getFusionSize(w, h, &fusionSrcRect, &fusionDstRect);
CLOGD("DEBUG(%s[%d]):= getFusionSize : (%d, %d, %d, %d) -> (%d, %d, %d, %d)", __FUNCTION__, __LINE__,
fusionSrcRect.x, fusionSrcRect.y, fusionSrcRect.w, fusionSrcRect.h,
fusionDstRect.x, fusionDstRect.y, fusionDstRect.w, fusionDstRect.h);
}
#endif
m_parameters->getPreviewSize(&w, &h);
CLOGD("DEBUG(%s[%d]):= getPreviewSize : %d x %d", __FUNCTION__, __LINE__, w, h);
m_parameters->getPictureBayerCropSize(&srcRect, &dstRect);
CLOGD("DEBUG(%s[%d]):= getPictureBayerCropSize : (%d, %d, %d, %d) -> (%d, %d, %d, %d)", __FUNCTION__, __LINE__,
srcRect.x, srcRect.y, srcRect.w, srcRect.h,
dstRect.x, dstRect.y, dstRect.w, dstRect.h);
m_parameters->getPictureBdsSize(&dstRect);
CLOGD("DEBUG(%s[%d]):= getPictureBdsSize : (%d, %d, %d, %d)", __FUNCTION__, __LINE__,
dstRect.x, dstRect.y, dstRect.w, dstRect.h);
m_parameters->getHwPictureSize(&w, &h);
CLOGD("DEBUG(%s[%d]):= getHwPictureSize : %d x %d", __FUNCTION__, __LINE__, w, h);
m_parameters->getPictureSize(&w, &h);
CLOGD("DEBUG(%s[%d]):= getPictureSize : %d x %d", __FUNCTION__, __LINE__, w, h);
CLOGD("DEBUG(%s[%d]):===================================================", __FUNCTION__, __LINE__);
}
status_t ExynosCamera::m_putFrameBuffer(ExynosCameraFrame *frame, int pipeId, enum buffer_direction_type bufferDirectionType)
{
status_t ret = NO_ERROR;
ExynosCameraBuffer buffer;
ExynosCameraBufferManager *bufferMgr = NULL;
switch (bufferDirectionType) {
case SRC_BUFFER_DIRECTION:
ret = frame->getSrcBuffer(pipeId, &buffer);
if (ret != NO_ERROR) {
CLOGE("ERR(%s[%d]):getSrcBuffer fail, pipeId(%d), ret(%d)",
__FUNCTION__, __LINE__, pipeId, ret);
return ret;
}
break;
case DST_BUFFER_DIRECTION:
ret = frame->getDstBuffer(pipeId, &buffer);
if (ret != NO_ERROR) {
CLOGE("ERR(%s[%d]):getDstBuffer fail, pipeId(%d), ret(%d)",
__FUNCTION__, __LINE__, pipeId, ret);
return ret;
}
break;
default:
CLOGE("ERR(%s[%d]):invalid bufferDirectionType(%d). so fail", __FUNCTION__, __LINE__, bufferDirectionType);
return INVALID_OPERATION;
}
if (0 <= buffer.index) {
ret = m_getBufferManager(pipeId, &bufferMgr, bufferDirectionType);
if (ret != NO_ERROR) {
CLOGE("ERR(%s[%d]):m_getBufferManager(pipeId(%d), SRC_BUFFER_DIRECTION)", __FUNCTION__, __LINE__, pipeId);
return ret;
}
if (bufferMgr == m_scpBufferMgr) {
ret = bufferMgr->cancelBuffer(buffer.index);
if (ret != NO_ERROR) {
CLOGE("ERR(%s[%d]):cancelBuffer(%d) fail", __FUNCTION__, __LINE__, buffer.index);
return ret;
}
} else {
ret = m_putBuffers(bufferMgr, buffer.index);
if (ret != NO_ERROR) {
CLOGE("ERR(%s[%d]):m_putBuffers(%d) fail", __FUNCTION__, __LINE__, buffer.index);
return ret;
}
}
}
return ret;
}
#ifdef BOARD_CAMERA_USES_DUAL_CAMERA
status_t ExynosCamera::m_syncPreviewWithFusion(int pipeId, ExynosCameraFrame *frame)
{
#ifdef DEBUG
ExynosCameraAutoTimer autoTimer(__FUNCTION__);
#endif
status_t ret = NO_ERROR;
ExynosRect srcRect, dstRect;
ExynosCameraBuffer srcBuf;
ExynosCameraBuffer dstBuf;
ExynosCameraBufferManager *srcBufMgr = NULL;
ExynosCameraBufferManager *dstBufMgr = NULL;
int srcNodeIndex = -1;
int dstNodeIndex = -1;
int scpNodeIndex = -1;
entity_state_t state = ENTITY_STATE_FRAME_SKIP;
entity_buffer_state_t bufferState = ENTITY_BUFFER_STATE_NOREQ;
// src
srcNodeIndex = 0;
ret = m_getBufferManager(pipeId, &srcBufMgr, SRC_BUFFER_DIRECTION);
if (ret != NO_ERROR) {
CLOGE("ERR(%s[%d]):m_getBufferManager(pipeId(%d), SRC_BUFFER_DIRECTION)", __FUNCTION__, __LINE__, pipeId);
goto func_exit;
}
// dst
if ((m_parameters->getDualMode() == true) &&
(getCameraId() == CAMERA_ID_FRONT || getCameraId() == CAMERA_ID_BACK_1)) {
dstNodeIndex = 0;
} else {
/*
* fusion looking dstNodeIndex 0, not PIPE_MCSC0.
* so, just set dstNodeIndex = 0;
*/
//dstNodeIndex = m_previewFrameFactory->getNodeType(PIPE_MCSC0);
dstNodeIndex = 0;
}
ret = m_getBufferManager(pipeId, &dstBufMgr, DST_BUFFER_DIRECTION);
if (ret != NO_ERROR) {
CLOGE("ERR(%s[%d]):m_getBufferManager(pipeId(%d), DST_BUFFER_DIRECTION)", __FUNCTION__, __LINE__, pipeId);
goto func_exit;
}
// scp
scpNodeIndex = m_previewFrameFactory->getNodeType(PIPE_MCSC0);
ret = frame->getEntityState(pipeId, &state);
if (ret != NO_ERROR) {
CLOGE("ERR(%s[%d]):getEntityState(pipeId(%d)) fail, frame(%d)",
__FUNCTION__, __LINE__, pipeId, frame->getFrameCount());
ret = INVALID_OPERATION;
goto func_exit;
}
if(state == ENTITY_STATE_FRAME_SKIP) {
CLOGE("ERR(%s[%d]):state == ENTITY_STATE_FRAME_SKIP. so, pipeId(%d), state(%d) frame(%d)",
__FUNCTION__, __LINE__, pipeId, state, frame->getFrameCount());
ret = INVALID_OPERATION;
goto func_exit;
}
bufferState = ENTITY_BUFFER_STATE_NOREQ;
ret = frame->getSrcBufferState(pipeId, &bufferState);
if( ret < 0 || bufferState == ENTITY_BUFFER_STATE_ERROR) {
CLOGE("ERR(%s[%d]):getSrcBufferState fail, pipeId(%d), entityState(%d) frame(%d)",__FUNCTION__, __LINE__, pipeId, bufferState, frame->getFrameCount());
ret = INVALID_OPERATION;
goto func_exit;
}
bufferState = ENTITY_BUFFER_STATE_NOREQ;
ret = frame->getDstBufferState(pipeId, &bufferState);
if( ret < 0 || bufferState == ENTITY_BUFFER_STATE_ERROR) {
CLOGE("ERR(%s[%d]):getDstBufferState fail, pipeId(%d), entityState(%d) frame(%d)",__FUNCTION__, __LINE__, pipeId, bufferState, frame->getFrameCount());
ret = INVALID_OPERATION;
goto func_exit;
}
srcBuf.index = -1;
dstBuf.index = -1;
ret = frame->getSrcBuffer(pipeId, &srcBuf);
if (ret != NO_ERROR) {
CLOGE("ERR(%s[%d]):getSrcBuffer fail, pipeId(%d), ret(%d) frame(%d)",__FUNCTION__, __LINE__, pipeId, ret, frame->getFrameCount());
ret = INVALID_OPERATION;
goto func_exit;
}
ret = frame->getDstBuffer(pipeId, &dstBuf, dstNodeIndex);
if (ret != NO_ERROR) {
CLOGE("ERR(%s[%d]):getDstBuffer fail, pipeId(%d), ret(%d) frame(%d)",__FUNCTION__, __LINE__, pipeId, ret, frame->getFrameCount());
ret = INVALID_OPERATION;
goto func_exit;
}
if (dstBuf.addr[dstBuf.planeCount - 1] == NULL ||
srcBuf.addr[srcBuf.planeCount - 1] == NULL) {
android_printAssert(NULL, LOG_TAG, "ASSERT(%s[%d]):dstBuf.addr[%d](%p) or srcBuf.addr[%d](%p) weird, assert!!!!",
__FUNCTION__, __LINE__,
dstBuf.planeCount - 1, dstBuf.addr[dstBuf.planeCount - 1],
srcBuf.planeCount - 1, srcBuf.addr[srcBuf.planeCount - 1]);
}
/* copy metadata src to dst */
memcpy(dstBuf.addr[dstBuf.planeCount - 1], srcBuf.addr[srcBuf.planeCount - 1], sizeof(struct camera2_stream));
ret = m_putFrameBuffer(frame, pipeId, SRC_BUFFER_DIRECTION);
if (ret < 0) {
CLOGE("ERR(%s[%d]):m_putFrameBuffer(frame(%d), pipeId(%d), SRC_BUFFER_DIRECTION) fail",
__FUNCTION__, __LINE__, frame->getFrameCount(), pipeId);
ret = INVALID_OPERATION;
goto func_exit;
}
/*
* after fusion lib, frame's dst pos is 0 (because fusion looking srcPos 0, dstPos 0)
* so, after fusion lib, we will change the frame's dst pos as scpNodeIndex.
*/
ret = frame->setDstBufferState(pipeId, ENTITY_BUFFER_STATE_REQUESTED, scpNodeIndex);
if (ret != NO_ERROR) {
CLOGE("ERR(%s[%d]):setDstBufferState(pipeId(%d), ENTITY_BUFFER_STATE_REQUESTED, scpNodeIndex(%d)) fail frame(%d)",
__FUNCTION__, __LINE__, pipeId, scpNodeIndex, frame->getFrameCount());
ret = INVALID_OPERATION;
goto func_exit;
}
ret = frame->setDstBuffer(pipeId, dstBuf, scpNodeIndex);
if (ret != NO_ERROR) {
CLOGE("ERR(%s[%d]):setDstBuffer(pipeId(%d), dstBuf(%d), scpNodeIndex(%d)) fail frame(%d)",
__FUNCTION__, __LINE__, pipeId, dstBuf.index, scpNodeIndex, frame->getFrameCount());
ret = INVALID_OPERATION;
goto func_exit;
}
ret = frame->setDstBufferState(pipeId, ENTITY_BUFFER_STATE_COMPLETE, scpNodeIndex);
if (ret != NO_ERROR) {
CLOGE("ERR(%s[%d]):setDstBufferState fail, pipeId(%d), ret(%d) frame(%d)",
__FUNCTION__, __LINE__, pipeId, ret, frame->getFrameCount());
}
ret = frame->setDstBufferState(pipeId, ENTITY_BUFFER_STATE_COMPLETE);
if (ret != NO_ERROR) {
CLOGE("ERR(%s[%d]):setDstBufferState fail, pipeId(%d), ret(%d) frame(%d)",
__FUNCTION__, __LINE__, pipeId, ret, frame->getFrameCount());
}
CLOGV("DEBUG(%s[%d]): m_syncPreviewWithFusion done. frame(%d) timeStamp(%d), ret(%d) src(%d) dst(%d)",
__FUNCTION__, __LINE__, frame->getFrameCount(), (int)(ns2ms(frame->getTimeStamp())), ret, srcBuf.index, dstBuf.index);
return ret;
func_exit:
CLOGE("ERR(%s[%d]): sync with fusion failed. frame(%d) timeStamp(%d), ret(%d) src(%d) dst(%d)",
__FUNCTION__, __LINE__, frame->getFrameCount(), (int)(ns2ms(frame->getTimeStamp())), ret, srcBuf.index, dstBuf.index);
ret = m_putFrameBuffer(frame, pipeId, SRC_BUFFER_DIRECTION);
if (ret != NO_ERROR) {
CLOGE("ERR(%s[%d]):m_putFrameBuffer(frame(%d), pipeId(%d), SRC_BUFFER_DIRECTION) fail",
__FUNCTION__, __LINE__, frame->getFrameCount(), pipeId);
}
// if error, we will skip this frame.
ret = frame->setEntityState(pipeId, ENTITY_STATE_FRAME_SKIP);
if (ret < 0) {
CLOGE("ERR(%s[%d]):setEntityState(%d, ENTITY_STATE_FRAME_SKIP) fail", __FUNCTION__, __LINE__, pipeId);
}
/*
* when SKIP, after this function, buffer release is skipped also.
* so, we must release here.
*/
ret = m_putFrameBuffer(frame, pipeId, DST_BUFFER_DIRECTION);
if (ret != NO_ERROR) {
CLOGE("ERR(%s[%d]):m_putFrameBuffer(frame(%d), pipeId(%d), DST_BUFFER_DIRECTION) fail",
__FUNCTION__, __LINE__, frame->getFrameCount(), pipeId);
}
/*
* after fusion lib, frame's dst pos is 0 (because fusion looking srcPos 0, dstPos 0)
* so, after fusion lib, we will change the frame's dst pos as scpNodeIndex.
*/
ret = frame->setDstBufferState(pipeId, ENTITY_BUFFER_STATE_REQUESTED, scpNodeIndex);
if (ret != NO_ERROR) {
CLOGE("ERR(%s[%d]):setDstBufferState(pipeId(%d), ENTITY_BUFFER_STATE_REQUESTED, scpNodeIndex(%d)) fail frame(%d)",
__FUNCTION__, __LINE__, pipeId, scpNodeIndex, frame->getFrameCount());
ret = INVALID_OPERATION;
}
ret = frame->setDstBuffer(pipeId, dstBuf, scpNodeIndex);
if (ret != NO_ERROR) {
CLOGE("ERR(%s[%d]):setDstBuffer(pipeId(%d), dstBuf(%d), scpNodeIndex(%d)) fail frame(%d)",
__FUNCTION__, __LINE__, pipeId, dstBuf.index, scpNodeIndex, frame->getFrameCount());
ret = INVALID_OPERATION;
}
ret = frame->setDstBufferState(pipeId, ENTITY_BUFFER_STATE_ERROR, scpNodeIndex);
if (ret != NO_ERROR) {
CLOGE("ERR(%s[%d]):setDstBufferState fail, pipeId(%d), ret(%d) frame(%d)",
__FUNCTION__, __LINE__, pipeId, ret, frame->getFrameCount());
}
ret = frame->setDstBufferState(pipeId, ENTITY_BUFFER_STATE_ERROR);
if (ret != NO_ERROR) {
CLOGE("ERR(%s[%d]):setDstBufferState fail, pipeId(%d), ret(%d) frame(%d)",
__FUNCTION__, __LINE__, pipeId, ret, frame->getFrameCount());
}
return INVALID_OPERATION;
}
#endif
}; /* namespace android */