| /* |
| ** |
| ** Copyright 2014, 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" |
| |
| #ifdef BURST_CAPTURE |
| #include <sys/resource.h> |
| #include <private/android_filesystem_config.h> |
| |
| #include <ctype.h> |
| #include <dirent.h> |
| #endif |
| |
| #ifdef TOUCH_AE |
| #define AE_RESULT 0xF351 |
| #endif |
| |
| namespace android { |
| |
| /* vision */ |
| #ifdef VISION_DUMP |
| int dumpIndex = 0; |
| #endif |
| |
| #ifdef MONITOR_LOG_SYNC |
| uint32_t ExynosCamera::cameraSyncLogId = 0; |
| #endif |
| |
| ExynosCamera::ExynosCamera(int cameraId, camera_device_t *dev) |
| { |
| ExynosCameraActivityUCTL *uctlMgr = NULL; |
| |
| BUILD_DATE(); |
| |
| checkAndroidVersion(); |
| |
| m_cameraId = cameraId; |
| memset(m_name, 0x00, sizeof(m_name)); |
| |
| m_exynosCameraParameters = new ExynosCameraParameters(m_cameraId); |
| CLOGD("DEBUG(%s):Parameters(Id=%d) created", __FUNCTION__, m_cameraId); |
| |
| m_exynosCameraParameters->setHalVersion(IS_HAL_VER_1_0); |
| |
| m_exynosCameraActivityControl = m_exynosCameraParameters->getActivityControl(); |
| |
| m_previewFrameFactory = NULL; |
| m_reprocessingFrameFactory = NULL; |
| /* vision */ |
| m_visionFrameFactory= NULL; |
| |
| m_ionAllocator = NULL; |
| m_grAllocator = NULL; |
| m_mhbAllocator = NULL; |
| |
| m_frameMgr = NULL; |
| |
| m_createInternalBufferManager(&m_bayerBufferMgr, "BAYER_BUF"); |
| m_createInternalBufferManager(&m_3aaBufferMgr, "3A1_BUF"); |
| m_createInternalBufferManager(&m_ispBufferMgr, "ISP_BUF"); |
| m_createInternalBufferManager(&m_hwDisBufferMgr, "HW_DIS_BUF"); |
| |
| /* reprocessing Buffer */ |
| m_createInternalBufferManager(&m_ispReprocessingBufferMgr, "ISP_RE_BUF"); |
| m_createInternalBufferManager(&m_sccReprocessingBufferMgr, "SCC_RE_BUF"); |
| |
| m_createInternalBufferManager(&m_sccBufferMgr, "SCC_BUF"); |
| m_createInternalBufferManager(&m_gscBufferMgr, "GSC_BUF"); |
| m_createInternalBufferManager(&m_jpegBufferMgr, "JPEG_BUF"); |
| |
| /* preview Buffer */ |
| m_scpBufferMgr = NULL; |
| m_createInternalBufferManager(&m_previewCallbackBufferMgr, "PREVIEW_CB_BUF"); |
| m_createInternalBufferManager(&m_highResolutionCallbackBufferMgr, "HIGH_RESOLUTION_CB_BUF"); |
| |
| /* recording Buffer */ |
| m_recordingCallbackHeap = NULL; |
| m_createInternalBufferManager(&m_recordingBufferMgr, "REC_BUF"); |
| |
| m_createThreads(); |
| |
| m_pipeFrameDoneQ = new frame_queue_t; |
| dstIspReprocessingQ = new frame_queue_t; |
| dstSccReprocessingQ = new frame_queue_t; |
| dstGscReprocessingQ = new frame_queue_t; |
| m_zoomPreviwWithCscQ = new frame_queue_t; |
| |
| dstJpegReprocessingQ = new frame_queue_t; |
| /* vision */ |
| m_pipeFrameVisionDoneQ = new frame_queue_t; |
| |
| m_frameFactoryQ = new framefactory_queue_t; |
| m_facedetectQ = new frame_queue_t; |
| m_facedetectQ->setWaitTime(500000000); |
| |
| m_previewQ = new frame_queue_t; |
| m_previewQ->setWaitTime(500000000); |
| m_previewCallbackGscFrameDoneQ = new frame_queue_t; |
| m_recordingQ = new frame_queue_t; |
| m_recordingQ->setWaitTime(500000000); |
| m_postPictureQ = new frame_queue_t(m_postPictureThread); |
| for(int i = 0 ; i < MAX_NUM_PIPES ; i++ ) { |
| m_mainSetupQ[i] = new frame_queue_t; |
| m_mainSetupQ[i]->setWaitTime(500000000); |
| } |
| m_jpegCallbackQ = new jpeg_callback_queue_t; |
| |
| for (int threadNum = JPEG_SAVE_THREAD0; threadNum < JPEG_SAVE_THREAD_MAX_COUNT; threadNum++) { |
| m_jpegSaveQ[threadNum] = new jpeg_callback_queue_t; |
| m_jpegSaveQ[threadNum]->setWaitTime(2000000000); |
| m_burst[threadNum] = false; |
| m_running[threadNum] = false; |
| } |
| |
| dstIspReprocessingQ->setWaitTime(20000000); |
| dstSccReprocessingQ->setWaitTime(50000000); |
| dstGscReprocessingQ->setWaitTime(500000000); |
| dstJpegReprocessingQ->setWaitTime(500000000); |
| /* vision */ |
| m_pipeFrameVisionDoneQ->setWaitTime(2000000000); |
| |
| m_jpegCallbackQ->setWaitTime(1000000000); |
| |
| memset(&m_frameMetadata, 0, sizeof(camera_frame_metadata_t)); |
| memset(m_faces, 0, sizeof(camera_face_t) * NUM_OF_DETECTED_FACES); |
| |
| 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_doCscRecording = true; |
| m_recordingBufferCount = NUM_RECORDING_BUFFERS; |
| m_frameSkipCount = 0; |
| #ifdef BURST_CAPTURE |
| m_burstCaptureCallbackCount = 0; |
| #endif |
| m_skipCount = 0; |
| |
| m_lensmoveCount = 0; |
| m_AFstatus = ExynosCameraActivityAutofocus::AUTOFOCUS_STATE_NONE; |
| m_currentSetStart = false; |
| m_flagMetaDataSet = false; |
| |
| #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_callbackState = 0; |
| m_callbackStateOld = 0; |
| m_callbackMonitorCount = 0; |
| |
| m_highResolutionCallbackRunning = false; |
| m_highResolutionCallbackQ = new frame_queue_t(m_highResolutionCallbackThread); |
| m_highResolutionCallbackQ->setWaitTime(500000000); |
| m_skipReprocessing = false; |
| m_isFirstStart = true; |
| m_exynosCameraParameters->setIsFirstStartFlag(m_isFirstStart); |
| |
| m_exynosconfig = NULL; |
| m_setConfigInform(); |
| |
| m_setFrameManager(); |
| |
| |
| /* HACK Reset Preview Flag*/ |
| m_resetPreview = false; |
| |
| m_dynamicSccCount = 0; |
| m_previewBufferCount = NUM_PREVIEW_BUFFERS; |
| |
| #ifdef FIRST_PREVIEW_TIME_CHECK |
| m_flagFirstPreviewTimerOn = false; |
| #endif |
| |
| /* init infomation of fd orientation*/ |
| m_exynosCameraParameters->setDeviceOrientation(0); |
| uctlMgr = m_exynosCameraActivityControl->getUCTLMgr(); |
| if (uctlMgr != NULL) |
| uctlMgr->setDeviceRotation(m_exynosCameraParameters->getFdOrientation()); |
| #ifdef MONITOR_LOG_SYNC |
| m_syncLogDuration = 0; |
| #endif |
| |
| m_initFrameFactory(); |
| |
| } |
| |
| 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_bayer_buffers = (getCameraId() == 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 = 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 = (getCameraId() == 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].pipeInfo.prepare[PIPE_FLITE] = (getCameraId() == 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] = (getCameraId() == CAMERA_ID_BACK) ? PIPE_3AA_ISP_PREPARE_COUNT : PIPE_FLITE_FRONT_PREPARE_COUNT; |
| exynosConfig.info[CONFIG_MODE::NORMAL].pipeInfo.prepare[PIPE_SCC] = (getCameraId() == CAMERA_ID_BACK) ? PIPE_3AA_ISP_PREPARE_COUNT : PIPE_FLITE_FRONT_PREPARE_COUNT; |
| exynosConfig.info[CONFIG_MODE::NORMAL].pipeInfo.prepare[PIPE_SCP] = (getCameraId() == 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_bayer_buffers = (getCameraId() == 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 = (getCameraId() == 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].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_bayer_buffers = (getCameraId() == 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 = (getCameraId() == 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].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; |
| #endif |
| |
| m_exynosCameraParameters->setConfig(&exynosConfig); |
| |
| m_exynosconfig = m_exynosCameraParameters->getConfig(); |
| |
| return NO_ERROR; |
| } |
| |
| void ExynosCamera::m_createThreads(void) |
| { |
| m_mainThread = new mainCameraThread(this, &ExynosCamera::m_mainThreadFunc, "ExynosCameraThread", PRIORITY_URGENT_DISPLAY); |
| CLOGD("DEBUG(%s):mainThread created", __FUNCTION__); |
| |
| m_previewThread = new mainCameraThread(this, &ExynosCamera::m_previewThreadFunc, "previewThread", PRIORITY_DISPLAY); |
| CLOGD("DEBUG(%s):previewThread created", __FUNCTION__); |
| |
| /* |
| * In here, we cannot know single, dual scenario. |
| * So, make all threads. |
| */ |
| /* if (m_exynosCameraParameters->isFlite3aaOtf() == true) { */ |
| if (1) { |
| m_mainSetupQThread[INDEX(PIPE_FLITE)] = new mainCameraThread(this, &ExynosCamera::m_mainThreadQSetupFLITE, "mainThreadQSetupFLITE", PRIORITY_URGENT_DISPLAY); |
| CLOGD("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); |
| CLOGD("DEBUG(%s):mainThreadQSetup3AAThread created", __FUNCTION__); |
| |
| } |
| m_setBuffersThread = new mainCameraThread(this, &ExynosCamera::m_setBuffersThreadFunc, "setBuffersThread"); |
| CLOGD("DEBUG(%s):setBuffersThread created", __FUNCTION__); |
| |
| m_startPictureInternalThread = new mainCameraThread(this, &ExynosCamera::m_startPictureInternalThreadFunc, "startPictureInternalThread"); |
| CLOGD("DEBUG(%s):startPictureInternalThread created", __FUNCTION__); |
| |
| m_startPictureBufferThread = new mainCameraThread(this, &ExynosCamera::m_startPictureBufferThreadFunc, "startPictureBufferThread"); |
| CLOGD("DEBUG(%s):startPictureBufferThread created", __FUNCTION__); |
| |
| m_prePictureThread = new mainCameraThread(this, &ExynosCamera::m_prePictureThreadFunc, "prePictureThread"); |
| CLOGD("DEBUG(%s):prePictureThread created", __FUNCTION__); |
| |
| m_pictureThread = new mainCameraThread(this, &ExynosCamera::m_pictureThreadFunc, "PictureThread"); |
| CLOGD("DEBUG(%s):pictureThread created", __FUNCTION__); |
| |
| m_postPictureThread = new mainCameraThread(this, &ExynosCamera::m_postPictureThreadFunc, "postPictureThread"); |
| CLOGD("DEBUG(%s):postPictureThread created", __FUNCTION__); |
| |
| m_recordingThread = new mainCameraThread(this, &ExynosCamera::m_recordingThreadFunc, "recordingThread"); |
| CLOGD("DEBUG(%s):recordingThread created", __FUNCTION__); |
| |
| m_autoFocusThread = new mainCameraThread(this, &ExynosCamera::m_autoFocusThreadFunc, "AutoFocusThread"); |
| CLOGD("DEBUG(%s):autoFocusThread created", __FUNCTION__); |
| |
| m_autoFocusContinousThread = new mainCameraThread(this, &ExynosCamera::m_autoFocusContinousThreadFunc, "AutoFocusContinousThread"); |
| CLOGD("DEBUG(%s):autoFocusContinousThread created", __FUNCTION__); |
| |
| m_facedetectThread = new mainCameraThread(this, &ExynosCamera::m_facedetectThreadFunc, "FaceDetectThread"); |
| CLOGD("DEBUG(%s):FaceDetectThread created", __FUNCTION__); |
| |
| m_monitorThread = new mainCameraThread(this, &ExynosCamera::m_monitorThreadFunc, "monitorThread"); |
| CLOGD("DEBUG(%s):monitorThread created", __FUNCTION__); |
| |
| m_framefactoryThread = new mainCameraThread(this, &ExynosCamera::m_frameFactoryInitThreadFunc, "FrameFactoryInitThread"); |
| CLOGD("DEBUG(%s):FrameFactoryInitThread created", __FUNCTION__); |
| |
| m_jpegCallbackThread = new mainCameraThread(this, &ExynosCamera::m_jpegCallbackThreadFunc, "jpegCallbackThread"); |
| CLOGD("DEBUG(%s):jpegCallbackThread created", __FUNCTION__); |
| |
| /* 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); |
| CLOGD("DEBUG(%s):%s created", __FUNCTION__, threadName); |
| } |
| |
| /* high resolution preview callback Thread */ |
| m_highResolutionCallbackThread = new mainCameraThread(this, &ExynosCamera::m_highResolutionCallbackThreadFunc, "m_highResolutionCallbackThread"); |
| CLOGD("DEBUG(%s):highResolutionCallbackThread created", __FUNCTION__); |
| |
| /* vision */ |
| m_visionThread = new mainCameraThread(this, &ExynosCamera::m_visionThreadFunc, "VisionThread", PRIORITY_URGENT_DISPLAY); |
| CLOGD("DEBUG(%s):visionThread created", __FUNCTION__); |
| |
| /* Shutter callback */ |
| m_shutterCallbackThread = new mainCameraThread(this, &ExynosCamera::m_shutterCallbackThreadFunc, "shutterCallbackThread"); |
| CLOGD("DEBUG(%s):shutterCallbackThread created", __FUNCTION__); |
| |
| } |
| |
| status_t ExynosCamera::m_setupFrameFactory(void) |
| { |
| CLOGI("INFO(%s[%d]): -IN-", __FUNCTION__, __LINE__); |
| |
| ExynosCameraAutoTimer autoTimer(__FUNCTION__); |
| |
| status_t ret = NO_ERROR; |
| |
| if (m_exynosCameraParameters->getVisionMode() == true) { |
| /* about vision */ |
| if( m_frameFactory[FRAME_FACTORY_TYPE_VISION] == NULL) { |
| m_frameFactory[FRAME_FACTORY_TYPE_VISION] = new ExynosCameraFrameFactoryVision(m_cameraId, m_exynosCameraParameters); |
| m_frameFactory[FRAME_FACTORY_TYPE_VISION]->setFrameManager(m_frameMgr); |
| } |
| m_visionFrameFactory = m_frameFactory[FRAME_FACTORY_TYPE_VISION]; |
| |
| if (m_frameFactory[FRAME_FACTORY_TYPE_VISION] != NULL && m_frameFactory[FRAME_FACTORY_TYPE_VISION]->isCreated() == false) { |
| CLOGD("DEBUG(%s[%d]):setupFrameFactory pushProcessQ(%d)", __FUNCTION__, __LINE__, FRAME_FACTORY_TYPE_VISION); |
| m_frameFactoryQ->pushProcessQ(&m_frameFactory[FRAME_FACTORY_TYPE_VISION]); |
| } |
| } else { |
| /* about preview */ |
| if (m_exynosCameraParameters->getDualMode() == true) { |
| m_previewFrameFactory = m_frameFactory[FRAME_FACTORY_TYPE_DUAL_PREVIEW]; |
| } else if (m_exynosCameraParameters->getTpuEnabledMode() == true) { |
| if (m_exynosCameraParameters->is3aaIspOtf() == true) |
| m_previewFrameFactory = m_frameFactory[FRAME_FACTORY_TYPE_3AA_ISP_OTF_TPU]; |
| else |
| m_previewFrameFactory = m_frameFactory[FRAME_FACTORY_TYPE_3AA_ISP_M2M_TPU]; |
| } else { |
| if (m_exynosCameraParameters->is3aaIspOtf() == true) |
| m_previewFrameFactory = m_frameFactory[FRAME_FACTORY_TYPE_3AA_ISP_OTF]; |
| else |
| m_previewFrameFactory = m_frameFactory[FRAME_FACTORY_TYPE_3AA_ISP_M2M]; |
| } |
| |
| /* find previewFrameFactory and push */ |
| for (int i = 0; i < FRAME_FACTORY_TYPE_MAX; i++) { |
| if (m_previewFrameFactory == m_frameFactory[i]) { |
| if (m_frameFactory[i] != NULL && m_frameFactory[i]->isCreated() == false) { |
| CLOGD("DEBUG(%s[%d]):setupFrameFactory pushProcessQ(%d)", __FUNCTION__, __LINE__, i); |
| m_frameFactoryQ->pushProcessQ(&m_frameFactory[i]); |
| } |
| break; |
| } |
| } |
| |
| /* about reprocessing */ |
| if (m_exynosCameraParameters->isReprocessing() == true) { |
| m_reprocessingFrameFactory = m_frameFactory[FRAME_FACTORY_TYPE_REPROCESSING]; |
| |
| if (m_frameFactory[FRAME_FACTORY_TYPE_REPROCESSING] != NULL && m_frameFactory[FRAME_FACTORY_TYPE_REPROCESSING]->isCreated() == false) { |
| CLOGD("DEBUG(%s[%d]):setupFrameFactory pushProcessQ(%d)", __FUNCTION__, __LINE__, FRAME_FACTORY_TYPE_REPROCESSING); |
| m_frameFactoryQ->pushProcessQ(&m_frameFactory[FRAME_FACTORY_TYPE_REPROCESSING]); |
| } |
| } |
| } |
| |
| /* |
| * disable until multi-instace is possible. |
| */ |
| /* |
| for (int i = 0; i < FRAME_FACTORY_TYPE_MAX; i++) { |
| if (m_frameFactory[i] != NULL && m_frameFactory[i]->isCreated() == false) { |
| CLOGD("DEBUG(%s[%d]):setupFrameFactory pushProcessQ(%d)", __FUNCTION__, __LINE__, i); |
| m_frameFactoryQ->pushProcessQ(&m_frameFactory[i]); |
| } else { |
| CLOGD("DEBUG(%s[%d]):setupFrameFactory no Push(%d)", __FUNCTION__, __LINE__, i); |
| } |
| } |
| */ |
| |
| CLOGI("INFO(%s[%d]): -OUT-", __FUNCTION__, __LINE__); |
| |
| return ret; |
| } |
| |
| status_t ExynosCamera::m_initFrameFactory(void) |
| { |
| CLOGI("INFO(%s[%d]): -IN-", __FUNCTION__, __LINE__); |
| |
| ExynosCameraAutoTimer autoTimer(__FUNCTION__); |
| status_t ret = NO_ERROR; |
| ExynosCameraFrameFactory *factory = NULL; |
| |
| m_previewFrameFactory = NULL; |
| m_pictureFrameFactory = NULL; |
| m_reprocessingFrameFactory = NULL; |
| m_visionFrameFactory = NULL; |
| |
| for(int i = 0; i < FRAME_FACTORY_TYPE_MAX; i++) |
| m_frameFactory[i] = NULL; |
| |
| /* |
| * new all FrameFactories. |
| * because this called on open(). so we don't know current scenario |
| */ |
| |
| factory = new ExynosCameraFrameFactory3aaIspM2M(m_cameraId, m_exynosCameraParameters); |
| m_frameFactory[FRAME_FACTORY_TYPE_3AA_ISP_M2M] = factory; |
| /* hack : for dual */ |
| if (getCameraId() == CAMERA_ID_FRONT) { |
| factory = new ExynosCameraFrameFactoryFront(m_cameraId, m_exynosCameraParameters); |
| m_frameFactory[FRAME_FACTORY_TYPE_DUAL_PREVIEW] = factory; |
| } else { |
| factory = new ExynosCameraFrameFactory3aaIspM2M(m_cameraId, m_exynosCameraParameters); |
| m_frameFactory[FRAME_FACTORY_TYPE_DUAL_PREVIEW] = factory; |
| } |
| |
| factory = new ExynosCameraFrameFactory3aaIspM2MTpu(m_cameraId, m_exynosCameraParameters); |
| m_frameFactory[FRAME_FACTORY_TYPE_3AA_ISP_M2M_TPU] = factory; |
| |
| factory = new ExynosCameraFrameFactory3aaIspOtf(m_cameraId, m_exynosCameraParameters); |
| m_frameFactory[FRAME_FACTORY_TYPE_3AA_ISP_OTF] = factory; |
| |
| factory = new ExynosCameraFrameFactory3aaIspOtfTpu(m_cameraId, m_exynosCameraParameters); |
| m_frameFactory[FRAME_FACTORY_TYPE_3AA_ISP_OTF_TPU] = factory; |
| |
| factory = new ExynosCameraFrameReprocessingFactory(m_cameraId, m_exynosCameraParameters); |
| m_frameFactory[FRAME_FACTORY_TYPE_REPROCESSING] = factory; |
| |
| for (int i = 0 ; i < FRAME_FACTORY_TYPE_MAX ; i++) { |
| factory = m_frameFactory[i]; |
| if( factory != NULL ) |
| factory->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; |
| ExynosCameraFrameFactory *frameFactory = NULL; |
| |
| for (int i = 0; i < FRAME_FACTORY_TYPE_MAX; i++) { |
| if (m_frameFactory[i] != NULL) { |
| frameFactory = m_frameFactory[i]; |
| |
| for (int k = i + 1; k < FRAME_FACTORY_TYPE_MAX; k++) { |
| if (frameFactory == m_frameFactory[k]) { |
| CLOGD("DEBUG(%s[%d]): m_frameFactory index(%d) and index(%d) are same instance, set index(%d) = NULL", |
| __FUNCTION__, __LINE__, i, k, k); |
| m_frameFactory[k] = NULL; |
| } |
| } |
| |
| if (m_frameFactory[i]->isCreated() == true) { |
| ret = m_frameFactory[i]->destroy(); |
| if (ret < 0) |
| CLOGE("ERR(%s[%d]):m_frameFactory[%d] destroy fail", __FUNCTION__, __LINE__, i); |
| } |
| |
| SAFE_DELETE(m_frameFactory[i]); |
| |
| CLOGD("DEBUG(%s[%d]):m_frameFactory[%d] destroyed", __FUNCTION__, __LINE__, i); |
| } |
| } |
| |
| m_previewFrameFactory = NULL; |
| m_pictureFrameFactory = NULL; |
| m_reprocessingFrameFactory = NULL; |
| m_visionFrameFactory = NULL; |
| |
| CLOGI("INFO(%s[%d]): -OUT-", __FUNCTION__, __LINE__); |
| |
| return ret; |
| } |
| |
| status_t ExynosCamera::m_setFrameManager() |
| { |
| sp<FrameWorker> worker; |
| m_frameMgr = new ExynosCameraFrameManager("FRAME MANAGER", m_cameraId, FRAMEMGR_OPER::SLIENT, 50, 100); |
| |
| worker = new CreateWorker("CREATE FRAME WORKER", m_cameraId, FRAMEMGR_OPER::SLIENT, 40); |
| 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; |
| } |
| |
| |
| ExynosCamera::~ExynosCamera() |
| { |
| this->release(); |
| } |
| |
| void ExynosCamera::release() |
| { |
| CLOGI("INFO(%s[%d]): -IN-", __FUNCTION__, __LINE__); |
| int ret = 0; |
| |
| if (m_frameMgr != NULL) { |
| m_frameMgr->stop(); |
| } |
| |
| /* release all framefactory */ |
| m_deinitFrameFactory(); |
| |
| if (m_exynosCameraParameters != NULL) { |
| delete m_exynosCameraParameters; |
| m_exynosCameraParameters = NULL; |
| CLOGD("DEBUG(%s):Parameters(Id=%d) destroyed", __FUNCTION__, m_cameraId); |
| } |
| |
| /* free all buffers */ |
| m_releaseBuffers(); |
| |
| 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; |
| } |
| |
| /* vision */ |
| if (m_pipeFrameVisionDoneQ != NULL) { |
| delete m_pipeFrameVisionDoneQ; |
| m_pipeFrameVisionDoneQ = NULL; |
| } |
| |
| if (dstIspReprocessingQ != NULL) { |
| delete dstIspReprocessingQ; |
| dstIspReprocessingQ = NULL; |
| } |
| |
| if (dstSccReprocessingQ != NULL) { |
| delete dstSccReprocessingQ; |
| dstSccReprocessingQ = NULL; |
| } |
| |
| if (dstGscReprocessingQ != NULL) { |
| delete dstGscReprocessingQ; |
| dstGscReprocessingQ = NULL; |
| } |
| |
| if (dstJpegReprocessingQ != NULL) { |
| delete dstJpegReprocessingQ; |
| dstJpegReprocessingQ = NULL; |
| } |
| |
| if (m_postPictureQ != NULL) { |
| delete m_postPictureQ; |
| m_postPictureQ = NULL; |
| } |
| |
| if (m_jpegCallbackQ != NULL) { |
| delete m_jpegCallbackQ; |
| m_jpegCallbackQ = 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_frameFactoryQ != NULL) { |
| delete m_frameFactoryQ; |
| m_frameFactoryQ = NULL; |
| CLOGD("DEBUG(%s):FrameFactoryQ destroyed", __FUNCTION__); |
| } |
| |
| if (m_bayerBufferMgr != NULL) { |
| delete m_bayerBufferMgr; |
| m_bayerBufferMgr = NULL; |
| CLOGD("DEBUG(%s):BufferManager(bayerBufferMgr) destroyed", __FUNCTION__); |
| } |
| |
| 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_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_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; |
| } |
| |
| CLOGI("INFO(%s[%d]): -OUT-", __FUNCTION__, __LINE__); |
| } |
| |
| int ExynosCamera::getCameraId() const |
| { |
| return m_cameraId; |
| } |
| |
| int ExynosCamera::getShotBufferIdex() const |
| { |
| return NUM_PLANES(V4L2_PIX_2_HAL_PIXEL_FORMAT(SCC_OUTPUT_COLOR_FMT)); |
| } |
| |
| status_t ExynosCamera::setPreviewWindow(preview_stream_ops *w) |
| { |
| CLOGI("INFO(%s[%d])", __FUNCTION__, __LINE__); |
| |
| status_t ret = NO_ERROR; |
| int width, height; |
| int halPreviewFmt = 0; |
| bool flagRestart = false; |
| buffer_manager_type bufferType = BUFFER_MANAGER_ION_TYPE; |
| |
| if (m_exynosCameraParameters != NULL) { |
| if (m_exynosCameraParameters->getVisionMode() == true) { |
| CLOGW("WRN(%s[%d]): Vision mode does not support", __FUNCTION__, __LINE__); |
| /* android_printAssert(NULL, LOG_TAG, "Cannot support this operation"); */ |
| |
| return NO_ERROR; |
| } |
| } else { |
| CLOGW("(%s):m_exynosCameraParameters is NULL. Skipped", __FUNCTION__); |
| return INVALID_OPERATION; |
| } |
| |
| if (previewEnabled() == true) { |
| CLOGW("WRN(%s[%d]): preview is started, we forcely re-start preview", __FUNCTION__, __LINE__); |
| flagRestart = true; |
| m_disablePreviewCB = true; |
| stopPreview(); |
| } |
| |
| m_previewWindow = w; |
| |
| if (m_scpBufferMgr != NULL) { |
| CLOGD("DEBUG(%s[%d]): scp buffer manager need recreate", __FUNCTION__, __LINE__); |
| m_scpBufferMgr->deinit(); |
| |
| delete m_scpBufferMgr; |
| m_scpBufferMgr = NULL; |
| } |
| |
| if (w == NULL) { |
| bufferType = BUFFER_MANAGER_ION_TYPE; |
| CLOGW("WARN(%s[%d]):window NULL, create internal buffer for preview", __FUNCTION__, __LINE__); |
| } else { |
| halPreviewFmt = m_exynosCameraParameters->getHalPixelFormat(); |
| bufferType = BUFFER_MANAGER_GRALLOC_TYPE; |
| m_exynosCameraParameters->getHwPreviewSize(&width, &height); |
| if (m_grAllocator == NULL) |
| m_grAllocator = new ExynosCameraGrallocAllocator(); |
| |
| #ifdef RESERVED_MEMORY_FOR_GRALLOC_ENABLE |
| if (!(((m_exynosCameraParameters->getShotMode() == SHOT_MODE_BEAUTY_FACE) && (getCameraId() == CAMERA_ID_BACK)) |
| || m_exynosCameraParameters->getRecordingHint() == true)) { |
| ret = m_grAllocator->init(m_previewWindow, m_exynosconfig->current->bufInfo.num_preview_buffers, |
| m_exynosconfig->current->bufInfo.preview_buffer_margin, (GRALLOC_SET_USAGE_FOR_CAMERA | GRALLOC_USAGE_CAMERA_RESERVED)); |
| } else |
| #endif |
| { |
| ret = m_grAllocator->init(m_previewWindow, m_exynosconfig->current->bufInfo.num_preview_buffers, m_exynosconfig->current->bufInfo.preview_buffer_margin); |
| } |
| |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]):gralloc init fail, ret(%d)", __FUNCTION__, __LINE__, ret); |
| goto func_exit; |
| } |
| |
| ret = m_grAllocator->setBuffersGeometry(width, height, halPreviewFmt); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]):gralloc setBufferGeomety fail, size(%dx%d), fmt(%d), ret(%d)", |
| __FUNCTION__, __LINE__, width, height, halPreviewFmt, ret); |
| goto func_exit; |
| } |
| } |
| |
| m_createBufferManager(&m_scpBufferMgr, "SCP_BUF", bufferType); |
| |
| if (bufferType == BUFFER_MANAGER_GRALLOC_TYPE) |
| m_scpBufferMgr->setAllocator(m_grAllocator); |
| |
| if (flagRestart == true) { |
| startPreview(); |
| } |
| |
| func_exit: |
| m_disablePreviewCB = false; |
| |
| return ret; |
| } |
| |
| 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__); |
| } |
| } |
| |
| void ExynosCamera::enableMsgType(int32_t msgType) |
| { |
| if (m_exynosCameraParameters) { |
| CLOGV("INFO(%s[%d]): enable Msg (%x)", __FUNCTION__, __LINE__, msgType); |
| m_exynosCameraParameters->enableMsgType(msgType); |
| } |
| } |
| |
| void ExynosCamera::disableMsgType(int32_t msgType) |
| { |
| if (m_exynosCameraParameters) { |
| CLOGV("INFO(%s[%d]): disable Msg (%x)", __FUNCTION__, __LINE__, msgType); |
| m_exynosCameraParameters->disableMsgType(msgType); |
| } |
| } |
| |
| bool ExynosCamera::msgTypeEnabled(int32_t msgType) |
| { |
| bool IsEnabled = false; |
| |
| if (m_exynosCameraParameters) { |
| CLOGV("INFO(%s[%d]): Msg type enabled (%x)", __FUNCTION__, __LINE__, msgType); |
| IsEnabled = m_exynosCameraParameters->msgTypeEnabled(msgType); |
| } |
| |
| return IsEnabled; |
| } |
| |
| status_t ExynosCamera::startPreview() |
| { |
| ExynosCameraAutoTimer autoTimer(__FUNCTION__); |
| |
| CLOGI("INFO(%s[%d])", __FUNCTION__, __LINE__); |
| |
| int ret = 0; |
| int32_t skipFrameCount = INITIAL_SKIP_FRAME; |
| unsigned int fdCallbackSize = 0; |
| |
| m_hdrSkipedFcount = 0; |
| m_isTryStopFlash= false; |
| m_exitAutoFocusThread = false; |
| m_curMinFps = 0; |
| m_isNeedAllocPictureBuffer = false; |
| m_flagThreadStop= false; |
| m_frameSkipCount = 0; |
| |
| #ifdef FIRST_PREVIEW_TIME_CHECK |
| if (m_flagFirstPreviewTimerOn == false) { |
| m_firstPreviewTimer.start(); |
| m_flagFirstPreviewTimerOn = true; |
| |
| CLOGD("DEBUG(%s[%d]):m_firstPreviewTimer start", __FUNCTION__, __LINE__); |
| } |
| #endif |
| |
| if (m_previewEnabled == true) { |
| return INVALID_OPERATION; |
| } |
| |
| /* frame manager start */ |
| m_frameMgr->start(); |
| |
| fdCallbackSize = sizeof(camera_frame_metadata_t) * NUM_OF_DETECTED_FACES; |
| |
| m_fdCallbackHeap = m_getMemoryCb(-1, fdCallbackSize, 1, m_callbackCookie); |
| if (!m_fdCallbackHeap || m_fdCallbackHeap->data == MAP_FAILED) { |
| CLOGE("ERR(%s[%d]):m_getMemoryCb(%d) fail", __FUNCTION__, __LINE__, fdCallbackSize); |
| goto err; |
| } |
| |
| /* |
| * This is for updating parameter value at once. |
| * This must be just before making factory |
| */ |
| m_exynosCameraParameters->updateTpuParameters(); |
| |
| /* setup frameFactory with scenario */ |
| m_setupFrameFactory(); |
| |
| /* vision */ |
| CLOGI("INFO(%s[%d]): getVisionMode(%d)", __FUNCTION__, __LINE__, m_exynosCameraParameters->getVisionMode()); |
| if (m_exynosCameraParameters->getVisionMode() == true) { |
| ret = m_setVisionBuffers(); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]):m_setVisionCallbackBuffer() fail", __FUNCTION__, __LINE__); |
| return ret; |
| } |
| |
| ret = m_setVisionCallbackBuffer(); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]):m_setVisionCallbackBuffer() fail", __FUNCTION__, __LINE__); |
| return INVALID_OPERATION; |
| } |
| |
| if (m_visionFrameFactory->isCreated() == false) { |
| ret = m_visionFrameFactory->create(); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]):m_visionFrameFactory->create() failed", __FUNCTION__, __LINE__); |
| goto err; |
| } |
| CLOGD("DEBUG(%s):FrameFactory(VisionFrameFactory) created", __FUNCTION__); |
| } |
| |
| m_exynosCameraParameters->setFrameSkipCount(INITIAL_SKIP_FRAME); |
| |
| ret = m_startVisionInternal(); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]):m_startVisionInternal() failed", __FUNCTION__, __LINE__); |
| goto err; |
| } |
| |
| m_visionThread->run(PRIORITY_DEFAULT); |
| return NO_ERROR; |
| } else { |
| m_exynosCameraParameters->setSeriesShotMode(SERIES_SHOT_MODE_NONE); |
| |
| if(m_exynosCameraParameters->increaseMaxBufferOfPreview()) { |
| m_exynosCameraParameters->setPreviewBufferCount(NUM_PREVIEW_BUFFERS + NUM_PREVIEW_SPARE_BUFFERS); |
| } else { |
| m_exynosCameraParameters->setPreviewBufferCount(NUM_PREVIEW_BUFFERS); |
| } |
| |
| if ((m_exynosCameraParameters->getRestartPreview() == true) || |
| m_previewBufferCount != m_exynosCameraParameters->getPreviewBufferCount()) { |
| ret = setPreviewWindow(m_previewWindow); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]):setPreviewWindow fail", __FUNCTION__, __LINE__); |
| return INVALID_OPERATION; |
| } |
| |
| m_previewBufferCount = m_exynosCameraParameters->getPreviewBufferCount(); |
| } |
| |
| CLOGI("INFO(%s[%d]):setBuffersThread is run", __FUNCTION__, __LINE__); |
| m_setBuffersThread->run(PRIORITY_DEFAULT); |
| |
| if (m_captureSelector == NULL) { |
| ExynosCameraBufferManager *bufMgr = NULL; |
| #ifdef DEBUG_RAWDUMP |
| bufMgr = m_bayerBufferMgr; |
| #else |
| if (m_exynosCameraParameters->isReprocessing() == true) |
| bufMgr = m_bayerBufferMgr; |
| #endif |
| m_captureSelector = new ExynosCameraFrameSelector(m_exynosCameraParameters, bufMgr, m_frameMgr); |
| |
| if (m_exynosCameraParameters->isReprocessing() == true) { |
| ret = m_captureSelector->setFrameHoldCount(REPROCESSING_BAYER_HOLD_COUNT); |
| if (ret < 0) |
| CLOGE("ERR(%s[%d]): setFrameHoldCount(%d) is fail", __FUNCTION__, __LINE__, REPROCESSING_BAYER_HOLD_COUNT); |
| } |
| } |
| |
| if (m_sccCaptureSelector == NULL) { |
| ExynosCameraBufferManager *bufMgr = NULL; |
| |
| if (m_exynosCameraParameters->isSccCapture() == true |
| || m_exynosCameraParameters->isUsing3acForIspc() == true) { |
| /* TODO: Dynamic select buffer manager for capture */ |
| bufMgr = m_sccBufferMgr; |
| } |
| |
| m_sccCaptureSelector = new ExynosCameraFrameSelector(m_exynosCameraParameters, bufMgr, m_frameMgr); |
| } |
| |
| if (m_captureSelector != NULL) |
| m_captureSelector->release(); |
| |
| if (m_sccCaptureSelector != NULL) |
| m_sccCaptureSelector->release(); |
| |
| if (m_previewFrameFactory->isCreated() == false) { |
| ret = m_previewFrameFactory->create(); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]):m_previewFrameFactory->create() failed", __FUNCTION__, __LINE__); |
| goto err; |
| } |
| CLOGD("DEBUG(%s):FrameFactory(previewFrameFactory) created", __FUNCTION__); |
| } |
| |
| if (m_exynosCameraParameters->getUseFastenAeStable() == true && |
| m_exynosCameraParameters->getCameraId() == CAMERA_ID_BACK && |
| m_exynosCameraParameters->getDualMode() == false && |
| m_exynosCameraParameters->getRecordingHint() == false && |
| m_isFirstStart == true) { |
| |
| ret = m_fastenAeStable(); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]):m_fastenAeStable() failed", __FUNCTION__, __LINE__); |
| ret = INVALID_OPERATION; |
| goto err; |
| } else { |
| skipFrameCount = 0; |
| m_exynosCameraParameters->setUseFastenAeStable(false); |
| } |
| } else if(m_exynosCameraParameters->getDualMode() == true) { |
| skipFrameCount = INITIAL_SKIP_FRAME + 2; |
| } |
| |
| #ifdef SET_FPS_SCENE /* This codes for 5260, Do not need other project */ |
| struct camera2_shot_ext *initMetaData = new struct camera2_shot_ext; |
| if (initMetaData != NULL) { |
| m_exynosCameraParameters->duplicateCtrlMetadata(initMetaData); |
| |
| ret = m_previewFrameFactory->setControl(V4L2_CID_IS_MIN_TARGET_FPS, initMetaData->shot.ctl.aa.aeTargetFpsRange[0], PIPE_FLITE); |
| if (ret < 0) |
| CLOGE("ERR(%s[%d]):FLITE setControl fail, ret(%d)", __FUNCTION__, __LINE__, ret); |
| |
| ret = m_previewFrameFactory->setControl(V4L2_CID_IS_MAX_TARGET_FPS, initMetaData->shot.ctl.aa.aeTargetFpsRange[1], PIPE_FLITE); |
| if (ret < 0) |
| CLOGE("ERR(%s[%d]):FLITE setControl fail, ret(%d)", __FUNCTION__, __LINE__, ret); |
| |
| ret = m_previewFrameFactory->setControl(V4L2_CID_IS_SCENE_MODE, initMetaData->shot.ctl.aa.sceneMode, PIPE_FLITE); |
| if (ret < 0) |
| CLOGE("ERR(%s[%d]):FLITE setControl fail, ret(%d)", __FUNCTION__, __LINE__, ret); |
| delete initMetaData; |
| initMetaData = NULL; |
| } else { |
| CLOGE("ERR(%s[%d]):initMetaData is NULL", __FUNCTION__, __LINE__); |
| } |
| #elif SET_FPS_FRONTCAM |
| if (m_exynosCameraParameters->getCameraId() == CAMERA_ID_FRONT) { |
| struct camera2_shot_ext *initMetaData = new struct camera2_shot_ext; |
| if (initMetaData != NULL) { |
| m_exynosCameraParameters->duplicateCtrlMetadata(initMetaData); |
| CLOGD("(%s:[%d]) : setControl for Frame Range.", __FUNCTION__, __LINE__); |
| |
| ret = m_previewFrameFactory->setControl(V4L2_CID_IS_MIN_TARGET_FPS, initMetaData->shot.ctl.aa.aeTargetFpsRange[0], PIPE_FLITE_FRONT); |
| if (ret < 0) |
| CLOGE("ERR(%s[%d]):FLITE setControl fail, ret(%d)", __FUNCTION__, __LINE__, ret); |
| |
| ret = m_previewFrameFactory->setControl(V4L2_CID_IS_MAX_TARGET_FPS, initMetaData->shot.ctl.aa.aeTargetFpsRange[1], PIPE_FLITE_FRONT); |
| if (ret < 0) |
| CLOGE("ERR(%s[%d]):FLITE setControl fail, ret(%d)", __FUNCTION__, __LINE__, ret); |
| |
| delete initMetaData; |
| initMetaData = NULL; |
| } else { |
| CLOGE("ERR(%s[%d]):initMetaData is NULL", __FUNCTION__, __LINE__); |
| } |
| } |
| #endif |
| |
| m_exynosCameraParameters->setFrameSkipCount(skipFrameCount); |
| |
| m_setBuffersThread->join(); |
| |
| ret = m_startPreviewInternal(); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]):m_startPreviewInternal() failed", __FUNCTION__, __LINE__); |
| goto err; |
| } |
| |
| if (m_exynosCameraParameters->isReprocessing() == true) { |
| #ifdef START_PICTURE_THREAD |
| #if !defined(USE_SNAPSHOT_ON_UHD_RECORDING) |
| if (!m_exynosCameraParameters->getDualRecordingHint() && !m_exynosCameraParameters->getUHDRecordingMode()) |
| #endif |
| { |
| m_startPictureInternalThread->run(PRIORITY_DEFAULT); |
| } |
| #endif |
| } else { |
| m_pictureFrameFactory = m_previewFrameFactory; |
| CLOGD("DEBUG(%s[%d]):FrameFactory(pictureFrameFactory) created", __FUNCTION__, __LINE__); |
| |
| /* |
| * Make remained frameFactory here. |
| * in case of SCC capture, make here. |
| */ |
| m_framefactoryThread->run(); |
| } |
| |
| #if defined(USE_UHD_RECORDING) && !defined(USE_SNAPSHOT_ON_UHD_RECORDING) |
| if (!m_exynosCameraParameters->getDualRecordingHint() && !m_exynosCameraParameters->getUHDRecordingMode()) |
| #endif |
| { |
| m_startPictureBufferThread->run(PRIORITY_DEFAULT); |
| } |
| |
| if (m_previewWindow != NULL) |
| m_previewWindow->set_timestamp(m_previewWindow, systemTime(SYSTEM_TIME_MONOTONIC)); |
| |
| /* setup frame thread */ |
| if (m_exynosCameraParameters->getDualMode() == true && getCameraId() == CAMERA_ID_FRONT) { |
| m_mainSetupQThread[INDEX(PIPE_FLITE)]->run(PRIORITY_URGENT_DISPLAY); |
| } else { |
| #ifdef DEBUG_RAWDUMP |
| m_mainSetupQThread[INDEX(PIPE_FLITE)]->run(PRIORITY_URGENT_DISPLAY); |
| #endif |
| m_mainSetupQThread[INDEX(PIPE_3AA)]->run(PRIORITY_URGENT_DISPLAY); |
| } |
| |
| if (m_facedetectThread->isRunning() == false) |
| m_facedetectThread->run(); |
| |
| m_previewThread->run(PRIORITY_DISPLAY); |
| m_mainThread->run(PRIORITY_DEFAULT); |
| m_autoFocusContinousThread->run(PRIORITY_DEFAULT); |
| m_monitorThread->run(PRIORITY_DEFAULT); |
| |
| if ((m_exynosCameraParameters->getHighResolutionCallbackMode() == true) && |
| (m_highResolutionCallbackRunning == false)) { |
| CLOGD("DEBUG(%s[%d]):High resolution preview callback start", __FUNCTION__, __LINE__); |
| if (skipFrameCount > 0) |
| m_skipReprocessing = true; |
| m_highResolutionCallbackRunning = true; |
| if (m_exynosCameraParameters->isReprocessing() == true) { |
| m_startPictureInternalThread->run(PRIORITY_DEFAULT); |
| m_startPictureInternalThread->join(); |
| } |
| m_prePictureThread->run(PRIORITY_DEFAULT); |
| } |
| |
| /* FD-AE is always on */ |
| #ifdef USE_FD_AE |
| if ((m_exynosCameraParameters->getDualMode() == true && m_exynosCameraParameters->getCameraId() == CAMERA_ID_BACK) || |
| (m_exynosCameraParameters->getVtMode() != 0) || |
| (m_exynosCameraParameters->getRecordingHint() == true)) { |
| m_startFaceDetection(false); |
| } else { |
| m_startFaceDetection(true); |
| } |
| #endif |
| |
| if (m_exynosCameraParameters->getUseFastenAeStable() == true && |
| m_exynosCameraParameters->getCameraId() == CAMERA_ID_BACK && |
| m_exynosCameraParameters->getDualMode() == false && |
| m_exynosCameraParameters->getRecordingHint() == false && |
| m_isFirstStart == true) { |
| /* AF mode is setted as INFINITY in fastenAE, and we should update that mode */ |
| m_exynosCameraActivityControl->setAutoFocusMode(FOCUS_MODE_INFINITY); |
| |
| m_exynosCameraParameters->setUseFastenAeStable(false); |
| m_exynosCameraActivityControl->setAutoFocusMode(m_exynosCameraParameters->getFocusMode()); |
| m_isFirstStart = false; |
| m_exynosCameraParameters->setIsFirstStartFlag(m_isFirstStart); |
| } |
| } |
| |
| #ifdef BURST_CAPTURE |
| m_burstInitFirst = true; |
| #endif |
| return NO_ERROR; |
| |
| err: |
| |
| /* frame manager stop */ |
| m_frameMgr->stop(); |
| |
| m_setBuffersThread->join(); |
| |
| m_releaseBuffers(); |
| |
| return ret; |
| } |
| |
| void ExynosCamera::stopPreview() |
| { |
| CLOGI("INFO(%s[%d])", __FUNCTION__, __LINE__); |
| int ret = 0; |
| |
| ExynosCameraActivityFlash *m_flashMgr = m_exynosCameraActivityControl->getFlashMgr(); |
| ExynosCameraActivityAutofocus *autoFocusMgr = m_exynosCameraActivityControl->getAutoFocusMgr(); |
| ExynosCameraFrame *frame = NULL; |
| |
| /* release about frameFactory */ |
| m_framefactoryThread->requestExitAndWait(); |
| m_frameFactoryQ->release(); |
| |
| if (m_previewEnabled == false) { |
| CLOGD("DEBUG(%s[%d]): preview is not enabled", __FUNCTION__, __LINE__); |
| return; |
| } |
| |
| if (m_exynosCameraParameters->getVisionMode() == true) { |
| m_visionThread->requestExitAndWait(); |
| ret = m_stopVisionInternal(); |
| if (ret < 0) |
| CLOGE("ERR(%s[%d]):m_stopVisionInternal fail", __FUNCTION__, __LINE__); |
| } else { |
| m_startPictureInternalThread->join(); |
| m_startPictureBufferThread->join(); |
| |
| m_exynosCameraActivityControl->cancelAutoFocus(); |
| |
| CLOGD("DEBUG(%s[%d]): (%d, %d)", __FUNCTION__, __LINE__, m_flashMgr->getNeedCaptureFlash(), m_pictureEnabled); |
| if (m_flashMgr->getNeedCaptureFlash() == true && m_pictureEnabled == true) { |
| CLOGD("DEBUG(%s[%d]): force flash off", __FUNCTION__, __LINE__); |
| m_exynosCameraActivityControl->cancelFlash(); |
| autoFocusMgr->stopAutofocus(); |
| m_isTryStopFlash = true; |
| m_exitAutoFocusThread = true; |
| } |
| |
| int flashMode = AA_FLASHMODE_OFF; |
| int waitingTime = FLASH_OFF_MAX_WATING_TIME / TOTAL_FLASH_WATING_COUNT; /* Max waiting time: 500ms, Count:10, Waiting time: 50ms */ |
| |
| flashMode = m_flashMgr->getFlashStatus(); |
| if ((flashMode == AA_FLASHMODE_ON_ALWAYS) || (m_flashMgr->getNeedFlashOffDelay() == true)) { |
| CLOGD("DEBUG(%s[%d]): flash torch was enabled", __FUNCTION__, __LINE__); |
| |
| m_exynosCameraParameters->setFrameSkipCount(100); |
| usleep(FLASH_OFF_MAX_WATING_TIME); |
| |
| for (int i = 0; i < TOTAL_FLASH_WATING_COUNT; ++i) { |
| flashMode = m_flashMgr->getFlashStatus(); |
| if (flashMode == AA_FLASHMODE_OFF || flashMode == AA_FLASHMODE_CANCEL) { |
| m_flashMgr->setFlashStep(ExynosCameraActivityFlash::FLASH_STEP_OFF); |
| break; |
| } |
| usleep(waitingTime); |
| } |
| } else if (m_isTryStopFlash == true) { |
| usleep(150000); |
| m_flashMgr->setFlashStep(ExynosCameraActivityFlash::FLASH_STEP_OFF); |
| } |
| |
| m_flashMgr->setNeedFlashOffDelay(false); |
| |
| m_previewFrameFactory->setStopFlag(); |
| if (m_exynosCameraParameters->isReprocessing() == true && m_reprocessingFrameFactory->isCreated() == true) |
| m_reprocessingFrameFactory->setStopFlag(); |
| m_flagThreadStop = true; |
| |
| m_takePictureCounter.clearCount(); |
| m_reprocessingCounter.clearCount(); |
| m_pictureCounter.clearCount(); |
| m_jpegCounter.clearCount(); |
| m_captureSelector->cancelPicture(); |
| |
| if ((m_exynosCameraParameters->getHighResolutionCallbackMode() == true) && |
| (m_highResolutionCallbackRunning == true)) { |
| m_skipReprocessing = false; |
| m_highResolutionCallbackRunning = false; |
| CLOGD("DEBUG(%s[%d]):High resolution preview callback stop", __FUNCTION__, __LINE__); |
| if(getCameraId() == CAMERA_ID_FRONT) { |
| m_sccCaptureSelector->cancelPicture(); |
| m_sccCaptureSelector->wakeupQ(); |
| CLOGD("DEBUG(%s[%d]):High resolution m_sccCaptureSelector cancel", __FUNCTION__, __LINE__); |
| } |
| |
| m_prePictureThread->requestExitAndWait(); |
| m_highResolutionCallbackQ->release(); |
| } |
| |
| ret = m_stopPictureInternal(); |
| if (ret < 0) |
| CLOGE("ERR(%s[%d]):m_stopPictureInternal fail", __FUNCTION__, __LINE__); |
| |
| m_exynosCameraActivityControl->stopAutoFocus(); |
| m_autoFocusThread->requestExitAndWait(); |
| |
| if (m_previewQ != NULL) { |
| m_previewQ->sendCmd(WAKE_UP); |
| } else { |
| CLOGI("INFO(%s[%d]): m_previewQ is NULL", __FUNCTION__, __LINE__); |
| } |
| |
| m_pipeFrameDoneQ->sendCmd(WAKE_UP); |
| m_mainThread->requestExitAndWait(); |
| m_monitorThread->requestExitAndWait(); |
| |
| m_shutterCallbackThread->requestExitAndWait(); |
| |
| m_previewThread->stop(); |
| if (m_previewQ != NULL) { |
| m_previewQ->sendCmd(WAKE_UP); |
| } |
| m_previewThread->requestExitAndWait(); |
| |
| if (m_exynosCameraParameters->isFlite3aaOtf() == true) { |
| m_mainSetupQThread[INDEX(PIPE_FLITE)]->stop(); |
| m_mainSetupQ[INDEX(PIPE_FLITE)]->sendCmd(WAKE_UP); |
| m_mainSetupQThread[INDEX(PIPE_FLITE)]->requestExitAndWait(); |
| |
| if (m_mainSetupQThread[INDEX(PIPE_3AC)] != NULL) { |
| m_mainSetupQThread[INDEX(PIPE_3AC)]->stop(); |
| m_mainSetupQ[INDEX(PIPE_3AC)]->sendCmd(WAKE_UP); |
| m_mainSetupQThread[INDEX(PIPE_3AC)]->requestExitAndWait(); |
| } |
| |
| m_mainSetupQThread[INDEX(PIPE_3AA)]->stop(); |
| m_mainSetupQ[INDEX(PIPE_3AA)]->sendCmd(WAKE_UP); |
| m_mainSetupQThread[INDEX(PIPE_3AA)]->requestExitAndWait(); |
| |
| if (m_mainSetupQThread[INDEX(PIPE_ISP)] != NULL) { |
| m_mainSetupQThread[INDEX(PIPE_ISP)]->stop(); |
| m_mainSetupQ[INDEX(PIPE_ISP)]->sendCmd(WAKE_UP); |
| m_mainSetupQThread[INDEX(PIPE_ISP)]->requestExitAndWait(); |
| } |
| |
| /* Comment out, because it included ISP */ |
| /* m_mainSetupQThread[INDEX(PIPE_SCP)]->requestExitAndWait(); */ |
| } |
| |
| m_autoFocusContinousThread->requestExitAndWait(); |
| m_autoFocusContinousQ.release(); |
| |
| m_facedetectThread->stop(); |
| m_facedetectQ->sendCmd(WAKE_UP); |
| m_facedetectThread->requestExitAndWait(); |
| while (m_facedetectQ->getSizeOfProcessQ()) { |
| m_facedetectQ->popProcessQ(&frame); |
| frame->decRef(); |
| m_frameMgr->deleteFrame(frame); |
| frame = NULL; |
| } |
| |
| if (m_previewQ != NULL) { |
| m_clearList(m_previewQ); |
| } |
| |
| if (m_zoomPreviwWithCscQ != NULL) { |
| m_zoomPreviwWithCscQ->release(); |
| } |
| |
| if (m_previewCallbackGscFrameDoneQ != NULL) { |
| m_clearList(m_previewCallbackGscFrameDoneQ); |
| } |
| |
| for(int i = 0 ; i < MAX_NUM_PIPES ; i++ ) { |
| m_clearList(m_mainSetupQ[i]); |
| } |
| |
| ret = m_stopPreviewInternal(); |
| if (ret < 0) |
| CLOGE("ERR(%s[%d]):m_stopPreviewInternal fail", __FUNCTION__, __LINE__); |
| } |
| |
| /* skip to free and reallocate buffers : flite / 3aa / isp / ispReprocessing */ |
| if (m_bayerBufferMgr != NULL) { |
| m_bayerBufferMgr->resetBuffers(); |
| } |
| if (m_3aaBufferMgr != NULL) { |
| m_3aaBufferMgr->resetBuffers(); |
| } |
| if (m_ispBufferMgr != NULL) { |
| m_ispBufferMgr->resetBuffers(); |
| } |
| if (m_hwDisBufferMgr != NULL) { |
| m_hwDisBufferMgr->resetBuffers(); |
| } |
| |
| /* realloc reprocessing buffer for change burst panorama <-> normal mode */ |
| if (m_ispReprocessingBufferMgr != NULL) { |
| m_ispReprocessingBufferMgr->resetBuffers(); |
| } |
| if (m_sccReprocessingBufferMgr != NULL) { |
| m_sccReprocessingBufferMgr->resetBuffers(); |
| } |
| |
| /* realloc callback buffers */ |
| if (m_scpBufferMgr != NULL) { |
| m_scpBufferMgr->deinit(); |
| m_scpBufferMgr->setBufferCount(0); |
| } |
| if (m_sccBufferMgr != NULL) { |
| m_sccBufferMgr->deinit(); |
| m_sccBufferMgr->setBufferCount(0); |
| } |
| if (m_gscBufferMgr != NULL) { |
| m_gscBufferMgr->resetBuffers(); |
| } |
| |
| if (m_jpegBufferMgr != NULL) { |
| m_jpegBufferMgr->resetBuffers(); |
| } |
| |
| if (m_hwDisBufferMgr != NULL) { |
| m_hwDisBufferMgr->deinit(); |
| } |
| |
| if (m_recordingBufferMgr != NULL) { |
| m_recordingBufferMgr->deinit(); |
| } |
| if (m_previewCallbackBufferMgr != NULL) { |
| m_previewCallbackBufferMgr->deinit(); |
| } |
| if (m_highResolutionCallbackBufferMgr != NULL) { |
| m_highResolutionCallbackBufferMgr->deinit(); |
| } |
| if (m_captureSelector != NULL) { |
| m_captureSelector->release(); |
| } |
| if (m_sccCaptureSelector != NULL) { |
| m_sccCaptureSelector->release(); |
| } |
| |
| #if 0 |
| /* skip to free and reallocate buffers : flite / 3aa / isp / ispReprocessing */ |
| CLOGE(" m_setBuffers free all buffers"); |
| if (m_bayerBufferMgr != NULL) { |
| m_bayerBufferMgr->deinit(); |
| } |
| if (m_3aaBufferMgr != NULL) { |
| m_3aaBufferMgr->deinit(); |
| } |
| if (m_ispBufferMgr != NULL) { |
| m_ispBufferMgr->deinit(); |
| } |
| if (m_hwDisBufferMgr != NULL) { |
| m_hwDisBufferMgr->deinit(); |
| } |
| #endif |
| /* frame manager stop */ |
| m_frameMgr->stop(); |
| m_frameMgr->deleteAllFrame(); |
| |
| |
| m_reprocessingCounter.clearCount(); |
| m_pictureCounter.clearCount(); |
| |
| m_hdrSkipedFcount = 0; |
| m_dynamicSccCount = 0; |
| |
| /* HACK Reset Preview Flag*/ |
| m_resetPreview = false; |
| |
| m_isTryStopFlash= false; |
| m_exitAutoFocusThread = false; |
| m_isNeedAllocPictureBuffer = false; |
| |
| if (m_fdCallbackHeap != NULL) { |
| m_fdCallbackHeap->release(m_fdCallbackHeap); |
| m_fdCallbackHeap = NULL; |
| } |
| |
| m_burstInitFirst = false; |
| |
| #ifdef FORCE_RESET_MULTI_FRAME_FACTORY |
| /* |
| * HACK |
| * This is force-reset frameFactory adn companion |
| */ |
| m_deinitFrameFactory(); |
| m_initFrameFactory(); |
| #endif |
| } |
| |
| bool ExynosCamera::previewEnabled() |
| { |
| CLOGI("INFO(%s[%d]):m_previewEnabled=%d", |
| __FUNCTION__, __LINE__, (int)m_previewEnabled); |
| |
| /* in scalable mode, we should controll out state */ |
| if (m_exynosCameraParameters != NULL && |
| (m_exynosCameraParameters->getScalableSensorMode() == true) && |
| (m_scalableSensorMgr.getMode() == EXYNOS_CAMERA_SCALABLE_CHANGING)) |
| return true; |
| else |
| return m_previewEnabled; |
| } |
| |
| status_t ExynosCamera::storeMetaDataInBuffers(bool enable) |
| { |
| CLOGI("INFO(%s[%d])", __FUNCTION__, __LINE__); |
| |
| return OK; |
| } |
| |
| status_t ExynosCamera::startRecording() |
| { |
| CLOGI("INFO(%s[%d])", __FUNCTION__, __LINE__); |
| |
| if (m_exynosCameraParameters != NULL) { |
| if (m_exynosCameraParameters->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; |
| } |
| } |
| |
| int ret = 0; |
| ExynosCameraActivityAutofocus *autoFocusMgr = m_exynosCameraActivityControl->getAutoFocusMgr(); |
| ExynosCameraActivityFlash *flashMgr = m_exynosCameraActivityControl->getFlashMgr(); |
| |
| if (m_getRecordingEnabled() == true) { |
| CLOGW("WARN(%s[%d]):m_recordingEnabled equals true", __FUNCTION__, __LINE__); |
| ret = INVALID_OPERATION; |
| goto func_exit; |
| } |
| |
| #ifdef USE_FD_AE |
| if (m_exynosCameraParameters != NULL) { |
| m_startFaceDetection(false); |
| } else { |
| CLOGW("(%s[%d]):m_exynosCameraParameters is NULL", __FUNCTION__, __LINE__); |
| return INVALID_OPERATION; |
| } |
| #endif |
| |
| |
| /* Do start recording process */ |
| ret = m_startRecordingInternal(); |
| if (ret < 0) { |
| CLOGE("ERR"); |
| return ret; |
| } |
| |
| m_lastRecordingTimeStamp = 0; |
| m_recordingStartTimeStamp = 0; |
| m_recordingFrameSkipCount = 0; |
| |
| m_setRecordingEnabled(true); |
| |
| autoFocusMgr->setRecordingHint(true); |
| flashMgr->setRecordingHint(true); |
| |
| func_exit: |
| /* wait for initial preview skip */ |
| if (m_exynosCameraParameters != NULL) { |
| int retry = 0; |
| while (m_exynosCameraParameters->getFrameSkipCount() > 0 && retry < 3) { |
| retry++; |
| usleep(33000); |
| CLOGI("INFO(%s[%d]): -OUT- (frameSkipCount:%d) (retry:%d)", __FUNCTION__, __LINE__, m_frameSkipCount, retry); |
| } |
| } |
| |
| return NO_ERROR; |
| } |
| |
| void ExynosCamera::stopRecording() |
| { |
| CLOGI("INFO(%s[%d])", __FUNCTION__, __LINE__); |
| |
| if (m_exynosCameraParameters != NULL) { |
| if (m_exynosCameraParameters->getVisionMode() == true) { |
| CLOGW("WRN(%s[%d]): Vision mode does not support", __FUNCTION__, __LINE__); |
| android_printAssert(NULL, LOG_TAG, "Cannot support this operation"); |
| |
| return; |
| } |
| } |
| |
| int ret = 0; |
| ExynosCameraActivityAutofocus *autoFocusMgr = m_exynosCameraActivityControl->getAutoFocusMgr(); |
| ExynosCameraActivityFlash *flashMgr = m_exynosCameraActivityControl->getFlashMgr(); |
| m_skipCount = 0; |
| |
| if (m_getRecordingEnabled() == false) { |
| return; |
| } |
| m_setRecordingEnabled(false); |
| |
| /* Do stop recording process */ |
| |
| ret = m_stopRecordingInternal(); |
| if (ret < 0) |
| CLOGE("ERR(%s[%d]):m_stopRecordingInternal fail", __FUNCTION__, __LINE__); |
| |
| #ifdef USE_FD_AE |
| if (m_exynosCameraParameters != NULL) { |
| if ((m_exynosCameraParameters->getDualMode() == true && m_exynosCameraParameters->getCameraId() == CAMERA_ID_BACK) || |
| (m_exynosCameraParameters->getVtMode() != 0)) { |
| m_startFaceDetection(false); |
| } else { |
| m_startFaceDetection(true); |
| } |
| } |
| #endif |
| |
| autoFocusMgr->setRecordingHint(false); |
| flashMgr->setRecordingHint(false); |
| flashMgr->setNeedFlashOffDelay(false); |
| } |
| |
| bool ExynosCamera::recordingEnabled() |
| { |
| bool ret = m_getRecordingEnabled(); |
| CLOGI("INFO(%s[%d]):m_recordingEnabled=%d", |
| __FUNCTION__, __LINE__, (int)ret); |
| |
| return ret; |
| } |
| |
| void ExynosCamera::releaseRecordingFrame(const void *opaque) |
| { |
| if (m_exynosCameraParameters != NULL) { |
| if (m_exynosCameraParameters->getVisionMode() == true) { |
| CLOGW("WRN(%s[%d]): Vision mode does not support", __FUNCTION__, __LINE__); |
| android_printAssert(NULL, LOG_TAG, "Cannot support this operation"); |
| |
| return; |
| } |
| } |
| |
| if (m_getRecordingEnabled() == false) { |
| CLOGW("WARN(%s[%d]):m_recordingEnabled equals false", __FUNCTION__, __LINE__); |
| return; |
| } |
| |
| if (m_recordingCallbackHeap == NULL) { |
| CLOGW("WARN(%s[%d]):recordingCallbackHeap equals NULL", __FUNCTION__, __LINE__); |
| return; |
| } |
| |
| bool found = false; |
| struct addrs *recordAddrs = (struct addrs *)m_recordingCallbackHeap->data; |
| struct addrs *releaseFrame = (struct addrs *)opaque; |
| |
| if (recordAddrs != NULL) { |
| for (int32_t i = 0; i < m_recordingBufferCount; i++) { |
| if ((char *)(&(recordAddrs[i])) == (char *)opaque) { |
| found = true; |
| CLOGV("DEBUG(%s[%d]):releaseFrame->bufIndex=%d, fdY=%d", |
| __FUNCTION__, __LINE__, releaseFrame->bufIndex, releaseFrame->fdPlaneY); |
| |
| if (m_doCscRecording == true) { |
| m_releaseRecordingBuffer(releaseFrame->bufIndex); |
| } else { |
| m_recordingTimeStamp[releaseFrame->bufIndex] = 0L; |
| m_recordingBufAvailable[releaseFrame->bufIndex] = true; |
| } |
| |
| break; |
| } |
| m_isFirstStart = false; |
| if (m_exynosCameraParameters != NULL) { |
| m_exynosCameraParameters->setIsFirstStartFlag(m_isFirstStart); |
| } |
| } |
| } |
| |
| if (found == false) |
| CLOGW("WARN(%s[%d]):**** releaseFrame not founded ****", __FUNCTION__, __LINE__); |
| |
| } |
| |
| status_t ExynosCamera::autoFocus() |
| { |
| CLOGI("INFO(%s[%d])", __FUNCTION__, __LINE__); |
| |
| if (m_exynosCameraParameters != NULL) { |
| if (m_exynosCameraParameters->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_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_exynosCameraParameters != NULL) { |
| if (m_exynosCameraParameters->getFocusMode() == FOCUS_MODE_AUTO) { |
| CLOGI("INFO(%s[%d]) ae awb lock", __FUNCTION__, __LINE__); |
| m_exynosCameraParameters->m_setAutoExposureLock(true); |
| m_exynosCameraParameters->m_setAutoWhiteBalanceLock(true); |
| } |
| } |
| #endif |
| |
| return NO_ERROR; |
| } |
| |
| status_t ExynosCamera::cancelAutoFocus() |
| { |
| CLOGI("INFO(%s[%d])", __FUNCTION__, __LINE__); |
| |
| if (m_exynosCameraParameters != NULL) { |
| if (m_exynosCameraParameters->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; |
| } |
| } |
| |
| m_autoFocusRunning = false; |
| |
| #if 0 // not used. |
| if (m_exynosCameraParameters != NULL) { |
| if (m_exynosCameraParameters->getFocusMode() == FOCUS_MODE_AUTO) { |
| CLOGI("INFO(%s[%d]) ae awb unlock", __FUNCTION__, __LINE__); |
| m_exynosCameraParameters->m_setAutoExposureLock(false); |
| m_exynosCameraParameters->m_setAutoWhiteBalanceLock(false); |
| } |
| } |
| #endif |
| |
| if (m_exynosCameraActivityControl->cancelAutoFocus() == false) { |
| CLOGE("ERR(%s):Fail on m_secCamera->cancelAutoFocus()", __FUNCTION__); |
| return UNKNOWN_ERROR; |
| } |
| |
| return NO_ERROR; |
| } |
| |
| status_t ExynosCamera::takePicture() |
| { |
| int ret = 0; |
| int takePictureCount = m_takePictureCounter.getCount(); |
| int seriesShotCount = 0; |
| int currentSeriesShotMode = 0; |
| ExynosCameraFrame *newFrame = NULL; |
| int32_t reprocessingBayerMode = 0; |
| |
| int retryCount = 0; |
| |
| if (m_exynosCameraParameters != NULL) { |
| seriesShotCount = m_exynosCameraParameters->getSeriesShotCount(); |
| currentSeriesShotMode = m_exynosCameraParameters->getSeriesShotMode(); |
| reprocessingBayerMode = m_exynosCameraParameters->getReprocessingBayerMode(); |
| if (m_exynosCameraParameters->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; |
| } |
| } else { |
| CLOGE("ERR(%s):m_exynosCameraParameters is NULL", __FUNCTION__); |
| return INVALID_OPERATION; |
| } |
| |
| /* wait autoFocus is over for turning on preFlash */ |
| m_autoFocusThread->join(); |
| |
| m_exynosCameraParameters->setMarkingOfExifFlash(0); |
| |
| /* HACK Reset Preview Flag*/ |
| while ((m_resetPreview == true) && (retryCount < 10)) { |
| usleep(200000); |
| retryCount ++; |
| CLOGI("INFO(%s[%d]) retryCount(%d) m_resetPreview(%d)", __FUNCTION__, __LINE__, retryCount, m_resetPreview); |
| } |
| |
| if (takePictureCount < 0) { |
| CLOGE("ERR(%s[%d]): takePicture is called too much. takePictureCount(%d) / seriesShotCount(%d) . so, fail", |
| __FUNCTION__, __LINE__, takePictureCount, seriesShotCount); |
| return INVALID_OPERATION; |
| } else if (takePictureCount == 0) { |
| if (seriesShotCount == 0) { |
| m_captureLock.lock(); |
| if (m_pictureEnabled == true) { |
| CLOGE("ERR(%s[%d]): take picture is inprogressing", __FUNCTION__, __LINE__); |
| /* return NO_ERROR; */ |
| m_captureLock.unlock(); |
| return INVALID_OPERATION; |
| } |
| m_captureLock.unlock(); |
| |
| /* general shot */ |
| seriesShotCount = 1; |
| } |
| m_takePictureCounter.setCount(seriesShotCount); |
| } |
| |
| CLOGI("INFO(%s[%d]): takePicture start m_takePictureCounter(%d), currentSeriesShotMode(%d) seriesShotCount(%d)", |
| __FUNCTION__, __LINE__, m_takePictureCounter.getCount(), currentSeriesShotMode, seriesShotCount); |
| |
| m_printExynosCameraInfo(__FUNCTION__); |
| |
| if(m_exynosCameraParameters->getShotMode() == SHOT_MODE_RICH_TONE) { |
| m_hdrEnabled = true; |
| } else { |
| m_hdrEnabled = false; |
| } |
| |
| /* TODO: Dynamic bayer capture, currently support only single shot */ |
| if (reprocessingBayerMode == REPROCESSING_BAYER_MODE_PURE_DYNAMIC) { |
| int pipeId = m_getBayerPipeId(); |
| |
| if (m_bayerBufferMgr->getNumOfAvailableBuffer() > 0) { |
| m_previewFrameFactory->setRequestFLITE(true); |
| ret = generateFrame(-1, &newFrame); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]):generateFrame fail", __FUNCTION__, __LINE__); |
| return ret; |
| } |
| m_previewFrameFactory->setRequestFLITE(false); |
| |
| ret = m_setupEntity(pipeId, newFrame); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]):setupEntity fail", __FUNCTION__, __LINE__); |
| return ret; |
| } |
| |
| m_previewFrameFactory->pushFrameToPipe(&newFrame, pipeId); |
| m_previewFrameFactory->setOutputFrameQToPipe(m_pipeFrameDoneQ, pipeId); |
| } |
| |
| m_previewFrameFactory->startThread(pipeId); |
| } else if (reprocessingBayerMode == REPROCESSING_BAYER_MODE_DIRTY_DYNAMIC) { |
| /* Comment out, because it included 3AA, it always running */ |
| /* |
| int pipeId = m_getBayerPipeId(); |
| |
| if (m_bayerBufferMgr->getNumOfAvailableBuffer() > 0) { |
| m_previewFrameFactory->setRequest3AC(true); |
| ret = generateFrame(-1, &newFrame); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]):generateFrame fail", __FUNCTION__, __LINE__); |
| return ret; |
| } |
| m_previewFrameFactory->setRequest3AC(false); |
| |
| ret = m_setupEntity(pipeId, newFrame); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]):setupEntity fail", __FUNCTION__, __LINE__); |
| return ret; |
| } |
| |
| m_previewFrameFactory->pushFrameToPipe(&newFrame, pipeId); |
| m_previewFrameFactory->setOutputFrameQToPipe(m_pipeFrameDoneQ, pipeId); |
| } |
| |
| m_previewFrameFactory->startThread(pipeId); |
| */ |
| if (m_bayerBufferMgr->getNumOfAvailableBuffer() > 0) |
| m_previewFrameFactory->setRequest3AC(true); |
| } else if (m_exynosCameraParameters->getRecordingHint() == true |
| && m_exynosCameraParameters->isUsing3acForIspc() == true) { |
| if (m_sccBufferMgr->getNumOfAvailableBuffer() > 0) |
| m_previewFrameFactory->setRequest3AC(true); |
| } |
| |
| |
| if (m_takePictureCounter.getCount() == seriesShotCount) { |
| ExynosCameraActivitySpecialCapture *m_sCaptureMgr = m_exynosCameraActivityControl->getSpecialCaptureMgr(); |
| ExynosCameraActivityFlash *m_flashMgr = m_exynosCameraActivityControl->getFlashMgr(); |
| |
| m_stopBurstShot = false; |
| |
| if (m_exynosCameraParameters->isReprocessing() == true) |
| m_captureSelector->setIsFirstFrame(true); |
| else |
| m_sccCaptureSelector->setIsFirstFrame(true); |
| |
| #if 0 |
| if (m_exynosCameraParameters->isReprocessing() == false || m_exynosCameraParameters->getSeriesShotCount() > 0 || |
| m_hdrEnabled == true) { |
| m_pictureFrameFactory = m_previewFrameFactory; |
| if (m_exynosCameraParameters->getUseDynamicScc() == true) { |
| if (isOwnScc(getCameraId()) == true) |
| m_previewFrameFactory->setRequestSCC(true); |
| else |
| m_previewFrameFactory->setRequestISPC(true); |
| |
| /* boosting dynamic SCC */ |
| if (m_hdrEnabled == false && |
| currentSeriesShotMode == SERIES_SHOT_MODE_NONE) { |
| ret = m_boostDynamicCapture(); |
| if (ret < 0) |
| CLOGW("WRN(%s[%d]): fail to boosting dynamic capture", __FUNCTION__, __LINE__); |
| } |
| |
| } |
| } else { |
| m_pictureFrameFactory = m_reprocessingFrameFactory; |
| } |
| #endif |
| |
| if (m_exynosCameraParameters->getScalableSensorMode()) { |
| m_exynosCameraParameters->setScalableSensorMode(false); |
| stopPreview(); |
| setPreviewWindow(m_previewWindow); |
| startPreview(); |
| m_exynosCameraParameters->setScalableSensorMode(true); |
| } |
| |
| CLOGI("INFO(%s[%d]): takePicture enabled, takePictureCount(%d)", |
| __FUNCTION__, __LINE__, m_takePictureCounter.getCount()); |
| m_pictureEnabled = true; |
| m_takePictureCounter.decCount(); |
| m_isNeedAllocPictureBuffer = true; |
| |
| m_startPictureBufferThread->join(); |
| |
| if (m_exynosCameraParameters->isReprocessing() == true) { |
| m_startPictureInternalThread->join(); |
| |
| #ifdef BURST_CAPTURE |
| if(seriesShotCount > 1) { |
| int allocCount = 0; |
| int addCount = 0; |
| CLOGD("DEBUG(%s[%d]): realloc buffer for burst shot", __FUNCTION__, __LINE__); |
| m_burstRealloc = false; |
| |
| allocCount = m_sccReprocessingBufferMgr->getAllocatedBufferCount(); |
| addCount = (allocCount <= NUM_BURST_GSC_JPEG_INIT_BUFFER)?(NUM_BURST_GSC_JPEG_INIT_BUFFER-allocCount):0; |
| if( addCount > 0 ){ |
| m_sccReprocessingBufferMgr->increase(addCount); |
| } |
| |
| allocCount = m_jpegBufferMgr->getAllocatedBufferCount(); |
| addCount = (allocCount <= NUM_BURST_GSC_JPEG_INIT_BUFFER)?(NUM_BURST_GSC_JPEG_INIT_BUFFER-allocCount):0; |
| if( addCount > 0 ){ |
| m_jpegBufferMgr->increase(addCount); |
| } |
| m_isNeedAllocPictureBuffer = true; |
| } |
| #endif |
| } |
| |
| CLOGD("DEBUG(%s[%d]): currentSeriesShotMode(%d), m_flashMgr->getNeedCaptureFlash(%d)", |
| __FUNCTION__, __LINE__, currentSeriesShotMode, m_flashMgr->getNeedCaptureFlash()); |
| |
| if (m_hdrEnabled == true) { |
| seriesShotCount = HDR_REPROCESSING_COUNT; |
| m_sCaptureMgr->setCaptureStep(ExynosCameraActivitySpecialCapture::SCAPTURE_STEP_START); |
| m_sCaptureMgr->resetHdrStartFcount(); |
| m_exynosCameraParameters->setFrameSkipCount(13); |
| } else if ((m_flashMgr->getNeedCaptureFlash() == true && currentSeriesShotMode == SERIES_SHOT_MODE_NONE)) { |
| m_exynosCameraParameters->setMarkingOfExifFlash(1); |
| |
| if (m_flashMgr->checkPreFlash() == false && m_isTryStopFlash == false) { |
| m_flashMgr->setCaptureStatus(true); |
| CLOGD("DEBUG(%s[%d]): checkPreFlash(false), Start auto focus internally", __FUNCTION__, __LINE__); |
| m_autoFocusType = AUTO_FOCUS_HAL; |
| m_flashMgr->setFlashTrigerPath(ExynosCameraActivityFlash::FLASH_TRIGGER_SHORT_BUTTON); |
| m_flashMgr->setFlashWaitCancel(false); |
| |
| /* execute autoFocus for preFlash */ |
| m_autoFocusThread->requestExitAndWait(); |
| m_autoFocusThread->run(PRIORITY_DEFAULT); |
| } |
| } |
| |
| m_exynosCameraParameters->setSetfileYuvRange(); |
| |
| m_reprocessingCounter.setCount(seriesShotCount); |
| if (m_prePictureThread->isRunning() == false) { |
| if (m_prePictureThread->run(PRIORITY_DEFAULT) != NO_ERROR) { |
| CLOGE("ERR(%s[%d]):couldn't run pre-picture thread", __FUNCTION__, __LINE__); |
| return INVALID_OPERATION; |
| } |
| } |
| |
| m_jpegCounter.setCount(seriesShotCount); |
| m_pictureCounter.setCount(seriesShotCount); |
| if (m_pictureThread->isRunning() == false) |
| ret = m_pictureThread->run(); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]):couldn't run picture thread, ret(%d)", __FUNCTION__, __LINE__, ret); |
| return INVALID_OPERATION; |
| } |
| |
| /* HDR, LLS, SIS should make YUV callback data. so don't use jpeg thread */ |
| if (!(m_hdrEnabled == true || |
| currentSeriesShotMode == SERIES_SHOT_MODE_LLS || |
| currentSeriesShotMode == SERIES_SHOT_MODE_SIS || |
| m_exynosCameraParameters->getShotMode() == SHOT_MODE_FRONT_PANORAMA)) { |
| m_jpegCallbackThread->join(); |
| ret = m_jpegCallbackThread->run(); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]):couldn't run jpeg callback thread, ret(%d)", __FUNCTION__, __LINE__, ret); |
| return INVALID_OPERATION; |
| } |
| } |
| } else { |
| /* HDR, LLS, SIS should make YUV callback data. so don't use jpeg thread */ |
| if (!(m_hdrEnabled == true || |
| currentSeriesShotMode == SERIES_SHOT_MODE_LLS || |
| currentSeriesShotMode == SERIES_SHOT_MODE_SIS || |
| m_exynosCameraParameters->getShotMode() == SHOT_MODE_FRONT_PANORAMA)) { |
| /* series shot : push buffer to callback thread. */ |
| m_jpegCallbackThread->join(); |
| ret = m_jpegCallbackThread->run(); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]):couldn't run jpeg callback thread, ret(%d)", __FUNCTION__, __LINE__, ret); |
| return INVALID_OPERATION; |
| } |
| } |
| CLOGI("INFO(%s[%d]): series shot takePicture, takePictureCount(%d)", |
| __FUNCTION__, __LINE__, m_takePictureCounter.getCount()); |
| m_takePictureCounter.decCount(); |
| |
| /* TODO : in case of no reprocesssing, we make zsl scheme or increse buf */ |
| if (m_exynosCameraParameters->isReprocessing() == false) |
| m_pictureEnabled = true; |
| } |
| |
| return NO_ERROR; |
| } |
| |
| status_t ExynosCamera::cancelPicture() |
| { |
| CLOGI("INFO(%s[%d])", __FUNCTION__, __LINE__); |
| |
| if (m_exynosCameraParameters != NULL) { |
| if (m_exynosCameraParameters->getVisionMode() == true) { |
| CLOGW("WRN(%s[%d]): Vision mode does not support", __FUNCTION__, __LINE__); |
| /* android_printAssert(NULL, LOG_TAG, "Cannot support this operation"); */ |
| |
| return NO_ERROR; |
| } |
| } |
| |
| /* |
| m_takePictureCounter.clearCount(); |
| m_reprocessingCounter.clearCount(); |
| m_pictureCounter.clearCount(); |
| m_jpegCounter.clearCount(); |
| */ |
| |
| return NO_ERROR; |
| } |
| |
| status_t ExynosCamera::setParameters(const CameraParameters& params) |
| { |
| status_t ret = NO_ERROR; |
| CLOGI("INFO(%s[%d])", __FUNCTION__, __LINE__); |
| |
| #ifdef SCALABLE_ON |
| m_exynosCameraParameters->setScalableSensorMode(true); |
| #else |
| m_exynosCameraParameters->setScalableSensorMode(false); |
| #endif |
| |
| ret = m_exynosCameraParameters->setParameters(params); |
| #if 1 |
| /* HACK Reset Preview Flag*/ |
| if (m_exynosCameraParameters->getRestartPreview() == true && m_previewEnabled == true) { |
| m_resetPreview = true; |
| ret = m_restartPreviewInternal(); |
| m_resetPreview = false; |
| CLOGI("INFO(%s[%d]) m_resetPreview(%d)", __FUNCTION__, __LINE__, m_resetPreview); |
| |
| if (ret < 0) |
| CLOGE("(%s[%d]): restart preview internal fail", __FUNCTION__, __LINE__); |
| } |
| #endif |
| return ret; |
| |
| } |
| |
| CameraParameters ExynosCamera::getParameters() const |
| { |
| CLOGI("INFO(%s[%d])", __FUNCTION__, __LINE__); |
| |
| return m_exynosCameraParameters->getParameters(); |
| } |
| |
| int ExynosCamera::getMaxNumDetectedFaces(void) |
| { |
| return m_exynosCameraParameters->getMaxNumDetectedFaces(); |
| } |
| |
| bool ExynosCamera::m_startFaceDetection(bool toggle) |
| { |
| CLOGD("DEBUG(%s[%d]) toggle : %d", __FUNCTION__, __LINE__, toggle); |
| |
| if (toggle == true) { |
| m_exynosCameraParameters->setFdEnable(true); |
| m_exynosCameraParameters->setFdMode(FACEDETECT_MODE_FULL); |
| } else { |
| m_exynosCameraParameters->setFdEnable(false); |
| m_exynosCameraParameters->setFdMode(FACEDETECT_MODE_OFF); |
| } |
| |
| memset(&m_frameMetadata, 0, sizeof(camera_frame_metadata_t)); |
| |
| return true; |
| } |
| |
| bool ExynosCamera::startFaceDetection(void) |
| { |
| if (m_flagStartFaceDetection == true) { |
| CLOGD("DEBUG(%s):Face detection already started..", __FUNCTION__); |
| return true; |
| } |
| |
| /* FD-AE is always on */ |
| #ifdef USE_FD_AE |
| #else |
| m_startFaceDetection(true); |
| #endif |
| |
| 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::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_startFaceDetection(false); |
| #endif |
| m_flagStartFaceDetection = false; |
| |
| return true; |
| } |
| |
| bool ExynosCamera::startCurrentSet(void) |
| { |
| m_currentSetStart = true; |
| |
| return true; |
| } |
| |
| bool ExynosCamera::stopCurrentSet(void) |
| { |
| m_currentSetStart = false; |
| |
| 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; |
| } |
| |
| bool ExynosCamera::m_facedetectThreadFunc(void) |
| { |
| int32_t status = 0; |
| bool ret = true; |
| |
| int index = 0; |
| int count = 0; |
| |
| ExynosCameraFrame *newFrame = NULL; |
| uint32_t frameCnt = 0; |
| |
| if (m_previewEnabled == false) { |
| CLOGD("DEBUG(%s):preview is stopped, thread stop", __FUNCTION__); |
| ret = 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); |
| ret = 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, ret(%d)", __FUNCTION__, ret); |
| } |
| goto func_exit; |
| } |
| |
| count = m_facedetectQ->getSizeOfProcessQ(); |
| if (count >= MAX_FACEDETECT_THREADQ_SIZE) { |
| CLOGE("ERR(%s[%d]):m_facedetectQ skipped QSize(%d) frame(%d)", __FUNCTION__, __LINE__, count, newFrame->getFrameCount()); |
| if (newFrame != NULL) { |
| newFrame->decRef(); |
| m_frameMgr->deleteFrame(newFrame); |
| newFrame = NULL; |
| } |
| for (int i = 0 ; i < count-1 ; i++) { |
| m_facedetectQ->popProcessQ(&newFrame); |
| if (newFrame != NULL) { |
| newFrame->decRef(); |
| m_frameMgr->deleteFrame(newFrame); |
| newFrame = NULL; |
| } |
| } |
| m_facedetectQ->popProcessQ(&newFrame); |
| } |
| |
| status = m_doFdCallbackFunc(newFrame); |
| if (status < 0) { |
| CLOGE("ERR(%s[%d]) m_doFdCallbackFunc failed(%d).", __FUNCTION__, __LINE__, status); |
| } |
| |
| if (m_facedetectQ->getSizeOfProcessQ() > 0) { |
| ret = true; |
| } |
| |
| if (newFrame != NULL) { |
| newFrame->decRef(); |
| m_frameMgr->deleteFrame(newFrame); |
| newFrame = NULL; |
| } |
| |
| func_exit: |
| |
| return ret; |
| } |
| |
| status_t ExynosCamera::m_doFdCallbackFunc(ExynosCameraFrame *frame) |
| { |
| ExynosCameraDurationTimer m_fdcallbackTimer; |
| long long m_fdcallbackTimerTime; |
| |
| struct camera2_shot_ext *meta_shot_ext = NULL; |
| meta_shot_ext = new struct camera2_shot_ext; |
| if (meta_shot_ext == NULL) { |
| CLOGE("ERR(%s[%d]) meta_shot_ext is null", __FUNCTION__, __LINE__); |
| return INVALID_OPERATION; |
| } |
| |
| memset(meta_shot_ext, 0x00, sizeof(struct camera2_shot_ext)); |
| if (frame->getDynamicMeta(meta_shot_ext) != NO_ERROR) { |
| CLOGE("ERR(%s[%d]) meta_shot_ext is null", __FUNCTION__, __LINE__); |
| if (meta_shot_ext) { |
| delete meta_shot_ext; |
| meta_shot_ext = NULL; |
| } |
| return INVALID_OPERATION; |
| } |
| |
| if (m_flagStartFaceDetection == true) { |
| int id[NUM_OF_DETECTED_FACES]; |
| int score[NUM_OF_DETECTED_FACES]; |
| ExynosRect2 detectedFace[NUM_OF_DETECTED_FACES]; |
| ExynosRect2 detectedLeftEye[NUM_OF_DETECTED_FACES]; |
| ExynosRect2 detectedRightEye[NUM_OF_DETECTED_FACES]; |
| ExynosRect2 detectedMouth[NUM_OF_DETECTED_FACES]; |
| int numOfDetectedFaces = 0; |
| int num = 0; |
| struct camera2_dm *dm = NULL; |
| int previewW, previewH; |
| |
| memset(&id, 0x00, sizeof(int) * NUM_OF_DETECTED_FACES); |
| memset(&score, 0x00, sizeof(int) * NUM_OF_DETECTED_FACES); |
| |
| m_exynosCameraParameters->getHwPreviewSize(&previewW, &previewH); |
| |
| dm = &(meta_shot_ext->shot.dm); |
| if (dm == NULL) { |
| CLOGE("ERR(%s[%d]) dm data is null", __FUNCTION__, __LINE__); |
| delete meta_shot_ext; |
| meta_shot_ext = NULL; |
| return INVALID_OPERATION; |
| } |
| |
| CLOGV("DEBUG(%s[%d]) faceDetectMode(%d)", __FUNCTION__, __LINE__, dm->stats.faceDetectMode); |
| CLOGV("[%d %d]", dm->stats.faceRectangles[0][0], dm->stats.faceRectangles[0][1]); |
| CLOGV("[%d %d]", dm->stats.faceRectangles[0][2], dm->stats.faceRectangles[0][3]); |
| |
| num = NUM_OF_DETECTED_FACES; |
| if (getMaxNumDetectedFaces() < num) |
| num = getMaxNumDetectedFaces(); |
| |
| switch (dm->stats.faceDetectMode) { |
| case FACEDETECT_MODE_SIMPLE: |
| case FACEDETECT_MODE_FULL: |
| break; |
| case FACEDETECT_MODE_OFF: |
| default: |
| num = 0; |
| break; |
| } |
| |
| for (int i = 0; i < num; i++) { |
| if (dm->stats.faceIds[i]) { |
| switch (dm->stats.faceDetectMode) { |
| case FACEDETECT_MODE_OFF: |
| break; |
| case FACEDETECT_MODE_SIMPLE: |
| detectedFace[i].x1 = dm->stats.faceRectangles[i][0]; |
| detectedFace[i].y1 = dm->stats.faceRectangles[i][1]; |
| detectedFace[i].x2 = dm->stats.faceRectangles[i][2]; |
| detectedFace[i].y2 = dm->stats.faceRectangles[i][3]; |
| numOfDetectedFaces++; |
| break; |
| case FACEDETECT_MODE_FULL: |
| id[i] = dm->stats.faceIds[i]; |
| score[i] = dm->stats.faceScores[i]; |
| |
| detectedFace[i].x1 = dm->stats.faceRectangles[i][0]; |
| detectedFace[i].y1 = dm->stats.faceRectangles[i][1]; |
| detectedFace[i].x2 = dm->stats.faceRectangles[i][2]; |
| detectedFace[i].y2 = dm->stats.faceRectangles[i][3]; |
| |
| detectedLeftEye[i].x1 |
| = detectedLeftEye[i].y1 |
| = detectedLeftEye[i].x2 |
| = detectedLeftEye[i].y2 = -1; |
| |
| detectedRightEye[i].x1 |
| = detectedRightEye[i].y1 |
| = detectedRightEye[i].x2 |
| = detectedRightEye[i].y2 = -1; |
| |
| detectedMouth[i].x1 |
| = detectedMouth[i].y1 |
| = detectedMouth[i].x2 |
| = detectedMouth[i].y2 = -1; |
| |
| numOfDetectedFaces++; |
| break; |
| default: |
| break; |
| } |
| } |
| } |
| |
| if (0 < numOfDetectedFaces) { |
| /* |
| * camera.h |
| * width : -1000~1000 |
| * height : -1000~1000 |
| * if eye, mouth is not detectable : -2000, -2000. |
| */ |
| memset(m_faces, 0, sizeof(camera_face_t) * NUM_OF_DETECTED_FACES); |
| |
| int realNumOfDetectedFaces = 0; |
| |
| for (int i = 0; i < numOfDetectedFaces; i++) { |
| /* |
| * over 50s, we will catch |
| * if (score[i] < 50) |
| * continue; |
| */ |
| m_faces[realNumOfDetectedFaces].rect[0] = m_calibratePosition(previewW, 2000, detectedFace[i].x1) - 1000; |
| m_faces[realNumOfDetectedFaces].rect[1] = m_calibratePosition(previewH, 2000, detectedFace[i].y1) - 1000; |
| m_faces[realNumOfDetectedFaces].rect[2] = m_calibratePosition(previewW, 2000, detectedFace[i].x2) - 1000; |
| m_faces[realNumOfDetectedFaces].rect[3] = m_calibratePosition(previewH, 2000, detectedFace[i].y2) - 1000; |
| |
| m_faces[realNumOfDetectedFaces].id = id[i]; |
| m_faces[realNumOfDetectedFaces].score = score[i] > 100 ? 100 : score[i]; |
| |
| m_faces[realNumOfDetectedFaces].left_eye[0] = (detectedLeftEye[i].x1 < 0) ? -2000 : m_calibratePosition(previewW, 2000, detectedLeftEye[i].x1) - 1000; |
| m_faces[realNumOfDetectedFaces].left_eye[1] = (detectedLeftEye[i].y1 < 0) ? -2000 : m_calibratePosition(previewH, 2000, detectedLeftEye[i].y1) - 1000; |
| |
| m_faces[realNumOfDetectedFaces].right_eye[0] = (detectedRightEye[i].x1 < 0) ? -2000 : m_calibratePosition(previewW, 2000, detectedRightEye[i].x1) - 1000; |
| m_faces[realNumOfDetectedFaces].right_eye[1] = (detectedRightEye[i].y1 < 0) ? -2000 : m_calibratePosition(previewH, 2000, detectedRightEye[i].y1) - 1000; |
| |
| m_faces[realNumOfDetectedFaces].mouth[0] = (detectedMouth[i].x1 < 0) ? -2000 : m_calibratePosition(previewW, 2000, detectedMouth[i].x1) - 1000; |
| m_faces[realNumOfDetectedFaces].mouth[1] = (detectedMouth[i].y1 < 0) ? -2000 : m_calibratePosition(previewH, 2000, detectedMouth[i].y1) - 1000; |
| |
| CLOGV("face posision(cal:%d,%d %dx%d)(org:%d,%d %dx%d), id(%d), score(%d)", |
| m_faces[realNumOfDetectedFaces].rect[0], m_faces[realNumOfDetectedFaces].rect[1], |
| m_faces[realNumOfDetectedFaces].rect[2], m_faces[realNumOfDetectedFaces].rect[3], |
| detectedFace[i].x1, detectedFace[i].y1, |
| detectedFace[i].x2, detectedFace[i].y2, |
| m_faces[realNumOfDetectedFaces].id, |
| m_faces[realNumOfDetectedFaces].score); |
| |
| CLOGV("DEBUG(%s[%d]): left eye(%d,%d), right eye(%d,%d), mouth(%dx%d), num of facese(%d)", |
| __FUNCTION__, __LINE__, |
| m_faces[realNumOfDetectedFaces].left_eye[0], |
| m_faces[realNumOfDetectedFaces].left_eye[1], |
| m_faces[realNumOfDetectedFaces].right_eye[0], |
| m_faces[realNumOfDetectedFaces].right_eye[1], |
| m_faces[realNumOfDetectedFaces].mouth[0], |
| m_faces[realNumOfDetectedFaces].mouth[1], |
| realNumOfDetectedFaces |
| ); |
| |
| realNumOfDetectedFaces++; |
| } |
| |
| m_frameMetadata.number_of_faces = realNumOfDetectedFaces; |
| m_frameMetadata.faces = m_faces; |
| |
| m_faceDetected = true; |
| m_fdThreshold = 0; |
| } else { |
| if (m_faceDetected == true && m_fdThreshold < NUM_OF_DETECTED_FACES_THRESHOLD) { |
| /* waiting the unexpected fail about face detected */ |
| m_fdThreshold++; |
| } else { |
| if (0 < m_frameMetadata.number_of_faces) |
| memset(m_faces, 0, sizeof(camera_face_t) * NUM_OF_DETECTED_FACES); |
| |
| m_frameMetadata.number_of_faces = 0; |
| m_frameMetadata.faces = m_faces; |
| m_fdThreshold = 0; |
| m_faceDetected = false; |
| } |
| } |
| } else { |
| if (0 < m_frameMetadata.number_of_faces) |
| memset(m_faces, 0, sizeof(camera_face_t) * NUM_OF_DETECTED_FACES); |
| |
| m_frameMetadata.number_of_faces = 0; |
| m_frameMetadata.faces = m_faces; |
| |
| m_fdThreshold = 0; |
| |
| m_faceDetected = false; |
| } |
| |
| #ifdef TOUCH_AE |
| if(((m_exynosCameraParameters->getMeteringMode() >= METERING_MODE_CENTER_TOUCH) && (m_exynosCameraParameters->getMeteringMode() <= METERING_MODE_AVERAGE_TOUCH)) |
| && ((meta_shot_ext->shot.dm.aa.aeState == AE_STATE_CONVERGED) || (meta_shot_ext->shot.dm.aa.aeState == AE_STATE_FLASH_REQUIRED))) { |
| m_notifyCb(AE_RESULT, 0, 0, m_callbackCookie); |
| CLOGV("INFO(%s[%d]): AE_RESULT(%d)", __FUNCTION__, __LINE__, meta_shot_ext->shot.dm.aa.aeState); |
| } |
| #endif |
| |
| delete meta_shot_ext; |
| meta_shot_ext = NULL; |
| |
| m_fdcallbackTimer.start(); |
| |
| if (m_exynosCameraParameters->msgTypeEnabled(CAMERA_MSG_PREVIEW_METADATA) && |
| (m_flagStartFaceDetection || m_flagLLSStart || m_flagLightCondition)) |
| { |
| setBit(&m_callbackState, CALLBACK_STATE_PREVIEW_META, false); |
| m_dataCb(CAMERA_MSG_PREVIEW_METADATA, m_fdCallbackHeap, 0, &m_frameMetadata, m_callbackCookie); |
| clearBit(&m_callbackState, CALLBACK_STATE_PREVIEW_META, false); |
| } |
| m_fdcallbackTimer.stop(); |
| m_fdcallbackTimerTime = m_fdcallbackTimer.durationUsecs(); |
| |
| if((int)m_fdcallbackTimerTime / 1000 > 50) { |
| CLOGD("INFO(%s[%d]): FD callback duration time : (%d)mec", __FUNCTION__, __LINE__, (int)m_fdcallbackTimerTime / 1000); |
| } |
| |
| return NO_ERROR; |
| } |
| |
| status_t ExynosCamera::sendCommand(int32_t command, int32_t arg1, int32_t arg2) |
| { |
| ExynosCameraActivityUCTL *uctlMgr = NULL; |
| CLOGV("INFO(%s[%d])", __FUNCTION__, __LINE__); |
| |
| if (m_exynosCameraParameters != NULL) { |
| if (m_exynosCameraParameters->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; |
| } |
| } else { |
| CLOGE("ERR(%s):m_exynosCameraParameters is NULL", __FUNCTION__); |
| return INVALID_OPERATION; |
| } |
| |
| /* TO DO : implemented based on the command */ |
| switch(command) { |
| case CAMERA_CMD_START_FACE_DETECTION: |
| case CAMERA_CMD_STOP_FACE_DETECTION: |
| if (getMaxNumDetectedFaces() == 0) { |
| CLOGE("ERR(%s):getMaxNumDetectedFaces == 0", __FUNCTION__); |
| return BAD_VALUE; |
| } |
| |
| if (arg1 == CAMERA_FACE_DETECTION_SW) { |
| CLOGD("DEBUG(%s):only support HW face dectection", __FUNCTION__); |
| return BAD_VALUE; |
| } |
| |
| if (command == CAMERA_CMD_START_FACE_DETECTION) { |
| CLOGD("DEBUG(%s):CAMERA_CMD_START_FACE_DETECTION is called!", __FUNCTION__); |
| if (m_flagStartFaceDetection == false |
| && startFaceDetection() == false) { |
| CLOGE("ERR(%s):startFaceDetection() fail", __FUNCTION__); |
| return BAD_VALUE; |
| } |
| } else { |
| CLOGD("DEBUG(%s):CAMERA_CMD_STOP_FACE_DETECTION is called!", __FUNCTION__); |
| if ( m_flagStartFaceDetection == true |
| && stopFaceDetection() == false) { |
| CLOGE("ERR(%s):stopFaceDetection() fail", __FUNCTION__); |
| return BAD_VALUE; |
| } |
| } |
| break; |
| #ifdef BURST_CAPTURE |
| case 1571: /* HAL_CMD_RUN_BURST_TAKE */ |
| CLOGD("DEBUG(%s):HAL_CMD_RUN_BURST_TAKE is called!", __FUNCTION__); |
| |
| if( m_burstInitFirst ) { |
| m_burstRealloc = true; |
| m_burstInitFirst = false; |
| } |
| m_exynosCameraParameters->setSeriesShotMode(SERIES_SHOT_MODE_BURST); |
| m_exynosCameraParameters->setSeriesShotSaveLocation(arg1); |
| m_takePictureCounter.setCount(0); |
| |
| m_burstCaptureCallbackCount = 0; |
| |
| { |
| // Check jpeg save path |
| char default_path[20]; |
| int SeriesSaveLocation = m_exynosCameraParameters->getSeriesShotSaveLocation(); |
| |
| memset(default_path, 0, sizeof(default_path)); |
| |
| if (SeriesSaveLocation == BURST_SAVE_PHONE) |
| strncpy(default_path, BURST_SAVE_PATH_PHONE, sizeof(default_path)-1); |
| else if (SeriesSaveLocation == BURST_SAVE_SDCARD) |
| strncpy(default_path, BURST_SAVE_PATH_EXT, sizeof(default_path)-1); |
| |
| m_CheckBurstJpegSavingPath(default_path); |
| } |
| |
| #ifdef USE_DVFS_LOCK |
| m_exynosCameraParameters->setDvfsLock(true); |
| #endif |
| break; |
| case 1572: /* HAL_CMD_STOP_BURST_TAKE */ |
| CLOGD("DEBUG(%s):HAL_CMD_STOP_BURST_TAKE is called!", __FUNCTION__); |
| m_takePictureCounter.setCount(0); |
| |
| if (m_exynosCameraParameters->getSeriesShotCount() == MAX_SERIES_SHOT_COUNT) { |
| m_reprocessingCounter.clearCount(); |
| m_pictureCounter.clearCount(); |
| m_jpegCounter.clearCount(); |
| } |
| |
| m_stopBurstShot = true; |
| |
| m_clearJpegCallbackThread(false); |
| |
| m_exynosCameraParameters->setSeriesShotMode(SERIES_SHOT_MODE_NONE); |
| |
| #ifdef USE_DVFS_LOCK |
| if (m_exynosCameraParameters->getDvfsLock() == true) |
| m_exynosCameraParameters->setDvfsLock(false); |
| #endif |
| break; |
| case 1573: /* HAL_CMD_DELETE_BURST_TAKE */ |
| CLOGD("DEBUG(%s):HAL_CMD_DELETE_BURST_TAKE is called!", __FUNCTION__); |
| m_takePictureCounter.setCount(0); |
| break; |
| #endif |
| case 1351: /*CAMERA_CMD_AUTO_LOW_LIGHT_SET */ |
| CLOGD("DEBUG(%s):CAMERA_CMD_AUTO_LOW_LIGHT_SET is called!%d", __FUNCTION__, arg1); |
| if(arg1) { |
| if( m_flagLLSStart != true) { |
| m_flagLLSStart = true; |
| } |
| } else { |
| m_flagLLSStart = false; |
| } |
| break; |
| case 1801: /* HAL_ENABLE_LIGHT_CONDITION*/ |
| CLOGD("DEBUG(%s):HAL_ENABLE_LIGHT_CONDITION is called!%d", __FUNCTION__, arg1); |
| if(arg1) { |
| m_flagLightCondition = true; |
| } else { |
| m_flagLightCondition = false; |
| } |
| break; |
| /* 1510: CAMERA_CMD_SET_FLIP */ |
| case 1510 : |
| CLOGD("DEBUG(%s):CAMERA_CMD_SET_FLIP is called!%d", __FUNCTION__, arg1); |
| m_exynosCameraParameters->setFlipHorizontal(arg1); |
| break; |
| /* 1521: CAMERA_CMD_DEVICE_ORIENTATION */ |
| case 1521: |
| CLOGD("DEBUG(%s):CAMERA_CMD_DEVICE_ORIENTATION is called!%d", __FUNCTION__, arg1); |
| m_exynosCameraParameters->setDeviceOrientation(arg1); |
| uctlMgr = m_exynosCameraActivityControl->getUCTLMgr(); |
| if (uctlMgr != NULL) |
| uctlMgr->setDeviceRotation(m_exynosCameraParameters->getFdOrientation()); |
| break; |
| /*1641: CAMERA_CMD_ADVANCED_MACRO_FOCUS*/ |
| case 1641: |
| CLOGD("DEBUG(%s):CAMERA_CMD_ADVANCED_MACRO_FOCUS is called!%d", __FUNCTION__, arg1); |
| m_exynosCameraParameters->setAutoFocusMacroPosition(ExynosCameraActivityAutofocus::AUTOFOCUS_MACRO_POSITION_CENTER); |
| break; |
| /*1642: CAMERA_CMD_FOCUS_LOCATION*/ |
| case 1642: |
| CLOGD("DEBUG(%s):CAMERA_CMD_FOCUS_LOCATION is called!%d", __FUNCTION__, arg1); |
| m_exynosCameraParameters->setAutoFocusMacroPosition(ExynosCameraActivityAutofocus::AUTOFOCUS_MACRO_POSITION_CENTER_UP); |
| break; |
| /*1661: CAMERA_CMD_START_ZOOM */ |
| case 1661: |
| CLOGD("DEBUG(%s):CAMERA_CMD_START_ZOOM is called!", __FUNCTION__); |
| m_exynosCameraParameters->setZoomActiveOn(true); |
| m_exynosCameraParameters->setFocusModeLock(true); |
| break; |
| /*1662: CAMERA_CMD_STOP_ZOOM */ |
| case 1662: |
| CLOGD("DEBUG(%s):CAMERA_CMD_STOP_ZOOM is called!", __FUNCTION__); |
| m_exynosCameraParameters->setZoomActiveOn(false); |
| m_exynosCameraParameters->setFocusModeLock(false); |
| break; |
| default: |
| CLOGV("DEBUG(%s):unexpectect command(%d)", __FUNCTION__, command); |
| break; |
| } |
| |
| return NO_ERROR; |
| } |
| |
| status_t ExynosCamera::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 (isOwnScc(getCameraId()) == 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::generateFrameSccScp(uint32_t pipeId, uint32_t *frameCount, ExynosCameraFrame **frame) |
| { |
| int ret = 0; |
| int regenerateFrame = 0; |
| int count = *frameCount; |
| ExynosCameraFrame *newframe = NULL; |
| |
| do { |
| *frame = NULL; |
| ret = generateFrame(count, frame); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]):generateFrame fail, pipeID: %d", __FUNCTION__, __LINE__, pipeId); |
| return ret; |
| } |
| |
| newframe = *frame; |
| if (((PIPE_SCP == pipeId) && newframe->getScpDrop()) || |
| ((m_cameraId == CAMERA_ID_FRONT) && (PIPE_SCC == pipeId) && (newframe->getSccDrop() == true)) || |
| ((m_cameraId == CAMERA_ID_FRONT) && (PIPE_ISPC == pipeId) && (newframe->getIspcDrop() == true))) { |
| count++; |
| |
| ret = newframe->setEntityState(pipeId, ENTITY_STATE_FRAME_SKIP); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]):setEntityState fail, pipeId(%d), state(%d), ret(%d)", |
| __FUNCTION__, __LINE__, pipeId, ENTITY_STATE_FRAME_SKIP, ret); |
| *frameCount = count; |
| return ret; |
| } |
| |
| /* let m_mainThreadFunc handle the processlist cleaning part */ |
| m_pipeFrameDoneQ->pushProcessQ(&newframe); |
| |
| regenerateFrame = 1; |
| continue; |
| } |
| regenerateFrame = 0; |
| } while (regenerateFrame); |
| |
| *frameCount = count; |
| return NO_ERROR; |
| } |
| |
| 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::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_fastenAeStable(void) |
| { |
| int ret = 0; |
| ExynosCameraBuffer fastenAeBuffer[NUM_FASTAESTABLE_BUFFER]; |
| ExynosCameraBufferManager *skipBufferMgr = NULL; |
| m_createInternalBufferManager(&skipBufferMgr, "SKIP_BUF"); |
| |
| unsigned int planeSize[EXYNOS_CAMERA_BUFFER_MAX_PLANES] = {0}; |
| unsigned int bytesPerLine[EXYNOS_CAMERA_BUFFER_MAX_PLANES] = {0}; |
| planeSize[0] = 32 * 64 * 2; |
| int planeCount = 2; |
| int bufferCount = NUM_FASTAESTABLE_BUFFER; |
| |
| if (skipBufferMgr == NULL) { |
| CLOGE("ERR(%s[%d]):createBufferManager failed", __FUNCTION__, __LINE__); |
| goto func_exit; |
| } |
| |
| ret = m_allocBuffers(skipBufferMgr, planeCount, planeSize, bytesPerLine, bufferCount, true, false); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]):m_3aaBufferMgr m_allocBuffers(bufferCount=%d) fail", |
| __FUNCTION__, __LINE__, bufferCount); |
| return ret; |
| } |
| |
| for (int i = 0; i < bufferCount; i++) { |
| int index = i; |
| ret = skipBufferMgr->getBuffer(&index, EXYNOS_CAMERA_BUFFER_POSITION_IN_HAL, &fastenAeBuffer[i]); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]):getBuffer fail", __FUNCTION__, __LINE__); |
| goto done; |
| } |
| } |
| |
| ret = m_previewFrameFactory->fastenAeStable(bufferCount, fastenAeBuffer); |
| if (ret < 0) { |
| ret = INVALID_OPERATION; |
| // doing some error handling |
| } |
| |
| done: |
| skipBufferMgr->deinit(); |
| delete skipBufferMgr; |
| skipBufferMgr = NULL; |
| |
| func_exit: |
| return ret; |
| } |
| |
| status_t ExynosCamera::m_startPreviewInternal(void) |
| { |
| ExynosCameraAutoTimer autoTimer(__FUNCTION__); |
| |
| CLOGI("DEBUG(%s[%d]):IN", __FUNCTION__, __LINE__); |
| |
| uint32_t minBayerFrameNum = 0; |
| uint32_t min3AAFrameNum = 0; |
| int ret = 0; |
| ExynosCameraFrame *newFrame = NULL; |
| ExynosCameraBuffer dstBuf; |
| int32_t reprocessingBayerMode = m_exynosCameraParameters->getReprocessingBayerMode(); |
| enum pipeline pipe; |
| |
| m_fliteFrameCount = 0; |
| m_3aa_ispFrameCount = 0; |
| m_ispFrameCount = 0; |
| m_sccFrameCount = 0; |
| m_scpFrameCount = 0; |
| m_displayPreviewToggle = 0; |
| |
| if (m_exynosCameraParameters->isFlite3aaOtf() == true) |
| minBayerFrameNum = m_exynosconfig->current->bufInfo.init_bayer_buffers; |
| else |
| minBayerFrameNum = m_exynosconfig->current->bufInfo.num_bayer_buffers |
| - m_exynosconfig->current->bufInfo.reprocessing_bayer_hold_count; |
| |
| /* |
| * with MCPipe, we need to putBuffer 3 buf. |
| */ |
| /* |
| if (reprocessingBayerMode == REPROCESSING_BAYER_MODE_DIRTY_ALWAYS_ON) |
| min3AAFrameNum = minBayerFrameNum; |
| else |
| min3AAFrameNum = m_exynosconfig->current->pipeInfo.prepare[PIPE_3AA]; |
| */ |
| |
| min3AAFrameNum = m_exynosconfig->current->pipeInfo.prepare[PIPE_3AA]; |
| |
| ExynosCameraBufferManager *taaBufferManager[MAX_NODE]; |
| ExynosCameraBufferManager *ispBufferManager[MAX_NODE]; |
| ExynosCameraBufferManager *disBufferManager[MAX_NODE]; |
| |
| for (int i = 0; i < MAX_NODE; i++) { |
| taaBufferManager[i] = NULL; |
| ispBufferManager[i] = NULL; |
| disBufferManager[i] = NULL; |
| } |
| |
| #ifdef FPS_CHECK |
| for (int i = 0; i < DEBUG_MAX_PIPE_NUM; i++) |
| m_debugFpsCount[i] = 0; |
| #endif |
| |
| switch (reprocessingBayerMode) { |
| case REPROCESSING_BAYER_MODE_NONE : /* Not using reprocessing */ |
| CLOGD("DEBUG(%s[%d]): Use REPROCESSING_BAYER_MODE_NONE", __FUNCTION__, __LINE__); |
| #ifdef DEBUG_RAWDUMP |
| m_previewFrameFactory->setRequestFLITE(true); |
| #else |
| m_previewFrameFactory->setRequestFLITE(false); |
| #endif |
| m_previewFrameFactory->setRequest3AC(false); |
| break; |
| case REPROCESSING_BAYER_MODE_PURE_ALWAYS_ON : |
| CLOGD("DEBUG(%s[%d]): Use REPROCESSING_BAYER_MODE_PURE_ALWAYS_ON", __FUNCTION__, __LINE__); |
| m_previewFrameFactory->setRequestFLITE(true); |
| m_previewFrameFactory->setRequest3AC(false); |
| break; |
| case REPROCESSING_BAYER_MODE_DIRTY_ALWAYS_ON : |
| CLOGD("DEBUG(%s[%d]): Use REPROCESSING_BAYER_MODE_DIRTY_ALWAYS_ON", __FUNCTION__, __LINE__); |
| m_previewFrameFactory->setRequestFLITE(false); |
| m_previewFrameFactory->setRequest3AC(true); |
| break; |
| case REPROCESSING_BAYER_MODE_PURE_DYNAMIC : |
| CLOGD("DEBUG(%s[%d]): Use REPROCESSING_BAYER_MODE_PURE_DYNAMIC", __FUNCTION__, __LINE__); |
| m_previewFrameFactory->setRequestFLITE(false); |
| m_previewFrameFactory->setRequest3AC(false); |
| break; |
| case REPROCESSING_BAYER_MODE_DIRTY_DYNAMIC : |
| CLOGD("DEBUG(%s[%d]): Use REPROCESSING_BAYER_MODE_DIRTY_DYNAMIC", __FUNCTION__, __LINE__); |
| m_previewFrameFactory->setRequestFLITE(false); |
| m_previewFrameFactory->setRequest3AC(false); |
| break; |
| default : |
| CLOGE("ERR(%s[%d]): Unknown dynamic bayer mode", __FUNCTION__, __LINE__); |
| m_previewFrameFactory->setRequest3AC(false); |
| break; |
| } |
| |
| if (m_exynosCameraParameters->getTpuEnabledMode() == true) { |
| m_previewFrameFactory->setRequestISPP(true); |
| m_previewFrameFactory->setRequestDIS(true); |
| |
| if (m_exynosCameraParameters->is3aaIspOtf() == true) { |
| taaBufferManager[m_previewFrameFactory->getNodeType(PIPE_3AA)] = m_3aaBufferMgr; |
| taaBufferManager[m_previewFrameFactory->getNodeType(PIPE_3AC)] = m_bayerBufferMgr; |
| taaBufferManager[m_previewFrameFactory->getNodeType(PIPE_ISPP)] = m_hwDisBufferMgr; |
| |
| disBufferManager[m_previewFrameFactory->getNodeType(PIPE_DIS)] = m_hwDisBufferMgr; |
| disBufferManager[m_previewFrameFactory->getNodeType(PIPE_SCP)] = m_scpBufferMgr; |
| } else { |
| taaBufferManager[m_previewFrameFactory->getNodeType(PIPE_3AA)] = m_3aaBufferMgr; |
| taaBufferManager[m_previewFrameFactory->getNodeType(PIPE_3AC)] = m_bayerBufferMgr; |
| taaBufferManager[m_previewFrameFactory->getNodeType(PIPE_3AP)] = m_ispBufferMgr; |
| |
| ispBufferManager[m_previewFrameFactory->getNodeType(PIPE_ISP)] = m_ispBufferMgr; |
| ispBufferManager[m_previewFrameFactory->getNodeType(PIPE_ISPP)] = m_hwDisBufferMgr; |
| |
| disBufferManager[m_previewFrameFactory->getNodeType(PIPE_DIS)] = m_hwDisBufferMgr; |
| disBufferManager[m_previewFrameFactory->getNodeType(PIPE_SCP)] = m_scpBufferMgr; |
| } |
| } else { |
| m_previewFrameFactory->setRequestISPP(false); |
| m_previewFrameFactory->setRequestDIS(false); |
| |
| if (m_exynosCameraParameters->is3aaIspOtf() == true) { |
| if (m_exynosCameraParameters->getDualMode() == true && getCameraId() == CAMERA_ID_FRONT) { |
| m_previewFrameFactory->setRequestFLITE(true); |
| m_previewFrameFactory->setRequestISPC(true); |
| |
| taaBufferManager[m_previewFrameFactory->getNodeType(PIPE_3AA)] = m_bayerBufferMgr; |
| taaBufferManager[m_previewFrameFactory->getNodeType(PIPE_ISPC)] = m_sccBufferMgr; |
| } else { |
| if (m_exynosCameraParameters->isUsing3acForIspc() == true) { |
| if (m_exynosCameraParameters->getRecordingHint() == true) |
| m_previewFrameFactory->setRequest3AC(false); |
| else |
| m_previewFrameFactory->setRequest3AC(true); |
| } |
| |
| taaBufferManager[m_previewFrameFactory->getNodeType(PIPE_3AA)] = m_3aaBufferMgr; |
| if (m_exynosCameraParameters->isUsing3acForIspc() == true) |
| taaBufferManager[m_previewFrameFactory->getNodeType(PIPE_3AC)] = m_sccBufferMgr; |
| else |
| taaBufferManager[m_previewFrameFactory->getNodeType(PIPE_3AC)] = m_bayerBufferMgr; |
| taaBufferManager[m_previewFrameFactory->getNodeType(PIPE_SCP)] = m_scpBufferMgr; |
| } |
| } else { |
| taaBufferManager[m_previewFrameFactory->getNodeType(PIPE_3AA)] = m_3aaBufferMgr; |
| taaBufferManager[m_previewFrameFactory->getNodeType(PIPE_3AC)] = m_bayerBufferMgr; |
| taaBufferManager[m_previewFrameFactory->getNodeType(PIPE_3AP)] = m_ispBufferMgr; |
| |
| ispBufferManager[m_previewFrameFactory->getNodeType(PIPE_ISP)] = m_ispBufferMgr; |
| ispBufferManager[m_previewFrameFactory->getNodeType(PIPE_SCP)] = m_scpBufferMgr; |
| } |
| } |
| |
| for (int i = 0; i < MAX_NODE; i++) { |
| /* If even one buffer slot is valid. call setBufferManagerToPipe() */ |
| if (taaBufferManager[i] != NULL) { |
| ret = m_previewFrameFactory->setBufferManagerToPipe(taaBufferManager, PIPE_3AA); |
| if (ret != NO_ERROR) { |
| CLOGE("ERR(%s[%d]):m_previewFrameFactory->setBufferManagerToPipe(taaBufferManager, %d) failed", |
| __FUNCTION__, __LINE__, PIPE_3AA); |
| return ret; |
| } |
| break; |
| } |
| } |
| |
| for (int i = 0; i < MAX_NODE; i++) { |
| /* If even one buffer slot is valid. call setBufferManagerToPipe() */ |
| if (ispBufferManager[i] != NULL) { |
| ret = m_previewFrameFactory->setBufferManagerToPipe(ispBufferManager, PIPE_ISP); |
| if (ret != NO_ERROR) { |
| CLOGE("ERR(%s[%d]):m_previewFrameFactory->setBufferManagerToPipe(ispBufferManager, %d) failed", |
| __FUNCTION__, __LINE__, PIPE_ISP); |
| return ret; |
| } |
| break; |
| } |
| } |
| if (m_exynosCameraParameters->getHWVdisMode()) { |
| for (int i = 0; i < MAX_NODE; i++) { |
| /* If even one buffer slot is valid. call setBufferManagerToPipe() */ |
| if (disBufferManager[i] != NULL) { |
| ret = m_previewFrameFactory->setBufferManagerToPipe(disBufferManager, PIPE_DIS); |
| if (ret != NO_ERROR) { |
| CLOGE("ERR(%s[%d]):m_previewFrameFactory->setBufferManagerToPipe(disBufferManager, %d) failed", |
| __FUNCTION__, __LINE__, PIPE_DIS); |
| return ret; |
| } |
| break; |
| } |
| } |
| } |
| |
| ret = m_previewFrameFactory->initPipes(); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]):m_previewFrameFactory->initPipes() failed", __FUNCTION__, __LINE__); |
| return ret; |
| } |
| |
| m_printExynosCameraInfo(__FUNCTION__); |
| |
| for (uint32_t i = 0; i < minBayerFrameNum; i++) { |
| ret = generateFrame(i, &newFrame); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]):generateFrame fail", __FUNCTION__, __LINE__); |
| return ret; |
| } |
| if (newFrame == NULL) { |
| CLOGE("ERR(%s[%d]):new faame is NULL", __FUNCTION__, __LINE__); |
| return ret; |
| } |
| |
| m_fliteFrameCount++; |
| |
| if (m_exynosCameraParameters->isFlite3aaOtf() == true) { |
| #ifndef DEBUG_RAWDUMP |
| if (reprocessingBayerMode == REPROCESSING_BAYER_MODE_PURE_ALWAYS_ON) |
| #endif |
| { |
| m_setupEntity(m_getBayerPipeId(), newFrame); |
| m_previewFrameFactory->setOutputFrameQToPipe(m_pipeFrameDoneQ, m_getBayerPipeId()); |
| m_previewFrameFactory->pushFrameToPipe(&newFrame, m_getBayerPipeId()); |
| } |
| |
| if (i < min3AAFrameNum) { |
| m_setupEntity(PIPE_3AA, newFrame); |
| |
| if (m_exynosCameraParameters->is3aaIspOtf() == true) { |
| m_previewFrameFactory->setOutputFrameQToPipe(m_pipeFrameDoneQ, PIPE_3AA); |
| |
| if (m_exynosCameraParameters->getTpuEnabledMode() == true) { |
| m_previewFrameFactory->setOutputFrameQToPipe(m_pipeFrameDoneQ, PIPE_DIS); |
| } |
| } else { |
| m_previewFrameFactory->setFrameDoneQToPipe(m_pipeFrameDoneQ, PIPE_3AA); |
| |
| if (m_exynosCameraParameters->getTpuEnabledMode() == true) { |
| m_previewFrameFactory->setOutputFrameQToPipe(m_pipeFrameDoneQ, PIPE_DIS); |
| m_previewFrameFactory->setFrameDoneQToPipe(m_pipeFrameDoneQ, PIPE_ISP); |
| } else { |
| m_previewFrameFactory->setOutputFrameQToPipe(m_pipeFrameDoneQ, PIPE_ISP); |
| } |
| } |
| |
| m_previewFrameFactory->pushFrameToPipe(&newFrame, PIPE_3AA); |
| m_3aa_ispFrameCount++; |
| } |
| } else { |
| m_setupEntity(m_getBayerPipeId(), newFrame); |
| m_previewFrameFactory->setOutputFrameQToPipe(m_pipeFrameDoneQ, m_getBayerPipeId()); |
| m_previewFrameFactory->pushFrameToPipe(&newFrame, m_getBayerPipeId()); |
| |
| if (m_exynosCameraParameters->is3aaIspOtf() == true) { |
| m_previewFrameFactory->setOutputFrameQToPipe(m_pipeFrameDoneQ, PIPE_3AA); |
| } else { |
| m_setupEntity(PIPE_3AA, newFrame); |
| m_previewFrameFactory->setFrameDoneQToPipe(m_pipeFrameDoneQ, PIPE_3AA); |
| m_previewFrameFactory->setOutputFrameQToPipe(m_pipeFrameDoneQ, PIPE_ISP); |
| m_previewFrameFactory->pushFrameToPipe(&newFrame, PIPE_3AA); |
| m_3aa_ispFrameCount++; |
| } |
| |
| } |
| #if 0 |
| /* SCC */ |
| if(m_exynosCameraParameters->isSccCapture() == true) { |
| m_sccFrameCount++; |
| |
| if (isOwnScc(getCameraId()) == true) { |
| pipe = PIPE_SCC; |
| } else { |
| pipe = PIPE_ISPC; |
| } |
| |
| if(newFrame->getRequest(pipe)) { |
| m_setupEntity(pipe, newFrame); |
| m_previewFrameFactory->setOutputFrameQToPipe(m_pipeFrameDoneQ, pipe); |
| m_previewFrameFactory->pushFrameToPipe(&newFrame, pipe); |
| } |
| } |
| #endif |
| /* SCP */ |
| /* Comment out, because it included ISP */ |
| /* |
| m_scpFrameCount++; |
| |
| m_setupEntity(PIPE_SCP, newFrame); |
| m_previewFrameFactory->setOutputFrameQToPipe(m_pipeFrameDoneQ, PIPE_SCP); |
| m_previewFrameFactory->pushFrameToPipe(&newFrame, PIPE_SCP); |
| */ |
| } |
| |
| /* Comment out, because it included ISP */ |
| /* |
| for (uint32_t i = minFrameNum; i < INIT_SCP_BUFFERS; i++) { |
| ret = generateFrame(i, &newFrame); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]):generateFrame fail", __FUNCTION__, __LINE__); |
| return ret; |
| } |
| if (newFrame == NULL) { |
| CLOGE("ERR(%s[%d]):new faame is NULL", __FUNCTION__, __LINE__); |
| return ret; |
| } |
| |
| m_scpFrameCount++; |
| |
| m_setupEntity(PIPE_SCP, newFrame); |
| m_previewFrameFactory->setOutputFrameQToPipe(m_pipeFrameDoneQ, PIPE_SCP); |
| m_previewFrameFactory->pushFrameToPipe(&newFrame, PIPE_SCP); |
| } |
| */ |
| |
| /* prepare pipes */ |
| ret = m_previewFrameFactory->preparePipes(); |
| if (ret < 0) { |
| CLOGE("ERR(%s):preparePipe fail", __FUNCTION__); |
| return ret; |
| } |
| |
| #ifndef START_PICTURE_THREAD |
| if (m_exynosCameraParameters->isReprocessing() == true) { |
| m_startPictureInternal(); |
| } |
| #endif |
| |
| /* stream on pipes */ |
| ret = m_previewFrameFactory->startPipes(); |
| if (ret < 0) { |
| m_previewFrameFactory->stopPipes(); |
| CLOGE("ERR(%s):startPipe fail", __FUNCTION__); |
| return ret; |
| } |
| |
| /* start all thread */ |
| ret = m_previewFrameFactory->startInitialThreads(); |
| if (ret < 0) { |
| CLOGE("ERR(%s):startInitialThreads fail", __FUNCTION__); |
| return ret; |
| } |
| |
| m_previewEnabled = true; |
| m_exynosCameraParameters->setPreviewRunning(m_previewEnabled); |
| |
| if (m_exynosCameraParameters->getFocusModeSetting() == true) { |
| CLOGD("set Focus Mode(%s[%d])", __FUNCTION__, __LINE__); |
| int focusmode = m_exynosCameraParameters->getFocusMode(); |
| m_exynosCameraActivityControl->setAutoFocusMode(focusmode); |
| m_exynosCameraParameters->setFocusModeSetting(false); |
| } |
| |
| CLOGI("DEBUG(%s[%d]):OUT", __FUNCTION__, __LINE__); |
| |
| return NO_ERROR; |
| } |
| |
| status_t ExynosCamera::m_stopPreviewInternal(void) |
| { |
| int ret = 0; |
| |
| CLOGI("DEBUG(%s[%d]):IN", __FUNCTION__, __LINE__); |
| if (m_previewFrameFactory != NULL) { |
| ret = m_previewFrameFactory->stopPipes(); |
| if (ret < 0) { |
| CLOGE("ERR(%s):stopPipe fail", __FUNCTION__); |
| return ret; |
| } |
| } |
| |
| CLOGD("DEBUG(%s[%d]):clear process Frame list", __FUNCTION__, __LINE__); |
| ret = m_clearList(&m_processList); |
| if (ret < 0) { |
| CLOGE("ERR(%s):m_clearList fail", __FUNCTION__); |
| return ret; |
| } |
| |
| m_pipeFrameDoneQ->release(); |
| |
| m_fliteFrameCount = 0; |
| m_3aa_ispFrameCount = 0; |
| m_ispFrameCount = 0; |
| m_sccFrameCount = 0; |
| m_scpFrameCount = 0; |
| |
| m_previewEnabled = false; |
| m_exynosCameraParameters->setPreviewRunning(m_previewEnabled); |
| |
| CLOGI("DEBUG(%s[%d]):OUT", __FUNCTION__, __LINE__); |
| |
| return NO_ERROR; |
| } |
| |
| status_t ExynosCamera::m_startPictureInternal(void) |
| { |
| ExynosCameraAutoTimer autoTimer(__FUNCTION__); |
| |
| int ret = 0; |
| unsigned int bytesPerLine[EXYNOS_CAMERA_BUFFER_MAX_PLANES] = {0}; |
| unsigned int planeSize[EXYNOS_CAMERA_BUFFER_MAX_PLANES] = {0}; |
| int hwPictureW, hwPictureH; |
| int planeCount = 1; |
| int minBufferCount = 1; |
| int maxBufferCount = 1; |
| exynos_camera_buffer_type_t type = EXYNOS_CAMERA_BUFFER_ION_CACHED_TYPE; |
| buffer_manager_allocation_mode_t allocMode = BUFFER_MANAGER_ALLOCATION_ONDEMAND; |
| ExynosCameraBufferManager *taaBufferManager[MAX_NODE]; |
| ExynosCameraBufferManager *ispBufferManager[MAX_NODE]; |
| for (int i = 0; i < MAX_NODE; i++) { |
| taaBufferManager[i] = NULL; |
| ispBufferManager[i] = NULL; |
| } |
| |
| if (m_zslPictureEnabled == true) { |
| CLOGD("DEBUG(%s[%d]): zsl picture is already initialized", __FUNCTION__, __LINE__); |
| return NO_ERROR; |
| } |
| |
| if (m_exynosCameraParameters->isReprocessing() == true) { |
| if( m_exynosCameraParameters->getHighSpeedRecording() ) { |
| m_exynosCameraParameters->getHwSensorSize(&hwPictureW, &hwPictureH); |
| CLOGI("(%s):HW Picture(HighSpeed) width x height = %dx%d", __FUNCTION__, hwPictureW, hwPictureH); |
| } else { |
| m_exynosCameraParameters->getMaxPictureSize(&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; |
| } |
| minBufferCount = 1; |
| maxBufferCount = NUM_PICTURE_BUFFERS; |
| |
| if (m_exynosCameraParameters->getHighResolutionCallbackMode() == true) { |
| /* SCC Reprocessing Buffer realloc for high resolution callback */ |
| minBufferCount = 2; |
| } |
| |
| ret = m_allocBuffers(m_sccReprocessingBufferMgr, planeCount, planeSize, bytesPerLine, minBufferCount, maxBufferCount, type, allocMode, true, false); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]):m_sccReprocessingBufferMgr m_allocBuffers(minBufferCount=%d, maxBufferCount=%d) fail", |
| __FUNCTION__, __LINE__, minBufferCount, maxBufferCount); |
| return ret; |
| } |
| |
| if (m_exynosCameraParameters->getUsePureBayerReprocessing() == true) { |
| ret = m_setReprocessingBuffer(); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]):m_setReprocessing Buffer fail", __FUNCTION__, __LINE__); |
| return ret; |
| } |
| } |
| } |
| |
| if (m_reprocessingFrameFactory->isCreated() == false) { |
| ret = m_reprocessingFrameFactory->create(); |
| if (ret < 0) { |
| CLOGE("ERR(%s):m_reprocessingFrameFactory->create() failed", __FUNCTION__); |
| return ret; |
| } |
| |
| m_pictureFrameFactory = m_reprocessingFrameFactory; |
| CLOGD("DEBUG(%s[%d]):FrameFactory(pictureFrameFactory) created", __FUNCTION__, __LINE__); |
| } |
| |
| /* If we want set buffer namanger from m_getBufferManager, use this */ |
| #if 0 |
| ret = m_getBufferManager(PIPE_3AA_REPROCESSING, bufferManager[m_reprocessingFrameFactory->getNodeType(PIPE_3AA_REPROCESSING)], SRC_BUFFER_DIRECTION); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]):getBufferManager() fail, pipeId(%d), ret(%d)", __FUNCTION__, __LINE__, PIPE_3AA_REPROCESSING, ret); |
| return ret; |
| } |
| |
| ret = m_getBufferManager(PIPE_3AA_REPROCESSING, bufferManager[m_reprocessingFrameFactory->getNodeType(PIPE_3AP_REPROCESSING)], DST_BUFFER_DIRECTION); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]):getBufferManager() fail, pipeId(%d), ret(%d)", __FUNCTION__, __LINE__, PIPE_3AP_REPROCESSING, ret); |
| return ret; |
| } |
| #else |
| if (m_exynosCameraParameters->isReprocessing3aaIspOTF() == false) { |
| taaBufferManager[m_reprocessingFrameFactory->getNodeType(PIPE_3AA_REPROCESSING)] = m_bayerBufferMgr; |
| taaBufferManager[m_reprocessingFrameFactory->getNodeType(PIPE_3AP_REPROCESSING)] = m_ispReprocessingBufferMgr; |
| } else { |
| taaBufferManager[m_reprocessingFrameFactory->getNodeType(PIPE_3AA_REPROCESSING)] = m_bayerBufferMgr; |
| taaBufferManager[m_reprocessingFrameFactory->getNodeType(PIPE_ISPC_REPROCESSING)] = m_sccReprocessingBufferMgr; |
| |
| taaBufferManager[OUTPUT_NODE] = m_bayerBufferMgr; |
| taaBufferManager[CAPTURE_NODE] = m_sccReprocessingBufferMgr; |
| } |
| #endif |
| |
| ret = m_reprocessingFrameFactory->setBufferManagerToPipe(taaBufferManager, PIPE_3AA_REPROCESSING); |
| if (ret < 0) { |
| CLOGE("ERR(%s):m_reprocessingFrameFactory->setBufferManagerToPipe() failed", __FUNCTION__); |
| return ret; |
| } |
| |
| ispBufferManager[m_reprocessingFrameFactory->getNodeType(PIPE_ISP_REPROCESSING)] = m_ispReprocessingBufferMgr; |
| ispBufferManager[m_reprocessingFrameFactory->getNodeType(PIPE_ISPC_REPROCESSING)] = m_sccReprocessingBufferMgr; |
| |
| ret = m_reprocessingFrameFactory->setBufferManagerToPipe(ispBufferManager, PIPE_ISP_REPROCESSING); |
| if (ret < 0) { |
| CLOGE("ERR(%s):m_reprocessingFrameFactory->setBufferManagerToPipe() failed", __FUNCTION__); |
| return ret; |
| } |
| |
| ret = m_reprocessingFrameFactory->initPipes(); |
| if (ret < 0) { |
| CLOGE("ERR(%s):m_reprocessingFrameFactory->initPipes() failed", __FUNCTION__); |
| return ret; |
| } |
| |
| ret = m_reprocessingFrameFactory->preparePipes(); |
| if (ret < 0) { |
| CLOGE("ERR(%s):m_reprocessingFrameFactory preparePipe fail", __FUNCTION__); |
| return ret; |
| } |
| |
| /* stream on pipes */ |
| ret = m_reprocessingFrameFactory->startPipes(); |
| if (ret < 0) { |
| CLOGE("ERR(%s):m_reprocessingFrameFactory startPipe fail", __FUNCTION__); |
| return ret; |
| } |
| |
| m_zslPictureEnabled = true; |
| |
| /* |
| * Make remained frameFactory here. |
| * in case of reprocessing capture, make here. |
| */ |
| m_framefactoryThread->run(); |
| |
| return NO_ERROR; |
| } |
| |
| status_t ExynosCamera::m_stopPictureInternal(void) |
| { |
| CLOGI("INFO(%s[%d])", __FUNCTION__, __LINE__); |
| int ret = 0; |
| |
| m_prePictureThread->join(); |
| m_pictureThread->join(); |
| m_postPictureThread->join(); |
| |
| if (m_exynosCameraParameters->getHighResolutionCallbackMode() == true) { |
| m_highResolutionCallbackThread->stop(); |
| if (m_highResolutionCallbackQ != NULL) |
| m_highResolutionCallbackQ->sendCmd(WAKE_UP); |
| m_highResolutionCallbackThread->requestExitAndWait(); |
| } |
| |
| m_jpegCallbackThread->join(); |
| |
| for (int threadNum = JPEG_SAVE_THREAD0; threadNum < JPEG_SAVE_THREAD_MAX_COUNT; threadNum++) { |
| m_jpegSaveThread[threadNum]->join(); |
| } |
| |
| if (m_zslPictureEnabled == true) { |
| ret = m_reprocessingFrameFactory->stopPipes(); |
| if (ret < 0) { |
| CLOGE("ERR(%s):m_reprocessingFrameFactory0>stopPipe() fail", __FUNCTION__); |
| } |
| } |
| |
| /* Clear frames & buffers which remain in capture processingQ */ |
| m_clearFrameQ(dstSccReprocessingQ, PIPE_SCC, DST_BUFFER_DIRECTION); |
| m_clearFrameQ(m_postPictureQ, PIPE_SCC, DST_BUFFER_DIRECTION); |
| m_clearFrameQ(dstJpegReprocessingQ, PIPE_JPEG, SRC_BUFFER_DIRECTION); |
| |
| dstIspReprocessingQ->release(); |
| dstGscReprocessingQ->release(); |
| dstJpegReprocessingQ->release(); |
| |
| m_jpegCallbackQ->release(); |
| |
| for (int threadNum = JPEG_SAVE_THREAD0; threadNum < JPEG_SAVE_THREAD_MAX_COUNT; threadNum++) { |
| m_jpegSaveQ[threadNum]->release(); |
| } |
| |
| if (m_highResolutionCallbackQ->getSizeOfProcessQ() != 0){ |
| CLOGD("DEBUG(%s[%d]):m_highResolutionCallbackQ->getSizeOfProcessQ(%d). release the highResolutionCallbackQ.", |
| __FUNCTION__, __LINE__, m_highResolutionCallbackQ->getSizeOfProcessQ()); |
| m_highResolutionCallbackQ->release(); |
| } |
| |
| CLOGD("DEBUG(%s[%d]):clear postProcess(Picture) Frame list", __FUNCTION__, __LINE__); |
| ret = m_clearList(&m_postProcessList); |
| if (ret < 0) { |
| CLOGE("ERR(%s):m_clearList fail", __FUNCTION__); |
| return ret; |
| } |
| |
| m_zslPictureEnabled = false; |
| |
| /* TODO: need timeout */ |
| return NO_ERROR; |
| } |
| |
| status_t ExynosCamera::m_startRecordingInternal(void) |
| { |
| int ret = 0; |
| |
| unsigned int bytesPerLine[EXYNOS_CAMERA_BUFFER_MAX_PLANES] = {0}; |
| unsigned int planeSize[EXYNOS_CAMERA_BUFFER_MAX_PLANES] = {0}; |
| int videoW = 0, videoH = 0; |
| int planeCount = 1; |
| int minBufferCount = 1; |
| int maxBufferCount = 1; |
| exynos_camera_buffer_type_t type = EXYNOS_CAMERA_BUFFER_ION_NONCACHED_TYPE; |
| buffer_manager_allocation_mode_t allocMode = BUFFER_MANAGER_ALLOCATION_SILENT; |
| int heapFd = 0; |
| |
| m_exynosCameraParameters->getVideoSize(&videoW, &videoH); |
| CLOGD("DEBUG(%s[%d]):videoSize = %d x %d", __FUNCTION__, __LINE__, videoW, videoH); |
| |
| m_doCscRecording = true; |
| if (m_exynosCameraParameters->doCscRecording() == true) { |
| m_recordingBufferCount = m_exynosconfig->current->bufInfo.num_recording_buffers; |
| CLOGI("INFO(%s[%d]):do Recording CSC !!! m_recordingBufferCount(%d)", __FUNCTION__, __LINE__, m_recordingBufferCount); |
| } else { |
| m_doCscRecording = false; |
| m_recordingBufferCount = m_exynosconfig->current->bufInfo.num_preview_buffers; |
| CLOGI("INFO(%s[%d]):skip Recording CSC !!! m_recordingBufferCount(%d->%d)", |
| __FUNCTION__, __LINE__, m_exynosconfig->current->bufInfo.num_recording_buffers, m_recordingBufferCount); |
| } |
| |
| for (int32_t i = 0; i < m_recordingBufferCount; i++) { |
| m_recordingTimeStamp[i] = 0L; |
| m_recordingBufAvailable[i] = true; |
| } |
| |
| /* alloc recording Callback Heap */ |
| m_recordingCallbackHeap = m_getMemoryCb(-1, sizeof(struct addrs), m_recordingBufferCount, &heapFd); |
| if (!m_recordingCallbackHeap || m_recordingCallbackHeap->data == MAP_FAILED) { |
| CLOGE("ERR(%s[%d]):m_getMemoryCb(%d) fail", __FUNCTION__, __LINE__, sizeof(struct addrs)); |
| ret = INVALID_OPERATION; |
| goto func_exit; |
| } |
| |
| if (m_doCscRecording == true) { |
| /* alloc recording Image buffer */ |
| planeSize[0] = ROUND_UP(videoW, CAMERA_MAGIC_ALIGN) * ROUND_UP(videoH, CAMERA_MAGIC_ALIGN) + MFC_7X_BUFFER_OFFSET; |
| planeSize[1] = ROUND_UP(videoW, CAMERA_MAGIC_ALIGN) * ROUND_UP(videoH / 2, CAMERA_MAGIC_ALIGN) + MFC_7X_BUFFER_OFFSET; |
| planeCount = 2; |
| if( m_exynosCameraParameters->getHighSpeedRecording() == true) |
| minBufferCount = m_recordingBufferCount; |
| else |
| minBufferCount = 1; |
| |
| maxBufferCount = m_recordingBufferCount; |
| |
| ret = m_allocBuffers(m_recordingBufferMgr, planeCount, planeSize, bytesPerLine, minBufferCount, maxBufferCount, type, allocMode, false, true); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]):m_recordingBufferMgr m_allocBuffers(minBufferCount=%d, maxBufferCount=%d) fail", |
| __FUNCTION__, __LINE__, minBufferCount, maxBufferCount); |
| } |
| } |
| |
| if (m_doCscRecording == true) { |
| int recPipeId = PIPE_GSC_VIDEO; |
| |
| m_previewFrameFactory->startThread(recPipeId); |
| |
| if (m_recordingQ->getSizeOfProcessQ() > 0) { |
| CLOGE("ERR(%s[%d]):m_startRecordingInternal recordingQ(%d)", __FUNCTION__, __LINE__, m_recordingQ->getSizeOfProcessQ()); |
| m_clearList(m_recordingQ); |
| } |
| |
| m_recordingThread->run(); |
| } |
| |
| func_exit: |
| |
| return ret; |
| } |
| |
| status_t ExynosCamera::m_stopRecordingInternal(void) |
| { |
| int ret = 0; |
| if (m_doCscRecording == true) { |
| int recPipeId = PIPE_GSC_VIDEO; |
| |
| m_previewFrameFactory->stopPipe(recPipeId); |
| m_recordingQ->sendCmd(WAKE_UP); |
| |
| m_recordingThread->requestExitAndWait(); |
| m_recordingQ->release(); |
| m_recordingListLock.lock(); |
| ret = m_clearList(&m_recordingProcessList); |
| if (ret < 0) { |
| CLOGE("ERR(%s):m_clearList fail", __FUNCTION__); |
| return ret; |
| } |
| m_recordingListLock.unlock(); |
| |
| m_recordingBufferMgr->deinit(); |
| } else { |
| CLOGI("INFO(%s[%d]):reset m_recordingBufferCount(%d->%d)", |
| __FUNCTION__, __LINE__, m_recordingBufferCount, m_exynosconfig->current->bufInfo.num_recording_buffers); |
| m_recordingBufferCount = m_exynosconfig->current->bufInfo.num_recording_buffers; |
| } |
| |
| if (m_recordingCallbackHeap != NULL) { |
| m_recordingCallbackHeap->release(m_recordingCallbackHeap); |
| m_recordingCallbackHeap = NULL; |
| } |
| |
| return NO_ERROR; |
| } |
| |
| status_t ExynosCamera::m_restartPreviewInternal(void) |
| { |
| CLOGI("INFO(%s[%d]): Internal restart preview", __FUNCTION__, __LINE__); |
| int ret = 0; |
| int err = 0; |
| |
| m_flagThreadStop = true; |
| |
| /* release about frameFactory */ |
| m_framefactoryThread->requestExitAndWait(); |
| m_frameFactoryQ->release(); |
| |
| m_startPictureInternalThread->join(); |
| m_startPictureBufferThread->join(); |
| |
| if (m_previewFrameFactory != NULL) |
| m_previewFrameFactory->setStopFlag(); |
| |
| m_mainThread->requestExitAndWait(); |
| |
| ret = m_stopPictureInternal(); |
| if (ret < 0) |
| CLOGE("ERR(%s[%d]):m_stopPictureInternal fail", __FUNCTION__, __LINE__); |
| |
| m_previewThread->stop(); |
| if(m_previewQ != NULL) |
| m_previewQ->sendCmd(WAKE_UP); |
| m_previewThread->requestExitAndWait(); |
| |
| if (m_exynosCameraParameters->isFlite3aaOtf() == true) { |
| m_mainSetupQThread[INDEX(PIPE_FLITE)]->stop(); |
| m_mainSetupQ[INDEX(PIPE_FLITE)]->sendCmd(WAKE_UP); |
| m_mainSetupQThread[INDEX(PIPE_FLITE)]->requestExitAndWait(); |
| |
| if (m_mainSetupQThread[INDEX(PIPE_3AC)] != NULL) { |
| m_mainSetupQThread[INDEX(PIPE_3AC)]->stop(); |
| m_mainSetupQ[INDEX(PIPE_3AC)]->sendCmd(WAKE_UP); |
| m_mainSetupQThread[INDEX(PIPE_3AC)]->requestExitAndWait(); |
| } |
| |
| m_mainSetupQThread[INDEX(PIPE_3AA)]->stop(); |
| m_mainSetupQ[INDEX(PIPE_3AA)]->sendCmd(WAKE_UP); |
| m_mainSetupQThread[INDEX(PIPE_3AA)]->requestExitAndWait(); |
| |
| if (m_mainSetupQThread[INDEX(PIPE_ISP)] != NULL) { |
| m_mainSetupQThread[INDEX(PIPE_ISP)]->stop(); |
| m_mainSetupQ[INDEX(PIPE_ISP)]->sendCmd(WAKE_UP); |
| m_mainSetupQThread[INDEX(PIPE_ISP)]->requestExitAndWait(); |
| } |
| |
| /* Comment out, because it included ISP */ |
| /* |
| m_mainSetupQThread[INDEX(PIPE_SCP)]->stop(); |
| m_mainSetupQ[INDEX(PIPE_SCP)]->sendCmd(WAKE_UP); |
| m_mainSetupQThread[INDEX(PIPE_SCP)]->requestExitAndWait(); |
| */ |
| |
| m_clearList(m_mainSetupQ[INDEX(PIPE_FLITE)]); |
| m_clearList(m_mainSetupQ[INDEX(PIPE_3AA)]); |
| m_clearList(m_mainSetupQ[INDEX(PIPE_ISP)]); |
| /* Comment out, because it included ISP */ |
| /* m_clearList(m_mainSetupQ[INDEX(PIPE_SCP)]); */ |
| |
| m_mainSetupQ[INDEX(PIPE_FLITE)]->release(); |
| m_mainSetupQ[INDEX(PIPE_3AA)]->release(); |
| m_mainSetupQ[INDEX(PIPE_ISP)]->release(); |
| /* Comment out, because it included ISP */ |
| /* m_mainSetupQ[INDEX(PIPE_SCP)]->release(); */ |
| } |
| |
| ret = m_stopPreviewInternal(); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]):m_stopPreviewInternal fail", __FUNCTION__, __LINE__); |
| err = ret; |
| } |
| |
| /* skip to free and reallocate buffers */ |
| if (m_bayerBufferMgr != NULL) { |
| m_bayerBufferMgr->resetBuffers(); |
| } |
| if (m_3aaBufferMgr != NULL) { |
| m_3aaBufferMgr->resetBuffers(); |
| } |
| if (m_ispBufferMgr != NULL) { |
| m_ispBufferMgr->resetBuffers(); |
| } |
| if (m_hwDisBufferMgr != NULL) { |
| m_hwDisBufferMgr->resetBuffers(); |
| } |
| if (m_sccBufferMgr != NULL) { |
| m_sccBufferMgr->deinit(); |
| m_sccBufferMgr->setBufferCount(0); |
| } |
| |
| if (m_highResolutionCallbackBufferMgr != NULL) { |
| m_highResolutionCallbackBufferMgr->resetBuffers(); |
| } |
| |
| /* skip to free and reallocate buffers */ |
| if (m_ispReprocessingBufferMgr != NULL) { |
| m_ispReprocessingBufferMgr->resetBuffers(); |
| } |
| if (m_sccReprocessingBufferMgr != NULL) { |
| m_sccReprocessingBufferMgr->resetBuffers(); |
| } |
| |
| if (m_gscBufferMgr != NULL) { |
| m_gscBufferMgr->resetBuffers(); |
| } |
| if (m_jpegBufferMgr != NULL) { |
| m_jpegBufferMgr->resetBuffers(); |
| } |
| if (m_recordingBufferMgr != NULL) { |
| m_recordingBufferMgr->resetBuffers(); |
| } |
| |
| /* realloc callback buffers */ |
| if (m_scpBufferMgr != NULL) { |
| m_scpBufferMgr->deinit(); |
| m_scpBufferMgr->setBufferCount(0); |
| } |
| if (m_previewCallbackBufferMgr != NULL) { |
| m_previewCallbackBufferMgr->deinit(); |
| } |
| |
| if (m_captureSelector != NULL) { |
| m_captureSelector->release(); |
| } |
| if (m_sccCaptureSelector != NULL) { |
| m_sccCaptureSelector->release(); |
| } |
| |
| if( m_exynosCameraParameters->getHighSpeedRecording() && m_exynosCameraParameters->getReallocBuffer() ) { |
| CLOGD("DEBUG(%s): realloc buffer all buffer deinit ", __FUNCTION__); |
| if (m_bayerBufferMgr != NULL) { |
| m_bayerBufferMgr->deinit(); |
| } |
| if (m_3aaBufferMgr != NULL) { |
| m_3aaBufferMgr->deinit(); |
| } |
| if (m_ispBufferMgr != NULL) { |
| m_ispBufferMgr->deinit(); |
| } |
| |
| if (m_sccBufferMgr != NULL) { |
| m_sccBufferMgr->deinit(); |
| } |
| /* |
| if (m_highResolutionCallbackBufferMgr != NULL) { |
| m_highResolutionCallbackBufferMgr->deinit(); |
| } |
| */ |
| if (m_gscBufferMgr != NULL) { |
| m_gscBufferMgr->deinit(); |
| } |
| if (m_jpegBufferMgr != NULL) { |
| m_jpegBufferMgr->deinit(); |
| } |
| if (m_recordingBufferMgr != NULL) { |
| m_recordingBufferMgr->deinit(); |
| } |
| } |
| |
| if (m_exynosCameraParameters->getTpuEnabledMode() == true) { |
| if (m_hwDisBufferMgr != NULL) { |
| m_hwDisBufferMgr->deinit(); |
| } |
| } |
| |
| m_flagThreadStop = false; |
| |
| ret = setPreviewWindow(m_previewWindow); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]):setPreviewWindow fail", __FUNCTION__, __LINE__); |
| err = ret; |
| } |
| |
| CLOGI("INFO(%s[%d]):setBuffersThread is run", __FUNCTION__, __LINE__); |
| m_setBuffersThread->run(PRIORITY_DEFAULT); |
| m_setBuffersThread->join(); |
| |
| #ifdef START_PICTURE_THREAD |
| m_startPictureInternalThread->join(); |
| #endif |
| m_startPictureBufferThread->join(); |
| |
| if (m_exynosCameraParameters->isReprocessing() == true) { |
| #ifdef START_PICTURE_THREAD |
| m_startPictureInternalThread->run(PRIORITY_DEFAULT); |
| #endif |
| } else { |
| m_pictureFrameFactory = m_previewFrameFactory; |
| CLOGD("DEBUG(%s[%d]):FrameFactory(pictureFrameFactory) created", __FUNCTION__, __LINE__); |
| |
| /* |
| * Make remained frameFactory here. |
| * in case of SCC capture, make here. |
| */ |
| m_framefactoryThread->run(); |
| } |
| |
| ret = m_startPreviewInternal(); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]):m_startPreviewInternal fail", __FUNCTION__, __LINE__); |
| err = ret; |
| } |
| |
| /* setup frame thread */ |
| if (m_exynosCameraParameters->getDualMode() == true && getCameraId() == CAMERA_ID_FRONT) { |
| m_mainSetupQThread[INDEX(PIPE_FLITE)]->run(PRIORITY_URGENT_DISPLAY); |
| } else { |
| #ifdef DEBUG_RAWDUMP |
| m_mainSetupQThread[INDEX(PIPE_FLITE)]->run(PRIORITY_URGENT_DISPLAY); |
| #endif |
| m_mainSetupQThread[INDEX(PIPE_3AA)]->run(PRIORITY_URGENT_DISPLAY); |
| } |
| |
| if (m_facedetectThread->isRunning() == false) |
| m_facedetectThread->run(); |
| |
| m_previewThread->run(PRIORITY_DISPLAY); |
| |
| m_mainThread->run(PRIORITY_DEFAULT); |
| m_startPictureInternalThread->join(); |
| |
| return err; |
| } |
| |
| bool ExynosCamera::m_mainThreadQSetup3AA() |
| { |
| #ifdef DEBUG |
| ExynosCameraAutoTimer autoTimer(__FUNCTION__); |
| #endif |
| |
| int ret = 0; |
| bool loop = true; |
| int pipeId_3AA = PIPE_3AA; |
| int pipeId_3AC = PIPE_3AC; |
| int pipeId_ISP = PIPE_ISP; |
| int pipeId_DIS = PIPE_DIS; |
| int pipeIdCsc = 0; |
| int maxbuffers = 0; |
| |
| ExynosCameraBuffer buffer; |
| ExynosCameraFrame *frame = NULL; |
| ExynosCameraFrame *newframe = NULL; |
| nsecs_t timeStamp = 0; |
| int frameCount = -1; |
| |
| CLOGV("INFO(%s[%d]):wait previewCancelQ", __FUNCTION__, __LINE__); |
| ret = m_mainSetupQ[INDEX(pipeId_3AA)]->waitAndPopProcessQ(&frame); |
| if (m_flagThreadStop == true) { |
| CLOGI("INFO(%s[%d]):m_flagThreadStop(%d)", __FUNCTION__, __LINE__, m_flagThreadStop); |
| goto func_exit; |
| } |
| |
| if (ret < 0) { |
| if (ret == TIMED_OUT) { |
| CLOGW("WARN(%s):wait timeout", __FUNCTION__); |
| } else { |
| CLOGE("ERR(%s):wait and pop fail, ret(%d)", __FUNCTION__, ret); |
| /* TODO: doing exception handling */ |
| } |
| goto func_exit; |
| } |
| |
| if (frame == NULL) { |
| CLOGE("ERR(%s[%d]):frame is NULL", __FUNCTION__, __LINE__); |
| goto func_exit; |
| } |
| |
| ret = generateFrame(m_3aa_ispFrameCount, &newframe); |
| if (ret < 0) { |
| 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_3AA, newframe); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]):setupEntity fail", __FUNCTION__, __LINE__); |
| } |
| |
| m_previewFrameFactory->pushFrameToPipe(&newframe, pipeId_3AA); |
| |
| if (m_exynosCameraParameters->is3aaIspOtf() == true) { |
| m_previewFrameFactory->setOutputFrameQToPipe(m_pipeFrameDoneQ, pipeId_3AA); |
| |
| if (m_exynosCameraParameters->getTpuEnabledMode() == true) |
| m_previewFrameFactory->setOutputFrameQToPipe(m_pipeFrameDoneQ, pipeId_DIS); |
| } else { |
| m_previewFrameFactory->setFrameDoneQToPipe(m_pipeFrameDoneQ, pipeId_3AA); |
| |
| if (m_exynosCameraParameters->getTpuEnabledMode() == true) { |
| m_previewFrameFactory->setFrameDoneQToPipe(m_pipeFrameDoneQ, pipeId_ISP); |
| m_previewFrameFactory->setOutputFrameQToPipe(m_pipeFrameDoneQ, pipeId_DIS); |
| } else { |
| m_previewFrameFactory->setOutputFrameQToPipe(m_pipeFrameDoneQ, pipeId_ISP); |
| } |
| } |
| |
| m_3aa_ispFrameCount++; |
| |
| func_exit: |
| if( frame != NULL ) { |
| frame->decRef(); |
| m_frameMgr->deleteFrame(frame);; |
| frame = NULL; |
| } |
| |
| return loop; |
| } |
| |
| bool ExynosCamera::m_mainThreadQSetup3AA_ISP() |
| { |
| #ifdef DEBUG |
| ExynosCameraAutoTimer autoTimer(__FUNCTION__); |
| #endif |
| |
| int ret = 0; |
| bool loop = true; |
| int pipeId = PIPE_3AA_ISP; |
| int pipeIdCsc = 0; |
| int maxbuffers = 0; |
| |
| ExynosCameraBuffer buffer; |
| ExynosCameraFrame *frame = NULL; |
| ExynosCameraFrame *newframe = NULL; |
| nsecs_t timeStamp = 0; |
| int frameCount = -1; |
| |
| 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 < 0) { |
| 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; |
| } |
| |
| while (m_3aaBufferMgr->getNumOfAvailableBuffer() > 0 && |
| m_ispBufferMgr->getNumOfAvailableBuffer() > 0) { |
| ret = generateFrame(m_3aa_ispFrameCount, &newframe); |
| if (ret < 0) { |
| 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 < 0) { |
| CLOGE("ERR(%s[%d]):setupEntity fail", __FUNCTION__, __LINE__); |
| } |
| |
| m_previewFrameFactory->pushFrameToPipe(&newframe, pipeId); |
| m_previewFrameFactory->setOutputFrameQToPipe(m_pipeFrameDoneQ, pipeId); |
| |
| m_3aa_ispFrameCount++; |
| |
| } |
| |
| func_exit: |
| if( frame != NULL ) { |
| frame->decRef(); |
| m_frameMgr->deleteFrame(frame);; |
| frame = NULL; |
| } |
| |
| /* |
| if (m_mainSetupQ[INDEX(pipeId)]->getSizeOfProcessQ() <= 0) |
| loop = false; |
| */ |
| |
| return loop; |
| } |
| |
| bool ExynosCamera::m_mainThreadQSetupISP() |
| { |
| #ifdef DEBUG |
| ExynosCameraAutoTimer autoTimer(__FUNCTION__); |
| #endif |
| |
| int ret = 0; |
| bool loop = false; |
| int pipeId = PIPE_ISP; |
| |
| ExynosCameraBuffer buffer; |
| ExynosCameraFrame *frame = NULL; |
| nsecs_t timeStamp = 0; |
| int frameCount = -1; |
| |
| 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 < 0) { |
| 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; |
| } |
| |
| func_exit: |
| if( frame != NULL ) { |
| frame->decRef(); |
| m_frameMgr->deleteFrame(frame); |
| frame = NULL; |
| } |
| |
| if (m_mainSetupQ[INDEX(pipeId)]->getSizeOfProcessQ() > 0) |
| loop = true; |
| |
| return loop; |
| } |
| |
| bool ExynosCamera::m_mainThreadQSetupFLITE() |
| { |
| #ifdef DEBUG |
| ExynosCameraAutoTimer autoTimer(__FUNCTION__); |
| #endif |
| |
| int ret = 0; |
| bool loop = true; |
| int pipeId = PIPE_FLITE; |
| int pipeIdCsc = 0; |
| int maxbuffers = 0; |
| |
| ExynosCameraBuffer buffer; |
| ExynosCameraFrame *frame = NULL; |
| ExynosCameraFrame *newframe = NULL; |
| nsecs_t timeStamp = 0; |
| int frameCount = -1; |
| |
| 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 < 0) { |
| if (ret == TIMED_OUT) { |
| CLOGW("WARN(%s):wait timeout", __FUNCTION__); |
| } else { |
| CLOGE("ERR(%s):wait and pop fail, ret(%d)", __FUNCTION__, ret); |
| /* TODO: doing exception handling */ |
| } |
| goto func_exit; |
| } |
| |
| |
| if (frame == NULL) { |
| CLOGE("ERR(%s[%d]):frame is NULL", __FUNCTION__, __LINE__); |
| goto func_exit; |
| } |
| |
| if (m_bayerBufferMgr->getNumOfAvailableBuffer() > 0) { |
| ret = generateFrame(m_fliteFrameCount, &newframe); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]):generateFrame fail", __FUNCTION__, __LINE__); |
| goto func_exit; |
| } |
| |
| ret = m_setupEntity(pipeId, newframe); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]):setupEntity fail", __FUNCTION__, __LINE__); |
| } |
| ret = newframe->getDstBuffer(pipeId, &buffer); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]):getDstBuffer fail, ret(%d)", __FUNCTION__, __LINE__, ret); |
| } |
| |
| m_previewFrameFactory->pushFrameToPipe(&newframe, pipeId); |
| m_previewFrameFactory->setOutputFrameQToPipe(m_pipeFrameDoneQ, pipeId); |
| |
| m_fliteFrameCount++; |
| } |
| |
| func_exit: |
| if( frame != NULL ) { |
| frame->decRef(); |
| m_frameMgr->deleteFrame(frame);; |
| frame = NULL; |
| } |
| |
| /* |
| if (m_mainSetupQ[INDEX(pipeId)]->getSizeOfProcessQ() <= 0) |
| loop = false; |
| */ |
| |
| return loop; |
| } |
| |
| bool ExynosCamera::m_mainThreadQSetup3AC() |
| { |
| #ifdef DEBUG |
| ExynosCameraAutoTimer autoTimer(__FUNCTION__); |
| #endif |
| |
| int ret = 0; |
| bool loop = true; |
| int pipeId = PIPE_3AC; |
| int pipeIdCsc = 0; |
| int maxbuffers = 0; |
| |
| ExynosCameraBuffer buffer; |
| ExynosCameraFrame *frame = NULL; |
| ExynosCameraFrame *newframe = NULL; |
| nsecs_t timeStamp = 0; |
| int frameCount = -1; |
| |
| 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 < 0) { |
| 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__); |
| ret = INVALID_OPERATION; |
| } |
| if (m_bayerBufferMgr->getNumOfAvailableBuffer() > 0) { |
| do { |
| ret = generateFrame(m_fliteFrameCount, &newframe); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]):generateFrame fail", __FUNCTION__, __LINE__); |
| goto func_exit; |
| } |
| |
| ret = m_setupEntity(pipeId, newframe); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]):setupEntity fail", __FUNCTION__, __LINE__); |
| } |
| ret = newframe->getDstBuffer(pipeId, &buffer); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]):getDstBuffer fail, ret(%d)", __FUNCTION__, __LINE__, ret); |
| } |
| |
| m_previewFrameFactory->pushFrameToPipe(&newframe, pipeId); |
| m_previewFrameFactory->setOutputFrameQToPipe(m_pipeFrameDoneQ, pipeId); |
| |
| m_fliteFrameCount++; |
| //} while (m_bayerBufferMgr->getAllocatedBufferCount() - PIPE_3AC_PREPARE_COUNT |
| // < m_bayerBufferMgr->getNumOfAvailableBuffer()); |
| } while (0 < m_bayerBufferMgr->getNumOfAvailableBuffer()); |
| } |
| |
| func_exit: |
| if( frame != NULL ) { |
| frame->decRef(); |
| m_frameMgr->deleteFrame(frame);; |
| } |
| |
| /* |
| if (m_mainSetupQ[INDEX(pipeId)]->getSizeOfProcessQ() <= 0) |
| loop = false; |
| */ |
| |
| return loop; |
| } |
| |
| bool ExynosCamera::m_mainThreadQSetupSCP() |
| { |
| #ifdef DEBUG |
| ExynosCameraAutoTimer autoTimer(__FUNCTION__); |
| #endif |
| |
| int ret = 0; |
| bool loop = true; |
| int pipeId = PIPE_SCP; |
| int pipeIdCsc = 0; |
| int maxbuffers = 0; |
| |
| camera2_node_group node_group_info_isp; |
| ExynosCameraBuffer resultBuffer; |
| ExynosCameraFrame *frame = NULL; |
| ExynosCameraFrame *newframe = NULL; |
| nsecs_t timeStamp = 0; |
| int frameCount = -1; |
| int frameGen = 1; |
| |
| 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 < 0) { |
| 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 = generateFrameSccScp(pipeId, &m_scpFrameCount, &newframe); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]):generateFrameSccScp fail", __FUNCTION__, __LINE__); |
| goto func_exit; |
| } |
| |
| if( frame->getFrameState() == FRAME_STATE_SKIPPED ) { |
| frame->getDstBuffer(pipeId, &resultBuffer); |
| m_setupEntity(pipeId, newframe, NULL, &resultBuffer); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]):setupEntity fail", __FUNCTION__, __LINE__); |
| } |
| newframe->getDstBuffer(pipeId, &resultBuffer); |
| } else { |
| ret = m_setupEntity(pipeId, newframe); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]):setupEntity fail", __FUNCTION__, __LINE__); |
| } |
| newframe->getDstBuffer(pipeId, &resultBuffer); |
| } |
| |
| /*check preview drop...*/ |
| newframe->getDstBuffer(pipeId, &resultBuffer); |
| if (resultBuffer.index < 0) { |
| newframe->setRequest(pipeId, false); |
| newframe->getNodeGroupInfo(&node_group_info_isp, PERFRAME_INFO_ISP); |
| node_group_info_isp.capture[PERFRAME_BACK_SCP_POS].request = 0; |
| newframe->storeNodeGroupInfo(&node_group_info_isp, PERFRAME_INFO_ISP); |
| m_previewFrameFactory->dump(); |
| |
| if (m_getRecordingEnabled() == true |
| && m_exynosCameraParameters->msgTypeEnabled(CAMERA_MSG_VIDEO_FRAME) |
| && m_exynosCameraParameters->getHighSpeedRecording() == false) { |
| CLOGW("WARN(%s[%d]):Recording preview drop. Failed to get preview buffer. FrameSkipCount(%d)", |
| __FUNCTION__, __LINE__, FRAME_SKIP_COUNT_RECORDING); |
| /* when preview buffer is not ready, we should drop preview to make preview buffer ready */ |
| m_exynosCameraParameters->setFrameSkipCount(FRAME_SKIP_COUNT_RECORDING); |
| } else { |
| CLOGW("WARN(%s[%d]):Preview drop. Failed to get preview buffer. FrameSkipCount (%d)", |
| __FUNCTION__, __LINE__, FRAME_SKIP_COUNT_PREVIEW); |
| /* when preview buffer is not ready, we should drop preview to make preview buffer ready */ |
| m_exynosCameraParameters->setFrameSkipCount(FRAME_SKIP_COUNT_PREVIEW); |
| } |
| } |
| |
| m_previewFrameFactory->pushFrameToPipe(&newframe, pipeId); |
| m_previewFrameFactory->setOutputFrameQToPipe(m_pipeFrameDoneQ, pipeId); |
| |
| m_scpFrameCount++; |
| |
| func_exit: |
| if( frame != NULL ) { |
| frame->decRef(); |
| m_frameMgr->deleteFrame(frame); |
| frame = NULL; |
| } |
| |
| /* |
| if (m_mainSetupQ[INDEX(pipeId)]->getSizeOfProcessQ() <= 0) |
| loop = false; |
| */ |
| |
| return loop; |
| } |
| |
| bool ExynosCamera::m_mainThreadFunc(void) |
| { |
| int ret = 0; |
| int index = 0; |
| ExynosCameraFrame *newFrame = NULL; |
| uint32_t frameCnt = 0; |
| |
| if (m_previewEnabled == false) { |
| CLOGD("DEBUG(%s):preview is stopped, thread stop", __FUNCTION__); |
| 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 < 0) { |
| /* TODO: We need to make timeout duration depends on FPS */ |
| if (ret == 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 (newFrame == NULL) { |
| CLOGE("ERR(%s[%d]):newFrame is NULL", __FUNCTION__, __LINE__); |
| return true; |
| } |
| |
| frameCnt = newFrame->getFrameCount(); |
| |
| /* HACK Reset Preview Flag*/ |
| #if 0 |
| if (m_exynosCameraParameters->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 |
| |
| if (m_exynosCameraParameters->isFlite3aaOtf() == true) { |
| ret = m_handlePreviewFrame(newFrame); |
| } else { |
| if (m_exynosCameraParameters->getDualMode()) |
| ret = m_handlePreviewFrameFrontDual(newFrame); |
| else |
| ret = m_handlePreviewFrameFront(newFrame); |
| } |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]):handle preview frame fail", __FUNCTION__, __LINE__); |
| 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(); */ |
| |
| m_autoFocusContinousQ.pushProcessQ(&frameCnt); |
| |
| return true; |
| } |
| |
| status_t ExynosCamera::m_handlePreviewFrame(ExynosCameraFrame *frame) |
| { |
| int ret = 0; |
| ExynosCameraFrameEntity *entity = NULL; |
| ExynosCameraFrame *newFrame = NULL; |
| ExynosCameraFrame *fdFrame = NULL; |
| |
| ExynosCameraBuffer buffer; |
| #ifdef SUPPORT_SW_VDIS |
| ExynosCameraBuffer vs_InputBuffer; |
| #endif /*SUPPORT_SW_VDIS*/ |
| ExynosCameraBuffer t3acBuffer; |
| int pipeID = 0; |
| /* to handle the high speed frame rate */ |
| bool skipPreview = false; |
| int ratio = 1; |
| uint32_t minFps = 0, maxFps = 0; |
| uint32_t dispFps = EXYNOS_CAMERA_PREVIEW_FPS_REFERENCE; |
| uint32_t fvalid = 0; |
| uint32_t fcount = 0; |
| uint32_t skipCount = 0; |
| struct camera2_stream *shot_stream = NULL; |
| ExynosCameraBuffer resultBuffer; |
| camera2_node_group node_group_info_isp; |
| int32_t reprocessingBayerMode = m_exynosCameraParameters->getReprocessingBayerMode(); |
| int ispDstBufferIndex = -1; |
| |
| entity = frame->getFrameDoneFirstEntity(); |
| if (entity == NULL) { |
| CLOGE("ERR(%s[%d]):current entity is NULL", __FUNCTION__, __LINE__); |
| /* TODO: doing exception handling */ |
| return true; |
| } |
| |
| pipeID = entity->getPipeId(); |
| |
| /* TODO: remove hard coding */ |
| switch(INDEX(entity->getPipeId())) { |
| case PIPE_3AA_ISP: |
| m_debugFpsCheck(entity->getPipeId()); |
| ret = frame->getSrcBuffer(entity->getPipeId(), &buffer); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]):getSrcBuffer fail, pipeId(%d), ret(%d)", |
| __FUNCTION__, __LINE__, entity->getPipeId(), ret); |
| return ret; |
| } |
| ret = m_putBuffers(m_3aaBufferMgr, buffer.index); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]):put Buffer fail", __FUNCTION__, __LINE__); |
| } |
| |
| CLOGV("DEBUG(%s[%d]):3AA_ISP frameCount(%d) frame.Count(%d)", |
| __FUNCTION__, __LINE__, |
| getMetaDmRequestFrameCount((struct camera2_shot_ext *)buffer.addr[1]), |
| frame->getFrameCount()); |
| |
| ret = frame->getDstBuffer(entity->getPipeId(), &buffer); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]):getDstBuffer fail, pipeId(%d), ret(%d)", |
| __FUNCTION__, __LINE__, entity->getPipeId(), ret); |
| return ret; |
| } |
| |
| ret = m_putBuffers(m_ispBufferMgr, buffer.index); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]):put Buffer fail", __FUNCTION__, __LINE__); |
| break; |
| } |
| |
| frame->setMetaDataEnable(true); |
| |
| /* Face detection */ |
| if(!m_exynosCameraParameters->getHighSpeedRecording()) { |
| skipCount = m_exynosCameraParameters->getFrameSkipCount(); |
| if( m_exynosCameraParameters->msgTypeEnabled(CAMERA_MSG_PREVIEW_METADATA) && |
| skipCount <= 0 && m_flagStartFaceDetection == true) { |
| struct camera2_shot_ext shot; |
| frame->getDynamicMeta(&shot); |
| fdFrame = m_frameMgr->createFrame(m_exynosCameraParameters, frame->getFrameCount()); |
| fdFrame->storeDynamicMeta(&shot); |
| m_facedetectQ->pushProcessQ(&fdFrame); |
| } |
| } |
| |
| /* ISP capture mode q/dq for vdis */ |
| if (m_exynosCameraParameters->getTpuEnabledMode() == true) { |
| #if 0 |
| /* case 1 : directly push on isp, tpu. */ |
| ret = m_pushFrameToPipeIspDIS(); |
| if (ret != NO_ERROR) { |
| CLOGE("ERR(%s[%d]):m_pushFrameToPipeIspDIS() fail", __FUNCTION__, __LINE__); |
| } |
| #else |
| /* case 2 : indirectly push on isp, tpu. */ |
| newFrame = m_frameMgr->createFrame(m_exynosCameraParameters, 0); |
| m_mainSetupQ[INDEX(PIPE_ISP)]->pushProcessQ(&newFrame); |
| #endif |
| } |
| |
| newFrame = m_frameMgr->createFrame(m_exynosCameraParameters, 0); |
| m_mainSetupQ[INDEX(entity->getPipeId())]->pushProcessQ(&newFrame); |
| break; |
| case PIPE_3AC: |
| case PIPE_FLITE: |
| m_debugFpsCheck(entity->getPipeId()); |
| |
| if (m_exynosCameraParameters->getHighSpeedRecording()) { |
| ret = frame->getDstBuffer(entity->getPipeId(), &buffer); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]):getDstBuffer fail, pipeId(%d), ret(%d)", |
| __FUNCTION__, __LINE__, entity->getPipeId(), ret); |
| return ret; |
| } |
| ret = m_putBuffers(m_bayerBufferMgr, buffer.index); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]):put Buffer fail", __FUNCTION__, __LINE__); |
| break; |
| } |
| } else { |
| if (frame->getSccDrop() == true || frame->getIspcDrop() == true) { |
| CLOGE("ERR(%s[%d]):getSccDrop() == %d || getIspcDrop()== %d. so drop this frame(frameCount : %d)", |
| __FUNCTION__, __LINE__, frame->getSccDrop(), frame->getIspcDrop(), frame->getFrameCount()); |
| |
| ret = frame->getDstBuffer(entity->getPipeId(), &buffer); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]):getDstBuffer fail, pipeId(%d), ret(%d)", |
| __FUNCTION__, __LINE__, entity->getPipeId(), ret); |
| return ret; |
| } |
| |
| ret = m_putBuffers(m_bayerBufferMgr, buffer.index); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]):m_putBuffers(%d) fail", __FUNCTION__, __LINE__, buffer.index); |
| break; |
| } |
| } else { |
| ret = m_captureSelector->manageFrameHoldList(frame, entity->getPipeId(), false); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]):manageFrameHoldList fail", __FUNCTION__, __LINE__); |
| return ret; |
| } |
| #ifdef DEBUG_RAWDUMP |
| newFrame = m_frameMgr->createFrame(m_exynosCameraParameters, 0); |
| m_mainSetupQ[INDEX(entity->getPipeId())]->pushProcessQ(&newFrame); |
| #endif |
| } |
| } |
| |
| /* TODO: Dynamic bayer capture, currently support only single shot */ |
| if (reprocessingBayerMode == REPROCESSING_BAYER_MODE_PURE_DYNAMIC |
| || reprocessingBayerMode == REPROCESSING_BAYER_MODE_DIRTY_DYNAMIC) |
| m_previewFrameFactory->stopThread(entity->getPipeId()); |
| |
| if (reprocessingBayerMode == REPROCESSING_BAYER_MODE_PURE_ALWAYS_ON |
| || reprocessingBayerMode == REPROCESSING_BAYER_MODE_DIRTY_ALWAYS_ON) { |
| newFrame = m_frameMgr->createFrame(m_exynosCameraParameters, 0); |
| m_mainSetupQ[INDEX(entity->getPipeId())]->pushProcessQ(&newFrame); |
| } |
| break; |
| case PIPE_ISP: |
| /* |
| if (entity->getSrcBufState() == ENTITY_BUFFER_STATE_ERROR) |
| m_previewFrameFactory->dump(); |
| */ |
| |
| ret = frame->getSrcBuffer(entity->getPipeId(), &buffer); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]):getSrcBuffer fail, pipeId(%d), ret(%d)", |
| __FUNCTION__, __LINE__, entity->getPipeId(), ret); |
| return ret; |
| } |
| |
| if (buffer.index >= 0) { |
| ret = m_putBuffers(m_ispBufferMgr, buffer.index); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]):put Buffer fail", __FUNCTION__, __LINE__); |
| break; |
| } |
| } |
| |
| /* Face detection */ |
| if (!m_exynosCameraParameters->getHighSpeedRecording() |
| && frame->getFrameState() != FRAME_STATE_SKIPPED) { |
| skipCount = m_exynosCameraParameters->getFrameSkipCount(); |
| if( m_exynosCameraParameters->msgTypeEnabled(CAMERA_MSG_PREVIEW_METADATA) && |
| skipCount <= 0 && m_flagStartFaceDetection == true) { |
| ret = m_doFdCallbackFunc(frame); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]):m_doFdCallbackFunc fail, ret(%d)", |
| __FUNCTION__, __LINE__, ret); |
| return ret; |
| } |
| } |
| } |
| |
| /* ISP capture mode q/dq for vdis */ |
| if (m_exynosCameraParameters->getTpuEnabledMode() == true) { |
| break; |
| } |
| case PIPE_3AA: |
| case PIPE_DIS: |
| /* The following switch allows both PIPE_3AA and PIPE_ISP to |
| * fall through to PIPE_SCP |
| */ |
| |
| switch(INDEX(entity->getPipeId())) { |
| case PIPE_3AA: |
| m_debugFpsCheck(entity->getPipeId()); |
| |
| /* |
| if (entity->getSrcBufState() == ENTITY_BUFFER_STATE_ERROR) |
| m_previewFrameFactory->dump(); |
| */ |
| |
| ret = frame->getSrcBuffer(entity->getPipeId(), &buffer); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]):getSrcBuffer fail, pipeId(%d), ret(%d)", |
| __FUNCTION__, __LINE__, entity->getPipeId(), ret); |
| return ret; |
| } |
| |
| if (buffer.index >= 0) { |
| ret = m_putBuffers(m_3aaBufferMgr, buffer.index); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]):put Buffer fail", __FUNCTION__, __LINE__); |
| } |
| } |
| |
| frame->setMetaDataEnable(true); |
| |
| newFrame = m_frameMgr->createFrame(m_exynosCameraParameters, 0); |
| m_mainSetupQ[INDEX(entity->getPipeId())]->pushProcessQ(&newFrame); |
| |
| /* 3AC buffer handling */ |
| t3acBuffer.index = -1; |
| |
| if (frame->getRequest(PIPE_3AC) == true) { |
| ret = frame->getDstBuffer(entity->getPipeId(), &t3acBuffer, m_previewFrameFactory->getNodeType(PIPE_3AC)); |
| if (ret != NO_ERROR) { |
| CLOGE("ERR(%s[%d]):getDstBuffer fail, pipeId(%d), ret(%d)", |
| __FUNCTION__, __LINE__, entity->getPipeId(), ret); |
| } |
| } |
| |
| if (0 <= t3acBuffer.index) { |
| if (frame->getRequest(PIPE_3AC) == true) { |
| if (m_exynosCameraParameters->getHighSpeedRecording() == true) { |
| if (m_exynosCameraParameters->isUsing3acForIspc() == true) |
| ret = m_putBuffers(m_sccBufferMgr, t3acBuffer.index); |
| else |
| ret = m_putBuffers(m_bayerBufferMgr, t3acBuffer.index); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]):m_putBuffers(m_bayerBufferMgr, %d) fail", __FUNCTION__, __LINE__, t3acBuffer.index); |
| break; |
| } |
| } else { |
| entity_buffer_state_t bufferstate = ENTITY_BUFFER_STATE_NOREQ; |
| ret = frame->getDstBufferState(entity->getPipeId(), &bufferstate, m_previewFrameFactory->getNodeType(PIPE_3AC)); |
| if (ret == NO_ERROR && bufferstate != ENTITY_BUFFER_STATE_ERROR) { |
| if (m_exynosCameraParameters->isUsing3acForIspc() == true) |
| ret = m_sccCaptureSelector->manageFrameHoldList(frame, entity->getPipeId(), false, m_previewFrameFactory->getNodeType(PIPE_3AC)); |
| else |
| ret = m_captureSelector->manageFrameHoldList(frame, entity->getPipeId(), false); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]):manageFrameHoldList fail", __FUNCTION__, __LINE__); |
| return ret; |
| } |
| } else { |
| if (m_exynosCameraParameters->isUsing3acForIspc() == true) |
| ret = m_putBuffers(m_sccBufferMgr, t3acBuffer.index); |
| else |
| ret = m_putBuffers(m_bayerBufferMgr, t3acBuffer.index); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]):m_putBuffers(m_bayerBufferMgr, %d) fail", __FUNCTION__, __LINE__, t3acBuffer.index); |
| break; |
| } |
| } |
| } |
| } else { |
| if (reprocessingBayerMode == REPROCESSING_BAYER_MODE_DIRTY_ALWAYS_ON) { |
| CLOGW("WARN(%s[%d]):frame->getRequest(PIPE_3AC) == false. so, just m_putBuffers(t3acBuffer.index(%d)..., pipeId(%d), ret(%d)", |
| __FUNCTION__, __LINE__, t3acBuffer.index, entity->getPipeId(), ret); |
| } |
| |
| if (m_exynosCameraParameters->isUsing3acForIspc() == true) |
| ret = m_putBuffers(m_sccBufferMgr, t3acBuffer.index); |
| else |
| ret = m_putBuffers(m_bayerBufferMgr, t3acBuffer.index); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]):m_putBuffers(m_bayerBufferMgr, %d) fail", __FUNCTION__, __LINE__, t3acBuffer.index); |
| break; |
| } |
| } |
| } |
| |
| /* Face detection for using 3AA-ISP OTF mode. */ |
| if (m_exynosCameraParameters->is3aaIspOtf() == true) { |
| skipCount = m_exynosCameraParameters->getFrameSkipCount(); |
| if (skipCount <= 0) { |
| /* Face detection */ |
| struct camera2_shot_ext shot; |
| frame->getDynamicMeta(&shot); |
| fdFrame = m_frameMgr->createFrame(m_exynosCameraParameters, frame->getFrameCount()); |
| fdFrame->storeDynamicMeta(&shot); |
| m_facedetectQ->pushProcessQ(&fdFrame); |
| } |
| } |
| |
| CLOGV("DEBUG(%s[%d]):3AA_ISP frameCount(%d) frame.Count(%d)", |
| __FUNCTION__, __LINE__, |
| getMetaDmRequestFrameCount((struct camera2_shot_ext *)buffer.addr[1]), |
| frame->getFrameCount()); |
| |
| break; |
| case PIPE_DIS: |
| m_debugFpsCheck(pipeID); |
| if (m_exynosCameraParameters->getTpuEnabledMode() == true) { |
| ret = frame->getSrcBuffer(PIPE_DIS, &buffer); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]):getSrcBuffer fail, pipeId(%d), ret(%d)", |
| __FUNCTION__, __LINE__, PIPE_ISP, ret); |
| return ret; |
| } |
| |
| if (buffer.index >= 0) { |
| ret = m_putBuffers(m_hwDisBufferMgr, buffer.index); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]):m_putBuffers(m_hwDisBufferMgr, %d) fail", __FUNCTION__, __LINE__, buffer.index); |
| } |
| } |
| } |
| |
| CLOGV("DEBUG(%s[%d]):DIS done HAL-frameCount(%d)", __FUNCTION__, __LINE__, frame->getFrameCount()); |
| |
| break; |
| default: |
| CLOGE("ERR(%s[%d]):Its impossible to be here. ", |
| __FUNCTION__, __LINE__); |
| break; |
| } |
| |
| if ((INDEX(entity->getPipeId())) == PIPE_3AA && |
| m_exynosCameraParameters->is3aaIspOtf() == true && |
| m_exynosCameraParameters->getTpuEnabledMode() == false) { |
| /* Fall through to PIPE_SCP */ |
| } else if ((INDEX(entity->getPipeId())) == PIPE_DIS) { |
| /* Fall through to PIPE_SCP */ |
| } else { |
| /* Break out of the outer switch and reach entity_state_complete: */ |
| break; |
| } |
| |
| case PIPE_SCP: |
| if (entity->getDstBufState() == ENTITY_BUFFER_STATE_ERROR) { |
| if (frame->getRequest(PIPE_SCP) == true) { |
| ret = frame->getDstBuffer(entity->getPipeId(), &buffer, m_previewFrameFactory->getNodeType(PIPE_SCP)); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]):getDstBuffer fail, pipeId(%d), ret(%d)", |
| __FUNCTION__, __LINE__, entity->getPipeId(), ret); |
| return ret; |
| } |
| |
| if (buffer.index >= 0) { |
| ret = m_scpBufferMgr->cancelBuffer(buffer.index); |
| if (ret < 0) |
| CLOGE("ERR(%s[%d]):SCP buffer return fail", __FUNCTION__, __LINE__); |
| } |
| /* For debug */ |
| /* m_previewFrameFactory->dump(); */ |
| |
| /* Comment out, because it included ISP */ |
| /* |
| newFrame = m_previewFrameFactory->createNewFrameOnlyOnePipe(PIPE_SCP, frame->getFrameCount()); |
| newFrame->setDstBuffer(PIPE_SCP, buffer); |
| newFrame->setFrameState(FRAME_STATE_SKIPPED); |
| |
| m_mainSetupQ[INDEX(entity->getPipeId())]->pushProcessQ(&newFrame); |
| */ |
| } |
| CLOGV("DEBUG(%s[%d]):SCP done HAL-frameCount(%d)", __FUNCTION__, __LINE__, frame->getFrameCount()); |
| } else if (entity->getDstBufState() == ENTITY_BUFFER_STATE_COMPLETE) { |
| m_debugFpsCheck(entity->getPipeId()); |
| |
| ret = frame->getDstBuffer(entity->getPipeId(), &buffer, m_previewFrameFactory->getNodeType(PIPE_SCP)); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]):getDstBuffer fail, pipeId(%d), ret(%d)", |
| __FUNCTION__, __LINE__, entity->getPipeId(), ret); |
| return ret; |
| } |
| |
| /* TO DO : skip frame for HDR */ |
| shot_stream = (struct camera2_stream *)buffer.addr[2]; |
| |
| if (shot_stream != NULL) { |
| getStreamFrameValid(shot_stream, &fvalid); |
| getStreamFrameCount(shot_stream, &fcount); |
| } else { |
| CLOGE("ERR(%s[%d]):shot_stream is NULL", __FUNCTION__, __LINE__); |
| fvalid = false; |
| fcount = 0; |
| } |
| |
| /* drop preview frame if lcd supported frame rate < scp frame rate */ |
| frame->getFpsRange(&minFps, &maxFps); |
| if (dispFps < maxFps) { |
| ratio = (int)((maxFps * 10 / dispFps) / 10); |
| m_displayPreviewToggle = (m_displayPreviewToggle + 1) % ratio; |
| skipPreview = (m_displayPreviewToggle == 0) ? true : false; |
| #ifdef DEBUG |
| CLOGE("DEBUG(%s[%d]):preview frame skip! frameCount(%d) (m_displayPreviewToggle=%d, maxFps=%d, dispFps=%d, ratio=%d, skipPreview=%d)", |
| __FUNCTION__, __LINE__, frame->getFrameCount(), m_displayPreviewToggle, maxFps, dispFps, ratio, (int)skipPreview); |
| #endif |
| } |
| |
| newFrame = m_previewFrameFactory->createNewFrameOnlyOnePipe(PIPE_SCP, frame->getFrameCount()); |
| newFrame->setDstBuffer(PIPE_SCP, buffer); |
| |
| m_exynosCameraParameters->getFrameSkipCount(&m_frameSkipCount); |
| if (m_frameSkipCount > 0) { |
| CLOGD("INFO(%s[%d]):Skip frame for frameSkipCount(%d) buffer.index(%d)", |
| __FUNCTION__, __LINE__, m_frameSkipCount, buffer.index); |
| newFrame->setFrameState(FRAME_STATE_SKIPPED); |
| if (buffer.index >= 0) { |
| ret = m_scpBufferMgr->cancelBuffer(buffer.index); |
| if (ret < 0) |
| CLOGE("ERR(%s[%d]):SCP buffer return fail", __FUNCTION__, __LINE__); |
| } |
| } else { |
| if (m_skipReprocessing == true) |
| m_skipReprocessing = false; |
| nsecs_t timeStamp = (nsecs_t)frame->getTimeStamp(); |
| if (m_getRecordingEnabled() == true |
| && m_exynosCameraParameters->msgTypeEnabled(CAMERA_MSG_VIDEO_FRAME)) { |
| if (timeStamp <= 0L) { |
| CLOGE("WARN(%s[%d]):timeStamp(%lld) Skip", __FUNCTION__, __LINE__, timeStamp); |
| } else { |
| if (m_exynosCameraParameters->doCscRecording() == true) { |
| /* get Recording Image buffer */ |
| int bufIndex = -2; |
| ExynosCameraBuffer recordingBuffer; |
| ret = m_recordingBufferMgr->getBuffer(&bufIndex, EXYNOS_CAMERA_BUFFER_POSITION_IN_HAL, &recordingBuffer); |
| if (ret < 0 || bufIndex < 0) { |
| if ((++m_recordingFrameSkipCount % 100) == 0) { |
| CLOGE("ERR(%s[%d]): Recording buffer is not available!! Recording Frames are Skipping(%d frames) (bufIndex=%d)", |
| __FUNCTION__, __LINE__, m_recordingFrameSkipCount, bufIndex); |
| m_recordingBufferMgr->printBufferQState(); |
| } |
| } else { |
| if (m_recordingFrameSkipCount != 0) { |
| CLOGE("ERR(%s[%d]): Recording buffer is not available!! Recording Frames are Skipped(%d frames) (bufIndex=%d) (recordingQ=%d)", |
| __FUNCTION__, __LINE__, m_recordingFrameSkipCount, bufIndex, m_recordingQ->getSizeOfProcessQ()); |
| m_recordingFrameSkipCount = 0; |
| m_recordingBufferMgr->printBufferQState(); |
| } |
| m_recordingTimeStamp[bufIndex] = timeStamp; |
| |
| ret = m_doPrviewToRecordingFunc(PIPE_GSC_VIDEO, buffer, recordingBuffer); |
| if (ret < 0) { |
| CLOGW("WARN(%s[%d]):recordingCallback Skip", __FUNCTION__, __LINE__); |
| } |
| } |
| } else { |
| m_recordingTimeStamp[buffer.index] = timeStamp; |
| |
| if (m_recordingStartTimeStamp == 0) { |
| m_recordingStartTimeStamp = timeStamp; |
| CLOGI("INFO(%s[%d]):m_recordingStartTimeStamp=%lld", |
| __FUNCTION__, __LINE__, m_recordingStartTimeStamp); |
| } |
| |
| if ((0L < timeStamp) |
| && (m_lastRecordingTimeStamp < timeStamp) |
| && (m_recordingStartTimeStamp <= timeStamp)) { |
| if (m_getRecordingEnabled() == true |
| && m_exynosCameraParameters->msgTypeEnabled(CAMERA_MSG_VIDEO_FRAME)) { |
| #ifdef CHECK_MONOTONIC_TIMESTAMP |
| CLOGD("DEBUG(%s[%d]):m_dataCbTimestamp::recordingFrameIndex=%d, recordingTimeStamp=%lld, fd[0]=%d", |
| __FUNCTION__, __LINE__, buffer.index, timeStamp, buffer.fd[0]); |
| #endif |
| #ifdef DEBUG |
| CLOGD("DEBUG(%s[%d]): - lastTimeStamp(%lld), systemTime(%lld), recordingStart(%lld)", |
| __FUNCTION__, __LINE__, |
| m_lastRecordingTimeStamp, |
| systemTime(SYSTEM_TIME_MONOTONIC), |
| m_recordingStartTimeStamp); |
| #endif |
| |
| if (m_recordingBufAvailable[buffer.index] == false) { |
| CLOGW("WARN(%s[%d]):recordingFrameIndex(%d) didn't release yet !!! drop the frame !!! " |
| " timeStamp(%lld) m_recordingBufAvailable(%d)", |
| __FUNCTION__, __LINE__, buffer.index, timeStamp, (int)m_recordingBufAvailable[buffer.index]); |
| } else { |
| struct addrs *recordAddrs = NULL; |
| |
| recordAddrs = (struct addrs *)m_recordingCallbackHeap->data; |
| recordAddrs[buffer.index].type = kMetadataBufferTypeCameraSource; |
| recordAddrs[buffer.index].fdPlaneY = (unsigned int)buffer.fd[0]; |
| recordAddrs[buffer.index].fdPlaneCbcr = (unsigned int)buffer.fd[1]; |
| recordAddrs[buffer.index].bufIndex = buffer.index; |
| |
| m_recordingBufAvailable[buffer.index] = false; |
| m_lastRecordingTimeStamp = timeStamp; |
| |
| if (m_getRecordingEnabled() == true |
| && m_exynosCameraParameters->msgTypeEnabled(CAMERA_MSG_VIDEO_FRAME)) { |
| m_dataCbTimestamp( |
| timeStamp, |
| CAMERA_MSG_VIDEO_FRAME, |
| m_recordingCallbackHeap, |
| buffer.index, |
| m_callbackCookie); |
| } |
| } |
| } |
| } else { |
| CLOGW("WARN(%s[%d]):recordingFrameIndex=%d, timeStamp(%lld) invalid -" |
| " lastTimeStamp(%lld), systemTime(%lld), recordingStart(%lld), m_recordingBufAvailable(%d)", |
| __FUNCTION__, __LINE__, buffer.index, timeStamp, |
| m_lastRecordingTimeStamp, |
| systemTime(SYSTEM_TIME_MONOTONIC), |
| m_recordingStartTimeStamp, |
| (int)m_recordingBufAvailable[buffer.index]); |
| m_recordingTimeStamp[buffer.index] = 0L; |
| } |
| } |
| } |
| } |
| |
| ExynosCameraBuffer callbackBuffer; |
| ExynosCameraFrame *callbackFrame = NULL; |
| struct camera2_shot_ext *shot_ext = new struct camera2_shot_ext; |
| |
| callbackFrame = m_previewFrameFactory->createNewFrameOnlyOnePipe(PIPE_SCP, frame->getFrameCount()); |
| frame->getDstBuffer(entity->getPipeId(), &callbackBuffer, m_previewFrameFactory->getNodeType(PIPE_SCP)); |
| frame->getMetaData(shot_ext); |
| callbackFrame->storeDynamicMeta(shot_ext); |
| callbackFrame->setDstBuffer(PIPE_SCP, callbackBuffer); |
| |
| if (((m_exynosCameraParameters->getPreviewBufferCount() == NUM_PREVIEW_BUFFERS + NUM_PREVIEW_SPARE_BUFFERS && |
| m_previewQ->getSizeOfProcessQ() >= 2) || |
| (m_exynosCameraParameters->getPreviewBufferCount() == NUM_PREVIEW_BUFFERS && |
| m_previewQ->getSizeOfProcessQ() >= 1)) && |
| (m_previewThread->isRunning() == true)) { |
| if ((m_getRecordingEnabled() == true) && (m_exynosCameraParameters->doCscRecording() == false)) { |
| CLOGW("WARN(%s[%d]):push frame to previewQ. PreviewQ(%d), PreviewBufferCount(%d)", |
| __FUNCTION__, |
| __LINE__, |
| m_previewQ->getSizeOfProcessQ(), |
| m_exynosCameraParameters->getPreviewBufferCount()); |
| m_previewQ->pushProcessQ(&callbackFrame); |
| } else { |
| CLOGW("WARN(%s[%d]):Frames are stacked in previewQ. Skip frame. PreviewQ(%d), PreviewBufferCount(%d)", |
| __FUNCTION__, __LINE__, |
| m_previewQ->getSizeOfProcessQ(), |
| m_exynosCameraParameters->getPreviewBufferCount()); |
| newFrame->setFrameState(FRAME_STATE_SKIPPED); |
| |
| callbackFrame->decRef(); |
| m_frameMgr->deleteFrame(callbackFrame); |
| callbackFrame = NULL; |
| } |
| } else if((m_exynosCameraParameters->getFastFpsMode() == 2) && (m_exynosCameraParameters->getRecordingHint() == 1)) { |
| m_skipCount++; |
| CLOGV("INFO(%s[%d]):push frame to previewQ", __FUNCTION__, __LINE__); |
| m_previewQ->pushProcessQ(&callbackFrame); |
| } else { |
| if (m_getRecordingEnabled() == true) { |
| CLOGV("INFO(%s[%d]):push frame to previewQ", __FUNCTION__, __LINE__); |
| m_previewQ->pushProcessQ(&callbackFrame); |
| } else { |
| CLOGV("INFO(%s[%d]):push frame to previewQ", __FUNCTION__, __LINE__); |
| m_previewQ->pushProcessQ(&callbackFrame); |
| } |
| } |
| delete shot_ext; |
| shot_ext = NULL; |
| } |
| newFrame->decRef(); |
| m_frameMgr->deleteFrame(newFrame); |
| //m_mainSetupQ[INDEX(entity->getPipeId())]->pushProcessQ(&newFrame); |
| CLOGV("DEBUG(%s[%d]):SCP done HAL-frameCount(%d)", __FUNCTION__, __LINE__, frame->getFrameCount()); |
| } else { |
| CLOGV("DEBUG(%s[%d]):SCP droped - SCP buffer is not ready HAL-frameCount(%d)", __FUNCTION__, __LINE__, frame->getFrameCount()); |
| |
| ret = frame->getDstBuffer(entity->getPipeId(), &buffer, m_previewFrameFactory->getNodeType(PIPE_SCP)); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]):getDstBuffer fail, pipeId(%d), ret(%d)", |
| __FUNCTION__, __LINE__, entity->getPipeId(), ret); |
| return ret; |
| } |
| |
| if (buffer.index >= 0) { |
| ret = m_scpBufferMgr->cancelBuffer(buffer.index); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]):SCP buffer return fail", __FUNCTION__, __LINE__); |
| } |
| } |
| |
| /* For debug */ |
| /* m_previewFrameFactory->dump(); */ |
| |
| /* Comment out, because it included ISP */ |
| /* |
| newFrame = m_previewFrameFactory->createNewFrameOnlyOnePipe(PIPE_SCP, frame->getFrameCount()); |
| newFrame->setDstBuffer(PIPE_SCP, buffer); |
| newFrame->setFrameState(FRAME_STATE_SKIPPED); |
| |
| m_mainSetupQ[INDEX(entity->getPipeId())]->pushProcessQ(&newFrame); |
| */ |
| } |
| break; |
| default: |
| break; |
| } |
| |
| entity_state_complete: |
| |
| ret = frame->setEntityState(entity->getPipeId(), ENTITY_STATE_COMPLETE); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]):setEntityState fail, pipeId(%d), state(%d), ret(%d)", |
| __FUNCTION__, __LINE__, entity->getPipeId(), ENTITY_STATE_COMPLETE, ret); |
| m_frameFliteDeleteBetweenPreviewReprocessing.unlock(); |
| return ret; |
| } |
| |
| if (frame->isComplete() == true) { |
| ret = m_removeFrameFromList(&m_processList, frame); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]):remove frame from processList fail, ret(%d)", __FUNCTION__, __LINE__, ret); |
| } |
| |
| frame->decRef(); |
| m_frameMgr->deleteFrame(frame); |
| } |
| |
| |
| return NO_ERROR; |
| } |
| |
| status_t ExynosCamera::m_handlePreviewFrameFrontDual(ExynosCameraFrame *frame) |
| { |
| int ret = 0; |
| ExynosCameraFrameEntity *entity = NULL; |
| ExynosCameraFrame *newFrame = NULL; |
| ExynosCameraFrame *fdFrame = NULL; |
| |
| ExynosCameraBuffer buffer; |
| ExynosCameraBuffer t3acBuffer; |
| int pipeID = 0; |
| /* to handle the high speed frame rate */ |
| bool skipPreview = false; |
| int ratio = 1; |
| uint32_t minFps = 0, maxFps = 0; |
| uint32_t dispFps = EXYNOS_CAMERA_PREVIEW_FPS_REFERENCE; |
| uint32_t fvalid = 0; |
| uint32_t fcount = 0; |
| uint32_t skipCount = 0; |
| struct camera2_stream *shot_stream = NULL; |
| ExynosCameraBuffer resultBuffer; |
| camera2_node_group node_group_info_isp; |
| int32_t reprocessingBayerMode = m_exynosCameraParameters->getReprocessingBayerMode(); |
| int ispDstBufferIndex = -1; |
| |
| entity = frame->getFrameDoneFirstEntity(); |
| if (entity == NULL) { |
| CLOGE("ERR(%s[%d]):current entity is NULL", __FUNCTION__, __LINE__); |
| /* TODO: doing exception handling */ |
| return true; |
| } |
| |
| pipeID = entity->getPipeId(); |
| |
| /* TODO: remove hard coding */ |
| switch(INDEX(entity->getPipeId())) { |
| case PIPE_3AA_ISP: |
| break; |
| case PIPE_3AC: |
| case PIPE_FLITE: |
| m_debugFpsCheck(entity->getPipeId()); |
| |
| ret = frame->getDstBuffer(entity->getPipeId(), &buffer); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]):getDstBuffer fail, pipeId(%d), ret(%d)", |
| __FUNCTION__, __LINE__, entity->getPipeId(), ret); |
| return ret; |
| } |
| |
| m_setupEntity(PIPE_3AA, frame, &buffer, NULL); |
| m_previewFrameFactory->setOutputFrameQToPipe(m_pipeFrameDoneQ, PIPE_3AA); |
| m_previewFrameFactory->pushFrameToPipe(&frame, PIPE_3AA); |
| |
| newFrame = m_frameMgr->createFrame(m_exynosCameraParameters, 0); |
| m_mainSetupQ[INDEX(entity->getPipeId())]->pushProcessQ(&newFrame); |
| |
| break; |
| case PIPE_3AA: |
| m_debugFpsCheck(entity->getPipeId()); |
| |
| ret = frame->getSrcBuffer(entity->getPipeId(), &buffer); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]):getSrcBuffer fail, pipeId(%d), ret(%d)", |
| __FUNCTION__, __LINE__, entity->getPipeId(), ret); |
| return ret; |
| } |
| |
| ret = m_sccCaptureSelector->manageFrameHoldList(frame, entity->getPipeId(), false, CAPTURE_NODE); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]):manageFrameHoldList fail", __FUNCTION__, __LINE__); |
| return ret; |
| } |
| |
| |
| if (buffer.index >= 0) { |
| ret = m_putBuffers(m_bayerBufferMgr, buffer.index); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]):put Buffer fail", __FUNCTION__, __LINE__); |
| } |
| } |
| |
| frame->setMetaDataEnable(true); |
| |
| CLOGV("DEBUG(%s[%d]):3AA_ISP frameCount(%d) frame.Count(%d)", |
| __FUNCTION__, __LINE__, |
| getMetaDmRequestFrameCount((struct camera2_shot_ext *)buffer.addr[1]), |
| frame->getFrameCount()); |
| |
| case PIPE_SCP: |
| if (entity->getDstBufState() == ENTITY_BUFFER_STATE_ERROR) { |
| if (frame->getFrameState() != FRAME_STATE_SKIPPED) { |
| ret = frame->getDstBuffer(entity->getPipeId(), &buffer, m_previewFrameFactory->getNodeType(PIPE_SCP)); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]):getDstBuffer fail, pipeId(%d), ret(%d)", |
| __FUNCTION__, __LINE__, entity->getPipeId(), ret); |
| return ret; |
| } |
| |
| if (buffer.index >= 0) { |
| ret = m_scpBufferMgr->cancelBuffer(buffer.index); |
| if (ret < 0) |
| CLOGE("ERR(%s[%d]):SCP buffer return fail", __FUNCTION__, __LINE__); |
| } |
| /* For debug */ |
| /* m_previewFrameFactory->dump(); */ |
| |
| /* Comment out, because it included ISP */ |
| /* |
| newFrame = m_previewFrameFactory->createNewFrameOnlyOnePipe(PIPE_SCP, frame->getFrameCount()); |
| newFrame->setDstBuffer(PIPE_SCP, buffer); |
| newFrame->setFrameState(FRAME_STATE_SKIPPED); |
| |
| m_mainSetupQ[INDEX(entity->getPipeId())]->pushProcessQ(&newFrame); |
| */ |
| } |
| CLOGV("DEBUG(%s[%d]):SCP done HAL-frameCount(%d)", __FUNCTION__, __LINE__, frame->getFrameCount()); |
| } else if (entity->getDstBufState() == ENTITY_BUFFER_STATE_COMPLETE) { |
| m_debugFpsCheck(entity->getPipeId()); |
| |
| ret = frame->getDstBuffer(entity->getPipeId(), &buffer, m_previewFrameFactory->getNodeType(PIPE_SCP)); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]):getDstBuffer fail, pipeId(%d), ret(%d)", |
| __FUNCTION__, __LINE__, entity->getPipeId(), ret); |
| return ret; |
| } |
| |
| /* TO DO : skip frame for HDR */ |
| shot_stream = (struct camera2_stream *)buffer.addr[2]; |
| |
| if (shot_stream != NULL) { |
| getStreamFrameValid(shot_stream, &fvalid); |
| getStreamFrameCount(shot_stream, &fcount); |
| } else { |
| CLOGE("ERR(%s[%d]):shot_stream is NULL", __FUNCTION__, __LINE__); |
| fvalid = false; |
| fcount = 0; |
| } |
| |
| /* drop preview frame if lcd supported frame rate < scp frame rate */ |
| frame->getFpsRange(&minFps, &maxFps); |
| if (dispFps < maxFps) { |
| ratio = (int)((maxFps * 10 / dispFps) / 10); |
| m_displayPreviewToggle = (m_displayPreviewToggle + 1) % ratio; |
| skipPreview = (m_displayPreviewToggle == 0) ? true : false; |
| #ifdef DEBUG |
| CLOGE("DEBUG(%s[%d]):preview frame skip! frameCount(%d) (m_displayPreviewToggle=%d, maxFps=%d, dispFps=%d, ratio=%d, skipPreview=%d)", |
| __FUNCTION__, __LINE__, frame->getFrameCount(), m_displayPreviewToggle, maxFps, dispFps, ratio, (int)skipPreview); |
| #endif |
| } |
| |
| newFrame = m_previewFrameFactory->createNewFrameOnlyOnePipe(PIPE_SCP, frame->getFrameCount()); |
| newFrame->setDstBuffer(PIPE_SCP, buffer); |
| |
| m_exynosCameraParameters->getFrameSkipCount(&m_frameSkipCount); |
| if (m_frameSkipCount > 0) { |
| CLOGD("INFO(%s[%d]):Skip frame for frameSkipCount(%d) buffer.index(%d)", |
| __FUNCTION__, __LINE__, m_frameSkipCount, buffer.index); |
| newFrame->setFrameState(FRAME_STATE_SKIPPED); |
| if (buffer.index >= 0) { |
| ret = m_scpBufferMgr->cancelBuffer(buffer.index); |
| if (ret < 0) |
| CLOGE("ERR(%s[%d]):SCP buffer return fail", __FUNCTION__, __LINE__); |
| } |
| } else { |
| if (m_skipReprocessing == true) |
| m_skipReprocessing = false; |
| nsecs_t timeStamp = (nsecs_t)frame->getTimeStamp(); |
| if (m_getRecordingEnabled() == true |
| && m_exynosCameraParameters->msgTypeEnabled(CAMERA_MSG_VIDEO_FRAME)) { |
| if (timeStamp <= 0L) { |
| CLOGE("WARN(%s[%d]):timeStamp(%lld) Skip", __FUNCTION__, __LINE__, timeStamp); |
| } else { |
| if (m_exynosCameraParameters->doCscRecording() == true) { |
| /* get Recording Image buffer */ |
| int bufIndex = -2; |
| ExynosCameraBuffer recordingBuffer; |
| ret = m_recordingBufferMgr->getBuffer(&bufIndex, EXYNOS_CAMERA_BUFFER_POSITION_IN_HAL, &recordingBuffer); |
| if (ret < 0 || bufIndex < 0) { |
| if ((++m_recordingFrameSkipCount % 100) == 0) { |
| CLOGE("ERR(%s[%d]): Recording buffer is not available!! Recording Frames are Skipping(%d frames) (bufIndex=%d)", |
| __FUNCTION__, __LINE__, m_recordingFrameSkipCount, bufIndex); |
| m_recordingBufferMgr->printBufferQState(); |
| } |
| } else { |
| if (m_recordingFrameSkipCount != 0) { |
| CLOGE("ERR(%s[%d]): Recording buffer is not available!! Recording Frames are Skipped(%d frames) (bufIndex=%d) (recordingQ=%d)", |
| __FUNCTION__, __LINE__, m_recordingFrameSkipCount, bufIndex, m_recordingQ->getSizeOfProcessQ()); |
| m_recordingFrameSkipCount = 0; |
| m_recordingBufferMgr->printBufferQState(); |
| } |
| m_recordingTimeStamp[bufIndex] = timeStamp; |
| |
| ret = m_doPrviewToRecordingFunc(PIPE_GSC_VIDEO, buffer, recordingBuffer); |
| if (ret < 0) { |
| CLOGW("WARN(%s[%d]):recordingCallback Skip", __FUNCTION__, __LINE__); |
| } |
| } |
| } else { |
| m_recordingTimeStamp[buffer.index] = timeStamp; |
| |
| if (m_recordingStartTimeStamp == 0) { |
| m_recordingStartTimeStamp = timeStamp; |
| CLOGI("INFO(%s[%d]):m_recordingStartTimeStamp=%lld", |
| __FUNCTION__, __LINE__, m_recordingStartTimeStamp); |
| } |
| |
| if ((0L < timeStamp) |
| && (m_lastRecordingTimeStamp < timeStamp) |
| && (m_recordingStartTimeStamp <= timeStamp)) { |
| if (m_getRecordingEnabled() == true |
| && m_exynosCameraParameters->msgTypeEnabled(CAMERA_MSG_VIDEO_FRAME)) { |
| #ifdef CHECK_MONOTONIC_TIMESTAMP |
| CLOGD("DEBUG(%s[%d]):m_dataCbTimestamp::recordingFrameIndex=%d, recordingTimeStamp=%lld, fd[0]=%d", |
| __FUNCTION__, __LINE__, buffer.index, timeStamp, buffer.fd[0]); |
| #endif |
| #ifdef DEBUG |
| CLOGD("DEBUG(%s[%d]): - lastTimeStamp(%lld), systemTime(%lld), recordingStart(%lld)", |
| __FUNCTION__, __LINE__, |
| m_lastRecordingTimeStamp, |
| systemTime(SYSTEM_TIME_MONOTONIC), |
| m_recordingStartTimeStamp); |
| #endif |
| |
| if (m_recordingBufAvailable[buffer.index] == false) { |
| CLOGW("WARN(%s[%d]):recordingFrameIndex(%d) didn't release yet !!! drop the frame !!! " |
| " timeStamp(%lld) m_recordingBufAvailable(%d)", |
| __FUNCTION__, __LINE__, buffer.index, timeStamp, (int)m_recordingBufAvailable[buffer.index]); |
| } else { |
| struct addrs *recordAddrs = NULL; |
| |
| recordAddrs = (struct addrs *)m_recordingCallbackHeap->data; |
| recordAddrs[buffer.index].type = kMetadataBufferTypeCameraSource; |
| recordAddrs[buffer.index].fdPlaneY = (unsigned int)buffer.fd[0]; |
| recordAddrs[buffer.index].fdPlaneCbcr = (unsigned int)buffer.fd[1]; |
| recordAddrs[buffer.index].bufIndex = buffer.index; |
| |
| m_recordingBufAvailable[buffer.index] = false; |
| m_lastRecordingTimeStamp = timeStamp; |
| |
| m_dataCbTimestamp( |
| timeStamp, |
| CAMERA_MSG_VIDEO_FRAME, |
| m_recordingCallbackHeap, |
| buffer.index, |
| m_callbackCookie); |
| } |
| } |
| } else { |
| CLOGW("WARN(%s[%d]):recordingFrameIndex=%d, timeStamp(%lld) invalid -" |
| " lastTimeStamp(%lld), systemTime(%lld), recordingStart(%lld), m_recordingBufAvailable(%d)", |
| __FUNCTION__, __LINE__, buffer.index, timeStamp, |
| m_lastRecordingTimeStamp, |
| systemTime(SYSTEM_TIME_MONOTONIC), |
| m_recordingStartTimeStamp, |
| (int)m_recordingBufAvailable[buffer.index]); |
| m_recordingTimeStamp[buffer.index] = 0L; |
| } |
| } |
| } |
| } |
| ExynosCameraBuffer callbackBuffer; |
| ExynosCameraFrame *callbackFrame = NULL; |
| struct camera2_shot_ext *shot_ext = new struct camera2_shot_ext; |
| callbackFrame = m_previewFrameFactory->createNewFrameOnlyOnePipe(PIPE_SCP, frame->getFrameCount()); |
| frame->getDstBuffer(entity->getPipeId(), &callbackBuffer, m_previewFrameFactory->getNodeType(PIPE_SCP)); |
| frame->getMetaData(shot_ext); |
| callbackFrame->storeDynamicMeta(shot_ext); |
| callbackFrame->setDstBuffer(PIPE_SCP, callbackBuffer); |
| |
| if (((m_exynosCameraParameters->getPreviewBufferCount() == NUM_PREVIEW_BUFFERS + NUM_PREVIEW_SPARE_BUFFERS && |
| m_previewQ->getSizeOfProcessQ() >= 2) || |
| (m_exynosCameraParameters->getPreviewBufferCount() == NUM_PREVIEW_BUFFERS && |
| m_previewQ->getSizeOfProcessQ() >= 1)) && |
| (m_previewThread->isRunning() == true)) { |
| CLOGW("WARN(%s[%d]):Frames are stacked in previewQ. Skip frame. PreviewQ(%d), PreviewBufferCount(%d)", |
| __FUNCTION__, __LINE__, |
| m_previewQ->getSizeOfProcessQ(), |
| m_exynosCameraParameters->getPreviewBufferCount()); |
| |
| newFrame->setFrameState(FRAME_STATE_SKIPPED); |
| if (buffer.index >= 0) { |
| ret = m_scpBufferMgr->cancelBuffer(buffer.index); |
| if (ret < 0) |
| CLOGE("ERR(%s[%d]):SCP buffer return fail", __FUNCTION__, __LINE__); |
| } |
| |
| callbackFrame->decRef(); |
| m_frameMgr->deleteFrame(callbackFrame); |
| callbackFrame = NULL; |
| } else if((m_exynosCameraParameters->getFastFpsMode() == 2) && (m_exynosCameraParameters->getRecordingHint() == 1)) { |
| m_skipCount++; |
| CLOGV("INFO(%s[%d]):push frame to previewQ", __FUNCTION__, __LINE__); |
| m_previewQ->pushProcessQ(&callbackFrame); |
| } else { |
| CLOGV("INFO(%s[%d]):push frame to previewQ", __FUNCTION__, __LINE__); |
| m_previewQ->pushProcessQ(&callbackFrame); |
| } |
| delete shot_ext; |
| shot_ext = NULL; |
| } |
| newFrame->decRef(); |
| m_frameMgr->deleteFrame(newFrame); |
| //m_mainSetupQ[INDEX(entity->getPipeId())]->pushProcessQ(&newFrame); |
| CLOGV("DEBUG(%s[%d]):SCP done HAL-frameCount(%d)", __FUNCTION__, __LINE__, frame->getFrameCount()); |
| } else { |
| CLOGV("DEBUG(%s[%d]):SCP droped - SCP buffer is not ready HAL-frameCount(%d)", __FUNCTION__, __LINE__, frame->getFrameCount()); |
| |
| ret = frame->getDstBuffer(entity->getPipeId(), &buffer, m_previewFrameFactory->getNodeType(PIPE_SCP)); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]):getDstBuffer fail, pipeId(%d), ret(%d)", |
| __FUNCTION__, __LINE__, entity->getPipeId(), ret); |
| return ret; |
| } |
| |
| if (buffer.index >= 0) { |
| ret = m_scpBufferMgr->cancelBuffer(buffer.index); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]):SCP buffer return fail", __FUNCTION__, __LINE__); |
| } |
| } |
| } |
| break; |
| default: |
| break; |
| } |
| |
| entity_state_complete: |
| |
| ret = frame->setEntityState(entity->getPipeId(), ENTITY_STATE_COMPLETE); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]):setEntityState fail, pipeId(%d), state(%d), ret(%d)", |
| __FUNCTION__, __LINE__, entity->getPipeId(), ENTITY_STATE_COMPLETE, ret); |
| return ret; |
| } |
| |
| if (frame->isComplete() == true) { |
| ret = m_removeFrameFromList(&m_processList, frame); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]):remove frame from processList fail, ret(%d)", __FUNCTION__, __LINE__, ret); |
| } |
| |
| frame->decRef(); |
| m_frameMgr->deleteFrame(frame); |
| } |
| |
| return NO_ERROR; |
| } |
| |
| bool ExynosCamera::m_frameFactoryInitThreadFunc(void) |
| { |
| |
| #ifdef DEBUG |
| ExynosCameraAutoTimer autoTimer(__FUNCTION__); |
| #endif |
| bool loop = false; |
| status_t ret = NO_ERROR; |
| |
| ExynosCameraFrameFactory *framefactory = NULL; |
| |
| ret = m_frameFactoryQ->waitAndPopProcessQ(&framefactory); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]):wait and pop fail, ret(%d)", __FUNCTION__, __LINE__, ret); |
| goto func_exit; |
| } |
| |
| if (framefactory == NULL) { |
| CLOGE("ERR(%s[%d]):framefactory is NULL", __FUNCTION__, __LINE__); |
| goto func_exit; |
| } |
| |
| if (framefactory->isCreated() == false) { |
| CLOGD("DEBUG(%s[%d]):framefactory create", __FUNCTION__, __LINE__); |
| framefactory->create(false); |
| } else { |
| CLOGD("DEBUG(%s[%d]):framefactory already create", __FUNCTION__, __LINE__); |
| } |
| |
| func_exit: |
| if (0 < m_frameFactoryQ->getSizeOfProcessQ()) { |
| if (m_previewEnabled == true) { |
| loop = true; |
| } else { |
| CLOGW("WARN(%s[%d]):Sudden stopPreview. so, stop making frameFactory (m_frameFactoryQ->getSizeOfProcessQ() : %d)", |
| __FUNCTION__, __LINE__, m_frameFactoryQ->getSizeOfProcessQ()); |
| loop = false; |
| } |
| } |
| |
| return loop; |
| } |
| |
| bool ExynosCamera::m_previewThreadFunc(void) |
| { |
| #ifdef DEBUG |
| ExynosCameraAutoTimer autoTimer(__FUNCTION__); |
| #endif |
| |
| int ret = 0; |
| bool loop = true; |
| int pipeId = 0; |
| int pipeIdCsc = 0; |
| int maxbuffers = 0; |
| #ifdef USE_PREVIEW_DURATION_CONTROL |
| uint32_t offset = 1000; /* 1ms */ |
| uint32_t curMinFps = 0; |
| uint32_t curMaxFps = 0; |
| uint64_t frameDurationUs; |
| #endif |
| ExynosCameraBuffer buffer; |
| ExynosCameraFrame *frame = NULL; |
| nsecs_t timeStamp = 0; |
| int frameCount = -1; |
| frame_queue_t *previewQ; |
| |
| #ifdef USE_PREVIEW_DURATION_CONTROL |
| m_exynosCameraParameters->getPreviewFpsRange(&curMinFps, &curMaxFps); |
| |
| /* Check the Slow/Fast Motion Scenario - sensor : 120fps, preview : 60fps */ |
| if((curMinFps == 120) && (curMaxFps == 120)) { |
| CLOGV("(%s[%d]) : Change PreviewDuration from (%d,%d) to (60000, 60000)", __FUNCTION__, __LINE__, curMinFps, curMaxFps); |
| curMinFps = 60; |
| curMaxFps = 60; |
| } |
| |
| frameDurationUs = 1000000/curMaxFps; |
| if (frameDurationUs > offset) { |
| frameDurationUs = frameDurationUs - offset; /* add the offset value for timing issue */ |
| } |
| PreviewDurationTimer.start(); |
| #endif |
| |
| pipeId = PIPE_SCP; |
| pipeIdCsc = PIPE_GSC; |
| |
| previewQ = m_previewQ; |
| |
| CLOGV("INFO(%s[%d]):wait previewQ", __FUNCTION__, __LINE__); |
| ret = previewQ->waitAndPopProcessQ(&frame); |
| if (m_flagThreadStop == true) { |
| CLOGI("INFO(%s[%d]):m_flagThreadStop(%d)", __FUNCTION__, __LINE__, m_flagThreadStop); |
| |
| if (frame != NULL) { |
| frame->decRef(); |
| m_frameMgr->deleteFrame(frame); |
| frame = NULL; |
| } |
| |
| return false; |
| } |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]):wait and pop fail, ret(%d)", __FUNCTION__, __LINE__, ret); |
| ret = INVALID_OPERATION; |
| goto func_exit; |
| } |
| |
| if (frame == NULL) { |
| CLOGE("ERR(%s[%d]):frame is NULL", __FUNCTION__, __LINE__); |
| ret = INVALID_OPERATION; |
| goto func_exit; |
| } |
| |
| CLOGV("INFO(%s[%d]):get frame from previewQ", __FUNCTION__, __LINE__); |
| timeStamp = (nsecs_t)frame->getTimeStamp(); |
| frameCount = frame->getFrameCount(); |
| ret = frame->getDstBuffer(pipeId, &buffer); |
| |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]):getDstBuffer fail, ret(%d)", __FUNCTION__, __LINE__, ret); |
| /* TODO: doing exception handling */ |
| goto func_exit; |
| } |
| |
| /* ------------- frome here "frame" cannot use ------------- */ |
| CLOGV("INFO(%s[%d]):push frame to previewReturnQ", __FUNCTION__, __LINE__); |
| if(m_exynosCameraParameters->increaseMaxBufferOfPreview()) { |
| maxbuffers = m_exynosCameraParameters->getPreviewBufferCount(); |
| } else { |
| maxbuffers = (int)m_exynosconfig->current->bufInfo.num_preview_buffers; |
| } |
| |
| if (buffer.index < 0 || buffer.index >= maxbuffers ) { |
| CLOGE("ERR(%s[%d]):Out of Index! (Max: %d, Index: %d)", __FUNCTION__, __LINE__, maxbuffers, buffer.index); |
| goto func_exit; |
| } |
| |
| CLOGV("INFO(%s[%d]):m_previewQ->getSizeOfProcessQ(%d) m_scpBufferMgr->getNumOfAvailableBuffer(%d)", __FUNCTION__, __LINE__, |
| previewQ->getSizeOfProcessQ(), m_scpBufferMgr->getNumOfAvailableBuffer()); |
| |
| /* Prevent displaying unprocessed beauty images in beauty shot. */ |
| if ((m_exynosCameraParameters->getShotMode() == SHOT_MODE_BEAUTY_FACE)) { |
| if (m_exynosCameraParameters->msgTypeEnabled(CAMERA_MSG_PREVIEW_FRAME) && |
| checkBit(&m_callbackState, CALLBACK_STATE_COMPRESSED_IMAGE)) { |
| CLOGV("INFO(%s[%d]):skip the preview callback and the preview display while compressed callback.", |
| __FUNCTION__, __LINE__); |
| ret = m_scpBufferMgr->cancelBuffer(buffer.index); |
| goto func_exit; |
| } |
| } |
| |
| if ((m_previewWindow == NULL) || |
| (m_getRecordingEnabled() == true) || |
| (m_exynosCameraParameters->getPreviewBufferCount() == NUM_PREVIEW_BUFFERS + NUM_PREVIEW_SPARE_BUFFERS && |
| m_scpBufferMgr->getNumOfAvailableAndNoneBuffer() > 4 && |
| previewQ->getSizeOfProcessQ() < 2) || |
| (m_exynosCameraParameters->getPreviewBufferCount() == NUM_PREVIEW_BUFFERS && |
| m_scpBufferMgr->getNumOfAvailableAndNoneBuffer() > 2 && |
| previewQ->getSizeOfProcessQ() < 1)) { |
| if (m_exynosCameraParameters->msgTypeEnabled(CAMERA_MSG_PREVIEW_FRAME) && |
| m_highResolutionCallbackRunning == false) { |
| ExynosCameraBuffer previewCbBuffer; |
| |
| ret = m_setPreviewCallbackBuffer(); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]):m_setPreviewCallback Buffer fail", __FUNCTION__, __LINE__); |
| return ret; |
| } |
| |
| int bufIndex = -2; |
| m_previewCallbackBufferMgr->getBuffer(&bufIndex, EXYNOS_CAMERA_BUFFER_POSITION_IN_HAL, &previewCbBuffer); |
| |
| ExynosCameraFrame *newFrame = NULL; |
| |
| newFrame = m_previewFrameFactory->createNewFrameOnlyOnePipe(pipeIdCsc); |
| if (newFrame == NULL) { |
| CLOGE("ERR(%s):newFrame is NULL", __FUNCTION__); |
| return UNKNOWN_ERROR; |
| } |
| |
| ret = m_doPreviewToCallbackFunc(pipeIdCsc, newFrame, buffer, previewCbBuffer); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]):m_doPreviewToCallbackFunc fail", __FUNCTION__, __LINE__); |
| } else { |
| if (m_exynosCameraParameters->getCallbackNeedCopy2Rendering() == true) { |
| ret = m_doCallbackToPreviewFunc(pipeIdCsc, frame, previewCbBuffer, buffer); |
| if (ret < 0) |
| CLOGE("ERR(%s[%d]):m_doCallbackToPreviewFunc fail", __FUNCTION__, __LINE__); |
| } |
| } |
| |
| if (newFrame != NULL) { |
| newFrame->decRef(); |
| m_frameMgr->deleteFrame(newFrame); |
| newFrame = NULL; |
| } |
| |
| m_previewCallbackBufferMgr->putBuffer(bufIndex, EXYNOS_CAMERA_BUFFER_POSITION_NONE); |
| } |
| |
| if (m_previewWindow != NULL) { |
| if (timeStamp > 0L) { |
| m_previewWindow->set_timestamp(m_previewWindow, (int64_t)timeStamp); |
| } else { |
| uint32_t fcount = 0; |
| getStreamFrameCount((struct camera2_stream *)buffer.addr[2], &fcount); |
| CLOGW("WRN(%s[%d]): frameCount(%d)(%d), Invalid timeStamp(%lld)", |
| __FUNCTION__, __LINE__, |
| frameCount, |
| fcount, |
| timeStamp); |
| } |
| } |
| |
| #ifdef FIRST_PREVIEW_TIME_CHECK |
| if (m_flagFirstPreviewTimerOn == true) { |
| m_firstPreviewTimer.stop(); |
| m_flagFirstPreviewTimerOn = false; |
| |
| CLOGD("DEBUG(%s[%d]):m_firstPreviewTimer stop", __FUNCTION__, __LINE__); |
| |
| CLOGD("DEBUG(%s[%d]):============= First Preview time ==================", "m_printExynosCameraInfo", __LINE__); |
| CLOGD("DEBUG(%s[%d]):= startPreview ~ first frame : %d msec", "m_printExynosCameraInfo", __LINE__, (int)m_firstPreviewTimer.durationMsecs()); |
| CLOGD("DEBUG(%s[%d]):===================================================", "m_printExynosCameraInfo", __LINE__); |
| } |
| #endif |
| |
| /* display the frame */ |
| ret = m_putBuffers(m_scpBufferMgr, buffer.index); |
| if (ret < 0) { |
| /* TODO: error handling */ |
| CLOGE("ERR(%s[%d]):put Buffer fail", __FUNCTION__, __LINE__); |
| } |
| } else { |
| ALOGW("WARN(%s[%d]):Preview frame buffer is canceled." |
| "PreviewThread is blocked or too many buffers are in Service." |
| "PreviewBufferCount(%d), ScpBufferMgr(%d), PreviewQ(%d)", |
| __FUNCTION__, __LINE__, |
| m_exynosCameraParameters->getPreviewBufferCount(), |
| m_scpBufferMgr->getNumOfAvailableAndNoneBuffer(), |
| previewQ->getSizeOfProcessQ()); |
| ret = m_scpBufferMgr->cancelBuffer(buffer.index); |
| } |
| |
| func_exit: |
| |
| if (frame != NULL) { |
| frame->decRef(); |
| m_frameMgr->deleteFrame(frame); |
| frame = NULL; |
| } |
| |
| #ifdef USE_PREVIEW_DURATION_CONTROL |
| PreviewDurationTimer.stop(); |
| if ((m_getRecordingEnabled() == true) && (curMinFps == curMaxFps) && |
| (m_exynosCameraParameters->getShotMode() != SHOT_MODE_SEQUENCE)) { |
| PreviewDurationTime = PreviewDurationTimer.durationUsecs(); |
| |
| if ( frameDurationUs > PreviewDurationTime ) { |
| uint64_t delay = frameDurationUs - PreviewDurationTime; |
| CLOGV("(%s):Delay Time(%lld),fpsRange(%d,%d), Duration(%lld)", __FUNCTION__, |
| frameDurationUs - PreviewDurationTime, |
| curMinFps, |
| curMaxFps, |
| frameDurationUs); |
| usleep(delay); |
| } |
| } |
| #endif |
| return loop; |
| } |
| |
| 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_exynosCameraParameters->getPreviewFormat(); |
| |
| m_exynosCameraParameters->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_doPreviewToCallbackFunc( |
| int32_t pipeId, |
| ExynosCameraFrame *newFrame, |
| ExynosCameraBuffer previewBuf, |
| ExynosCameraBuffer callbackBuf) |
| { |
| CLOGV("DEBUG(%s): converting preview to callback buffer", __FUNCTION__); |
| |
| int ret = 0; |
| status_t statusRet = NO_ERROR; |
| |
| int hwPreviewW = 0, hwPreviewH = 0; |
| int hwPreviewFormat = m_exynosCameraParameters->getHwPreviewFormat(); |
| bool useCSC = m_exynosCameraParameters->getCallbackNeedCSC(); |
| |
| ExynosCameraDurationTimer probeTimer; |
| int probeTimeMSEC; |
| uint32_t fcount = 0; |
| |
| m_exynosCameraParameters->getHwPreviewSize(&hwPreviewW, &hwPreviewH); |
| |
| ExynosRect srcRect, dstRect; |
| |
| camera_memory_t *previewCallbackHeap = NULL; |
| previewCallbackHeap = m_getMemoryCb(callbackBuf.fd[0], callbackBuf.size[0], 1, m_callbackCookie); |
| if (!previewCallbackHeap || previewCallbackHeap->data == MAP_FAILED) { |
| CLOGE("ERR(%s[%d]):m_getMemoryCb(%d) fail", __FUNCTION__, __LINE__, callbackBuf.size[0]); |
| statusRet = INVALID_OPERATION; |
| goto done; |
| } |
| |
| ret = m_setCallbackBufferInfo(&callbackBuf, (char *)previewCallbackHeap->data); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]): setCallbackBufferInfo fail, ret(%d)", __FUNCTION__, __LINE__, ret); |
| statusRet = INVALID_OPERATION; |
| goto done; |
| } |
| |
| ret = m_calcPreviewGSCRect(&srcRect, &dstRect); |
| |
| if (useCSC) { |
| ret = newFrame->setSrcRect(pipeId, &srcRect); |
| ret = newFrame->setDstRect(pipeId, &dstRect); |
| |
| ret = m_setupEntity(pipeId, newFrame, &previewBuf, &callbackBuf); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]):setupEntity fail, pipeId(%d), ret(%d)", |
| __FUNCTION__, __LINE__, pipeId, ret); |
| statusRet = INVALID_OPERATION; |
| goto done; |
| } |
| m_previewFrameFactory->pushFrameToPipe(&newFrame, pipeId); |
| m_previewFrameFactory->setOutputFrameQToPipe(m_previewCallbackGscFrameDoneQ, pipeId); |
| |
| CLOGV("INFO(%s[%d]):wait preview callback output", __FUNCTION__, __LINE__); |
| ret = m_previewCallbackGscFrameDoneQ->waitAndPopProcessQ(&newFrame); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]):wait and pop fail, ret(%d)", __FUNCTION__, __LINE__, ret); |
| /* TODO: doing exception handling */ |
| statusRet = INVALID_OPERATION; |
| goto done; |
| } |
| if (newFrame == NULL) { |
| CLOGE("ERR(%s[%d]):newFrame is NULL", __FUNCTION__, __LINE__); |
| statusRet = INVALID_OPERATION; |
| goto done; |
| } |
| CLOGV("INFO(%s[%d]):preview callback done", __FUNCTION__, __LINE__); |
| |
| #if 0 |
| int remainedH = m_orgPreviewRect.h - dst_height; |
| |
| if (remainedH != 0) { |
| char *srcAddr = NULL; |
| char *dstAddr = NULL; |
| int planeDiver = 1; |
| |
| for (int plane = 0; plane < 2; plane++) { |
| planeDiver = (plane + 1) * 2 / 2; |
| |
| srcAddr = previewBuf.virt.extP[plane] + (ALIGN_UP(hwPreviewW, CAMERA_ISP_ALIGN) * dst_crop_height / planeDiver); |
| dstAddr = callbackBuf->virt.extP[plane] + (m_orgPreviewRect.w * dst_crop_height / planeDiver); |
| |
| for (int i = 0; i < remainedH; i++) { |
| memcpy(dstAddr, srcAddr, (m_orgPreviewRect.w / planeDiver)); |
| |
| srcAddr += (ALIGN_UP(hwPreviewW, CAMERA_ISP_ALIGN) / planeDiver); |
| dstAddr += (m_orgPreviewRect.w / planeDiver); |
| } |
| } |
| } |
| #endif |
| } else { /* neon memcpy */ |
| char *srcAddr = NULL; |
| char *dstAddr = NULL; |
| int planeCount = getYuvPlaneCount(hwPreviewFormat); |
| if (planeCount <= 0) { |
| CLOGE("ERR(%s[%d]):getYuvPlaneCount(%d) fail", __FUNCTION__, __LINE__, hwPreviewFormat); |
| statusRet = INVALID_OPERATION; |
| goto done; |
| } |
| |
| /* TODO : have to consider all fmt(planes) and stride */ |
| for (int plane = 0; plane < planeCount; plane++) { |
| srcAddr = previewBuf.addr[plane]; |
| dstAddr = callbackBuf.addr[plane]; |
| memcpy(dstAddr, srcAddr, callbackBuf.size[plane]); |
| } |
| } |
| |
| probeTimer.start(); |
| if (m_exynosCameraParameters->msgTypeEnabled(CAMERA_MSG_PREVIEW_FRAME) && |
| !checkBit(&m_callbackState, CALLBACK_STATE_COMPRESSED_IMAGE) && |
| m_disablePreviewCB == false) { |
| 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); |
| } |
| probeTimer.stop(); |
| getStreamFrameCount((struct camera2_stream *)previewBuf.addr[2], &fcount); |
| probeTimeMSEC = (int)probeTimer.durationMsecs(); |
| |
| if (probeTimeMSEC > 33 && probeTimeMSEC <= 66) |
| CLOGV("(%s[%d]):(%d) duration time(%5d msec)", __FUNCTION__, __LINE__, fcount, (int)probeTimer.durationMsecs()); |
| else if(probeTimeMSEC > 66) |
| CLOGD("(%s[%d]):(%d) duration time(%5d msec)", __FUNCTION__, __LINE__, fcount, (int)probeTimer.durationMsecs()); |
| else |
| CLOGV("(%s[%d]):(%d) duration time(%5d msec)", __FUNCTION__, __LINE__, fcount, (int)probeTimer.durationMsecs()); |
| |
| done: |
| if (previewCallbackHeap != NULL) { |
| previewCallbackHeap->release(previewCallbackHeap); |
| } |
| |
| return statusRet; |
| } |
| |
| status_t ExynosCamera::m_doCallbackToPreviewFunc( |
| int32_t pipeId, |
| ExynosCameraFrame *newFrame, |
| ExynosCameraBuffer callbackBuf, |
| ExynosCameraBuffer previewBuf) |
| { |
| CLOGV("DEBUG(%s): converting callback to preview buffer", __FUNCTION__); |
| |
| int ret = 0; |
| status_t statusRet = NO_ERROR; |
| |
| int hwPreviewW = 0, hwPreviewH = 0; |
| int hwPreviewFormat = m_exynosCameraParameters->getHwPreviewFormat(); |
| bool useCSC = m_exynosCameraParameters->getCallbackNeedCSC(); |
| |
| m_exynosCameraParameters->getHwPreviewSize(&hwPreviewW, &hwPreviewH); |
| |
| camera_memory_t *previewCallbackHeap = NULL; |
| previewCallbackHeap = m_getMemoryCb(callbackBuf.fd[0], callbackBuf.size[0], 1, m_callbackCookie); |
| if (!previewCallbackHeap || previewCallbackHeap->data == MAP_FAILED) { |
| CLOGE("ERR(%s[%d]):m_getMemoryCb(%d) fail", __FUNCTION__, __LINE__, callbackBuf.size[0]); |
| statusRet = INVALID_OPERATION; |
| goto done; |
| } |
| |
| ret = m_setCallbackBufferInfo(&callbackBuf, (char *)previewCallbackHeap->data); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]): setCallbackBufferInfo fail, ret(%d)", __FUNCTION__, __LINE__, ret); |
| statusRet = INVALID_OPERATION; |
| goto done; |
| } |
| |
| if (useCSC) { |
| #if 0 |
| if (m_exynosPreviewCSC) { |
| csc_set_src_format(m_exynosPreviewCSC, |
| ALIGN_DOWN(m_orgPreviewRect.w, CAMERA_MAGIC_ALIGN), ALIGN_DOWN(m_orgPreviewRect.h, CAMERA_MAGIC_ALIGN), |
| 0, 0, ALIGN_DOWN(m_orgPreviewRect.w, CAMERA_MAGIC_ALIGN), ALIGN_DOWN(m_orgPreviewRect.h, CAMERA_MAGIC_ALIGN), |
| V4L2_PIX_2_HAL_PIXEL_FORMAT(m_orgPreviewRect.colorFormat), |
| 1); |
| |
| csc_set_dst_format(m_exynosPreviewCSC, |
| previewW, previewH, |
| 0, 0, previewW, previewH, |
| V4L2_PIX_2_HAL_PIXEL_FORMAT(previewFormat), |
| 0); |
| |
| csc_set_src_buffer(m_exynosPreviewCSC, |
| (void **)callbackBuf->virt.extP, CSC_MEMORY_USERPTR); |
| |
| csc_set_dst_buffer(m_exynosPreviewCSC, |
| (void **)previewBuf.fd.extFd, CSC_MEMORY_TYPE); |
| |
| if (csc_convert_with_rotation(m_exynosPreviewCSC, 0, m_flip_horizontal, 0) != 0) |
| CLOGE("ERR(%s):csc_convert() from callback to lcd fail", __FUNCTION__); |
| } else { |
| CLOGE("ERR(%s):m_exynosPreviewCSC == NULL", __FUNCTION__); |
| } |
| #else |
| CLOGW("WRN(%s[%d]): doCallbackToPreview use CSC is not yet possible", __FUNCTION__, __LINE__); |
| #endif |
| } else { /* neon memcpy */ |
| char *srcAddr = NULL; |
| char *dstAddr = NULL; |
| int planeCount = getYuvPlaneCount(hwPreviewFormat); |
| if (planeCount <= 0) { |
| CLOGE("ERR(%s[%d]):getYuvPlaneCount(%d) fail", __FUNCTION__, __LINE__, hwPreviewFormat); |
| statusRet = INVALID_OPERATION; |
| goto done; |
| } |
| |
| /* TODO : have to consider all fmt(planes) and stride */ |
| for (int plane = 0; plane < planeCount; plane++) { |
| srcAddr = callbackBuf.addr[plane]; |
| dstAddr = previewBuf.addr[plane]; |
| memcpy(dstAddr, srcAddr, callbackBuf.size[plane]); |
| } |
| } |
| |
| done: |
| if (previewCallbackHeap != NULL) { |
| previewCallbackHeap->release(previewCallbackHeap); |
| } |
| |
| return statusRet; |
| } |
| |
| status_t ExynosCamera::m_handlePreviewFrameFront(ExynosCameraFrame *frame) |
| { |
| int ret = 0; |
| uint32_t skipCount = 0; |
| ExynosCameraFrameEntity *entity = NULL; |
| ExynosCameraFrame *newFrame = NULL; |
| ExynosCameraFrame *fdFrame = NULL; |
| ExynosCameraBuffer buffer; |
| int pipeID = 0; |
| ExynosCameraBuffer resultBuffer; |
| camera2_node_group node_group_info_isp; |
| enum pipeline pipe; |
| |
| entity = frame->getFrameDoneEntity(); |
| if (entity == NULL) { |
| CLOGE("ERR(%s[%d]):current entity is NULL, frameCount(%d)", |
| __FUNCTION__, __LINE__, frame->getFrameCount()); |
| /* TODO: doing exception handling */ |
| return true; |
| } |
| |
| if (entity->getEntityState() == ENTITY_STATE_FRAME_SKIP) |
| goto entity_state_complete; |
| |
| pipeID = entity->getPipeId(); |
| |
| switch(entity->getPipeId()) { |
| case PIPE_ISP: |
| m_debugFpsCheck(entity->getPipeId()); |
| ret = frame->getSrcBuffer(entity->getPipeId(), &buffer); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]):getSrcBuffer fail, pipeId(%d), ret(%d)", |
| __FUNCTION__, __LINE__, entity->getPipeId(), ret); |
| return ret; |
| } |
| frame->setMetaDataEnable(true); |
| |
| ret = m_putBuffers(m_ispBufferMgr, buffer.index); |
| |
| ret = frame->getSrcBuffer(PIPE_3AA, &buffer); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]):getSrcBuffer fail, pipeId(%d), ret(%d)", |
| __FUNCTION__, __LINE__, entity->getPipeId(), ret); |
| return ret; |
| } |
| |
| if (m_exynosCameraParameters->isReprocessing() == true) { |
| ret = m_captureSelector->manageFrameHoldList(frame, pipeID, true); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]):manageFrameHoldList fail", __FUNCTION__, __LINE__); |
| return ret; |
| } |
| } else { |
| /* TODO: This is unusual case, flite buffer and isp buffer */ |
| ret = m_putBuffers(m_bayerBufferMgr, buffer.index); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]):put Buffer fail", __FUNCTION__, __LINE__); |
| } |
| } |
| |
| skipCount = m_exynosCameraParameters->getFrameSkipCount(); |
| if (skipCount <= 0 && m_flagStartFaceDetection == true) { |
| /* Face detection */ |
| struct camera2_shot_ext shot; |
| frame->getDynamicMeta(&shot); |
| fdFrame = m_frameMgr->createFrame(m_exynosCameraParameters, frame->getFrameCount()); |
| fdFrame->storeDynamicMeta(&shot); |
| m_facedetectQ->pushProcessQ(&fdFrame); |
| } |
| |
| ret = generateFrame(m_3aa_ispFrameCount, &newFrame); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]):generateFrame fail", __FUNCTION__, __LINE__); |
| return ret; |
| } |
| |
| m_setupEntity(PIPE_FLITE, newFrame); |
| m_previewFrameFactory->pushFrameToPipe(&newFrame, PIPE_FLITE); |
| |
| m_setupEntity(PIPE_3AA, newFrame); |
| m_setupEntity(PIPE_ISP, newFrame); |
| m_previewFrameFactory->setOutputFrameQToPipe(m_pipeFrameDoneQ, PIPE_ISP); |
| |
| m_3aa_ispFrameCount++; |
| |
| /* HACK: When SCC pipe is stopped, generate frame for SCC */ |
| if ((m_sccBufferMgr->getNumOfAvailableBuffer() > 2)) { |
| CLOGW("WRN(%s[%d]): Too many available SCC buffers, generating frame for SCC", __FUNCTION__, __LINE__); |
| |
| pipe = (isOwnScc(getCameraId()) == true) ? PIPE_SCC : PIPE_ISPC; |
| |
| while (m_sccBufferMgr->getNumOfAvailableBuffer() > 0) { |
| ret = generateFrame(m_sccFrameCount, &newFrame); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]):generateFrame fail", __FUNCTION__, __LINE__); |
| return ret; |
| } |
| |
| m_setupEntity(pipe, newFrame); |
| m_previewFrameFactory->pushFrameToPipe(&newFrame, pipe); |
| m_previewFrameFactory->setOutputFrameQToPipe(m_pipeFrameDoneQ, pipe); |
| |
| m_sccFrameCount++; |
| } |
| } |
| |
| break; |
| case PIPE_ISPC: |
| case PIPE_SCC: |
| m_debugFpsCheck(entity->getPipeId()); |
| if (entity->getDstBufState() == ENTITY_BUFFER_STATE_COMPLETE) { |
| ret = m_sccCaptureSelector->manageFrameHoldList(frame, entity->getPipeId(), false); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]):manageFrameHoldList fail", __FUNCTION__, __LINE__); |
| return ret; |
| } |
| } |
| |
| pipe = (isOwnScc(getCameraId()) == true) ? PIPE_SCC : PIPE_ISPC; |
| |
| while (m_sccBufferMgr->getNumOfAvailableBuffer() > 0) { |
| ret = generateFrameSccScp(pipe, &m_sccFrameCount, &newFrame); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]):generateFrameSccScp fail", __FUNCTION__, __LINE__); |
| return ret; |
| } |
| |
| m_setupEntity(pipe, newFrame); |
| m_previewFrameFactory->pushFrameToPipe(&newFrame, pipe); |
| m_previewFrameFactory->setOutputFrameQToPipe(m_pipeFrameDoneQ, pipe); |
| |
| m_sccFrameCount++; |
| } |
| break; |
| case PIPE_SCP: |
| if (entity->getDstBufState() == ENTITY_BUFFER_STATE_ERROR) { |
| ret = frame->getDstBuffer(entity->getPipeId(), &buffer, m_previewFrameFactory->getNodeType(PIPE_SCP)); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]):getDstBuffer fail, pipeId(%d), ret(%d)", |
| __FUNCTION__, __LINE__, entity->getPipeId(), ret); |
| return ret; |
| } |
| ret = m_scpBufferMgr->cancelBuffer(buffer.index); |
| |
| } else if (entity->getDstBufState() == ENTITY_BUFFER_STATE_COMPLETE) { |
| m_debugFpsCheck(entity->getPipeId()); |
| ret = frame->getDstBuffer(entity->getPipeId(), &buffer, m_previewFrameFactory->getNodeType(PIPE_SCP)); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]):getDstBuffer fail, pipeId(%d), ret(%d)", |
| __FUNCTION__, __LINE__, entity->getPipeId(), ret); |
| return ret; |
| } |
| |
| m_exynosCameraParameters->getFrameSkipCount(&m_frameSkipCount); |
| if (m_frameSkipCount > 0) { |
| CLOGD("INFO(%s[%d]):frameSkipCount=%d", __FUNCTION__, __LINE__, m_frameSkipCount); |
| ret = m_scpBufferMgr->cancelBuffer(buffer.index); |
| } else { |
| nsecs_t timeStamp = (nsecs_t)frame->getTimeStamp(); |
| if (m_getRecordingEnabled() == true |
| && m_exynosCameraParameters->msgTypeEnabled(CAMERA_MSG_VIDEO_FRAME)) { |
| if (timeStamp <= 0L) { |
| CLOGE("WARN(%s[%d]):timeStamp(%lld) Skip", __FUNCTION__, __LINE__, timeStamp); |
| } else { |
| /* get Recording Image buffer */ |
| int bufIndex = -2; |
| ExynosCameraBuffer recordingBuffer; |
| ret = m_recordingBufferMgr->getBuffer(&bufIndex, EXYNOS_CAMERA_BUFFER_POSITION_IN_HAL, &recordingBuffer); |
| if (ret < 0 || bufIndex < 0) { |
| if ((++m_recordingFrameSkipCount % 100) == 0) { |
| CLOGE("ERR(%s[%d]): Recording buffer is not available!! Recording Frames are Skipping(%d frames) (bufIndex=%d)", |
| __FUNCTION__, __LINE__, m_recordingFrameSkipCount, bufIndex); |
| } |
| } else { |
| if (m_recordingFrameSkipCount != 0) { |
| CLOGE("ERR(%s[%d]): Recording buffer is not available!! Recording Frames are Skipped(%d frames) (bufIndex=%d)", |
| __FUNCTION__, __LINE__, m_recordingFrameSkipCount, bufIndex); |
| m_recordingFrameSkipCount = 0; |
| } |
| m_recordingTimeStamp[bufIndex] = timeStamp; |
| ret = m_doPrviewToRecordingFunc(PIPE_GSC_VIDEO, buffer, recordingBuffer); |
| if (ret < 0) { |
| CLOGW("WARN(%s[%d]):recordingCallback Skip", __FUNCTION__, __LINE__); |
| } |
| } |
| } |
| } |
| |
| ExynosCameraBuffer callbackBuffer; |
| ExynosCameraFrame *callbackFrame = NULL; |
| struct camera2_shot_ext *shot_ext = new struct camera2_shot_ext; |
| |
| callbackFrame = m_previewFrameFactory->createNewFrameOnlyOnePipe(PIPE_SCP); |
| frame->getDstBuffer(PIPE_SCP, &callbackBuffer, m_previewFrameFactory->getNodeType(PIPE_SCP)); |
| frame->getMetaData(shot_ext); |
| callbackFrame->storeDynamicMeta(shot_ext); |
| callbackFrame->setDstBuffer(PIPE_SCP, callbackBuffer); |
| delete shot_ext; |
| |
| CLOGV("INFO(%s[%d]):push frame to front previewQ", __FUNCTION__, __LINE__); |
| m_previewQ->pushProcessQ(&callbackFrame); |
| |
| CLOGV("DEBUG(%s[%d]):SCP done HAL-frameCount(%d)", __FUNCTION__, __LINE__, frame->getFrameCount()); |
| } |
| } else { |
| CLOGV("DEBUG(%s[%d]):SCP droped - SCP buffer is not ready HAL-frameCount(%d)", __FUNCTION__, __LINE__, frame->getFrameCount()); |
| |
| ret = frame->getDstBuffer(entity->getPipeId(), &buffer, m_previewFrameFactory->getNodeType(PIPE_SCP)); |
| if (buffer.index >= 0) { |
| ret = m_scpBufferMgr->cancelBuffer(buffer.index); |
| if (ret < 0) |
| CLOGE("ERR(%s[%d]):SCP buffer return fail", __FUNCTION__, __LINE__); |
| } |
| m_previewFrameFactory->dump(); |
| } |
| |
| ret = generateFrameSccScp(PIPE_SCP, &m_scpFrameCount, &newFrame); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]):generateFrameSccScp fail", __FUNCTION__, __LINE__); |
| return ret; |
| } |
| |
| m_setupEntity(PIPE_SCP, newFrame); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]):setupEntity fail", __FUNCTION__, __LINE__); |
| break; |
| } |
| |
| /*check preview drop...*/ |
| newFrame->getDstBuffer(PIPE_SCP, &resultBuffer, m_previewFrameFactory->getNodeType(PIPE_SCP)); |
| if (resultBuffer.index < 0) { |
| newFrame->setRequest(PIPE_SCP, false); |
| newFrame->getNodeGroupInfo(&node_group_info_isp, PERFRAME_INFO_ISP); |
| node_group_info_isp.capture[PERFRAME_FRONT_SCP_POS].request = 0; |
| newFrame->storeNodeGroupInfo(&node_group_info_isp, PERFRAME_INFO_ISP); |
| |
| m_previewFrameFactory->dump(); |
| |
| /* when preview buffer is not ready, we should drop preview to make preview buffer ready */ |
| CLOGW("WARN(%s[%d]):Front preview drop. Failed to get preview buffer. FrameSkipcount(%d)", |
| __FUNCTION__, __LINE__, FRAME_SKIP_COUNT_PREVIEW_FRONT); |
| m_exynosCameraParameters->setFrameSkipCount(FRAME_SKIP_COUNT_PREVIEW_FRONT); |
| } |
| |
| m_previewFrameFactory->pushFrameToPipe(&newFrame, PIPE_SCP); |
| m_previewFrameFactory->setOutputFrameQToPipe(m_pipeFrameDoneQ, PIPE_SCP); |
| |
| m_scpFrameCount++; |
| break; |
| default: |
| break; |
| } |
| |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]):put Buffer fail", __FUNCTION__, __LINE__); |
| return ret; |
| } |
| |
| entity_state_complete: |
| |
| ret = frame->setEntityState(entity->getPipeId(), ENTITY_STATE_COMPLETE); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]):setEntityState fail, pipeId(%d), state(%d), ret(%d)", |
| __FUNCTION__, __LINE__, entity->getPipeId(), ENTITY_STATE_COMPLETE, ret); |
| m_frameFliteDeleteBetweenPreviewReprocessing.unlock(); |
| return ret; |
| } |
| |
| if (frame->isComplete() == true) { |
| ret = m_removeFrameFromList(&m_processList, frame); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]):remove frame from processList fail, ret(%d)", __FUNCTION__, __LINE__, ret); |
| } |
| |
| frame->decRef(); |
| m_frameMgr->deleteFrame(frame); |
| } |
| |
| return NO_ERROR; |
| } |
| |
| status_t ExynosCamera::m_doZoomPrviewWithCSC(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 *bufferMgr = NULL; |
| int zoom = 0; |
| int previewH, previewW; |
| int bufIndex = -1; |
| int waitCount = 0; |
| int scpNodeIndex = -1; |
| int srcNodeIndex = -1; |
| int srcFmt = -1; |
| |
| previewFormat = m_exynosCameraParameters->getHwPreviewFormat(); |
| m_exynosCameraParameters->getHwPreviewSize(&previewW, &previewH); |
| |
| /* get Scaler src Buffer Node Index*/ |
| if (m_exynosCameraParameters->getDualMode() == true && getCameraId() == CAMERA_ID_FRONT) { |
| srcNodeIndex = m_previewFrameFactory->getNodeType(PIPE_ISPC); |
| srcFmt = m_exynosCameraParameters->getHWVdisFormat(); |
| scpNodeIndex = m_previewFrameFactory->getNodeType(PIPE_SCP); |
| } else { |
| srcFmt = previewFormat; |
| return true; |
| } |
| |
| /* get scaler source buffer */ |
| srcBuf.index = -1; |
| ret = frame->getDstBuffer(pipeId, &srcBuf, srcNodeIndex); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]):getDstBuffer fail, pipeId(%d), ret(%d)",__FUNCTION__, __LINE__, pipeId, ret); |
| return ret; |
| } |
| |
| /* getMetadata to get buffer size */ |
| meta = (struct camera2_stream*)srcBuf.addr[srcBuf.planeCount-1]; |
| |
| output = meta->output_crop_region; |
| |
| /* check scaler conditions( compare the crop size & format ) */ |
| if (output[2] == previewW && output[3] == previewH && srcFmt == previewFormat) { |
| return ret; |
| } |
| |
| /* wait unitil get buffers */ |
| do { |
| dstBuf.index = -2; |
| waitCount++; |
| |
| if (m_scpBufferMgr->getNumOfAvailableBuffer() > 0) |
| m_scpBufferMgr->getBuffer(&bufIndex, EXYNOS_CAMERA_BUFFER_POSITION_IN_HAL, &dstBuf); |
| |
| if (dstBuf.index < 0) { |
| usleep(WAITING_TIME); |
| |
| if (waitCount % 20 == 0) { |
| CLOGW("WRN(%s[%d]):retry JPEG getBuffer(%d) ", __FUNCTION__, __LINE__, bufIndex, m_zoomPreviwWithCscQ->getSizeOfProcessQ()); |
| m_scpBufferMgr->dump(); |
| } |
| } else { |
| break; |
| } |
| /* this will retry until 300msec */ |
| } while (waitCount < (TOTAL_WAITING_TIME / WAITING_TIME) && previewEnabled() == false); |
| |
| /* 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; |
| |
| 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 = frame->setSrcRect(gscPipe, srcRect); |
| ret = frame->setDstRect(gscPipe, dstRect); |
| |
| ret = m_setupEntity(gscPipe, frame, &srcBuf, &dstBuf); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]):setupEntity fail, pipeId(%d), ret(%d)", __FUNCTION__, __LINE__, gscPipe, ret); |
| ret = INVALID_OPERATION; |
| } |
| |
| m_previewFrameFactory->pushFrameToPipe(&frame, gscPipe); |
| m_previewFrameFactory->setOutputFrameQToPipe(m_zoomPreviwWithCscQ, gscPipe); |
| |
| /* wait GSC done */ |
| CLOGV("INFO(%s[%d]):wait GSC output", __FUNCTION__, __LINE__); |
| waitCount = 0; |
| |
| do { |
| ret = m_zoomPreviwWithCscQ->waitAndPopProcessQ(&frame); |
| waitCount++; |
| } while (ret == TIMED_OUT && waitCount < 100 && m_flagThreadStop != true); |
| |
| if (ret < 0) { |
| CLOGW("WARN(%s[%d]):GSC wait and pop return, ret(%d)", __FUNCTION__, __LINE__, ret); |
| } |
| if (frame == NULL) { |
| CLOGE("ERR(%s[%d]):frame is NULL", __FUNCTION__, __LINE__); |
| goto func_exit; |
| } |
| |
| /* copy metadata src to dst*/ |
| memcpy(dstBuf.addr[dstBuf.planeCount-1],srcBuf.addr[srcBuf.planeCount-1], sizeof(struct camera2_stream)); |
| |
| if (m_exynosCameraParameters->getDualMode() == true && getCameraId() == CAMERA_ID_FRONT) { |
| /* in case of dual front path buffer returned frameSelector, do not return buffer. */ |
| } else { |
| ret = m_scpBufferMgr->cancelBuffer(srcBuf.index); |
| } |
| |
| frame->setDstBufferState(pipeId, ENTITY_BUFFER_STATE_REQUESTED, scpNodeIndex); |
| ret = frame->setDstBuffer(pipeId, dstBuf, scpNodeIndex); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]):setdst Buffer failed(%d)", __FUNCTION__, __LINE__, ret); |
| } |
| frame->setDstBufferState(pipeId, ENTITY_BUFFER_STATE_COMPLETE, scpNodeIndex); |
| |
| CLOGV("DEBUG(%s[%d]):--OUT--", __FUNCTION__, __LINE__); |
| |
| return ret; |
| func_exit: |
| |
| |
| return ret; |
| } |
| |
| bool ExynosCamera::m_setBuffersThreadFunc(void) |
| { |
| int ret = 0; |
| |
| ret = m_setBuffers(); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]):m_setBuffers failed", __FUNCTION__, __LINE__); |
| |
| /* TODO: Need release buffers and error exit */ |
| |
| return false; |
| } |
| |
| return false; |
| } |
| |
| bool ExynosCamera::m_startPictureInternalThreadFunc(void) |
| { |
| int ret = 0; |
| |
| ret = m_startPictureInternal(); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]):m_setBuffers failed", __FUNCTION__, __LINE__); |
| |
| /* TODO: Need release buffers and error exit */ |
| |
| return false; |
| } |
| |
| return false; |
| } |
| |
| 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_exynosCameraParameters->getSeriesShotDuration(); |
| |
| m_burstPrePictureTimer.start(); |
| |
| if (m_exynosCameraParameters->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; |
| } |
| |
| /* |
| * 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; |
| #ifdef DEBUG_RAWDUMP |
| ExynosCameraBuffer bayerBuffer; |
| ExynosCameraBuffer pictureBuffer; |
| ExynosCameraFrame *inListFrame = NULL; |
| ExynosCameraFrame *bayerFrame = NULL; |
| #endif |
| int pipeId = 0; |
| int bufPipeId = 0; |
| bool isSrc = false; |
| int retryCount = 3; |
| |
| if (m_hdrEnabled) |
| retryCount = 15; |
| |
| if (isOwnScc(getCameraId()) == true) |
| bufPipeId = PIPE_SCC; |
| else if (m_exynosCameraParameters->isUsing3acForIspc() == true) |
| bufPipeId = PIPE_3AC; |
| else |
| bufPipeId = PIPE_ISPC; |
| |
| if (m_exynosCameraParameters->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()); |
| |
| m_postProcessList.push_back(newFrame); |
| |
| if ((m_exynosCameraParameters->getHighResolutionCallbackMode() == true) && |
| (m_highResolutionCallbackRunning == true)) { |
| m_highResolutionCallbackQ->pushProcessQ(&newFrame); |
| } else { |
| 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_exynosCameraParameters->getHighResolutionCallbackMode() == true) && |
| (m_highResolutionCallbackRunning == true)) |
| loop = true; |
| |
| if (m_reprocessingCounter.getCount() > 0) { |
| loop = true; |
| |
| } |
| |
| *pIsProcessed = true; |
| |
| #ifdef DEBUG_RAWDUMP |
| retryCount = 30; /* 200ms x 30 */ |
| bayerBuffer.index = -2; |
| |
| m_captureSelector->setWaitTime(200000000); |
| bayerFrame = m_captureSelector->selectFrames(1, PIPE_FLITE, isSrc, retryCount); |
| if (bayerFrame == NULL) { |
| CLOGE("ERR(%s[%d]):bayerFrame is NULL", __FUNCTION__, __LINE__); |
| } else { |
| ret = bayerFrame->getDstBuffer(PIPE_FLITE, &bayerBuffer); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]): getDstBuffer fail, pipeId(%d), ret(%d)", __FUNCTION__, __LINE__, PIPE_FLITE, ret); |
| } else { |
| if (m_exynosCameraParameters->checkBayerDumpEnable()) { |
| int sensorMaxW, sensorMaxH; |
| int sensorMarginW, sensorMarginH; |
| bool bRet; |
| char filePath[70]; |
| int fliteFcount = 0; |
| int pictureFcount = 0; |
| |
| camera2_shot_ext *shot_ext = NULL; |
| |
| ret = newFrame->getDstBuffer(PIPE_3AA, &pictureBuffer); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]): getDstBuffer fail, pipeId(%d), ret(%d)", __FUNCTION__, __LINE__, PIPE_3AA, ret); |
| } |
| |
| shot_ext = (camera2_shot_ext *)(bayerBuffer.addr[1]); |
| if (shot_ext != NULL) |
| fliteFcount = shot_ext->shot.dm.request.frameCount; |
| else |
| ALOGE("ERR(%s[%d]):fliteBayerBuffer is null", __FUNCTION__, __LINE__); |
| |
| shot_ext->shot.dm.request.frameCount = 0; |
| shot_ext = (camera2_shot_ext *)(pictureBuffer.addr[1]); |
| if (shot_ext != NULL) |
| pictureFcount = shot_ext->shot.dm.request.frameCount; |
| else |
| ALOGE("ERR(%s[%d]):PictureBuffer is null", __FUNCTION__, __LINE__); |
| |
| CLOGD("DEBUG(%s[%d]):bayer fcount(%d) picture fcount(%d)", __FUNCTION__, __LINE__, fliteFcount, pictureFcount); |
| /* The driver frame count is used to check the match between the 3AA frame and the FLITE frame. |
| if the match fails then the bayer buffer does not correspond to the capture output and hence |
| not written to the file */ |
| if (fliteFcount == pictureFcount) { |
| memset(filePath, 0, sizeof(filePath)); |
| snprintf(filePath, sizeof(filePath), "/data/rawdump/RawCapture%d_%d.raw",m_cameraId, pictureFcount); |
| |
| bRet = dumpToFile((char *)filePath, |
| bayerBuffer.addr[0], |
| bayerBuffer.size[0]); |
| if (bRet != true) |
| CLOGE("couldn't make a raw file"); |
| } |
| } |
| |
| if (bayerFrame != NULL) { |
| ret = m_bayerBufferMgr->putBuffer(bayerBuffer.index, EXYNOS_CAMERA_BUFFER_POSITION_IN_HAL); |
| if (ret < 0) { |
| ALOGE("ERR(%s[%d]):putBuffer failed Index is %d", __FUNCTION__, __LINE__, bayerBuffer.index); |
| m_bayerBufferMgr->printBufferState(); |
| m_bayerBufferMgr->printBufferQState(); |
| } |
| if (m_frameMgr != NULL) { |
| #ifdef USE_FRAME_REFERENCE_COUNT |
| bayerFrame->decRef(); |
| #endif |
| m_frameMgr->deleteFrame(bayerFrame); |
| } else { |
| ALOGE("ERR(%s[%d]):m_frameMgr is NULL (%d)", __FUNCTION__, __LINE__, bayerFrame->getFrameCount()); |
| } |
| bayerFrame = NULL; |
| } |
| } |
| } |
| #endif |
| return loop; |
| |
| CLEAN: |
| if (newFrame != NULL) { |
| newFrame->printEntity(); |
| CLOGD("DEBUG(%s[%d]): Picture frame delete(%d)", __FUNCTION__, __LINE__, newFrame->getFrameCount()); |
| newFrame->decRef(); |
| m_frameMgr->deleteFrame(newFrame); |
| newFrame = NULL; |
| } |
| |
| 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; |
| |
| } |
| |
| bool ExynosCamera::m_shutterCallbackThreadFunc(void) |
| { |
| CLOGI("INFO(%s[%d]):", __FUNCTION__, __LINE__); |
| int loop = false; |
| |
| if (m_exynosCameraParameters->msgTypeEnabled(CAMERA_MSG_SHUTTER)) { |
| CLOGI("INFO(%s[%d]): CAMERA_MSG_SHUTTER callback S", __FUNCTION__, __LINE__); |
| #ifdef BURST_CAPTURE |
| m_notifyCb(CAMERA_MSG_SHUTTER, m_exynosCameraParameters->getSeriesShotDuration(), 0, m_callbackCookie); |
| #else |
| m_notifyCb(CAMERA_MSG_SHUTTER, 0, 0, m_callbackCookie); |
| #endif |
| CLOGI("INFO(%s[%d]): CAMERA_MSG_SHUTTER callback E", __FUNCTION__, __LINE__); |
| } |
| |
| /* one shot */ |
| return loop; |
| } |
| |
| bool ExynosCamera::m_reprocessingPrePictureInternal(void) |
| { |
| ExynosCameraAutoTimer autoTimer(__FUNCTION__); |
| CLOGI("DEBUG(%s[%d]):", __FUNCTION__, __LINE__); |
| |
| int ret = 0; |
| bool loop = false; |
| int retry = 0; |
| int retryIsp = 0; |
| ExynosCameraFrame *newFrame = NULL; |
| ExynosCameraFrameEntity *entity = NULL; |
| camera2_shot_ext *shot_ext = NULL; |
| camera2_stream *shot_stream = NULL; |
| uint32_t bayerFrameCount = 0; |
| struct camera2_node_output output_crop_info; |
| |
| ExynosCameraBufferManager *bufferMgr = NULL; |
| |
| int bayerPipeId = 0; |
| int prePictureDonePipeId = 0; |
| enum pipeline pipe; |
| ExynosCameraBuffer bayerBuffer; |
| ExynosCameraBuffer ispReprocessingBuffer; |
| |
| camera2_shot_ext *updateDmShot = new struct camera2_shot_ext; |
| memset(updateDmShot, 0x0, sizeof(struct camera2_shot_ext)); |
| |
| bayerBuffer.index = -2; |
| ispReprocessingBuffer.index = -2; |
| |
| /* |
| * in case of pureBayer and 3aa_isp OTF, buffer will go isp directly |
| */ |
| if (m_exynosCameraParameters->getUsePureBayerReprocessing() == true) { |
| if (m_exynosCameraParameters->isReprocessing3aaIspOTF() == true) |
| prePictureDonePipeId = PIPE_3AA_REPROCESSING; |
| else |
| prePictureDonePipeId = PIPE_ISP_REPROCESSING; |
| } else { |
| prePictureDonePipeId = PIPE_ISP_REPROCESSING; |
| } |
| |
| if (m_exynosCameraParameters->getHighResolutionCallbackMode() == true) { |
| if (m_highResolutionCallbackRunning == true) { |
| /* will be removed */ |
| while (m_skipReprocessing == true) { |
| usleep(WAITING_TIME); |
| if (m_skipReprocessing == false) { |
| CLOGD("DEBUG(%s[%d]:stop skip frame for high resolution preview callback", __FUNCTION__, __LINE__); |
| break; |
| } |
| } |
| } else if (m_highResolutionCallbackRunning == false) { |
| CLOGW("WRN(%s[%d]): m_reprocessingThreadfunc stop for high resolution preview callback", __FUNCTION__, __LINE__); |
| loop = false; |
| goto CLEAN_FRAME; |
| } |
| } |
| |
| if (m_exynosCameraParameters->getReprocessingBayerMode() == REPROCESSING_BAYER_MODE_PURE_ALWAYS_ON || |
| m_exynosCameraParameters->getReprocessingBayerMode() == REPROCESSING_BAYER_MODE_PURE_DYNAMIC) { |
| /* Get Bayer buffer for reprocessing */ |
| ret = m_getBayerBuffer(m_getBayerPipeId(), &bayerBuffer); |
| } else if (m_exynosCameraParameters->getReprocessingBayerMode() == REPROCESSING_BAYER_MODE_DIRTY_ALWAYS_ON || |
| m_exynosCameraParameters->getReprocessingBayerMode() == REPROCESSING_BAYER_MODE_DIRTY_DYNAMIC) { |
| /* Get Bayer buffer for reprocessing */ |
| ret = m_getBayerBuffer(m_getBayerPipeId(), &bayerBuffer, updateDmShot); |
| } else { |
| CLOGE("ERR(%s[%d]): bayer mode is not valid (%d)", __FUNCTION__, __LINE__, |
| m_exynosCameraParameters->getReprocessingBayerMode()); |
| goto CLEAN_FRAME; |
| } |
| |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]): getBayerBuffer fail, ret(%d)", __FUNCTION__, __LINE__, ret); |
| goto CLEAN_FRAME; |
| } |
| |
| CLOGD("DEBUG(%s[%d]):bayerBuffer index %d", __FUNCTION__, __LINE__, bayerBuffer.index); |
| |
| if (m_exynosCameraParameters->getReprocessingBayerMode() == REPROCESSING_BAYER_MODE_DIRTY_DYNAMIC) { |
| m_frameFliteDeleteBetweenPreviewReprocessing.lock(); |
| m_captureSelector->clearList(m_getBayerPipeId(), false); |
| m_frameFliteDeleteBetweenPreviewReprocessing.unlock(); |
| } |
| |
| m_shutterCallbackThread->join(); |
| m_shutterCallbackThread->run(); |
| |
| /* Generate reprocessing Frame */ |
| ret = generateFrameReprocessing(&newFrame); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]):generateFrameReprocessing fail, ret(%d)", __FUNCTION__, __LINE__, ret); |
| goto CLEAN_FRAME; |
| } |
| |
| #ifdef DEBUG_RAWDUMP |
| if (m_exynosCameraParameters->checkBayerDumpEnable()) { |
| int sensorMaxW, sensorMaxH; |
| int sensorMarginW, sensorMarginH; |
| bool bRet; |
| char filePath[70]; |
| |
| memset(filePath, 0, sizeof(filePath)); |
| snprintf(filePath, sizeof(filePath), "/data/media/0/RawCapture%d_%d.raw",m_cameraId, m_fliteFrameCount); |
| if (m_exynosCameraParameters->getUsePureBayerReprocessing() == true) |
| /* Pure Bayer Buffer Size == MaxPictureSize + Sensor Margin == Max Sensor Size */ |
| m_exynosCameraParameters->getMaxSensorSize(&sensorMaxW, &sensorMaxH); |
| else |
| m_exynosCameraParameters->getMaxPictureSize(&sensorMaxW, &sensorMaxH); |
| |
| bRet = dumpToFile((char *)filePath, |
| bayerBuffer.addr[0], |
| sensorMaxW * sensorMaxH * 2); |
| if (bRet != true) |
| CLOGE("couldn't make a raw file"); |
| } |
| #endif /* DEBUG_RAWDUMP */ |
| |
| if (m_exynosCameraParameters->getUsePureBayerReprocessing() == false) { |
| /* TODO: HACK: Will be removed, this is driver's job */ |
| ret = m_convertingStreamToShotExt(&bayerBuffer, &output_crop_info); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]): shot_stream to shot_ext converting fail, ret(%d)", __FUNCTION__, __LINE__, ret); |
| goto CLEAN_FRAME; |
| } |
| |
| camera2_node_group node_group_info; |
| ExynosRect srcRect , dstRect; |
| int pictureW = 0, pictureH = 0; |
| |
| memset(&node_group_info, 0x0, sizeof(camera2_node_group)); |
| m_exynosCameraParameters->getPictureSize(&pictureW, &pictureH); |
| |
| newFrame->getNodeGroupInfo(&node_group_info, PERFRAME_INFO_DIRTY_REPROCESSING_ISP); |
| node_group_info.leader.input.cropRegion[0] = output_crop_info.cropRegion[0]; |
| node_group_info.leader.input.cropRegion[1] = output_crop_info.cropRegion[1]; |
| node_group_info.leader.input.cropRegion[2] = output_crop_info.cropRegion[2]; |
| node_group_info.leader.input.cropRegion[3] = output_crop_info.cropRegion[3]; |
| 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]; |
| |
| node_group_info.capture[PERFRAME_REPROCESSING_SCC_POS].input.cropRegion[0] = node_group_info.leader.output.cropRegion[0]; |
| node_group_info.capture[PERFRAME_REPROCESSING_SCC_POS].input.cropRegion[1] = node_group_info.leader.output.cropRegion[1]; |
| node_group_info.capture[PERFRAME_REPROCESSING_SCC_POS].input.cropRegion[2] = node_group_info.leader.output.cropRegion[2]; |
| node_group_info.capture[PERFRAME_REPROCESSING_SCC_POS].input.cropRegion[3] = node_group_info.leader.output.cropRegion[3]; |
| node_group_info.capture[PERFRAME_REPROCESSING_SCC_POS].output.cropRegion[0] = 0; |
| node_group_info.capture[PERFRAME_REPROCESSING_SCC_POS].output.cropRegion[1] = 0; |
| if (isOwnScc(getCameraId()) == true) { |
| node_group_info.capture[PERFRAME_REPROCESSING_SCC_POS].output.cropRegion[2] = pictureW; |
| node_group_info.capture[PERFRAME_REPROCESSING_SCC_POS].output.cropRegion[3] = pictureH; |
| } else { |
| node_group_info.capture[PERFRAME_REPROCESSING_SCC_POS].output.cropRegion[2] = node_group_info.leader.output.cropRegion[2]; |
| node_group_info.capture[PERFRAME_REPROCESSING_SCC_POS].output.cropRegion[3] = node_group_info.leader.output.cropRegion[3]; |
| } |
| |
| CLOGV("DEBUG(%s[%d]): isp capture input(%d %d %d %d), output(%d %d %d %d)", __FUNCTION__, __LINE__, |
| node_group_info.capture[PERFRAME_REPROCESSING_SCC_POS].input.cropRegion[0], |
| node_group_info.capture[PERFRAME_REPROCESSING_SCC_POS].input.cropRegion[1], |
| node_group_info.capture[PERFRAME_REPROCESSING_SCC_POS].input.cropRegion[2], |
| node_group_info.capture[PERFRAME_REPROCESSING_SCC_POS].input.cropRegion[3], |
| node_group_info.capture[PERFRAME_REPROCESSING_SCC_POS].output.cropRegion[0], |
| node_group_info.capture[PERFRAME_REPROCESSING_SCC_POS].output.cropRegion[1], |
| node_group_info.capture[PERFRAME_REPROCESSING_SCC_POS].output.cropRegion[2], |
| node_group_info.capture[PERFRAME_REPROCESSING_SCC_POS].output.cropRegion[3]); |
| |
| if (node_group_info.leader.output.cropRegion[2] < node_group_info.capture[PERFRAME_REPROCESSING_SCC_POS].input.cropRegion[2]) { |
| CLOGI("INFO(%s[%d]:(%d -> %d))", __FUNCTION__, __LINE__, |
| node_group_info.capture[PERFRAME_REPROCESSING_SCC_POS].input.cropRegion[2], |
| node_group_info.leader.output.cropRegion[2]); |
| |
| node_group_info.capture[PERFRAME_REPROCESSING_SCC_POS].input.cropRegion[2] = node_group_info.leader.output.cropRegion[2]; |
| } |
| if (node_group_info.leader.output.cropRegion[3] < node_group_info.capture[PERFRAME_REPROCESSING_SCC_POS].input.cropRegion[3]) { |
| CLOGI("INFO(%s[%d]:(%d -> %d))", __FUNCTION__, __LINE__, |
| node_group_info.capture[PERFRAME_REPROCESSING_SCC_POS].input.cropRegion[3], |
| node_group_info.leader.output.cropRegion[3]); |
| |
| node_group_info.capture[PERFRAME_REPROCESSING_SCC_POS].input.cropRegion[3] = node_group_info.leader.output.cropRegion[3]; |
| } |
| |
| newFrame->storeNodeGroupInfo(&node_group_info, PERFRAME_INFO_DIRTY_REPROCESSING_ISP); |
| } |
| |
| shot_ext = (struct camera2_shot_ext *)(bayerBuffer.addr[1]); |
| |
| /* Meta setting */ |
| if (shot_ext != NULL) { |
| if (m_exynosCameraParameters->getReprocessingBayerMode() == REPROCESSING_BAYER_MODE_PURE_ALWAYS_ON || |
| m_exynosCameraParameters->getReprocessingBayerMode() == REPROCESSING_BAYER_MODE_PURE_DYNAMIC) { |
| ret = newFrame->storeDynamicMeta(shot_ext); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]): storeDynamicMeta fail ret(%d)", __FUNCTION__, __LINE__, ret); |
| goto CLEAN_FRAME; |
| } |
| |
| ret = newFrame->storeUserDynamicMeta(shot_ext); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]): storeUserDynamicMeta fail ret(%d)", __FUNCTION__, __LINE__, ret); |
| goto CLEAN_FRAME; |
| } |
| } else if (m_exynosCameraParameters->getReprocessingBayerMode() == REPROCESSING_BAYER_MODE_DIRTY_ALWAYS_ON || |
| m_exynosCameraParameters->getReprocessingBayerMode() == REPROCESSING_BAYER_MODE_DIRTY_DYNAMIC) { |
| ret = newFrame->storeDynamicMeta(updateDmShot); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]): storeDynamicMeta fail ret(%d)", __FUNCTION__, __LINE__, ret); |
| goto CLEAN_FRAME; |
| } |
| |
| ret = newFrame->storeUserDynamicMeta(updateDmShot); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]): storeUserDynamicMeta fail ret(%d)", __FUNCTION__, __LINE__, ret); |
| goto CLEAN_FRAME; |
| } |
| } |
| |
| newFrame->getMetaData(shot_ext); |
| m_exynosCameraParameters->duplicateCtrlMetadata((void *)shot_ext); |
| |
| CLOGD("DEBUG(%s[%d]):meta_shot_ext->shot.dm.request.frameCount : %d", |
| __FUNCTION__, __LINE__, |
| getMetaDmRequestFrameCount(shot_ext)); |
| } else { |
| CLOGE("DEBUG(%s[%d]):shot_ext is NULL", __FUNCTION__, __LINE__); |
| } |
| |
| /* SCC */ |
| if (isOwnScc(getCameraId()) == true) { |
| pipe = PIPE_SCC_REPROCESSING; |
| |
| m_getBufferManager(pipe, &bufferMgr, DST_BUFFER_DIRECTION); |
| |
| ret = m_checkBufferAvailable(pipe, bufferMgr); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]): Waiting buffer timeout, pipeId(%d), ret(%d)", |
| __FUNCTION__, __LINE__, pipe, ret); |
| goto CLEAN_FRAME; |
| } |
| |
| ret = m_setupEntity(pipe, newFrame); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]:setupEntity fail, pipeId(%d), ret(%d)", |
| __FUNCTION__, __LINE__, pipe, ret); |
| goto CLEAN_FRAME; |
| } |
| |
| if ((m_exynosCameraParameters->getHighResolutionCallbackMode() == true) && |
| (m_highResolutionCallbackRunning == true)) { |
| m_reprocessingFrameFactory->setOutputFrameQToPipe(m_highResolutionCallbackQ, pipe); |
| } else { |
| m_reprocessingFrameFactory->setOutputFrameQToPipe(dstSccReprocessingQ, pipe); |
| } |
| |
| /* push frame to SCC pipe */ |
| m_reprocessingFrameFactory->pushFrameToPipe(&newFrame, pipe); |
| } else { |
| if (m_exynosCameraParameters->isReprocessing3aaIspOTF() == false) { |
| pipe = PIPE_ISP_REPROCESSING; |
| |
| m_getBufferManager(pipe, &bufferMgr, DST_BUFFER_DIRECTION); |
| |
| ret = m_checkBufferAvailable(pipe, bufferMgr); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]): Waiting buffer timeout, pipeId(%d), ret(%d)", |
| __FUNCTION__, __LINE__, pipe, ret); |
| goto CLEAN_FRAME; |
| } |
| |
| } else { |
| pipe = PIPE_3AA_REPROCESSING; |
| } |
| |
| if ((m_exynosCameraParameters->getHighResolutionCallbackMode() == true) && |
| (m_highResolutionCallbackRunning == true)) { |
| m_reprocessingFrameFactory->setFrameDoneQToPipe(m_highResolutionCallbackQ, pipe); |
| } else { |
| m_reprocessingFrameFactory->setFrameDoneQToPipe(dstSccReprocessingQ, pipe); |
| } |
| |
| } |
| |
| /* Add frame to post processing list */ |
| CLOGD("DEBUG(%s[%d]): postPictureList size(%d), frame(%d)", |
| __FUNCTION__, __LINE__, m_postProcessList.size(), newFrame->getFrameCount()); |
| newFrame->frameLock(); |
| m_postProcessList.push_back(newFrame); |
| |
| ret = m_reprocessingFrameFactory->startInitialThreads(); |
| if (ret < 0) { |
| CLOGE("ERR(%s):startInitialThreads fail", __FUNCTION__); |
| goto CLEAN; |
| } |
| |
| if (isOwnScc(getCameraId()) == true) { |
| retry = 0; |
| do { |
| if( m_reprocessingFrameFactory->checkPipeThreadRunning(pipe) == false ) { |
| ret = m_reprocessingFrameFactory->startInitialThreads(); |
| if (ret < 0) { |
| CLOGE("ERR(%s):startInitialThreads fail", __FUNCTION__); |
| } |
| } |
| |
| ret = newFrame->ensureDstBufferState(pipe, ENTITY_BUFFER_STATE_PROCESSING); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]): ensure buffer state(ENTITY_BUFFER_STATE_PROCESSING) fail(retry), ret(%d)", __FUNCTION__, __LINE__, ret); |
| usleep(1000); |
| retry++; |
| } |
| } while (ret < 0 && retry < 100); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]): ensure buffer state(ENTITY_BUFFER_STATE_PROCESSING) fail, ret(%d)", __FUNCTION__, __LINE__, ret); |
| goto CLEAN; |
| } |
| } |
| |
| /* Get bayerPipeId at first entity */ |
| bayerPipeId = newFrame->getFirstEntity()->getPipeId(); |
| CLOGD("DEBUG(%s[%d]): bayer Pipe ID(%d)", __FUNCTION__, __LINE__, bayerPipeId); |
| |
| /* Check available buffer */ |
| ret = m_getBufferManager(bayerPipeId, &bufferMgr, DST_BUFFER_DIRECTION); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]): getBufferManager fail, ret(%d)", __FUNCTION__, __LINE__, ret); |
| goto CLEAN; |
| } |
| if (bufferMgr != NULL) { |
| ret = m_checkBufferAvailable(bayerPipeId, bufferMgr); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]): Waiting buffer timeout, bayerPipeId(%d), ret(%d)", |
| __FUNCTION__, __LINE__, bayerPipeId, ret); |
| goto CLEAN; |
| } |
| } |
| |
| ret = m_setupEntity(bayerPipeId, newFrame, &bayerBuffer, NULL); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]:setupEntity fail, bayerPipeId(%d), ret(%d)", |
| __FUNCTION__, __LINE__, bayerPipeId, ret); |
| goto CLEAN; |
| } |
| |
| m_reprocessingFrameFactory->setOutputFrameQToPipe(dstIspReprocessingQ, prePictureDonePipeId); |
| |
| /* push the newFrameReprocessing to pipe */ |
| m_reprocessingFrameFactory->pushFrameToPipe(&newFrame, bayerPipeId); |
| |
| /* When enabled SCC capture or pureBayerReprocessing, we need to start bayer pipe thread */ |
| if (m_exynosCameraParameters->getUsePureBayerReprocessing() == true || |
| m_exynosCameraParameters->isSccCapture() == true) |
| m_reprocessingFrameFactory->startThread(bayerPipeId); |
| |
| /* wait ISP done */ |
| CLOGI("INFO(%s[%d]):wait ISP output", __FUNCTION__, __LINE__); |
| do { |
| ret = dstIspReprocessingQ->waitAndPopProcessQ(&newFrame); |
| retryIsp++; |
| } while (ret == TIMED_OUT && retryIsp < 100 && m_flagThreadStop != true); |
| |
| if (ret < 0) { |
| CLOGW("WARN(%s[%d]):ISP wait and pop return, 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(bayerPipeId, ENTITY_STATE_COMPLETE); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]):setEntityState(ENTITY_STATE_PROCESSING) fail, pipeId(%d), ret(%d)", __FUNCTION__, __LINE__, bayerPipeId, ret); |
| |
| if (updateDmShot != NULL) { |
| delete updateDmShot; |
| updateDmShot = NULL; |
| } |
| |
| return ret; |
| } |
| |
| CLOGI("INFO(%s[%d]):ISP output done", __FUNCTION__, __LINE__); |
| |
| newFrame->setMetaDataEnable(true); |
| |
| /* put bayer buffer */ |
| ret = m_putBuffers(m_bayerBufferMgr, bayerBuffer.index); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]): 3AA src putBuffer fail, index(%d), ret(%d)", __FUNCTION__, __LINE__, bayerBuffer.index, ret); |
| goto CLEAN; |
| } |
| |
| /* put isp buffer */ |
| if (m_exynosCameraParameters->getUsePureBayerReprocessing() == true) { |
| ret = m_getBufferManager(bayerPipeId, &bufferMgr, DST_BUFFER_DIRECTION); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]): getBufferManager fail, ret(%d)", __FUNCTION__, __LINE__, ret); |
| goto CLEAN; |
| } |
| if (bufferMgr != NULL) { |
| ret = newFrame->getDstBuffer(bayerPipeId, &ispReprocessingBuffer, m_previewFrameFactory->getNodeType(PIPE_FLITE)); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]):getDstBuffer fail, bayerPipeId(%d), ret(%d)", |
| __FUNCTION__, __LINE__, bayerPipeId, ret); |
| goto CLEAN; |
| } |
| ret = m_putBuffers(m_ispReprocessingBufferMgr, ispReprocessingBuffer.index); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]): ISP src putBuffer fail, index(%d), ret(%d)", __FUNCTION__, __LINE__, bayerBuffer.index, ret); |
| goto CLEAN; |
| } |
| } |
| } |
| |
| m_reprocessingCounter.decCount(); |
| |
| CLOGI("INFO(%s[%d]):reprocessing 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_exynosCameraParameters->getHighResolutionCallbackMode() == true) && |
| (m_highResolutionCallbackRunning == true)) |
| loop = true; |
| |
| if (m_reprocessingCounter.getCount() > 0) |
| loop = true; |
| |
| if (updateDmShot != NULL) { |
| delete updateDmShot; |
| updateDmShot = NULL; |
| } |
| |
| /* one shot */ |
| return loop; |
| |
| CLEAN_FRAME: |
| /* newFrame is not pushed any pipes, we can delete newFrame */ |
| if (newFrame != NULL) { |
| newFrame->printEntity(); |
| CLOGD("DEBUG(%s[%d]): Reprocessing frame delete(%d)", __FUNCTION__, __LINE__, newFrame->getFrameCount()); |
| newFrame->decRef(); |
| m_frameMgr->deleteFrame(newFrame); |
| newFrame = NULL; |
| } |
| |
| CLEAN: |
| if (bayerBuffer.index != -2 && m_bayerBufferMgr != NULL) |
| m_putBuffers(m_bayerBufferMgr, bayerBuffer.index); |
| if (ispReprocessingBuffer.index != -2 && m_ispReprocessingBufferMgr != NULL) |
| m_putBuffers(m_ispReprocessingBufferMgr, ispReprocessingBuffer.index); |
| |
| /* newFrame is already pushed some pipes, we can not delete newFrame until frame is complete */ |
| 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); |
| } |
| |
| newFrame->printEntity(); |
| CLOGD("DEBUG(%s[%d]): Reprocessing frame delete(%d)", __FUNCTION__, __LINE__, newFrame->getFrameCount()); |
| newFrame->decRef(); |
| m_frameMgr->deleteFrame(newFrame); |
| newFrame = NULL; |
| } |
| |
| if (updateDmShot != NULL) { |
| delete updateDmShot; |
| updateDmShot = NULL; |
| } |
| |
| 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_exynosCameraParameters->getHighResolutionCallbackMode() == true) && |
| (m_highResolutionCallbackRunning == true)) |
| loop = true; |
| |
| if (m_reprocessingCounter.getCount() > 0) |
| loop = true; |
| |
| CLOGI("INFO(%s[%d]): reprocessing fail, remaining count(%d)", __FUNCTION__, __LINE__, m_reprocessingCounter.getCount()); |
| |
| return loop; |
| } |
| |
| bool ExynosCamera::m_CheckBurstJpegSavingPath(char *dir) |
| { |
| int ret = false; |
| |
| struct dirent **items; |
| struct stat fstat; |
| |
| char *burstPath = m_exynosCameraParameters->getSeriesShotFilePath(); |
| |
| char ChangeDirPath[BURST_CAPTURE_FILEPATH_SIZE] = {'\0',}; |
| |
| memset(m_burstSavePath, 0, sizeof(m_burstSavePath)); |
| |
| // Check access path |
| if (burstPath && sizeof(m_burstSavePath) >= sizeof(burstPath)) { |
| strncpy(m_burstSavePath, burstPath, sizeof(m_burstSavePath)-1); |
| } else { |
| CLOGW("WARN(%s[%d]) Parameter burstPath is NULL. Change to Default Path", __FUNCTION__, __LINE__); |
| snprintf(m_burstSavePath, sizeof(m_burstSavePath), "%s/DCIM/Camera/", dir); |
| } |
| |
| if (access(m_burstSavePath, 0)==0) { |
| CLOGW("WARN(%s[%d]) success access dir = %s", __FUNCTION__, __LINE__, m_burstSavePath); |
| 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 |
| 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 |
| 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(m_burstSavePath, "%s/%s/", ChangeDirPath, items[j]->d_name); |
| CLOGW("WARN(%s[%d]) change save path = %s", __FUNCTION__, __LINE__, m_burstSavePath); |
| j = jitems; |
| ret = true; |
| break; |
| } |
| } |
| } |
| i = iitems; |
| break; |
| } |
| } |
| } |
| |
| if (items != NULL) { |
| free(items); |
| } |
| |
| return ret; |
| } |
| |
| bool ExynosCamera::m_pictureThreadFunc(void) |
| { |
| ExynosCameraAutoTimer autoTimer(__FUNCTION__); |
| CLOGI("INFO(%s[%d]):", __FUNCTION__, __LINE__); |
| |
| int ret = 0; |
| int loop = false; |
| int bufIndex = -2; |
| int retryCountGSC = 4; |
| |
| ExynosCameraFrame *newFrame = NULL; |
| |
| ExynosCameraBuffer sccReprocessingBuffer; |
| ExynosCameraBufferManager *bufferMgr = NULL; |
| struct camera2_stream *shot_stream = NULL; |
| ExynosRect srcRect, dstRect; |
| int pictureW = 0, pictureH = 0, pictureFormat = 0; |
| int hwPictureW = 0, hwPictureH = 0, hwPictureFormat = 0; |
| int buffer_idx = getShotBufferIdex(); |
| float zoomRatio = m_exynosCameraParameters->getZoomRatio(0) / 1000; |
| |
| sccReprocessingBuffer.index = -2; |
| |
| int pipeId_scc = 0; |
| int pipeId_gsc = 0; |
| bool isSrc = false; |
| |
| if (m_exynosCameraParameters->isReprocessing() == true) { |
| if (m_exynosCameraParameters->isReprocessing3aaIspOTF() == false) |
| pipeId_scc = (isOwnScc(getCameraId()) == true) ? PIPE_SCC_REPROCESSING : PIPE_ISP_REPROCESSING; |
| else |
| pipeId_scc = PIPE_3AA_REPROCESSING; |
| |
| pipeId_gsc = PIPE_GSC_REPROCESSING; |
| isSrc = true; |
| } else if (m_exynosCameraParameters->isUsing3acForIspc() == true) { |
| pipeId_scc = PIPE_3AA; |
| pipeId_gsc = PIPE_GSC_PICTURE; |
| } else { |
| switch (getCameraId()) { |
| case CAMERA_ID_FRONT: |
| if (m_exynosCameraParameters->getDualMode() == true) { |
| pipeId_scc = PIPE_3AA; |
| } else { |
| pipeId_scc = (isOwnScc(getCameraId()) == true) ? PIPE_SCC : PIPE_ISPC; |
| } |
| pipeId_gsc = PIPE_GSC_PICTURE; |
| break; |
| default: |
| CLOGE("ERR(%s[%d]):Current picture mode is not yet supported, CameraId(%d), reprocessing(%d)", |
| __FUNCTION__, __LINE__, getCameraId(), m_exynosCameraParameters->isReprocessing()); |
| break; |
| } |
| } |
| |
| /* wait SCC */ |
| CLOGI("INFO(%s[%d]):wait SCC output", __FUNCTION__, __LINE__); |
| int retry = 0; |
| do { |
| ret = dstSccReprocessingQ->waitAndPopProcessQ(&newFrame); |
| retry++; |
| } while (ret == TIMED_OUT && retry < 40 && |
| (m_takePictureCounter.getCount() > 0 || m_exynosCameraParameters->getSeriesShotCount() == 0)); |
| |
| if (ret < 0) { |
| CLOGW("WARN(%s[%d]):wait and pop fail, ret(%d), retry(%d), takePictuerCount(%d), seriesShotCount(%d)", |
| __FUNCTION__, __LINE__, ret, retry, m_takePictureCounter.getCount(), m_exynosCameraParameters->getSeriesShotCount()); |
| // TODO: doing exception handling |
| goto CLEAN; |
| } |
| |
| if (newFrame == NULL) { |
| CLOGE("ERR(%s[%d]):newFrame is NULL", __FUNCTION__, __LINE__); |
| goto CLEAN; |
| } |
| |
| if (m_postProcessList.size() <= 0) { |
| CLOGE("ERR(%s[%d]): postPictureList size(%d)", __FUNCTION__, __LINE__, m_postProcessList.size()); |
| usleep(5000); |
| if(m_postProcessList.size() <= 0) { |
| CLOGE("ERR(%s[%d]):Retry postPictureList size(%d)", __FUNCTION__, __LINE__, m_postProcessList.size()); |
| goto CLEAN; |
| } |
| } |
| |
| /* |
| * When Non-reprocessing scenario does not setEntityState, |
| * because Non-reprocessing scenario share preview and capture frames |
| */ |
| if (m_exynosCameraParameters->isReprocessing() == true) { |
| ret = newFrame->setEntityState(pipeId_scc, ENTITY_STATE_COMPLETE); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]):setEntityState(ENTITY_STATE_COMPLETE) fail, pipeId(%d), ret(%d)", __FUNCTION__, __LINE__, pipeId_scc, ret); |
| return ret; |
| } |
| } |
| |
| CLOGI("INFO(%s[%d]):SCC output done, frame Count(%d)", __FUNCTION__, __LINE__, newFrame->getFrameCount()); |
| |
| /* Shutter Callback */ |
| if (pipeId_scc != PIPE_SCC_REPROCESSING && |
| pipeId_scc != PIPE_ISP_REPROCESSING) { |
| if (m_exynosCameraParameters->msgTypeEnabled(CAMERA_MSG_SHUTTER)) { |
| CLOGI("INFO(%s[%d]): CAMERA_MSG_SHUTTER callback S", __FUNCTION__, __LINE__); |
| #ifdef BURST_CAPTURE |
| m_notifyCb(CAMERA_MSG_SHUTTER, m_exynosCameraParameters->getSeriesShotDuration(), 0, m_callbackCookie); |
| #else |
| m_notifyCb(CAMERA_MSG_SHUTTER, 0, 0, m_callbackCookie); |
| #endif |
| CLOGI("INFO(%s[%d]): CAMERA_MSG_SHUTTER callback E", __FUNCTION__, __LINE__); |
| } |
| } |
| |
| if (needGSCForCapture(getCameraId()) == true) { |
| /* set GSC buffer */ |
| if (m_exynosCameraParameters->isReprocessing() == true) |
| ret = newFrame->getDstBuffer(pipeId_scc, &sccReprocessingBuffer, m_reprocessingFrameFactory->getNodeType(PIPE_ISPC_REPROCESSING)); |
| else if (m_exynosCameraParameters->isUsing3acForIspc() == true) |
| ret = newFrame->getDstBuffer(pipeId_scc, &sccReprocessingBuffer, m_previewFrameFactory->getNodeType(PIPE_3AC)); |
| else |
| ret = newFrame->getDstBuffer(pipeId_scc, &sccReprocessingBuffer, m_previewFrameFactory->getNodeType(PIPE_ISPC)); |
| |
| 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) { |
| CLOGD("DEBUG(%s[%d]):(%d %d %d %d)", __FUNCTION__, __LINE__, |
| shot_stream->fcount, |
| shot_stream->rcount, |
| shot_stream->findex, |
| shot_stream->fvalid); |
| CLOGD("DEBUG(%s[%d]):(%d %d %d %d)(%d %d %d %d)", __FUNCTION__, __LINE__, |
| shot_stream->input_crop_region[0], |
| shot_stream->input_crop_region[1], |
| shot_stream->input_crop_region[2], |
| shot_stream->input_crop_region[3], |
| shot_stream->output_crop_region[0], |
| shot_stream->output_crop_region[1], |
| shot_stream->output_crop_region[2], |
| shot_stream->output_crop_region[3]); |
| } else { |
| CLOGE("DEBUG(%s[%d]):shot_stream is NULL", __FUNCTION__, __LINE__); |
| goto CLEAN; |
| } |
| |
| int retry = 0; |
| m_getBufferManager(pipeId_gsc, &bufferMgr, DST_BUFFER_DIRECTION); |
| do { |
| ret = -1; |
| retry++; |
| if (bufferMgr->getNumOfAvailableBuffer() > 0) { |
| ret = m_setupEntity(pipeId_gsc, newFrame, &sccReprocessingBuffer, NULL); |
| } else { |
| /* wait available SCC buffer */ |
| usleep(WAITING_TIME); |
| } |
| |
| if (retry % 10 == 0) { |
| CLOGW("WRAN(%s[%d]):retry setupEntity for GSC postPictureQ(%d), saveQ0(%d), saveQ1(%d), saveQ2(%d)", |
| __FUNCTION__, __LINE__, |
| m_postPictureQ->getSizeOfProcessQ(), |
| m_jpegSaveQ[JPEG_SAVE_THREAD0]->getSizeOfProcessQ(), |
| m_jpegSaveQ[JPEG_SAVE_THREAD1]->getSizeOfProcessQ(), |
| m_jpegSaveQ[JPEG_SAVE_THREAD2]->getSizeOfProcessQ()); |
| } |
| } while(ret < 0 && retry < (TOTAL_WAITING_TIME/WAITING_TIME) && m_stopBurstShot == false); |
| |
| if (ret < 0) { |
| if (retry >= (TOTAL_WAITING_TIME/WAITING_TIME)) { |
| CLOGE("ERR(%s[%d]):setupEntity fail, pipeId(%d), retry(%d), ret(%d), m_stopBurstShot(%d)", |
| __FUNCTION__, __LINE__, pipeId_gsc, retry, ret, m_stopBurstShot); |
| /* HACK for debugging P150108-08143 */ |
| bufferMgr->printBufferState(); |
| android_printAssert(NULL, LOG_TAG, "BURST_SHOT_TIME_ASSERT(%s[%d]): unexpected error, get GSC buffer failed, assert!!!!", __FUNCTION__, __LINE__); |
| } else { |
| CLOGD("DEBUG(%s[%d]):setupEntity stopped, pipeId(%d), retry(%d), ret(%d), m_stopBurstShot(%d)", |
| __FUNCTION__, __LINE__, pipeId_gsc, retry, ret, m_stopBurstShot); |
| } |
| goto CLEAN; |
| } |
| /* should change size calculation code in pure bayer */ |
| #if 0 |
| if (shot_stream != NULL) { |
| ret = m_calcPictureRect(&srcRect, &dstRect); |
| ret = newFrame->setSrcRect(pipeId_gsc, &srcRect); |
| ret = newFrame->setDstRect(pipeId_gsc, &dstRect); |
| } |
| #else |
| m_exynosCameraParameters->getPictureSize(&pictureW, &pictureH); |
| pictureFormat = m_exynosCameraParameters->getPictureFormat(); |
| #if 1 /* HACK in case of 3AA-OTF-ISP input_cropRegion always 0, use output crop region, check the driver */ |
| 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]; |
| #endif |
| srcRect.fullW = shot_stream->output_crop_region[2]; |
| srcRect.fullH = shot_stream->output_crop_region[3]; |
| srcRect.colorFormat = pictureFormat; |
| |
| dstRect.x = 0; |
| dstRect.y = 0; |
| dstRect.w = pictureW; |
| dstRect.h = pictureH; |
| dstRect.fullW = pictureW; |
| dstRect.fullH = pictureH; |
| dstRect.colorFormat = JPEG_INPUT_COLOR_FMT; |
| |
| ret = getCropRectAlign(srcRect.w, srcRect.h, |
| pictureW, pictureH, |
| &srcRect.x, &srcRect.y, |
| &srcRect.w, &srcRect.h, |
| 2, 2, 0, zoomRatio); |
| |
| ret = newFrame->setSrcRect(pipeId_gsc, &srcRect); |
| ret = newFrame->setDstRect(pipeId_gsc, &dstRect); |
| #endif |
| |
| CLOGD("DEBUG(%s):size (%d, %d, %d, %d %d %d)", __FUNCTION__, |
| srcRect.x, srcRect.y, srcRect.w, srcRect.h, srcRect.fullW, srcRect.fullH); |
| CLOGD("DEBUG(%s):size (%d, %d, %d, %d %d %d)", __FUNCTION__, |
| dstRect.x, dstRect.y, dstRect.w, dstRect.h, dstRect.fullW, dstRect.fullH); |
| |
| /* push frame to GSC pipe */ |
| m_pictureFrameFactory->pushFrameToPipe(&newFrame, pipeId_gsc); |
| m_pictureFrameFactory->setOutputFrameQToPipe(dstGscReprocessingQ, pipeId_gsc); |
| |
| /* wait GSC */ |
| newFrame = NULL; |
| CLOGI("INFO(%s[%d]):wait GSC output", __FUNCTION__, __LINE__); |
| while (retryCountGSC > 0) { |
| ret = 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 */ |
| if (m_exynosCameraParameters->isReprocessing() == true) |
| ret = newFrame->getDstBuffer(pipeId_scc, &sccReprocessingBuffer, m_reprocessingFrameFactory->getNodeType(PIPE_ISPC_REPROCESSING)); |
| else if (m_exynosCameraParameters->isUsing3acForIspc() == true) |
| ret = newFrame->getDstBuffer(pipeId_scc, &sccReprocessingBuffer, m_previewFrameFactory->getNodeType(PIPE_3AC)); |
| else |
| ret = newFrame->getDstBuffer(pipeId_scc, &sccReprocessingBuffer, m_previewFrameFactory->getNodeType(PIPE_ISPC)); |
| |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]):getDstBuffer fail, pipeId(%d), ret(%d)", __FUNCTION__, __LINE__, pipeId_scc, ret); |
| goto CLEAN; |
| } |
| |
| m_getBufferManager(pipeId_scc, &bufferMgr, DST_BUFFER_DIRECTION); |
| ret = m_putBuffers(bufferMgr, sccReprocessingBuffer.index); |
| if (ret < 0) { |
| CLOGE("ERR(%s)(%d):m_putBuffers fail, ret(%d)", __FUNCTION__, __LINE__, ret); |
| /* TODO: doing exception handling */ |
| goto CLEAN; |
| } |
| } |
| |
| /* push postProcess */ |
| m_postPictureQ->pushProcessQ(&newFrame); |
| |
| m_pictureCounter.decCount(); |
| |
| CLOGI("INFO(%s[%d]):picture thread complete, remaining count(%d)", __FUNCTION__, __LINE__, m_pictureCounter.getCount()); |
| |
| if (m_pictureCounter.getCount() > 0) { |
| loop = true; |
| } else { |
| if (m_exynosCameraParameters->isReprocessing() == true) |
| CLOGD("DEBUG(%s[%d]): ", __FUNCTION__, __LINE__); |
| else { |
| if (m_exynosCameraParameters->getUseDynamicScc() == true) { |
| CLOGD("DEBUG(%s[%d]): Use dynamic bayer", __FUNCTION__, __LINE__); |
| |
| if (isOwnScc(getCameraId()) == true) |
| m_previewFrameFactory->setRequestSCC(false); |
| else |
| m_previewFrameFactory->setRequestISPC(false); |
| } else if (m_exynosCameraParameters->getRecordingHint() == true |
| && m_exynosCameraParameters->isUsing3acForIspc() == true) { |
| CLOGD("DEBUG(%s[%d]): Use dynamic bayer", __FUNCTION__, __LINE__); |
| m_previewFrameFactory->setRequest3AC(false); |
| } |
| |
| m_frameFliteDeleteBetweenPreviewReprocessing.lock(); |
| m_sccCaptureSelector->clearList(pipeId_scc, isSrc); |
| m_frameFliteDeleteBetweenPreviewReprocessing.unlock(); |
| } |
| |
| dstSccReprocessingQ->release(); |
| } |
| |
| /* one shot */ |
| return loop; |
| |
| CLEAN: |
| if (sccReprocessingBuffer.index != -2) { |
| CLOGD("DEBUG(%s[%d]): putBuffer sccReprocessingBuffer(index:%d) in error state", |
| __FUNCTION__, __LINE__, sccReprocessingBuffer.index); |
| m_putBuffers(bufferMgr, sccReprocessingBuffer.index); |
| } |
| |
| CLOGI("INFO(%s[%d]):take picture fail, remaining count(%d)", __FUNCTION__, __LINE__, m_pictureCounter.getCount()); |
| |
| if (m_pictureCounter.getCount() > 0) |
| loop = true; |
| |
| /* one shot */ |
| return loop; |
| } |
| |
| camera_memory_t *ExynosCamera::m_getJpegCallbackHeap(ExynosCameraBuffer jpegBuf, int seriesShotNumber) |
| { |
| CLOGI("INFO(%s[%d]):", __FUNCTION__, __LINE__); |
| |
| camera_memory_t *jpegCallbackHeap = NULL; |
| |
| #ifdef BURST_CAPTURE |
| if (1 < m_exynosCameraParameters->getSeriesShotCount()) { |
| int seriesShotSaveLocation = m_exynosCameraParameters->getSeriesShotSaveLocation(); |
| |
| if (seriesShotNumber < 0 || seriesShotNumber > m_exynosCameraParameters->getSeriesShotCount()) { |
| CLOGE("ERR(%s[%d]): Invalid shot number (%d)", __FUNCTION__, __LINE__, seriesShotNumber); |
| goto done; |
| } |
| |
| if (seriesShotSaveLocation == BURST_SAVE_CALLBACK) { |
| CLOGD("DEBUG(%s[%d]):burst callback : size (%d), count(%d)", __FUNCTION__, __LINE__, jpegBuf.size[0], seriesShotNumber); |
| |
| jpegCallbackHeap = m_getMemoryCb(jpegBuf.fd[0], jpegBuf.size[0], 1, m_callbackCookie); |
| if (!jpegCallbackHeap || jpegCallbackHeap->data == MAP_FAILED) { |
| CLOGE("ERR(%s[%d]):m_getMemoryCb(%d) fail", __FUNCTION__, __LINE__, jpegBuf.size[0]); |
| goto done; |
| } |
| if (jpegBuf.fd[0] < 0) |
| memcpy(jpegCallbackHeap->data, jpegBuf.addr[0], jpegBuf.size[0]); |
| } else { |
| char filePath[100]; |
| int nw, cnt = 0; |
| uint32_t written = 0; |
| camera_memory_t *tempJpegCallbackHeap = NULL; |
| |
| memset(filePath, 0, sizeof(filePath)); |
| |
| snprintf(filePath, sizeof(filePath), "%sBurst%02d.jpg", m_burstSavePath, seriesShotNumber); |
| CLOGD("DEBUG(%s[%d]):burst callback : size (%d), filePath(%s)", __FUNCTION__, __LINE__, jpegBuf.size[0], filePath); |
| |
| jpegCallbackHeap = m_getMemoryCb(-1, sizeof(filePath), 1, m_callbackCookie); |
| if (!jpegCallbackHeap || jpegCallbackHeap->data == MAP_FAILED) { |
| CLOGE("ERR(%s[%d]):m_getMemoryCb(%s) fail", __FUNCTION__, __LINE__, filePath); |
| goto done; |
| } |
| |
| memcpy(jpegCallbackHeap->data, filePath, sizeof(filePath)); |
| } |
| } else |
| #endif |
| { |
| CLOGD("DEBUG(%s[%d]):general callback : size (%d)", __FUNCTION__, __LINE__, jpegBuf.size[0]); |
| |
| jpegCallbackHeap = m_getMemoryCb(jpegBuf.fd[0], jpegBuf.size[0], 1, m_callbackCookie); |
| if (!jpegCallbackHeap || jpegCallbackHeap->data == MAP_FAILED) { |
| CLOGE("ERR(%s[%d]):m_getMemoryCb(%d) fail", __FUNCTION__, __LINE__, jpegBuf.size[0]); |
| goto done; |
| } |
| |
| if (jpegBuf.fd[0] < 0) |
| memcpy(jpegCallbackHeap->data, jpegBuf.addr[0], jpegBuf.size[0]); |
| } |
| |
| done: |
| if (jpegCallbackHeap == NULL || |
| jpegCallbackHeap->data == MAP_FAILED) { |
| |
| if (jpegCallbackHeap) { |
| jpegCallbackHeap->release(jpegCallbackHeap); |
| jpegCallbackHeap = NULL; |
| } |
| |
| m_notifyCb(CAMERA_MSG_ERROR, -1, 0, m_callbackCookie); |
| } |
| |
| CLOGD("INFO(%s[%d]):making callback buffer done", __FUNCTION__, __LINE__); |
| |
| return jpegCallbackHeap; |
| } |
| |
| bool ExynosCamera::m_postPictureThreadFunc(void) |
| { |
| ExynosCameraAutoTimer autoTimer(__FUNCTION__); |
| CLOGI("INFO(%s[%d]):", __FUNCTION__, __LINE__); |
| |
| int ret = 0; |
| int loop = false; |
| int bufIndex = -2; |
| int buffer_idx = getShotBufferIdex(); |
| int retryCountJPEG = 4; |
| |
| ExynosCameraFrame *newFrame = NULL; |
| |
| ExynosCameraBuffer gscReprocessingBuffer; |
| ExynosCameraBuffer jpegReprocessingBuffer; |
| |
| gscReprocessingBuffer.index = -2; |
| jpegReprocessingBuffer.index = -2; |
| |
| int pipeId_gsc = 0; |
| int pipeId_jpeg = 0; |
| |
| int currentSeriesShotMode = 0; |
| |
| if (m_exynosCameraParameters->isReprocessing() == true) { |
| if (needGSCForCapture(getCameraId()) == true) { |
| pipeId_gsc = PIPE_GSC_REPROCESSING; |
| } else { |
| pipeId_gsc = (isOwnScc(getCameraId()) == true) ? PIPE_SCC_REPROCESSING : PIPE_ISP_REPROCESSING; |
| } |
| pipeId_jpeg = PIPE_JPEG_REPROCESSING; |
| } else { |
| if (needGSCForCapture(getCameraId()) == true) { |
| pipeId_gsc = PIPE_GSC_PICTURE; |
| } else { |
| if (isOwnScc(getCameraId()) == true) { |
| pipeId_gsc = PIPE_SCC; |
| } else { |
| if (m_exynosCameraParameters->isUsing3acForIspc() == true) |
| pipeId_gsc = PIPE_3AA; |
| else |
| pipeId_gsc = PIPE_ISPC; |
| } |
| } |
| |
| pipeId_jpeg = PIPE_JPEG; |
| } |
| |
| ExynosCameraBufferManager *bufferMgr = NULL; |
| ret = m_getBufferManager(pipeId_gsc, &bufferMgr, DST_BUFFER_DIRECTION); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]):getBufferManager(SRC) fail, pipeId(%d), ret(%d)", __FUNCTION__, __LINE__, pipeId_gsc, ret); |
| return ret; |
| } |
| |
| CLOGI("INFO(%s[%d]):wait postPictureQ output", __FUNCTION__, __LINE__); |
| ret = m_postPictureQ->waitAndPopProcessQ(&newFrame); |
| if (ret < 0) { |
| CLOGW("WARN(%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; |
| } |
| |
| if (m_jpegCounter.getCount() <= 0) { |
| CLOGD("DEBUG(%s[%d]): Picture canceled", __FUNCTION__, __LINE__); |
| goto CLEAN; |
| } |
| |
| CLOGI("INFO(%s[%d]):postPictureQ output done", __FUNCTION__, __LINE__); |
| |
| /* put picture callback buffer */ |
| /* get gsc dst buffers */ |
| ret = newFrame->getDstBuffer(pipeId_gsc, &gscReprocessingBuffer); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]):getDstBuffer fail, pipeId(%d), ret(%d)", __FUNCTION__, __LINE__, pipeId_gsc, ret); |
| goto CLEAN; |
| } |
| |
| /* callback */ |
| if (m_hdrEnabled == false && m_exynosCameraParameters->getSeriesShotCount() <= 0) { |
| if (m_exynosCameraParameters->msgTypeEnabled(CAMERA_MSG_RAW_IMAGE)) { |
| CLOGD("DEBUG(%s[%d]): RAW callabck", __FUNCTION__, __LINE__); |
| camera_memory_t *rawCallbackHeap = NULL; |
| rawCallbackHeap = m_getMemoryCb(gscReprocessingBuffer.fd[0], gscReprocessingBuffer.size[0], 1, m_callbackCookie); |
| if (!rawCallbackHeap || rawCallbackHeap->data == MAP_FAILED) { |
| CLOGE("ERR(%s[%d]):m_getMemoryCb(%d) fail", __FUNCTION__, __LINE__, gscReprocessingBuffer.size[0]); |
| goto CLEAN; |
| } |
| |
| setBit(&m_callbackState, CALLBACK_STATE_RAW_IMAGE, true); |
| m_dataCb(CAMERA_MSG_RAW_IMAGE, rawCallbackHeap, 0, NULL, m_callbackCookie); |
| clearBit(&m_callbackState, CALLBACK_STATE_RAW_IMAGE, true); |
| rawCallbackHeap->release(rawCallbackHeap); |
| } |
| |
| if (m_exynosCameraParameters->msgTypeEnabled(CAMERA_MSG_RAW_IMAGE_NOTIFY)) { |
| CLOGD("DEBUG(%s[%d]): RAW_IMAGE_NOTIFY callabck", __FUNCTION__, __LINE__); |
| |
| m_notifyCb(CAMERA_MSG_RAW_IMAGE_NOTIFY, 0, 0, m_callbackCookie); |
| } |
| |
| if ((m_exynosCameraParameters->msgTypeEnabled(CAMERA_MSG_POSTVIEW_FRAME))) { |
| CLOGD("DEBUG(%s[%d]): POSTVIEW callabck", __FUNCTION__, __LINE__); |
| |
| camera_memory_t *postviewCallbackHeap = NULL; |
| postviewCallbackHeap = m_getMemoryCb(gscReprocessingBuffer.fd[0], gscReprocessingBuffer.size[0], 1, m_callbackCookie); |
| if (!postviewCallbackHeap || postviewCallbackHeap->data == MAP_FAILED) { |
| CLOGE("ERR(%s[%d]):m_getMemoryCb(%d) fail", __FUNCTION__, __LINE__, gscReprocessingBuffer.size[0]); |
| goto CLEAN; |
| } |
| |
| setBit(&m_callbackState, CALLBACK_STATE_POSTVIEW_FRAME, true); |
| m_dataCb(CAMERA_MSG_POSTVIEW_FRAME, postviewCallbackHeap, 0, NULL, m_callbackCookie); |
| clearBit(&m_callbackState, CALLBACK_STATE_POSTVIEW_FRAME, true); |
| postviewCallbackHeap->release(postviewCallbackHeap); |
| } |
| } |
| |
| currentSeriesShotMode = m_exynosCameraParameters->getSeriesShotMode(); |
| |
| /* Make compressed image */ |
| if (m_exynosCameraParameters->msgTypeEnabled(CAMERA_MSG_COMPRESSED_IMAGE) || |
| m_exynosCameraParameters->getSeriesShotCount() > 0 || |
| m_hdrEnabled == true) { |
| |
| /* HDR callback */ |
| if (m_hdrEnabled == true || |
| currentSeriesShotMode == SERIES_SHOT_MODE_LLS || |
| currentSeriesShotMode == SERIES_SHOT_MODE_SIS || |
| m_exynosCameraParameters->getShotMode() == SHOT_MODE_FRONT_PANORAMA) { |
| CLOGD("DEBUG(%s[%d]): HDR callback", __FUNCTION__, __LINE__); |
| |
| /* send yuv image with jpeg callback */ |
| camera_memory_t *jpegCallbackHeap = NULL; |
| jpegCallbackHeap = m_getMemoryCb(gscReprocessingBuffer.fd[0], gscReprocessingBuffer.size[0], 1, m_callbackCookie); |
| if (!jpegCallbackHeap || jpegCallbackHeap->data == MAP_FAILED) { |
| CLOGE("ERR(%s[%d]):m_getMemoryCb(%d) fail", __FUNCTION__, __LINE__, gscReprocessingBuffer.size[0]); |
| goto CLEAN; |
| } |
| |
| setBit(&m_callbackState, CALLBACK_STATE_COMPRESSED_IMAGE, true); |
| m_dataCb(CAMERA_MSG_COMPRESSED_IMAGE, jpegCallbackHeap, 0, NULL, m_callbackCookie); |
| clearBit(&m_callbackState, CALLBACK_STATE_COMPRESSED_IMAGE, true); |
| |
| jpegCallbackHeap->release(jpegCallbackHeap); |
| |
| /* put GSC buffer */ |
| ret = m_putBuffers(bufferMgr, gscReprocessingBuffer.index); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]):bufferMgr->putBuffers() fail, pipeId(%d), ret(%d)", |
| __FUNCTION__, __LINE__, pipeId_gsc, ret); |
| goto CLEAN; |
| } |
| |
| m_jpegCounter.decCount(); |
| } else { |
| int retry = 0; |
| |
| /* 1. get wait available JPEG src buffer */ |
| do { |
| bufIndex = -2; |
| retry++; |
| |
| if (m_pictureEnabled == false) { |
| CLOGI("INFO(%s[%d]):m_pictureEnable is false", __FUNCTION__, __LINE__); |
| goto CLEAN; |
| } |
| if (m_jpegBufferMgr->getNumOfAvailableBuffer() > 0) |
| m_jpegBufferMgr->getBuffer(&bufIndex, EXYNOS_CAMERA_BUFFER_POSITION_IN_HAL, &jpegReprocessingBuffer); |
| |
| if (bufIndex < 0) { |
| usleep(WAITING_TIME); |
| |
| if (retry % 20 == 0) { |
| CLOGW("WRN(%s[%d]):retry JPEG getBuffer(%d) postPictureQ(%d), saveQ0(%d), saveQ1(%d), saveQ2(%d)", |
| __FUNCTION__, __LINE__, bufIndex, |
| m_postPictureQ->getSizeOfProcessQ(), |
| m_jpegSaveQ[JPEG_SAVE_THREAD0]->getSizeOfProcessQ(), |
| m_jpegSaveQ[JPEG_SAVE_THREAD1]->getSizeOfProcessQ(), |
| m_jpegSaveQ[JPEG_SAVE_THREAD2]->getSizeOfProcessQ()); |
| m_jpegBufferMgr->dump(); |
| } |
| } |
| /* this will retry until 300msec */ |
| } while (bufIndex < 0 && retry < (TOTAL_WAITING_TIME / WAITING_TIME) && m_stopBurstShot == false); |
| |
| if (bufIndex < 0) { |
| if (retry >= (TOTAL_WAITING_TIME / WAITING_TIME)) { |
| CLOGE("ERR(%s[%d]):getBuffer totally fail, retry(%d), m_stopBurstShot(%d)", |
| __FUNCTION__, __LINE__, retry, m_stopBurstShot); |
| /* HACK for debugging P150108-08143 */ |
| bufferMgr->printBufferState(); |
| android_printAssert(NULL, LOG_TAG, "BURST_SHOT_TIME_ASSERT(%s[%d]): unexpected error, get jpeg buffer failed, assert!!!!", __FUNCTION__, __LINE__); |
| } else { |
| CLOGD("DEBUG(%s[%d]):getBuffer stopped, retry(%d), m_stopBurstShot(%d)", |
| __FUNCTION__, __LINE__, retry, m_stopBurstShot); |
| } |
| ret = m_putBuffers(bufferMgr, gscReprocessingBuffer.index); |
| goto CLEAN; |
| } |
| |
| /* 2. setup Frame Entity */ |
| ret = m_setupEntity(pipeId_jpeg, newFrame, &gscReprocessingBuffer, &jpegReprocessingBuffer); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]):setupEntity fail, pipeId(%d), ret(%d)", |
| __FUNCTION__, __LINE__, pipeId_jpeg, ret); |
| goto CLEAN; |
| } |
| |
| /* 3. Q Set-up */ |
| m_pictureFrameFactory->setOutputFrameQToPipe(dstJpegReprocessingQ, pipeId_jpeg); |
| |
| /* 4. push the newFrame to pipe */ |
| m_pictureFrameFactory->pushFrameToPipe(&newFrame, pipeId_jpeg); |
| |
| /* 5. wait outputQ */ |
| CLOGI("INFO(%s[%d]):wait Jpeg output", __FUNCTION__, __LINE__); |
| while (retryCountJPEG > 0) { |
| ret = dstJpegReprocessingQ->waitAndPopProcessQ(&newFrame); |
| if (ret == TIMED_OUT) { |
| CLOGW("WRN(%s)(%d):wait and pop timeout, ret(%d)", __FUNCTION__, __LINE__, ret); |
| m_pictureFrameFactory->startThread(pipeId_jpeg); |
| } 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; |
| } |
| retryCountJPEG--; |
| } |
| |
| if (newFrame == NULL) { |
| CLOGE("ERR(%s[%d]):newFrame is NULL", __FUNCTION__, __LINE__); |
| goto CLEAN; |
| } |
| |
| /* |
| * When Non-reprocessing scenario does not setEntityState, |
| * because Non-reprocessing scenario share preview and capture frames |
| */ |
| if (m_exynosCameraParameters->isReprocessing() == true) { |
| ret = newFrame->setEntityState(pipeId_jpeg, ENTITY_STATE_COMPLETE); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]):setEntityState(ENTITY_STATE_COMPLETE) fail, pipeId(%d), ret(%d)", __FUNCTION__, __LINE__, pipeId_jpeg, ret); |
| return ret; |
| } |
| } |
| |
| /* put GSC buffer */ |
| ret = m_putBuffers(bufferMgr, gscReprocessingBuffer.index); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]):bufferMgr->putBuffers() fail, pipeId(%d), ret(%d)", |
| __FUNCTION__, __LINE__, pipeId_gsc, ret); |
| goto CLEAN; |
| } |
| |
| int jpegOutputSize = newFrame->getJpegSize(); |
| CLOGI("INFO(%s[%d]):Jpeg output done, jpeg size(%d)", __FUNCTION__, __LINE__, jpegOutputSize); |
| |
| if (jpegOutputSize <= 0) { |
| CLOGW("WRN(%s[%d]): jpegOutput size(%d) is invalid", __FUNCTION__, __LINE__, jpegOutputSize); |
| jpegOutputSize = jpegReprocessingBuffer.size[0]; |
| } |
| |
| jpegReprocessingBuffer.size[0] = jpegOutputSize; |
| |
| /* push postProcess to call CAMERA_MSG_COMPRESSED_IMAGE */ |
| jpeg_callback_buffer_t jpegCallbackBuf; |
| jpegCallbackBuf.buffer = jpegReprocessingBuffer; |
| #ifdef BURST_CAPTURE |
| m_burstCaptureCallbackCount++; |
| CLOGI("INFO(%s[%d]): burstCaptureCallbackCount(%d)", __FUNCTION__, __LINE__, m_burstCaptureCallbackCount); |
| #endif |
| retry: |
| if ((m_exynosCameraParameters->getSeriesShotCount() > 0)) { |
| int threadNum = 0; |
| |
| if (m_burst[JPEG_SAVE_THREAD0] == false && m_jpegSaveThread[JPEG_SAVE_THREAD0]->isRunning() == false) { |
| threadNum = JPEG_SAVE_THREAD0; |
| } else if (m_burst[JPEG_SAVE_THREAD1] == false && m_jpegSaveThread[JPEG_SAVE_THREAD1]->isRunning() == false) { |
| threadNum = JPEG_SAVE_THREAD1; |
| } else if (m_burst[JPEG_SAVE_THREAD2] == false && m_jpegSaveThread[JPEG_SAVE_THREAD2]->isRunning() == false) { |
| threadNum = JPEG_SAVE_THREAD2; |
| } else { |
| CLOGW("WARN(%s[%d]): wait for available save thread, thread running(%d, %d, %d,)", |
| __FUNCTION__, __LINE__, |
| m_jpegSaveThread[JPEG_SAVE_THREAD0]->isRunning(), |
| m_jpegSaveThread[JPEG_SAVE_THREAD1]->isRunning(), |
| m_jpegSaveThread[JPEG_SAVE_THREAD2]->isRunning()); |
| usleep(WAITING_TIME * 10); |
| goto retry; |
| } |
| |
| m_burst[threadNum] = true; |
| ret = m_jpegSaveThread[threadNum]->run(); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]): m_jpegSaveThread%d run fail, ret(%d)", __FUNCTION__, __LINE__, threadNum, ret); |
| m_burst[threadNum] = false; |
| m_running[threadNum] = false; |
| goto retry; |
| } |
| |
| jpegCallbackBuf.callbackNumber = m_burstCaptureCallbackCount; |
| m_jpegSaveQ[threadNum]->pushProcessQ(&jpegCallbackBuf); |
| } else { |
| jpegCallbackBuf.callbackNumber = 0; |
| m_jpegCallbackQ->pushProcessQ(&jpegCallbackBuf); |
| } |
| |
| m_jpegCounter.decCount(); |
| } |
| } else { |
| CLOGD("DEBUG(%s[%d]): Disabled compressed image", __FUNCTION__, __LINE__); |
| |
| /* put GSC buffer */ |
| ret = m_putBuffers(bufferMgr, gscReprocessingBuffer.index); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]):bufferMgr->putBuffers() fail, pipeId(%d), ret(%d)", |
| __FUNCTION__, __LINE__, pipeId_gsc, ret); |
| goto CLEAN; |
| } |
| |
| m_jpegCounter.decCount(); |
| } |
| |
| 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); |
| } |
| |
| CLOGD("DEBUG(%s[%d]): Picture frame delete(%d)", __FUNCTION__, __LINE__, newFrame->getFrameCount()); |
| newFrame->decRef(); |
| m_frameMgr->deleteFrame(newFrame); |
| newFrame = NULL; |
| } |
| |
| CLOGI("INFO(%s[%d]):postPicture thread complete, remaining count(%d)", __FUNCTION__, __LINE__, m_jpegCounter.getCount()); |
| |
| if (m_jpegCounter.getCount() <= 0) { |
| if (m_hdrEnabled == true) { |
| CLOGI("INFO(%s[%d]): End of HDR capture!", __FUNCTION__, __LINE__); |
| m_hdrEnabled = false; |
| m_pictureEnabled = false; |
| } |
| if (currentSeriesShotMode == SERIES_SHOT_MODE_LLS || |
| currentSeriesShotMode == SERIES_SHOT_MODE_SIS) { |
| CLOGI("INFO(%s[%d]): End of LLS/SIS capture!", __FUNCTION__, __LINE__); |
| m_pictureEnabled = false; |
| } |
| |
| if(m_exynosCameraParameters->getShotMode() == SHOT_MODE_FRONT_PANORAMA) { |
| CLOGI("INFO(%s[%d]): End of wideselfie capture!", __FUNCTION__, __LINE__); |
| m_pictureEnabled = false; |
| } |
| |
| CLOGD("DEBUG(%s[%d]): free gsc buffers", __FUNCTION__, __LINE__); |
| m_gscBufferMgr->resetBuffers(); |
| |
| if (currentSeriesShotMode != SERIES_SHOT_MODE_BURST) { |
| CLOGD("DEBUG(%s[%d]): clearList postProcessList, series shot mode(%d)", __FUNCTION__, __LINE__, currentSeriesShotMode); |
| if (m_clearList(&m_postProcessList) < 0) { |
| CLOGE("ERR(%s):m_clearList fail", __FUNCTION__); |
| } |
| } |
| } |
| |
| if (m_exynosCameraParameters->getScalableSensorMode()) { |
| m_scalableSensorMgr.setMode(EXYNOS_CAMERA_SCALABLE_CHANGING); |
| ret = m_restartPreviewInternal(); |
| if (ret < 0) |
| CLOGE("(%s[%d]): restart preview internal fail", __FUNCTION__, __LINE__); |
| m_scalableSensorMgr.setMode(EXYNOS_CAMERA_SCALABLE_NONE); |
| } |
| |
| CLEAN: |
| /* HACK: Sometimes, m_postPictureThread is finished without waiting the last picture */ |
| int waitCount = 5; |
| while (m_postPictureQ->getSizeOfProcessQ() == 0 && 0 < waitCount) { |
| usleep(10000); |
| waitCount--; |
| } |
| |
| if (m_postPictureQ->getSizeOfProcessQ() > 0 || |
| currentSeriesShotMode != SERIES_SHOT_MODE_NONE) { |
| CLOGD("DEBUG(%s[%d]):postPicture thread will run again. currentSeriesShotMode(%d), postPictureQ size(%d)", |
| __func__, __LINE__, currentSeriesShotMode, m_postPictureQ->getSizeOfProcessQ()); |
| loop = true; |
| } |
| |
| return loop; |
| } |
| |
| bool ExynosCamera::m_jpegSaveThreadFunc(void) |
| { |
| ExynosCameraAutoTimer autoTimer(__FUNCTION__); |
| CLOGI("DEBUG(%s[%d]):", __FUNCTION__, __LINE__); |
| |
| int ret = 0; |
| int loop = false; |
| int curThreadNum = -1; |
| char burstFilePath[100]; |
| #ifdef BURST_CAPTURE |
| int fd = -1; |
| #endif |
| |
| jpeg_callback_buffer_t jpegCallbackBuf; |
| ExynosCameraBuffer jpegSaveBuffer; |
| int seriesShotNumber = -1; |
| // camera_memory_t *jpegCallbackHeap = NULL; |
| |
| for (int threadNum = JPEG_SAVE_THREAD0; threadNum < JPEG_SAVE_THREAD_MAX_COUNT; threadNum++) { |
| if (m_burst[threadNum] == true && m_running[threadNum] == false) { |
| m_running[threadNum] = true; |
| curThreadNum = threadNum; |
| if (m_jpegSaveQ[curThreadNum]->waitAndPopProcessQ(&jpegCallbackBuf) < 0) { |
| CLOGE("ERR(%s[%d]):wait and pop fail, ret(%d)", __FUNCTION__, __LINE__, ret); |
| goto done; |
| } |
| break; |
| } |
| } |
| |
| if (curThreadNum < 0 || curThreadNum > JPEG_SAVE_THREAD2) { |
| CLOGE("ERR(%s[%d]): invalid thrad num (%d)", __FUNCTION__, __LINE__, curThreadNum); |
| goto done; |
| } |
| |
| jpegSaveBuffer = jpegCallbackBuf.buffer; |
| seriesShotNumber = jpegCallbackBuf.callbackNumber; |
| |
| #ifdef BURST_CAPTURE |
| if (m_exynosCameraParameters->getSeriesShotCount() > 0) { |
| |
| int seriesShotSaveLocation = m_exynosCameraParameters->getSeriesShotSaveLocation(); |
| |
| if (seriesShotSaveLocation == BURST_SAVE_CALLBACK) { |
| jpegCallbackBuf.buffer = jpegSaveBuffer; |
| jpegCallbackBuf.callbackNumber = 0; |
| m_jpegCallbackQ->pushProcessQ(&jpegCallbackBuf); |
| goto done; |
| } else { |
| int nw, cnt = 0; |
| uint32_t written = 0; |
| camera_memory_t *tempJpegCallbackHeap = NULL; |
| |
| memset(burstFilePath, 0, sizeof(burstFilePath)); |
| |
| m_burstCaptureCallbackCountLock.lock(); |
| snprintf(burstFilePath, sizeof(burstFilePath), "%sBurst%02d.jpg", m_burstSavePath, seriesShotNumber); |
| m_burstCaptureCallbackCountLock.unlock(); |
| |
| CLOGD("DEBUG(%s[%d]):%s fd:%d jpegSize : %d", __FUNCTION__, __LINE__, burstFilePath, jpegSaveBuffer.fd[0], jpegSaveBuffer.size[0]); |
| |
| m_burstCaptureSaveLock.lock(); |
| |
| fd = open(burstFilePath, O_RDWR | O_CREAT, 0664); |
| if (fd < 0) { |
| CLOGD("DEBUG(%s[%d]):failed to create file [%s]: %s", |
| __FUNCTION__, __LINE__, burstFilePath, strerror(errno)); |
| m_burstCaptureSaveLock.unlock(); |
| goto done; |
| } |
| |
| m_burstSaveTimer.start(); |
| CLOGD("DEBUG(%s[%d]):%s jpegSize : %d", __FUNCTION__, __LINE__, burstFilePath, jpegSaveBuffer.size[0]); |
| |
| char *data = NULL; |
| |
| if (jpegSaveBuffer.fd[0] < 0) { |
| data = jpegSaveBuffer.addr[0]; |
| } else { |
| /* TODO : we need to use jpegBuf's buffer directly */ |
| tempJpegCallbackHeap = m_getMemoryCb(jpegSaveBuffer.fd[0], jpegSaveBuffer.size[0], 1, m_callbackCookie); |
| if (!tempJpegCallbackHeap || tempJpegCallbackHeap->data == MAP_FAILED) { |
| CLOGE("ERR(%s[%d]):m_getMemoryCb(fd:%d, size:%d) fail", __FUNCTION__, __LINE__, jpegSaveBuffer.fd[0], jpegSaveBuffer.size[0]); |
| m_burstCaptureSaveLock.unlock(); |
| goto done; |
| } |
| |
| data = (char *)tempJpegCallbackHeap->data; |
| } |
| |
| CLOGD("DEBUG(%s[%d]):(%s)file write start)", __FUNCTION__, __LINE__, burstFilePath); |
| while (written < jpegSaveBuffer.size[0]) { |
| nw = ::write(fd, (const char *)(data) + written, jpegSaveBuffer.size[0] - written); |
| |
| if (nw < 0) { |
| CLOGD("DEBUG(%s[%d]):failed to write file [%s]: %s", |
| __FUNCTION__, __LINE__, burstFilePath, strerror(errno)); |
| break; |
| } |
| |
| written += nw; |
| cnt++; |
| } |
| CLOGD("DEBUG(%s[%d]):(%s)file write end)", __FUNCTION__, __LINE__, burstFilePath); |
| |
| if (fd > 0) |
| ::close(fd); |
| |
| if (chmod(burstFilePath,0664) < 0) { |
| CLOGE("failed chmod [%s]", burstFilePath); |
| } |
| if (chown(burstFilePath,AID_MEDIA,AID_MEDIA_RW) < 0) { |
| CLOGE("failed chown [%s] user(%d), group(%d)", burstFilePath,AID_MEDIA,AID_MEDIA_RW); |
| } |
| |
| m_burstCaptureSaveLock.unlock(); |
| |
| if (tempJpegCallbackHeap) { |
| tempJpegCallbackHeap->release(tempJpegCallbackHeap); |
| tempJpegCallbackHeap = NULL; |
| } |
| |
| m_burstSaveTimer.stop(); |
| m_burstSaveTimerTime = m_burstSaveTimer.durationUsecs(); |
| if (m_burstSaveTimerTime > (m_burstDuration - 33000)) { |
| m_burstDuration += (int)((m_burstSaveTimerTime - m_burstDuration + 33000) / 33000) * 33000; |
| CLOGD("Increase burst duration = %d", m_burstDuration); |
| } |
| |
| CLOGD("DEBUG(%s[%d]):m_burstSaveTimerTime : %d msec, path(%s)", __FUNCTION__, __LINE__, (int)m_burstSaveTimerTime / 1000, burstFilePath); |
| } |
| jpegCallbackBuf.buffer = jpegSaveBuffer; |
| jpegCallbackBuf.callbackNumber = seriesShotNumber; |
| m_jpegCallbackQ->pushProcessQ(&jpegCallbackBuf); |
| } else |
| #endif |
| { |
| jpegCallbackBuf.buffer = jpegSaveBuffer; |
| jpegCallbackBuf.callbackNumber = 0; |
| m_jpegCallbackQ->pushProcessQ(&jpegCallbackBuf); |
| } |
| |
| done: |
| /* |
| if (jpegCallbackHeap == NULL || |
| jpegCallbackHeap->data == MAP_FAILED) { |
| |
| if (jpegCallbackHeap) { |
| jpegCallbackHeap->release(jpegCallbackHeap); |
| jpegCallbackHeap = NULL; |
| } |
| |
| m_notifyCb(CAMERA_MSG_ERROR, -1, 0, m_callbackCookie); |
| } |
| */ |
| if (JPEG_SAVE_THREAD0 <= curThreadNum && curThreadNum < JPEG_SAVE_THREAD_MAX_COUNT) { |
| m_burst[curThreadNum] = false; |
| m_running[curThreadNum] = false; |
| } |
| |
| CLOGI("INFO(%s[%d]):saving jpeg buffer done", __FUNCTION__, __LINE__); |
| |
| /* one shot */ |
| return false; |
| } |
| |
| bool ExynosCamera::m_jpegCallbackThreadFunc(void) |
| { |
| ExynosCameraAutoTimer autoTimer(__FUNCTION__); |
| CLOGI("DEBUG(%s[%d]):", __FUNCTION__, __LINE__); |
| |
| int ret = 0; |
| int retry = 0, maxRetry = 0; |
| int loop = false; |
| int seriesShotNumber = -1; |
| |
| jpeg_callback_buffer_t jpegCallbackBuf; |
| ExynosCameraBuffer jpegCallbackBuffer; |
| camera_memory_t *jpegCallbackHeap = NULL; |
| |
| jpegCallbackBuffer.index = -2; |
| |
| ExynosCameraActivityFlash *m_flashMgr = m_exynosCameraActivityControl->getFlashMgr(); |
| if (m_flashMgr->getNeedFlash() == true) { |
| maxRetry = TOTAL_FLASH_WATING_COUNT; |
| } else { |
| maxRetry = TOTAL_WAITING_COUNT; |
| } |
| |
| do { |
| ret = m_jpegCallbackQ->waitAndPopProcessQ(&jpegCallbackBuf); |
| if (ret < 0) { |
| retry++; |
| CLOGW("WARN(%s[%d]):jpegCallbackQ pop fail, retry(%d)", __FUNCTION__, __LINE__, retry); |
| } |
| } while(ret < 0 && retry < maxRetry && m_jpegCounter.getCount() > 0); |
| |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]):wait and pop fail, ret(%d)", __FUNCTION__, __LINE__, ret); |
| loop = true; |
| goto CLEAN; |
| } |
| |
| jpegCallbackBuffer = jpegCallbackBuf.buffer; |
| seriesShotNumber = jpegCallbackBuf.callbackNumber; |
| |
| CLOGD("DEBUG(%s[%d]):jpeg calllback is start", __FUNCTION__, __LINE__); |
| |
| /* Make compressed image */ |
| if (m_exynosCameraParameters->msgTypeEnabled(CAMERA_MSG_COMPRESSED_IMAGE) || |
| m_exynosCameraParameters->getSeriesShotCount() > 0) { |
| m_captureLock.lock(); |
| camera_memory_t *jpegCallbackHeap = m_getJpegCallbackHeap(jpegCallbackBuffer, seriesShotNumber); |
| if (jpegCallbackHeap == NULL) { |
| CLOGE("ERR(%s[%d]):wait and pop fail, ret(%d)", __FUNCTION__, __LINE__, ret); |
| /* TODO: doing exception handling */ |
| android_printAssert(NULL, LOG_TAG, "Cannot recoverable, assert!!!!"); |
| } |
| |
| setBit(&m_callbackState, CALLBACK_STATE_COMPRESSED_IMAGE, true); |
| m_dataCb(CAMERA_MSG_COMPRESSED_IMAGE, jpegCallbackHeap, 0, NULL, m_callbackCookie); |
| clearBit(&m_callbackState, CALLBACK_STATE_COMPRESSED_IMAGE, true); |
| CLOGD("DEBUG(%s[%d]): CAMERA_MSG_COMPRESSED_IMAGE callabck (%d)", __FUNCTION__, __LINE__, m_burstCaptureCallbackCount); |
| |
| /* put JPEG callback buffer */ |
| if (m_jpegBufferMgr->putBuffer(jpegCallbackBuffer.index, EXYNOS_CAMERA_BUFFER_POSITION_NONE) != NO_ERROR) |
| CLOGE("ERR(%s[%d]):putBuffer(%d) fail", __FUNCTION__, __LINE__, jpegCallbackBuffer.index); |
| |
| jpegCallbackHeap->release(jpegCallbackHeap); |
| } else { |
| CLOGD("DEBUG(%s[%d]): Disabled compressed image", __FUNCTION__, __LINE__); |
| } |
| |
| CLEAN: |
| CLOGI("INFO(%s[%d]):jpeg callback thread complete, remaining count(%d)", __FUNCTION__, __LINE__, m_takePictureCounter.getCount()); |
| if (m_takePictureCounter.getCount() == 0) { |
| m_pictureEnabled = false; |
| loop = false; |
| m_clearJpegCallbackThread(true); |
| m_captureLock.unlock(); |
| } else { |
| m_captureLock.unlock(); |
| } |
| |
| return loop; |
| } |
| |
| void ExynosCamera::m_clearJpegCallbackThread(bool callFromJpeg) |
| { |
| jpeg_callback_buffer_t jpegCallbackBuf; |
| ExynosCameraBuffer jpegCallbackBuffer; |
| int ret = 0; |
| |
| CLOGI("INFO(%s[%d]): takePicture disabled, takePicture callback done takePictureCounter(%d)", |
| __FUNCTION__, __LINE__, m_takePictureCounter.getCount()); |
| m_pictureEnabled = false; |
| |
| if (m_exynosCameraParameters->getUseDynamicScc() == true) { |
| CLOGD("DEBUG(%s[%d]): Use dynamic bayer", __FUNCTION__, __LINE__); |
| if (isOwnScc(getCameraId()) == true) |
| m_previewFrameFactory->setRequestSCC(false); |
| else |
| m_previewFrameFactory->setRequestISPC(false); |
| } |
| |
| m_prePictureThread->requestExit(); |
| m_pictureThread->requestExit(); |
| m_postPictureThread->requestExit(); |
| m_jpegCallbackThread->requestExit(); |
| |
| CLOGI("INFO(%s[%d]): wait m_prePictureThrad", __FUNCTION__, __LINE__); |
| m_prePictureThread->requestExitAndWait(); |
| CLOGI("INFO(%s[%d]): wait m_pictureThrad", __FUNCTION__, __LINE__); |
| m_pictureThread->requestExitAndWait(); |
| CLOGI("INFO(%s[%d]): wait m_postPictureThrad", __FUNCTION__, __LINE__); |
| m_postPictureThread->requestExitAndWait(); |
| CLOGI("INFO(%s[%d]): wait m_jpegCallbackThrad", __FUNCTION__, __LINE__); |
| if (!callFromJpeg) |
| m_jpegCallbackThread->requestExitAndWait(); |
| |
| for (int threadNum = JPEG_SAVE_THREAD0; threadNum < JPEG_SAVE_THREAD_MAX_COUNT; threadNum++) { |
| CLOGI("INFO(%s[%d]): wait m_jpegSaveThrad%d", __FUNCTION__, __LINE__, threadNum); |
| m_jpegSaveThread[threadNum]->requestExitAndWait(); |
| } |
| |
| CLOGI("INFO(%s[%d]): All picture threads done", __FUNCTION__, __LINE__); |
| |
| if (m_exynosCameraParameters->isReprocessing() == true) { |
| enum pipeline pipe = (isOwnScc(getCameraId()) == true) ? PIPE_SCC_REPROCESSING : PIPE_ISP_REPROCESSING; |
| |
| m_reprocessingFrameFactory->stopThread(pipe); |
| } |
| |
| while (m_jpegCallbackQ->getSizeOfProcessQ() > 0) { |
| m_jpegCallbackQ->popProcessQ(&jpegCallbackBuf); |
| jpegCallbackBuffer = jpegCallbackBuf.buffer; |
| |
| CLOGD("DEBUG(%s[%d]):put remaining jpeg buffer(index: %d)", __FUNCTION__, __LINE__, jpegCallbackBuffer.index); |
| if (m_jpegBufferMgr->putBuffer(jpegCallbackBuffer.index, EXYNOS_CAMERA_BUFFER_POSITION_NONE) != NO_ERROR) { |
| CLOGE("ERR(%s[%d]):putBuffer(%d) fail", __FUNCTION__, __LINE__, jpegCallbackBuffer.index); |
| } |
| |
| int seriesShotSaveLocation = m_exynosCameraParameters->getSeriesShotSaveLocation(); |
| char command[100]; |
| memset(command, 0, sizeof(command)); |
| |
| snprintf(command, sizeof(command), "rm %sBurst%02d.jpg", m_burstSavePath, jpegCallbackBuf.callbackNumber); |
| |
| system(command); |
| CLOGD("run %s", command); |
| } |
| |
| for (int threadNum = JPEG_SAVE_THREAD0; threadNum < JPEG_SAVE_THREAD_MAX_COUNT; threadNum++) { |
| while (m_jpegSaveQ[threadNum]->getSizeOfProcessQ() > 0) { |
| m_jpegSaveQ[threadNum]->popProcessQ(&jpegCallbackBuf); |
| jpegCallbackBuffer = jpegCallbackBuf.buffer; |
| |
| CLOGD("DEBUG(%s[%d]):put remaining SaveQ%d jpeg buffer(index: %d)", |
| __FUNCTION__, __LINE__, threadNum, jpegCallbackBuffer.index); |
| if (m_jpegBufferMgr->putBuffer(jpegCallbackBuffer.index, EXYNOS_CAMERA_BUFFER_POSITION_NONE) != NO_ERROR) { |
| CLOGE("ERR(%s[%d]):putBuffer(%d) fail", __FUNCTION__, __LINE__, jpegCallbackBuffer.index); |
| } |
| |
| } |
| |
| m_burst[threadNum] = false; |
| } |
| |
| CLOGD("DEBUG(%s[%d]): clear postProcessList", __FUNCTION__, __LINE__); |
| if (m_clearList(&m_postProcessList) < 0) { |
| CLOGE("ERR(%s):m_clearList fail", __FUNCTION__); |
| } |
| |
| #if 1 |
| CLOGD("DEBUG(%s[%d]): clear postPictureQ", __FUNCTION__, __LINE__); |
| m_postPictureQ->release(); |
| |
| CLOGD("DEBUG(%s[%d]): clear dstSccReprocessingQ", __FUNCTION__, __LINE__); |
| dstSccReprocessingQ->release(); |
| |
| CLOGD("DEBUG(%s[%d]): clear dstJpegReprocessingQ", __FUNCTION__, __LINE__); |
| dstJpegReprocessingQ->release(); |
| #else |
| ExynosCameraFrame *frame = NULL; |
| |
| CLOGD("DEBUG(%s[%d]): clear postPictureQ", __FUNCTION__, __LINE__); |
| while(m_postPictureQ->getSizeOfProcessQ()) { |
| m_postPictureQ->popProcessQ(&frame); |
| if (frame != NULL) { |
| delete frame; |
| frame = NULL; |
| } |
| } |
| |
| CLOGD("DEBUG(%s[%d]): clear dstSccReprocessingQ", __FUNCTION__, __LINE__); |
| while(dstSccReprocessingQ->getSizeOfProcessQ()) { |
| dstSccReprocessingQ->popProcessQ(&frame); |
| if (frame != NULL) { |
| delete frame; |
| frame = NULL; |
| } |
| } |
| #endif |
| |
| CLOGD("DEBUG(%s[%d]): reset buffer gsc buffers", __FUNCTION__, __LINE__); |
| m_gscBufferMgr->resetBuffers(); |
| CLOGD("DEBUG(%s[%d]): reset buffer jpeg buffers", __FUNCTION__, __LINE__); |
| m_jpegBufferMgr->resetBuffers(); |
| CLOGD("DEBUG(%s[%d]): reset buffer sccReprocessing buffers", __FUNCTION__, __LINE__); |
| m_sccReprocessingBufferMgr->resetBuffers(); |
| } |
| |
| 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_exynosCameraParameters->getPreviewSize(&cbPreviewW, &cbPreviewH); |
| previewFormat = m_exynosCameraParameters->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; |
| |
| if (m_exynosCameraParameters->isUsing3acForIspc() == true) { |
| pipeId_scc = PIPE_3AA; |
| pipeId_gsc = PIPE_GSC_PICTURE; |
| } else { |
| pipeId_scc = (isOwnScc(getCameraId()) == 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_exynosCameraParameters->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_exynosCameraParameters->msgTypeEnabled(CAMERA_MSG_PREVIEW_FRAME)) { |
| /* get GSC src buffer */ |
| if (m_exynosCameraParameters->isUsing3acForIspc() == true) |
| ret = newFrame->getDstBuffer(pipeId_scc, &sccReprocessingBuffer, m_previewFrameFactory->getNodeType(PIPE_3AC)); |
| else |
| 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->pushFrameToPipe(&newFrame, pipeId_gsc); |
| m_pictureFrameFactory->setOutputFrameQToPipe(dstGscReprocessingQ, pipeId_gsc); |
| |
| /* wait GSC for high resolution preview callback */ |
| CLOGI("INFO(%s[%d]):wait GSC output", __FUNCTION__, __LINE__); |
| while (retryCountGSC > 0) { |
| ret = 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 */ |
| if (m_exynosCameraParameters->isUsing3acForIspc() == true) { |
| ret = newFrame->getDstBuffer(pipeId_scc, &sccReprocessingBuffer, m_previewFrameFactory->getNodeType(PIPE_3AC)); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]):getDstBuffer fail, pipeId(%d), ret(%d)", __FUNCTION__, __LINE__, pipeId_scc, ret); |
| goto CLEAN; |
| } |
| ret = m_putBuffers(m_sccBufferMgr, sccReprocessingBuffer.index); |
| } else { |
| 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_exynosCameraParameters->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 */ |
| if (m_exynosCameraParameters->isUsing3acForIspc() == true) { |
| ret = newFrame->getDstBuffer(pipeId_scc, &sccReprocessingBuffer, m_previewFrameFactory->getNodeType(PIPE_3AC)); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]):getDstBuffer fail, pipeId(%d), ret(%d)", __FUNCTION__, __LINE__, pipeId_scc, ret); |
| goto CLEAN; |
| } |
| ret = m_putBuffers(m_sccBufferMgr, sccReprocessingBuffer.index); |
| } else { |
| 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_exynosCameraParameters->getHighResolutionCallbackMode() == true) { |
| CLOGD("DEBUG(%s[%d]):highResolutionCallbackQ size(%d), highResolutionCallbackMode(%s), start again", |
| __FUNCTION__, __LINE__, |
| m_highResolutionCallbackQ->getSizeOfProcessQ(), |
| (m_exynosCameraParameters->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_exynosCameraParameters->getHighResolutionCallbackMode() == true) { |
| CLOGD("DEBUG(%s[%d]):highResolutionCallbackQ size(%d), highResolutionCallbackMode(%s), start again", |
| __FUNCTION__, __LINE__, |
| m_highResolutionCallbackQ->getSizeOfProcessQ(), |
| (m_exynosCameraParameters->getHighResolutionCallbackMode() == true)? "TRUE" : "FALSE"); |
| loop = true; |
| } |
| } |
| |
| CLOGI("INFO(%s[%d]):high resolution callback thread fail, loop(%d)", __FUNCTION__, __LINE__, loop); |
| |
| /* one shot */ |
| return loop; |
| } |
| |
| status_t ExynosCamera::m_doPrviewToRecordingFunc( |
| int32_t pipeId, |
| ExynosCameraBuffer previewBuf, |
| ExynosCameraBuffer recordingBuf) |
| { |
| #ifdef DEBUG |
| ExynosCameraAutoTimer autoTimer(__FUNCTION__); |
| #endif |
| |
| CLOGV("DEBUG(%s[%d]):--IN-- (previewBuf.index=%d, recordingBuf.index=%d)", |
| __FUNCTION__, __LINE__, previewBuf.index, recordingBuf.index); |
| |
| status_t ret = NO_ERROR; |
| ExynosRect srcRect, dstRect; |
| ExynosCameraFrame *newFrame = NULL; |
| |
| newFrame = m_previewFrameFactory->createNewFrameVideoOnly(); |
| if (newFrame == NULL) { |
| CLOGE("ERR(%s):newFrame is NULL", __FUNCTION__); |
| return UNKNOWN_ERROR; |
| } |
| |
| /* csc and scaling */ |
| ret = m_calcRecordingGSCRect(&srcRect, &dstRect); |
| ret = newFrame->setSrcRect(pipeId, srcRect); |
| ret = newFrame->setDstRect(pipeId, dstRect); |
| |
| ret = m_setupEntity(pipeId, newFrame, &previewBuf, &recordingBuf); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]):setupEntity fail, pipeId(%d), ret(%d)", |
| __FUNCTION__, __LINE__, pipeId, ret); |
| ret = INVALID_OPERATION; |
| if (newFrame != NULL) { |
| newFrame->decRef(); |
| m_frameMgr->deleteFrame(newFrame); |
| newFrame = NULL; |
| } |
| goto func_exit; |
| } |
| m_recordingListLock.lock(); |
| m_recordingProcessList.push_back(newFrame); |
| m_recordingListLock.unlock(); |
| m_previewFrameFactory->pushFrameToPipe(&newFrame, pipeId); |
| m_previewFrameFactory->setOutputFrameQToPipe(m_recordingQ, pipeId); |
| |
| func_exit: |
| |
| CLOGV("DEBUG(%s[%d]):--OUT--", __FUNCTION__, __LINE__); |
| return ret; |
| |
| } |
| |
| bool ExynosCamera::m_recordingThreadFunc(void) |
| { |
| #ifdef DEBUG |
| ExynosCameraAutoTimer autoTimer(__FUNCTION__); |
| #endif |
| |
| int ret = 0; |
| int pipeId = PIPE_GSC_VIDEO; |
| nsecs_t timeStamp = 0; |
| |
| ExynosCameraBuffer buffer; |
| ExynosCameraFrame *frame = NULL; |
| |
| CLOGV("INFO(%s[%d]):wait gsc done output", __FUNCTION__, __LINE__); |
| ret = m_recordingQ->waitAndPopProcessQ(&frame); |
| if (m_getRecordingEnabled() == false) { |
| CLOGI("INFO(%s[%d]):recording stopped", __FUNCTION__, __LINE__); |
| goto func_exit; |
| } |
| |
| if (ret < 0) { |
| if (ret == TIMED_OUT) { |
| CLOGW("WARN(%s):wait timeout", __FUNCTION__); |
| } else { |
| CLOGE("ERR(%s):wait and pop fail, ret(%d)", __FUNCTION__, ret); |
| /* TODO: doing exception handling */ |
| } |
| goto func_exit; |
| } |
| |
| if (frame == NULL) { |
| CLOGE("ERR(%s[%d]):frame is NULL", __FUNCTION__, __LINE__); |
| ret = INVALID_OPERATION; |
| goto func_exit; |
| } |
| CLOGV("INFO(%s[%d]):gsc done for recording callback", __FUNCTION__, __LINE__); |
| |
| ret = frame->getDstBuffer(pipeId, &buffer); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]):getDstBuffer fail, ret(%d)", __FUNCTION__, __LINE__, ret); |
| /* TODO: doing exception handling */ |
| goto func_exit; |
| } |
| |
| if (buffer.index < 0 || buffer.index >= (int)m_recordingBufferCount) { |
| CLOGE("ERR(%s[%d]):Out of Index! (Max: %d, Index: %d)", __FUNCTION__, __LINE__, m_recordingBufferCount, buffer.index); |
| goto func_exit; |
| } |
| |
| timeStamp = m_recordingTimeStamp[buffer.index]; |
| |
| if (m_recordingStartTimeStamp == 0) { |
| m_recordingStartTimeStamp = timeStamp; |
| CLOGI("INFO(%s[%d]):m_recordingStartTimeStamp=%lld", |
| __FUNCTION__, __LINE__, m_recordingStartTimeStamp); |
| } |
| |
| if ((0L < timeStamp) |
| && (m_lastRecordingTimeStamp < timeStamp) |
| && (m_recordingStartTimeStamp <= timeStamp)) { |
| if (m_getRecordingEnabled() == true |
| && m_exynosCameraParameters->msgTypeEnabled(CAMERA_MSG_VIDEO_FRAME)) { |
| #ifdef CHECK_MONOTONIC_TIMESTAMP |
| CLOGD("DEBUG(%s[%d]):m_dataCbTimestamp::recordingFrameIndex=%d, recordingTimeStamp=%lld", |
| __FUNCTION__, __LINE__, buffer.index, timeStamp); |
| #endif |
| #ifdef DEBUG |
| CLOGD("DEBUG(%s[%d]): - lastTimeStamp(%lld), systemTime(%lld), recordingStart(%lld)", |
| __FUNCTION__, __LINE__, |
| m_lastRecordingTimeStamp, |
| systemTime(SYSTEM_TIME_MONOTONIC), |
| m_recordingStartTimeStamp); |
| #endif |
| struct addrs *recordAddrs = NULL; |
| |
| recordAddrs = (struct addrs *)m_recordingCallbackHeap->data; |
| recordAddrs[buffer.index].type = kMetadataBufferTypeCameraSource; |
| recordAddrs[buffer.index].fdPlaneY = (unsigned int)buffer.fd[0]; |
| recordAddrs[buffer.index].fdPlaneCbcr = (unsigned int)buffer.fd[1]; |
| recordAddrs[buffer.index].bufIndex = buffer.index; |
| |
| m_dataCbTimestamp( |
| timeStamp, |
| CAMERA_MSG_VIDEO_FRAME, |
| m_recordingCallbackHeap, |
| buffer.index, |
| m_callbackCookie); |
| m_lastRecordingTimeStamp = timeStamp; |
| } |
| } else { |
| CLOGW("WARN(%s[%d]):recordingFrameIndex=%d, timeStamp(%lld) invalid -" |
| " lastTimeStamp(%lld), systemTime(%lld), recordingStart(%lld)", |
| __FUNCTION__, __LINE__, buffer.index, timeStamp, |
| m_lastRecordingTimeStamp, |
| systemTime(SYSTEM_TIME_MONOTONIC), |
| m_recordingStartTimeStamp); |
| m_releaseRecordingBuffer(buffer.index); |
| } |
| |
| func_exit: |
| |
| m_recordingListLock.lock(); |
| if (frame != NULL) { |
| ret = m_removeFrameFromList(&m_recordingProcessList, frame); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]):remove frame from processList fail, ret(%d)", __FUNCTION__, __LINE__, ret); |
| } |
| frame->decRef(); |
| m_frameMgr->deleteFrame(frame);; |
| frame = NULL; |
| } |
| m_recordingListLock.unlock(); |
| |
| return m_recordingEnabled; |
| } |
| |
| 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; |
| } |
| |
| m_recordingTimeStamp[bufIndex] = 0L; |
| 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_exynosCameraParameters->calcPreviewGSCRect(srcRect, dstRect); |
| } |
| |
| status_t ExynosCamera::m_calcHighResolutionPreviewGSCRect(ExynosRect *srcRect, ExynosRect *dstRect) |
| { |
| return m_exynosCameraParameters->calcHighResolutionPreviewGSCRect(srcRect, dstRect); |
| } |
| |
| status_t ExynosCamera::m_calcRecordingGSCRect(ExynosRect *srcRect, ExynosRect *dstRect) |
| { |
| return m_exynosCameraParameters->calcRecordingGSCRect(srcRect, dstRect); |
| } |
| |
| status_t ExynosCamera::m_calcPictureRect(ExynosRect *srcRect, ExynosRect *dstRect) |
| { |
| return m_exynosCameraParameters->calcPictureRect(srcRect, dstRect); |
| } |
| |
| status_t ExynosCamera::m_calcPictureRect(int originW, int originH, ExynosRect *srcRect, ExynosRect *dstRect) |
| { |
| return m_exynosCameraParameters->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); |
| /* removed message */ |
| /* curFrame->printEntity(); */ |
| 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(%d), 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 |
| 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(%d)", 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); |
| |
| CLOGD("DEBUG(%s):BufferManager(%s) created", __FUNCTION__, name); |
| |
| return ret; |
| } |
| |
| bool ExynosCamera::m_releasebuffersForRealloc() |
| { |
| status_t ret = NO_ERROR; |
| /* skip to free and reallocate buffers : flite / 3aa / isp / ispReprocessing */ |
| CLOGD("DEBUG(%s[%d]):m_setBuffers free all buffers", __FUNCTION__, __LINE__); |
| if (m_bayerBufferMgr != NULL) { |
| m_bayerBufferMgr->deinit(); |
| } |
| if (m_3aaBufferMgr != NULL) { |
| m_3aaBufferMgr->deinit(); |
| } |
| if (m_ispBufferMgr != NULL) { |
| m_ispBufferMgr->deinit(); |
| } |
| if (m_hwDisBufferMgr != NULL) { |
| m_hwDisBufferMgr->deinit(); |
| } |
| |
| /* realloc callback buffers */ |
| if (m_scpBufferMgr != NULL) { |
| m_scpBufferMgr->deinit(); |
| m_scpBufferMgr->setBufferCount(0); |
| } |
| |
| if (m_sccBufferMgr != NULL) { |
| m_sccBufferMgr->deinit(); |
| } |
| |
| if (m_previewCallbackBufferMgr != NULL) { |
| m_previewCallbackBufferMgr->deinit(); |
| } |
| if (m_highResolutionCallbackBufferMgr != NULL) { |
| m_highResolutionCallbackBufferMgr->deinit(); |
| } |
| |
| m_exynosCameraParameters->setReallocBuffer(false); |
| |
| if (m_exynosCameraParameters->getRestartPreview() == true) { |
| ret = setPreviewWindow(m_previewWindow); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]):setPreviewWindow fail", __FUNCTION__, __LINE__); |
| return INVALID_OPERATION; |
| } |
| } |
| |
| return true; |
| } |
| |
| |
| status_t ExynosCamera::m_setBuffers(void) |
| { |
| ExynosCameraAutoTimer autoTimer(__FUNCTION__); |
| |
| CLOGI("INFO(%s[%d]):alloc buffer - camera ID: %d", |
| __FUNCTION__, __LINE__, m_cameraId); |
| int ret = 0; |
| unsigned int bytesPerLine[EXYNOS_CAMERA_BUFFER_MAX_PLANES] = {0}; |
| unsigned int planeSize[EXYNOS_CAMERA_BUFFER_MAX_PLANES] = {0}; |
| int hwPreviewW, hwPreviewH; |
| int hwPictureW, hwPictureH; |
| |
| int previewMaxW, previewMaxH; |
| int pictureMaxW, pictureMaxH; |
| int sensorMaxW, sensorMaxH; |
| int sensorMarginW, sensorMarginH; |
| ExynosRect bdsRect; |
| |
| int planeCount = 1; |
| int minBufferCount = 1; |
| int maxBufferCount = 1; |
| exynos_camera_buffer_type_t type = EXYNOS_CAMERA_BUFFER_ION_NONCACHED_TYPE; |
| buffer_manager_allocation_mode_t allocMode = BUFFER_MANAGER_ALLOCATION_ATONCE; |
| |
| if( m_exynosCameraParameters->getReallocBuffer() ) { |
| /* skip to free and reallocate buffers : flite / 3aa / isp / ispReprocessing */ |
| m_releasebuffersForRealloc(); |
| } |
| |
| m_exynosCameraParameters->getHwPreviewSize(&hwPreviewW, &hwPreviewH); |
| CLOGI("(%s):HW Preview width x height = %dx%d", __FUNCTION__, hwPreviewW, hwPreviewH); |
| m_exynosCameraParameters->getHwPictureSize(&hwPictureW, &hwPictureH); |
| CLOGI("(%s):HW Picture width x height = %dx%d", __FUNCTION__, hwPictureW, hwPictureH); |
| m_exynosCameraParameters->getMaxPictureSize(&pictureMaxW, &pictureMaxH); |
| CLOGI("(%s):Picture MAX width x height = %dx%d", __FUNCTION__, pictureMaxW, pictureMaxH); |
| if( m_exynosCameraParameters->getHighSpeedRecording() ) { |
| m_exynosCameraParameters->getHwSensorSize(&sensorMaxW, &sensorMaxH); |
| CLOGI("(%s):HW Sensor(HighSpeed) MAX width x height = %dx%d", __FUNCTION__, sensorMaxW, sensorMaxH); |
| m_exynosCameraParameters->getHwPreviewSize(&previewMaxW, &previewMaxH); |
| CLOGI("(%s):HW Preview(HighSpeed) MAX width x height = %dx%d", __FUNCTION__, previewMaxW, previewMaxH); |
| } else { |
| m_exynosCameraParameters->getMaxSensorSize(&sensorMaxW, &sensorMaxH); |
| CLOGI("(%s):Sensor MAX width x height = %dx%d", __FUNCTION__, sensorMaxW, sensorMaxH); |
| m_exynosCameraParameters->getMaxPreviewSize(&previewMaxW, &previewMaxH); |
| CLOGI("(%s):Preview MAX width x height = %dx%d", __FUNCTION__, previewMaxW, previewMaxH); |
| } |
| |
| #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_exynosCameraParameters->calcNormalToTpuSize(previewMaxW, previewMaxH, &w, &h); |
| if (ret < 0) { |
| 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 |
| |
| m_exynosCameraParameters->getPreviewBdsSize(&bdsRect); |
| |
| /* FLITE */ |
| #ifdef CAMERA_PACKED_BAYER_ENABLE |
| #ifdef DEBUG_RAWDUMP |
| if (m_exynosCameraParameters->checkBayerDumpEnable()) { |
| bytesPerLine[0] = sensorMaxW * 2; |
| planeSize[0] = sensorMaxW * sensorMaxH * 2; |
| } else |
| #endif /* DEBUG_RAWDUMP */ |
| { |
| bytesPerLine[0] = ROUND_UP(sensorMaxW , 10) * 8 / 5; |
| planeSize[0] = bytesPerLine[0] * sensorMaxH; |
| } |
| #else |
| planeSize[0] = sensorMaxW * sensorMaxH * 2; |
| #endif |
| planeCount = 2; |
| |
| /* TO DO : make num of buffers samely */ |
| maxBufferCount = m_exynosconfig->current->bufInfo.num_bayer_buffers; |
| #ifdef RESERVED_MEMORY_ENABLE |
| if (getCameraId() == CAMERA_ID_BACK) { |
| type = EXYNOS_CAMERA_BUFFER_ION_RESERVED_TYPE; |
| m_bayerBufferMgr->setContigBufCount(RESERVED_NUM_BAYER_BUFFERS); |
| } else { |
| if (m_exynosCameraParameters->getDualMode() == false) { |
| type = EXYNOS_CAMERA_BUFFER_ION_RESERVED_TYPE; |
| m_bayerBufferMgr->setContigBufCount(FRONT_RESERVED_NUM_BAYER_BUFFERS); |
| } |
| } |
| #endif |
| |
| #ifndef DEBUG_RAWDUMP |
| if (m_exynosCameraParameters->isUsing3acForIspc() == false |
| || m_exynosCameraParameters->getDualMode() == true) |
| #endif |
| { |
| ret = m_allocBuffers(m_bayerBufferMgr, planeCount, planeSize, bytesPerLine, maxBufferCount, maxBufferCount, type, true, false); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]):bayerBuffer m_allocBuffers(bufferCount=%d) fail", |
| __FUNCTION__, __LINE__, maxBufferCount); |
| return ret; |
| } |
| } |
| |
| type = EXYNOS_CAMERA_BUFFER_ION_NONCACHED_TYPE; |
| |
| #ifdef CAMERA_PACKED_BAYER_ENABLE |
| memset(&bytesPerLine, 0, sizeof(unsigned int) * EXYNOS_CAMERA_BUFFER_MAX_PLANES); |
| #endif |
| |
| /* for preview */ |
| planeSize[0] = 32 * 64 * 2; |
| planeCount = 2; |
| /* TO DO : make num of buffers samely */ |
| if (m_exynosCameraParameters->isFlite3aaOtf() == true) |
| maxBufferCount = m_exynosconfig->current->bufInfo.num_3aa_buffers; |
| else |
| maxBufferCount = m_exynosconfig->current->bufInfo.num_bayer_buffers; |
| |
| ret = m_allocBuffers(m_3aaBufferMgr, planeCount, planeSize, bytesPerLine, maxBufferCount, true, false); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]):m_3aaBufferMgr m_allocBuffers(bufferCount=%d) fail", |
| __FUNCTION__, __LINE__, maxBufferCount); |
| return ret; |
| } |
| |
| if (m_exynosCameraParameters->isReprocessing() == true) { |
| #ifdef CAMERA_PACKED_BAYER_ENABLE |
| #ifdef DEBUG_RAWDUMP |
| if (m_exynosCameraParameters->checkBayerDumpEnable()) { |
| bytesPerLine[0] = previewMaxW * 2; |
| planeSize[0] = previewMaxW * previewMaxH * 2; |
| } else |
| #endif /* DEBUG_RAWDUMP */ |
| { |
| if (m_exynosCameraParameters->getDualMode() == true && getCameraId() == CAMERA_ID_FRONT) { |
| planeSize[0] = previewMaxW * previewMaxH * 2; |
| } else { |
| bytesPerLine[0] = ROUND_UP((previewMaxW * 3 / 2), 16); |
| planeSize[0] = bytesPerLine[0] * previewMaxH; |
| } |
| } |
| #else |
| /* planeSize[0] = width * height * 2; */ |
| planeSize[0] = previewMaxW * previewMaxH * 2; |
| #endif |
| } else { |
| /* Picture Max Size == Sensor Max Size - Sensor Margin */ |
| #ifdef CAMERA_PACKED_BAYER_ENABLE |
| #ifdef DEBUG_RAWDUMP |
| if (m_exynosCameraParameters->checkBayerDumpEnable()) { |
| bytesPerLine[0] = pictureMaxW * 2; |
| planeSize[0] = pictureMaxW * pictureMaxH * 2; |
| } else |
| #endif /* DEBUG_RAWDUMP */ |
| { |
| bytesPerLine[0] = ROUND_UP((pictureMaxW * 3 / 2), 16); |
| planeSize[0] = bytesPerLine[0] * pictureMaxH; |
| } |
| #else |
| /* planeSize[0] = width * height * 2; */ |
| planeSize[0] = pictureMaxW * pictureMaxH * 2; |
| #endif |
| } |
| planeCount = 2; |
| /* TO DO : make num of buffers samely */ |
| if (m_exynosCameraParameters->isFlite3aaOtf() == true) { |
| maxBufferCount = m_exynosconfig->current->bufInfo.num_3aa_buffers; |
| #ifdef RESERVED_MEMORY_ENABLE |
| type = EXYNOS_CAMERA_BUFFER_ION_RESERVED_TYPE; |
| m_ispBufferMgr->setContigBufCount(RESERVED_NUM_ISP_BUFFERS); |
| #endif |
| } else { |
| maxBufferCount = m_exynosconfig->current->bufInfo.num_bayer_buffers; |
| #ifdef RESERVED_MEMORY_ENABLE |
| if (m_exynosCameraParameters->getDualMode() == false) { |
| type = EXYNOS_CAMERA_BUFFER_ION_RESERVED_TYPE; |
| m_ispBufferMgr->setContigBufCount(FRONT_RESERVED_NUM_ISP_BUFFERS); |
| } |
| #endif |
| } |
| |
| if (m_exynosCameraParameters->is3aaIspOtf() == false) { |
| ret = m_allocBuffers(m_ispBufferMgr, planeCount, planeSize, bytesPerLine, maxBufferCount, maxBufferCount, type, true, false); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]):m_ispBufferMgr m_allocBuffers(bufferCount=%d) fail", |
| __FUNCTION__, __LINE__, maxBufferCount); |
| return ret; |
| } |
| } |
| |
| /* HW VDIS memory */ |
| if (m_exynosCameraParameters->getTpuEnabledMode() == true) { |
| maxBufferCount = m_exynosconfig->current->bufInfo.num_hwdis_buffers; |
| |
| /* DIS MEMORY */ |
| int disFormat = m_exynosCameraParameters->getHWVdisFormat(); |
| unsigned int bpp = 0; |
| unsigned int disPlanes = 0; |
| |
| getYuvFormatInfo(disFormat, &bpp, &disPlanes); |
| |
| switch (disFormat) { |
| case V4L2_PIX_FMT_YUYV: |
| planeSize[0] = bdsRect.w * bdsRect.h * 2; |
| break; |
| default: |
| CLOGE("ERR(%s[%d]):unexpected VDIS format(%d). so, fail", __FUNCTION__, __LINE__, disFormat); |
| return INVALID_OPERATION; |
| break; |
| } |
| |
| exynos_camera_buffer_type_t type = EXYNOS_CAMERA_BUFFER_ION_CACHED_TYPE; |
| |
| ret = m_allocBuffers(m_hwDisBufferMgr, planeCount, planeSize, bytesPerLine, maxBufferCount, maxBufferCount, type, true, false); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]):m_hwDisBufferMgr m_allocBuffers(bufferCount=%d) fail", |
| __FUNCTION__, __LINE__, maxBufferCount); |
| return ret; |
| } |
| |
| CLOGD("DEBUG(%s[%d]):m_allocBuffers(m_hwDisBufferMgr): %d x %d, planeCount(%d), maxBufferCount(%d)", |
| __FUNCTION__, __LINE__, bdsRect.w, bdsRect.h, planeCount, maxBufferCount); |
| } |
| |
| /* SW VDIS memory */ |
| type = EXYNOS_CAMERA_BUFFER_ION_NONCACHED_TYPE; |
| |
| planeSize[0] = hwPreviewW * hwPreviewH; |
| planeSize[1] = hwPreviewW * hwPreviewH / 2; |
| planeCount = 3; |
| if(m_exynosCameraParameters->increaseMaxBufferOfPreview()){ |
| maxBufferCount = m_exynosCameraParameters->getPreviewBufferCount(); |
| } else { |
| maxBufferCount = m_exynosconfig->current->bufInfo.num_preview_buffers; |
| } |
| |
| bool needMmap = false; |
| if (m_previewWindow == NULL) |
| needMmap = true; |
| |
| ret = m_allocBuffers(m_scpBufferMgr, 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 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 |
| |
| m_exynosCameraParameters->setHwPreviewStride(stride); |
| |
| if (m_exynosCameraParameters->isSccCapture() == true |
| || m_exynosCameraParameters->isUsing3acForIspc() == true) { |
| m_exynosCameraParameters->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_exynosCameraParameters->isFlite3aaOtf() == true) |
| maxBufferCount = m_exynosconfig->current->bufInfo.num_picture_buffers; |
| else |
| maxBufferCount = m_exynosconfig->current->bufInfo.num_bayer_buffers; |
| |
| if (m_exynosCameraParameters->isUsing3acForIspc() == true) { |
| allocMode = BUFFER_MANAGER_ALLOCATION_SILENT; |
| minBufferCount = 1; |
| } else { |
| allocMode = BUFFER_MANAGER_ALLOCATION_ATONCE; |
| minBufferCount = maxBufferCount; |
| } |
| type = EXYNOS_CAMERA_BUFFER_ION_NONCACHED_TYPE; |
| |
| ret = m_allocBuffers(m_sccBufferMgr, planeCount, planeSize, bytesPerLine, minBufferCount, maxBufferCount, type, allocMode, true, false); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]):m_sccBufferMgr m_allocBuffers(bufferCount=%d) fail", |
| __FUNCTION__, __LINE__, maxBufferCount); |
| return ret; |
| } |
| } |
| |
| CLOGI("INFO(%s[%d]):alloc buffer done - camera ID: %d", |
| __FUNCTION__, __LINE__, m_cameraId); |
| |
| return NO_ERROR; |
| } |
| |
| status_t ExynosCamera::m_setReprocessingBuffer(void) |
| { |
| int ret = 0; |
| int pictureMaxW, pictureMaxH; |
| unsigned int planeSize[EXYNOS_CAMERA_BUFFER_MAX_PLANES] = {0}; |
| unsigned int bytesPerLine[EXYNOS_CAMERA_BUFFER_MAX_PLANES] = {0}; |
| int planeCount = 0; |
| int bufferCount = 0; |
| int minBufferCount = NUM_REPROCESSING_BUFFERS; |
| int maxBufferCount = NUM_PICTURE_BUFFERS; |
| exynos_camera_buffer_type_t type = EXYNOS_CAMERA_BUFFER_ION_NONCACHED_TYPE; |
| buffer_manager_allocation_mode_t allocMode = BUFFER_MANAGER_ALLOCATION_ONDEMAND; |
| |
| m_exynosCameraParameters->getMaxPictureSize(&pictureMaxW, &pictureMaxH); |
| CLOGI("(%s):HW Picture MAX width x height = %dx%d", __FUNCTION__, pictureMaxW, pictureMaxH); |
| |
| /* for reprocessing */ |
| #ifdef CAMERA_PACKED_BAYER_ENABLE |
| #ifdef DEBUG_RAWDUMP |
| if (m_exynosCameraParameters->checkBayerDumpEnable()) { |
| bytesPerLine[0] = pictureMaxW * 2; |
| planeSize[0] = pictureMaxW * pictureMaxH * 2; |
| } else |
| #endif /* DEBUG_RAWDUMP */ |
| { |
| bytesPerLine[0] = ROUND_UP((pictureMaxW * 3 / 2), 16); |
| planeSize[0] = bytesPerLine[0] * pictureMaxH; |
| } |
| #else |
| planeSize[0] = pictureMaxW * pictureMaxH * 2; |
| #endif |
| planeCount = 2; |
| bufferCount = NUM_REPROCESSING_BUFFERS; |
| |
| if (m_exynosCameraParameters->getHighResolutionCallbackMode() == true) { |
| /* ISP Reprocessing Buffer realloc for high resolution callback */ |
| minBufferCount = 2; |
| } |
| |
| ret = m_allocBuffers(m_ispReprocessingBufferMgr, planeCount, planeSize, bytesPerLine, minBufferCount, maxBufferCount, type, allocMode, true, false); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]):m_ispReprocessingBufferMgr m_allocBuffers(minBufferCount=%d/maxBufferCount=%d) fail", |
| __FUNCTION__, __LINE__, minBufferCount, maxBufferCount); |
| return ret; |
| } |
| |
| return NO_ERROR; |
| } |
| |
| status_t ExynosCamera::m_setPreviewCallbackBuffer(void) |
| { |
| int ret = 0; |
| int previewW = 0, previewH = 0; |
| int previewFormat = 0; |
| m_exynosCameraParameters->getPreviewSize(&previewW, &previewH); |
| previewFormat = m_exynosCameraParameters->getPreviewFormat(); |
| |
| unsigned int planeSize[EXYNOS_CAMERA_BUFFER_MAX_PLANES] = {0}; |
| unsigned int bytesPerLine[EXYNOS_CAMERA_BUFFER_MAX_PLANES] = {0}; |
| |
| int planeCount = getYuvPlaneCount(previewFormat); |
| int bufferCount = 1; |
| exynos_camera_buffer_type_t type = EXYNOS_CAMERA_BUFFER_ION_CACHED_TYPE; |
| |
| if (m_previewCallbackBufferMgr == NULL) { |
| CLOGE("ERR(%s[%d]): m_previewCallbackBufferMgr is NULL", __FUNCTION__, __LINE__); |
| return INVALID_OPERATION; |
| } |
| |
| if (m_previewCallbackBufferMgr->isAllocated() == true) { |
| if (m_exynosCameraParameters->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, false, false); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]):m_previewCallbackBufferMgr m_allocBuffers(bufferCount=%d) fail", |
| __FUNCTION__, __LINE__, bufferCount); |
| return ret; |
| } |
| |
| return NO_ERROR; |
| } |
| |
| 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; |
| } |
| |
| status_t ExynosCamera::m_setPictureBuffer(void) |
| { |
| int ret = 0; |
| unsigned int planeSize[3] = {0}; |
| unsigned int bytesPerLine[3] = {0}; |
| int pictureW = 0, pictureH = 0, pictureFormat = 0; |
| int planeCount = 0; |
| int minBufferCount = 1; |
| int maxBufferCount = 1; |
| exynos_camera_buffer_type_t type = EXYNOS_CAMERA_BUFFER_ION_NONCACHED_TYPE; |
| buffer_manager_allocation_mode_t allocMode = BUFFER_MANAGER_ALLOCATION_ONDEMAND; |
| |
| m_exynosCameraParameters->getMaxPictureSize(&pictureW, &pictureH); |
| pictureFormat = m_exynosCameraParameters->getPictureFormat(); |
| if ((needGSCForCapture(getCameraId()) == true)) { |
| if (SCC_OUTPUT_COLOR_FMT == V4L2_PIX_FMT_NV21M) { |
| planeSize[0] = pictureW * pictureH; |
| planeSize[1] = pictureW * pictureH / 2; |
| planeCount = 2; |
| } else if (SCC_OUTPUT_COLOR_FMT == V4L2_PIX_FMT_NV21) { |
| planeSize[0] = pictureW * pictureH * 3 / 2; |
| planeCount = 1; |
| }else { |
| planeSize[0] = pictureW * pictureH * 2; |
| planeCount = 1; |
| } |
| |
| minBufferCount = 1; |
| maxBufferCount = m_exynosconfig->current->bufInfo.num_picture_buffers; |
| |
| // Pre-allocate certain amount of buffers enough to fed into 3 JPEG save threads. |
| if (m_exynosCameraParameters->getSeriesShotCount() > 0) |
| minBufferCount = NUM_BURST_GSC_JPEG_INIT_BUFFER; |
| |
| ret = m_allocBuffers(m_gscBufferMgr, planeCount, planeSize, bytesPerLine, minBufferCount, maxBufferCount, type, allocMode, false, false); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]):m_gscBufferMgr m_allocBuffers(minBufferCount=%d, maxBufferCount=%d) fail", |
| __FUNCTION__, __LINE__, minBufferCount, maxBufferCount); |
| return ret; |
| } |
| } |
| |
| if( m_hdrEnabled == false ) { |
| if (SCC_OUTPUT_COLOR_FMT == V4L2_PIX_FMT_NV21M) { |
| planeSize[0] = pictureW * pictureH * 3 / 2; |
| } else { |
| planeSize[0] = FRAME_SIZE(V4L2_PIX_2_HAL_PIXEL_FORMAT(pictureFormat), pictureW, pictureH); |
| } |
| planeCount = 1; |
| minBufferCount = 1; |
| maxBufferCount = m_exynosconfig->current->bufInfo.num_picture_buffers; |
| |
| type = EXYNOS_CAMERA_BUFFER_ION_CACHED_TYPE; |
| CLOGD("DEBUG(%s[%d]): jpegBuffer picture(%dx%d) size(%d)", __FUNCTION__, __LINE__, pictureW, pictureH, planeSize[0]); |
| |
| // Same with above GSC buffers |
| if (m_exynosCameraParameters->getSeriesShotCount() > 0) |
| minBufferCount = NUM_BURST_GSC_JPEG_INIT_BUFFER; |
| |
| ret = m_allocBuffers(m_jpegBufferMgr, planeCount, planeSize, bytesPerLine, minBufferCount, maxBufferCount, type, allocMode, false, true); |
| if (ret < 0) |
| CLOGE("ERR(%s:%d):jpegSrcHeapBuffer m_allocBuffers(bufferCount=%d) fail", |
| __FUNCTION__, __LINE__, NUM_REPROCESSING_BUFFERS); |
| } |
| |
| return ret; |
| } |
| |
| status_t ExynosCamera::m_releaseBuffers(void) |
| { |
| CLOGI("INFO(%s[%d]):release buffer", __FUNCTION__, __LINE__); |
| int ret = 0; |
| |
| if (m_bayerBufferMgr != NULL) { |
| m_bayerBufferMgr->deinit(); |
| } |
| 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(); |
| } |
| if (m_ispReprocessingBufferMgr != NULL) { |
| m_ispReprocessingBufferMgr->deinit(); |
| } |
| if (m_sccReprocessingBufferMgr != NULL) { |
| m_sccReprocessingBufferMgr->deinit(); |
| } |
| if (m_sccBufferMgr != NULL) { |
| m_sccBufferMgr->deinit(); |
| } |
| if (m_gscBufferMgr != NULL) { |
| m_gscBufferMgr->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(); |
| } |
| |
| CLOGI("INFO(%s[%d]):free buffer done", __FUNCTION__, __LINE__); |
| |
| return NO_ERROR; |
| } |
| |
| status_t ExynosCamera::m_putBuffers(ExynosCameraBufferManager *bufManager, int bufIndex) |
| { |
| if (bufManager != NULL) |
| bufManager->putBuffer(bufIndex, EXYNOS_CAMERA_BUFFER_POSITION_NONE); |
| |
| 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; |
| |
| 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) { |
| CLOGE("ERR(%s[%d]):alloc fail", __FUNCTION__, __LINE__); |
| goto func_exit; |
| } |
| |
| func_exit: |
| |
| 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; |
| } |
| |
| bool ExynosCamera::m_monitorThreadFunc(void) |
| { |
| CLOGV("INFO(%s[%d]):", __FUNCTION__, __LINE__); |
| |
| int *threadState; |
| struct timeval dqTime; |
| uint64_t *timeInterval; |
| int *countRenew; |
| int camId = getCameraId(); |
| int ret = NO_ERROR; |
| int loopCount = 0; |
| |
| int dtpStatus = 0; |
| int pipeIdFlite = 0; |
| int pipeIdErrorCheck = 0; |
| |
| for (loopCount = 0; loopCount < MONITOR_THREAD_INTERVAL; loopCount += (MONITOR_THREAD_INTERVAL/20)) { |
| if (m_flagThreadStop == true) { |
| CLOGI("INFO(%s[%d]): m_flagThreadStop(%d)", __FUNCTION__, __LINE__, m_flagThreadStop); |
| |
| return false; |
| } |
| |
| usleep(MONITOR_THREAD_INTERVAL/20); |
| } |
| |
| if (m_previewFrameFactory == NULL) { |
| CLOGW("WARN(%s[%d]): m_previewFrameFactory is NULL. Skip monitoring.", __FUNCTION__, __LINE__); |
| |
| return false; |
| } |
| |
| pipeIdFlite = PIPE_FLITE; |
| |
| if (m_exynosCameraParameters->is3aaIspOtf() == true) { |
| if (m_exynosCameraParameters->getTpuEnabledMode() == true) |
| pipeIdErrorCheck = PIPE_DIS; |
| else |
| pipeIdErrorCheck = PIPE_3AA; |
| } else { |
| pipeIdErrorCheck = PIPE_ISP; |
| } |
| |
| #ifdef MONITOR_LOG_SYNC |
| uint32_t pipeIdIsp = 0; |
| |
| /* define pipe for isp node cause of sync log sctrl */ |
| if (m_exynosCameraParameters->isFlite3aaOtf() == true) |
| pipeIdIsp = PIPE_3AA; |
| else |
| pipeIdIsp = PIPE_3AA; |
| |
| /* If it is not front camera in dual and sensor pipe is running, do sync log */ |
| if (m_previewFrameFactory->checkPipeThreadRunning(pipeIdIsp) && |
| !(getCameraId() == CAMERA_ID_FRONT && m_exynosCameraParameters->getDualMode())){ |
| if (!(m_syncLogDuration % MONITOR_LOG_SYNC_INTERVAL)) { |
| uint32_t syncLogId = m_getSyncLogId(); |
| CLOGI("INFO(%s[%d]): @FIMC_IS_SYNC %d", __FUNCTION__, __LINE__, syncLogId); |
| m_previewFrameFactory->syncLog(pipeIdIsp, syncLogId); |
| } |
| m_syncLogDuration++; |
| } |
| #endif |
| |
| m_previewFrameFactory->getControl(V4L2_CID_IS_G_DTPSTATUS, &dtpStatus, pipeIdFlite); |
| if (dtpStatus == 1) { |
| CLOGD("DEBUG(%s[%d]):DTP Detected. dtpStatus(%d)", __FUNCTION__, __LINE__, dtpStatus); |
| dump(); |
| |
| /* in GED */ |
| m_notifyCb(CAMERA_MSG_ERROR, 100, 0, m_callbackCookie); |
| return false; |
| } |
| |
| #ifdef SENSOR_OVERFLOW_CHECK |
| m_previewFrameFactory->getControl(V4L2_CID_IS_G_DTPSTATUS, &dtpStatus, pipeIdFlite); |
| if (dtpStatus == 1) { |
| CLOGD("DEBUG(%s[%d]):DTP Detected. dtpStatus(%d)", __FUNCTION__, __LINE__, dtpStatus); |
| dump(); |
| |
| /* in GED */ |
| /* m_notifyCb(CAMERA_MSG_ERROR, 100, 0, m_callbackCookie); */ |
| /* specifically defined */ |
| /* m_notifyCb(CAMERA_MSG_ERROR, 1002, 0, m_callbackCookie); */ |
| /* or */ |
| android_printAssert(NULL, LOG_TAG, "killed by itself"); |
| |
| return false; |
| } |
| #endif |
| |
| m_previewFrameFactory->getThreadState(&threadState, pipeIdErrorCheck); |
| m_previewFrameFactory->getThreadRenew(&countRenew, pipeIdErrorCheck); |
| |
| if ((*threadState == ERROR_POLLING_DETECTED) || (*countRenew > ERROR_DQ_BLOCKED_COUNT)) { |
| CLOGD("DEBUG(%s[%d]):ESD Detected. threadState(%d) *countRenew(%d)", __FUNCTION__, __LINE__, *threadState, *countRenew); |
| dump(); |
| |
| /* in GED */ |
| /* skip error callback */ |
| /* m_notifyCb(CAMERA_MSG_ERROR, 100, 0, m_callbackCookie); */ |
| |
| return false; |
| } else { |
| CLOGV("[%s] (%d) (%d)", __FUNCTION__, __LINE__, *threadState); |
| } |
| |
| #if 0 |
| m_checkThreadState(threadState, countRenew)?:ret = false; |
| m_checkThreadInterval(PIPE_SCP, WARNING_SCP_THREAD_INTERVAL, threadState)?:ret = false; |
| |
| enum pipeline pipe; |
| |
| /* check PIPE_3AA thread state & interval */ |
| if (m_exynosCameraParameters->isFlite3aaOtf() == true) { |
| pipe = PIPE_3AA_ISP; |
| |
| m_previewFrameFactory->getThreadRenew(&countRenew, pipe); |
| m_checkThreadState(threadState, countRenew)?:ret = false; |
| |
| if (ret == false) { |
| dump(); |
| |
| /* in GED */ |
| m_notifyCb(CAMERA_MSG_ERROR, 100, 0, m_callbackCookie); |
| /* specifically defined */ |
| /* m_notifyCb(CAMERA_MSG_ERROR, 1001, 0, m_callbackCookie); */ |
| /* or */ |
| android_printAssert(NULL, LOG_TAG, "killed by itself"); |
| } |
| } else { |
| pipe = PIPE_3AA; |
| |
| m_previewFrameFactory->getThreadRenew(&countRenew, pipe); |
| m_checkThreadState(threadState, countRenew)?:ret = false; |
| |
| if (ret == false) { |
| dump(); |
| |
| /* in GED */ |
| m_notifyCb(CAMERA_MSG_ERROR, 100, 0, m_callbackCookie); |
| /* specifically defined */ |
| /* m_notifyCb(CAMERA_MSG_ERROR, 1001, 0, m_callbackCookie); */ |
| /* or */ |
| android_printAssert(NULL, LOG_TAG, "killed by itself"); |
| } |
| } |
| |
| m_checkThreadInterval(pipe, WARNING_3AA_THREAD_INTERVAL, threadState)?:ret = false; |
| |
| if (m_callbackState == 0) { |
| m_callbackStateOld = 0; |
| m_callbackState = 0; |
| m_callbackMonitorCount = 0; |
| } else { |
| if (m_callbackStateOld != m_callbackState) { |
| m_callbackStateOld = m_callbackState; |
| CLOGD("INFO(%s[%d]):callback state is updated (0x%x)", __FUNCTION__, __LINE__, m_callbackStateOld); |
| } else { |
| if ((m_callbackStateOld & m_callbackState) != 0) |
| CLOGE("ERR(%s[%d]):callback is blocked (0x%x), Duration:%d msec", __FUNCTION__, __LINE__, m_callbackState, m_callbackMonitorCount*(MONITOR_THREAD_INTERVAL/1000)); |
| } |
| } |
| #endif |
| |
| gettimeofday(&dqTime, NULL); |
| m_previewFrameFactory->getThreadInterval(&timeInterval, pipeIdErrorCheck); |
| |
| CLOGV("Thread IntervalTime [%lld]", *timeInterval); |
| CLOGV("Thread Renew Count [%d]", *countRenew); |
| |
| m_previewFrameFactory->incThreadRenew(pipeIdErrorCheck); |
| |
| return true; |
| } |
| |
| #ifdef MONITOR_LOG_SYNC |
| uint32_t ExynosCamera::m_getSyncLogId(void) |
| { |
| return ++cameraSyncLogId; |
| } |
| #endif |
| |
| bool ExynosCamera::m_autoFocusResetNotify(int focusMode) |
| { |
| /* show restart */ |
| CLOGD("DEBUG(%s):CAMERA_MSG_FOCUS(%d) mode(%d)", __func__, 4, focusMode); |
| m_notifyCb(CAMERA_MSG_FOCUS, 4, 0, m_callbackCookie); |
| |
| /* show focusing */ |
| CLOGD("DEBUG(%s):CAMERA_MSG_FOCUS(%d) mode(%d)", __func__, 3, focusMode); |
| m_notifyCb(CAMERA_MSG_FOCUS, 3, 0, m_callbackCookie); |
| |
| return true; |
| } |
| |
| bool ExynosCamera::m_autoFocusThreadFunc(void) |
| { |
| CLOGI("INFO(%s[%d]): -IN-", __FUNCTION__, __LINE__); |
| |
| bool afResult = false; |
| int focusMode = 0; |
| |
| /* block until we're told to start. we don't want to use |
| * a restartable thread and requestExitAndWait() in cancelAutoFocus() |
| * because it would cause deadlock between our callbacks and the |
| * caller of cancelAutoFocus() which both want to grab the same lock |
| * in CameraServices layer. |
| */ |
| |
| if (getCameraId() == CAMERA_ID_FRONT) { |
| if (m_exynosCameraParameters->msgTypeEnabled(CAMERA_MSG_FOCUS)) { |
| if (m_notifyCb != NULL) { |
| CLOGD("DEBUG(%s):Do not support autoFocus in front camera.", __FUNCTION__); |
| m_notifyCb(CAMERA_MSG_FOCUS, true, 0, m_callbackCookie); |
| } else { |
| CLOGD("DEBUG(%s):m_notifyCb is NULL!", __FUNCTION__); |
| } |
| } else { |
| CLOGD("DEBUG(%s):autoFocus msg disabled !!", __FUNCTION__); |
| } |
| return false; |
| } |
| |
| if (m_autoFocusType == AUTO_FOCUS_SERVICE) { |
| focusMode = m_exynosCameraParameters->getFocusMode(); |
| } else if (m_autoFocusType == AUTO_FOCUS_HAL) { |
| focusMode = FOCUS_MODE_AUTO; |
| |
| m_autoFocusResetNotify(focusMode); |
| } |
| |
| /* check early exit request */ |
| if (m_exitAutoFocusThread == true) { |
| CLOGD("DEBUG(%s):exiting on request", __FUNCTION__); |
| goto done; |
| } |
| |
| m_autoFocusLock.lock(); |
| m_autoFocusRunning = true; |
| |
| if (m_autoFocusRunning == true) { |
| afResult = m_exynosCameraActivityControl->autoFocus(focusMode, m_autoFocusType); |
| if (afResult == true) |
| CLOGV("DEBUG(%s):autoFocus Success!!", __FUNCTION__); |
| else |
| CLOGV("DEBUG(%s):autoFocus Fail !!", __FUNCTION__); |
| } else { |
| CLOGV("DEBUG(%s):autoFocus canceled !!", __FUNCTION__); |
| } |
| |
| /* |
| * CAMERA_MSG_FOCUS only takes a bool. true for |
| * finished and false for failure. |
| * If cancelAutofocus() called, no callback. |
| */ |
| if ((m_autoFocusRunning == true) && |
| m_exynosCameraParameters->msgTypeEnabled(CAMERA_MSG_FOCUS)) { |
| |
| if (m_notifyCb != NULL) { |
| int afFinalResult = (int)afResult; |
| |
| /* if inactive detected, tell it */ |
| if (focusMode == FOCUS_MODE_CONTINUOUS_PICTURE) { |
| if (m_exynosCameraActivityControl->getCAFResult() == 2) { |
| afFinalResult = 2; |
| } |
| } |
| |
| CLOGD("DEBUG(%s):CAMERA_MSG_FOCUS(%d) mode(%d)", __FUNCTION__, afFinalResult, focusMode); |
| m_notifyCb(CAMERA_MSG_FOCUS, afFinalResult, 0, m_callbackCookie); |
| } else { |
| CLOGD("DEBUG(%s):m_notifyCb is NULL mode(%d)", __FUNCTION__, focusMode); |
| } |
| } else { |
| CLOGV("DEBUG(%s):autoFocus canceled, no callback !!", __FUNCTION__); |
| } |
| |
| m_autoFocusRunning = false; |
| |
| CLOGV("DEBUG(%s):exiting with no error", __FUNCTION__); |
| |
| done: |
| m_autoFocusLock.unlock(); |
| |
| CLOGI("DEBUG(%s):end", __FUNCTION__); |
| |
| return false; |
| } |
| |
| bool ExynosCamera::m_autoFocusContinousThreadFunc(void) |
| { |
| int ret = 0; |
| int index = 0; |
| uint32_t frameCnt = 0; |
| uint32_t count = 0; |
| |
| |
| ret = m_autoFocusContinousQ.waitAndPopProcessQ(&frameCnt); |
| if (m_flagThreadStop == true) { |
| CLOGI("INFO(%s[%d]):m_flagThreadStop(%d)", __FUNCTION__, __LINE__, m_flagThreadStop); |
| return false; |
| } |
| if (ret < 0) { |
| /* TODO: We need to make timeout duration depends on FPS */ |
| if (ret == 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; |
| } |
| |
| count = m_autoFocusContinousQ.getSizeOfProcessQ(); |
| if( count >= MAX_FOCUSCONTINUS_THREADQ_SIZE ) { |
| for( uint32_t i = 0 ; i < count ; i++) { |
| m_autoFocusContinousQ.popProcessQ(&frameCnt); |
| } |
| CLOGD("DEBUG(%s[%d]):m_autoFocusContinousQ skipped QSize(%d) frame(%d)", __FUNCTION__, __LINE__, count, frameCnt); |
| } |
| |
| /* Continuous Auto-focus */ |
| if (m_exynosCameraParameters->getFocusMode() == FOCUS_MODE_CONTINUOUS_PICTURE) { |
| int afstatus = 0; |
| static int afResult = 1; |
| int prev_afstatus = afResult; |
| afstatus = m_exynosCameraActivityControl->getCAFResult(); |
| afResult = afstatus; |
| |
| if (afstatus == 3 && (prev_afstatus == 0 || prev_afstatus == 1)) { |
| afResult = 4; |
| } |
| |
| if (m_exynosCameraParameters->msgTypeEnabled(CAMERA_MSG_FOCUS) |
| && (prev_afstatus != afstatus)) { |
| CLOGD("DEBUG(%s):CAMERA_MSG_FOCUS(%d) mode(%d)", |
| __FUNCTION__, afResult, m_exynosCameraParameters->getFocusMode()); |
| m_notifyCb(CAMERA_MSG_FOCUS, afResult, 0, m_callbackCookie); |
| } |
| } |
| |
| return true; |
| } |
| |
| status_t ExynosCamera::dump(int fd) const |
| { |
| CLOGI("INFO(%s[%d]):", __FUNCTION__, __LINE__); |
| |
| return NO_ERROR; |
| } |
| |
| void ExynosCamera::dump() |
| { |
| CLOGI("INFO(%s[%d]):", __FUNCTION__, __LINE__); |
| |
| m_printExynosCameraInfo(__FUNCTION__); |
| |
| if (m_previewFrameFactory != NULL) |
| m_previewFrameFactory->dump(); |
| |
| if (m_bayerBufferMgr != NULL) |
| m_bayerBufferMgr->dump(); |
| 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(); |
| |
| if (m_ispReprocessingBufferMgr != NULL) |
| m_ispReprocessingBufferMgr->dump(); |
| if (m_sccReprocessingBufferMgr != NULL) |
| m_sccReprocessingBufferMgr->dump(); |
| if (m_sccBufferMgr != NULL) |
| m_sccBufferMgr->dump(); |
| if (m_gscBufferMgr != NULL) |
| m_gscBufferMgr->dump(); |
| |
| return; |
| } |
| |
| status_t ExynosCamera::m_getBufferManager(uint32_t pipeId, ExynosCameraBufferManager **bufMgr, uint32_t direction) |
| { |
| status_t ret = NO_ERROR; |
| ExynosCameraBufferManager **bufMgrList[2] = {NULL}; |
| *bufMgr = NULL; |
| int internalPipeId = pipeId; |
| |
| /* |
| * front / back is different up to scenario(3AA OTF/M2M, etc) |
| * so, we don't need to distinguish front / back camera. |
| * but. reprocessing must handle the separated operation |
| */ |
| if (pipeId < PIPE_FLITE_REPROCESSING) |
| internalPipeId = INDEX(pipeId); |
| |
| switch (internalPipeId) { |
| case PIPE_FLITE: |
| bufMgrList[0] = NULL; |
| bufMgrList[1] = &m_bayerBufferMgr; |
| break; |
| case PIPE_3AA_ISP: |
| bufMgrList[0] = &m_3aaBufferMgr; |
| bufMgrList[1] = &m_ispBufferMgr; |
| break; |
| case PIPE_3AC: |
| bufMgrList[0] = NULL; |
| bufMgrList[1] = &m_bayerBufferMgr; |
| break; |
| case PIPE_3AA: |
| if (m_exynosCameraParameters->getDualMode() == true && getCameraId() == CAMERA_ID_FRONT) { |
| bufMgrList[0] = &m_bayerBufferMgr; |
| bufMgrList[1] = &m_sccBufferMgr; |
| } else { |
| bufMgrList[0] = &m_3aaBufferMgr; |
| if (m_exynosCameraParameters->isUsing3acForIspc() == true) |
| bufMgrList[1] = &m_sccBufferMgr; |
| else |
| bufMgrList[1] = &m_ispBufferMgr; |
| } |
| break; |
| case PIPE_ISP: |
| bufMgrList[0] = &m_ispBufferMgr; |
| |
| if (m_exynosCameraParameters->getTpuEnabledMode() == true) |
| bufMgrList[1] = &m_hwDisBufferMgr; |
| else |
| bufMgrList[1] = &m_scpBufferMgr; |
| break; |
| case PIPE_DIS: |
| bufMgrList[0] = &m_ispBufferMgr; |
| bufMgrList[1] = &m_scpBufferMgr; |
| break; |
| case PIPE_ISPC: |
| case PIPE_SCC: |
| bufMgrList[0] = NULL; |
| bufMgrList[1] = &m_sccBufferMgr; |
| break; |
| case PIPE_SCP: |
| bufMgrList[0] = NULL; |
| bufMgrList[1] = &m_scpBufferMgr; |
| break; |
| case PIPE_GSC: |
| if (m_exynosCameraParameters->getDualMode() == true && getCameraId() == CAMERA_ID_FRONT) |
| bufMgrList[0] = &m_sccBufferMgr; |
| else |
| bufMgrList[0] = &m_scpBufferMgr; |
| bufMgrList[1] = &m_scpBufferMgr; |
| break; |
| case PIPE_GSC_PICTURE: |
| bufMgrList[0] = &m_sccBufferMgr; |
| bufMgrList[1] = &m_gscBufferMgr; |
| break; |
| case PIPE_3AA_REPROCESSING: |
| bufMgrList[0] = &m_bayerBufferMgr; |
| if (m_exynosCameraParameters->getDualMode() == false) |
| bufMgrList[1] = &m_ispReprocessingBufferMgr; |
| else |
| bufMgrList[1] = &m_sccReprocessingBufferMgr; |
| break; |
| case PIPE_ISP_REPROCESSING: |
| bufMgrList[0] = &m_ispReprocessingBufferMgr; |
| bufMgrList[1] = &m_sccReprocessingBufferMgr; |
| break; |
| case PIPE_ISPC_REPROCESSING: |
| case PIPE_SCC_REPROCESSING: |
| bufMgrList[0] = NULL; |
| bufMgrList[1] = &m_sccReprocessingBufferMgr; |
| break; |
| case PIPE_GSC_REPROCESSING: |
| bufMgrList[0] = &m_sccReprocessingBufferMgr; |
| bufMgrList[1] = &m_gscBufferMgr; |
| break; |
| default: |
| CLOGE("ERR(%s[%d]): Unknown pipeId(%d)", __FUNCTION__, __LINE__, pipeId); |
| bufMgrList[0] = NULL; |
| bufMgrList[1] = NULL; |
| ret = BAD_VALUE; |
| break; |
| } |
| |
| if (bufMgrList[direction] != NULL) |
| *bufMgr = *bufMgrList[direction]; |
| |
| return ret; |
| } |
| |
| uint32_t ExynosCamera::m_getBayerPipeId(void) |
| { |
| uint32_t pipeId = 0; |
| |
| if (m_exynosCameraParameters->getUsePureBayerReprocessing() == true) { |
| pipeId = PIPE_FLITE; |
| } else { |
| pipeId = PIPE_3AA; |
| } |
| #ifdef DEBUG_RAWDUMP |
| pipeId = PIPE_FLITE; |
| #endif |
| return pipeId; |
| } |
| |
| void ExynosCamera::m_debugFpsCheck(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] == 30) { |
| m_debugFpsTimer[id].stop(); |
| long long durationTime = m_debugFpsTimer[id].durationMsecs(); |
| CLOGI("DEBUG: FPS_CHECK(id:%d), duration %lld / 30 = %lld ms", pipeId, durationTime, 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[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[1], 0x0, sizeof(struct camera2_shot_ext)); |
| |
| shot_ext = (struct camera2_shot_ext *)buffer->addr[1]; |
| shot_ext->shot.dm.request.frameCount = bayerFrameCount; |
| |
| return ret; |
| } |
| |
| status_t ExynosCamera::m_getBayerBuffer(uint32_t pipeId, ExynosCameraBuffer *buffer, camera2_shot_ext *updateDmShot) |
| { |
| status_t ret = NO_ERROR; |
| bool isSrc = false; |
| int retryCount = 30; /* 200ms x 30 */ |
| camera2_shot_ext *shot_ext = NULL; |
| camera2_stream *shot_stream = NULL; |
| ExynosCameraFrame *inListFrame = NULL; |
| |
| m_captureSelector->setWaitTime(200000000); |
| ExynosCameraFrame *bayerFrame = m_captureSelector->selectFrames(m_reprocessingCounter.getCount(), pipeId, isSrc, retryCount); |
| if (bayerFrame == NULL) { |
| CLOGE("ERR(%s[%d]):bayerFrame is NULL", __FUNCTION__, __LINE__); |
| ret = INVALID_OPERATION; |
| goto CLEAN; |
| } |
| |
| if (pipeId == PIPE_3AA) { |
| ret = bayerFrame->getDstBuffer(pipeId, buffer, m_previewFrameFactory->getNodeType(pipeId)); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]): getDstBuffer fail, pipeId(%d), ret(%d)", __FUNCTION__, __LINE__, pipeId, ret); |
| goto CLEAN; |
| } |
| } else if (pipeId == PIPE_FLITE) { |
| ret = bayerFrame->getDstBuffer(pipeId, buffer); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]): getDstBuffer fail, pipeId(%d), ret(%d)", __FUNCTION__, __LINE__, pipeId, ret); |
| goto CLEAN; |
| } |
| } |
| |
| if (m_exynosCameraParameters->getReprocessingBayerMode() == REPROCESSING_BAYER_MODE_PURE_ALWAYS_ON || |
| m_exynosCameraParameters->getReprocessingBayerMode() == REPROCESSING_BAYER_MODE_PURE_DYNAMIC) { |
| shot_ext = (struct camera2_shot_ext *)buffer->addr[1]; |
| CLOGD("DEBUG(%s[%d]): Selected frame count(hal : %d / driver : %d)", __FUNCTION__, __LINE__, |
| bayerFrame->getFrameCount(), shot_ext->shot.dm.request.frameCount); |
| } else if (m_exynosCameraParameters->getReprocessingBayerMode() == REPROCESSING_BAYER_MODE_DIRTY_ALWAYS_ON || |
| m_exynosCameraParameters->getReprocessingBayerMode() == REPROCESSING_BAYER_MODE_DIRTY_DYNAMIC) { |
| if (updateDmShot == NULL) { |
| CLOGE("ERR(%s[%d]): updateDmShot is NULL", __FUNCTION__, __LINE__); |
| goto CLEAN; |
| } |
| |
| retryCount = 12; /* 80ms * 12 */ |
| while(retryCount > 0) { |
| if(bayerFrame->getMetaDataEnable() == false) { |
| CLOGD("DEBUG(%s[%d]): Waiting for update jpeg metadata failed (%d), retryCount(%d)", __FUNCTION__, __LINE__, ret, retryCount); |
| } else { |
| break; |
| } |
| retryCount--; |
| usleep(DM_WAITING_TIME); |
| } |
| |
| /* update meta like pure bayer */ |
| bayerFrame->getUserDynamicMeta(updateDmShot); |
| bayerFrame->getDynamicMeta(updateDmShot); |
| |
| shot_stream = (struct camera2_stream *)buffer->addr[1]; |
| CLOGD("DEBUG(%s[%d]): Selected fcount(hal : %d / driver : %d)", __FUNCTION__, __LINE__, |
| bayerFrame->getFrameCount(), shot_stream->fcount); |
| } else { |
| CLOGE("ERR(%s[%d]): reprocessing is not valid pipeId(%d), ret(%d)", __FUNCTION__, __LINE__, pipeId, ret); |
| goto CLEAN; |
| } |
| |
| CLEAN: |
| |
| if (bayerFrame != NULL) { |
| bayerFrame->frameUnlock(); |
| |
| ret = m_searchFrameFromList(&m_processList, bayerFrame->getFrameCount(), &inListFrame); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]):searchFrameFromList fail", __FUNCTION__, __LINE__); |
| } else { |
| CLOGD("DEBUG(%s[%d]): Selected frame(%d) complete, Delete", __FUNCTION__, __LINE__, bayerFrame->getFrameCount()); |
| bayerFrame->decRef(); |
| m_frameMgr->deleteFrame(bayerFrame); |
| bayerFrame = NULL; |
| } |
| } |
| |
| 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)); |
| |
| return ret; |
| } |
| |
| status_t ExynosCamera::m_boostDynamicCapture(void) |
| { |
| status_t ret = NO_ERROR; |
| #if 0 /* TODO: need to implementation for bayer */ |
| uint32_t pipeId = (isOwnScc(getCameraId()) == 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; |
| } |
| |
| void ExynosCamera::m_updateBoostDynamicCaptureSize(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_exynosCameraParameters->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_exynosCameraParameters->getPreviewFpsRange(&curMinFps, &curMaxFps); |
| |
| if (m_curMinFps != curMinFps) { |
| CLOGD("DEBUG(%s[%d]):(%d)(%d)", __FUNCTION__, __LINE__, curMinFps, curMaxFps); |
| |
| enum pipeline pipe = (isOwnScc(getCameraId()) == 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; |
| } |
| |
| /* vision */ |
| status_t ExynosCamera::m_startVisionInternal(void) |
| { |
| ExynosCameraAutoTimer autoTimer(__FUNCTION__); |
| |
| CLOGI("DEBUG(%s[%d]):IN", __FUNCTION__, __LINE__); |
| |
| uint32_t minFrameNum = FRONT_NUM_BAYER_BUFFERS; |
| int ret = 0; |
| ExynosCameraFrame *newFrame = NULL; |
| ExynosCameraBuffer dstBuf; |
| |
| m_fliteFrameCount = 0; |
| m_3aa_ispFrameCount = 0; |
| m_ispFrameCount = 0; |
| m_sccFrameCount = 0; |
| m_scpFrameCount = 0; |
| m_displayPreviewToggle = 0; |
| |
| ret = m_visionFrameFactory->initPipes(); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]):m_visionFrameFactory->initPipes() failed", __FUNCTION__, __LINE__); |
| return ret; |
| } |
| |
| m_visionFps = 10; |
| m_visionAe = 0x2A; |
| |
| ret = m_visionFrameFactory->setControl(V4L2_CID_SENSOR_SET_FRAME_RATE, m_visionFps, PIPE_FLITE); |
| if (ret < 0) |
| CLOGE("ERR(%s[%d]):FLITE setControl fail, ret(%d)", __FUNCTION__, __LINE__, ret); |
| |
| CLOGD("DEBUG(%s[%d]):m_visionFps(%d)", __FUNCTION__, __LINE__, m_visionFps); |
| |
| ret = m_visionFrameFactory->setControl(V4L2_CID_SENSOR_SET_AE_TARGET, m_visionAe, PIPE_FLITE); |
| if (ret < 0) |
| CLOGE("ERR(%s[%d]):FLITE setControl fail, ret(%d)", __FUNCTION__, __LINE__, ret); |
| |
| CLOGD("DEBUG(%s[%d]):m_visionAe(%d)", __FUNCTION__, __LINE__, m_visionAe); |
| |
| for (uint32_t i = 0; i < minFrameNum; i++) { |
| ret = generateFrameVision(i, &newFrame); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]):generateFrame fail", __FUNCTION__, __LINE__); |
| return ret; |
| } |
| if (newFrame == NULL) { |
| CLOGE("ERR(%s[%d]):new faame is NULL", __FUNCTION__, __LINE__); |
| return ret; |
| } |
| |
| m_fliteFrameCount++; |
| |
| m_setupEntity(PIPE_FLITE, newFrame); |
| m_visionFrameFactory->pushFrameToPipe(&newFrame, PIPE_FLITE); |
| m_visionFrameFactory->setOutputFrameQToPipe(m_pipeFrameVisionDoneQ, PIPE_FLITE); |
| } |
| |
| /* prepare pipes */ |
| ret = m_visionFrameFactory->preparePipes(); |
| if (ret < 0) { |
| CLOGE("ERR(%s):preparePipe fail", __FUNCTION__); |
| return ret; |
| } |
| |
| /* stream on pipes */ |
| ret = m_visionFrameFactory->startPipes(); |
| if (ret < 0) { |
| CLOGE("ERR(%s):startPipe fail", __FUNCTION__); |
| return ret; |
| } |
| |
| /* start all thread */ |
| ret = m_visionFrameFactory->startInitialThreads(); |
| if (ret < 0) { |
| CLOGE("ERR(%s):startInitialThreads fail", __FUNCTION__); |
| return ret; |
| } |
| |
| m_previewEnabled = true; |
| m_exynosCameraParameters->setPreviewRunning(m_previewEnabled); |
| |
| CLOGI("DEBUG(%s[%d]):OUT", __FUNCTION__, __LINE__); |
| |
| return NO_ERROR; |
| } |
| |
| status_t ExynosCamera::m_stopVisionInternal(void) |
| { |
| int ret = 0; |
| |
| CLOGI("DEBUG(%s[%d]):IN", __FUNCTION__, __LINE__); |
| |
| ret = m_visionFrameFactory->stopPipes(); |
| if (ret < 0) { |
| CLOGE("ERR(%s):stopPipe fail", __FUNCTION__); |
| return ret; |
| } |
| |
| CLOGD("DEBUG(%s[%d]):clear process Frame list", __FUNCTION__, __LINE__); |
| ret = m_clearList(&m_processList); |
| if (ret < 0) { |
| CLOGE("ERR(%s):m_clearList fail", __FUNCTION__); |
| return ret; |
| } |
| |
| m_clearList(m_pipeFrameVisionDoneQ); |
| |
| m_fliteFrameCount = 0; |
| m_3aa_ispFrameCount = 0; |
| m_ispFrameCount = 0; |
| m_sccFrameCount = 0; |
| m_scpFrameCount = 0; |
| |
| m_previewEnabled = false; |
| m_exynosCameraParameters->setPreviewRunning(m_previewEnabled); |
| |
| CLOGI("DEBUG(%s[%d]):OUT", __FUNCTION__, __LINE__); |
| |
| return NO_ERROR; |
| } |
| |
| status_t ExynosCamera::generateFrameVision(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_visionFrameFactory->createNewFrame(); |
| |
| if (*newFrame == NULL) { |
| CLOGE("ERR(%s):newFrame is NULL", __FUNCTION__); |
| return UNKNOWN_ERROR; |
| } |
| |
| m_processList.push_back(*newFrame); |
| } |
| |
| return ret; |
| } |
| |
| status_t ExynosCamera::m_setVisionBuffers(void) |
| { |
| ExynosCameraAutoTimer autoTimer(__FUNCTION__); |
| |
| CLOGI("INFO(%s[%d]):alloc buffer - camera ID: %d", |
| __FUNCTION__, __LINE__, m_cameraId); |
| int ret = 0; |
| unsigned int bytesPerLine[EXYNOS_CAMERA_BUFFER_MAX_PLANES] = {0}; |
| unsigned int planeSize[EXYNOS_CAMERA_BUFFER_MAX_PLANES] = {0}; |
| int hwPreviewW, hwPreviewH; |
| int hwSensorW, hwSensorH; |
| int hwPictureW, hwPictureH; |
| |
| int previewMaxW, previewMaxH; |
| int sensorMaxW, sensorMaxH; |
| |
| int planeCount = 1; |
| int minBufferCount = 1; |
| int maxBufferCount = 1; |
| |
| maxBufferCount = FRONT_NUM_BAYER_BUFFERS; |
| planeSize[0] = VISION_WIDTH * VISION_HEIGHT; |
| planeCount = 2; |
| exynos_camera_buffer_type_t type = EXYNOS_CAMERA_BUFFER_ION_NONCACHED_TYPE; |
| |
| /* ret = m_allocBuffers(m_bayerBufferMgr, planeCount, planeSize, bytesPerLine, maxBufferCount, maxBufferCount, type, true, false); */ |
| ret = m_allocBuffers(m_bayerBufferMgr, planeCount, planeSize, bytesPerLine, maxBufferCount, maxBufferCount, type, true, true); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]):bayerBuffer m_allocBuffers(bufferCount=%d) fail", |
| __FUNCTION__, __LINE__, maxBufferCount); |
| return ret; |
| } |
| |
| CLOGI("INFO(%s[%d]):alloc buffer done - camera ID: %d", |
| __FUNCTION__, __LINE__, m_cameraId); |
| |
| return NO_ERROR; |
| } |
| |
| status_t ExynosCamera::m_setVisionCallbackBuffer(void) |
| { |
| int ret = 0; |
| int previewW = 0, previewH = 0; |
| int previewFormat = 0; |
| m_exynosCameraParameters->getPreviewSize(&previewW, &previewH); |
| previewFormat = m_exynosCameraParameters->getPreviewFormat(); |
| |
| unsigned int planeSize[EXYNOS_CAMERA_BUFFER_MAX_PLANES] = {0}; |
| unsigned int bytesPerLine[EXYNOS_CAMERA_BUFFER_MAX_PLANES] = {0}; |
| |
| int planeCount = getYuvPlaneCount(previewFormat); |
| int bufferCount = FRONT_NUM_BAYER_BUFFERS; |
| exynos_camera_buffer_type_t type = EXYNOS_CAMERA_BUFFER_ION_CACHED_TYPE; |
| |
| planeSize[0] = VISION_WIDTH * VISION_HEIGHT; |
| planeCount = 1; |
| ret = m_allocBuffers(m_previewCallbackBufferMgr, planeCount, planeSize, bytesPerLine, bufferCount, bufferCount, type, false, true); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]):m_previewCallbackBufferMgr m_allocBuffers(bufferCount=%d) fail", |
| __FUNCTION__, __LINE__, bufferCount); |
| return ret; |
| } |
| |
| return NO_ERROR; |
| } |
| |
| |
| bool ExynosCamera::m_visionThreadFunc(void) |
| { |
| int ret = 0; |
| int index = 0; |
| |
| int frameSkipCount = 0; |
| ExynosCameraFrameEntity *entity = NULL; |
| ExynosCameraFrame *handleFrame = NULL; |
| ExynosCameraFrame *newFrame = NULL; |
| ExynosCameraBuffer bayerBuffer; |
| int pipeID = 0; |
| /* to handle the high speed frame rate */ |
| bool skipPreview = false; |
| int ratio = 1; |
| uint32_t minFps = 0, maxFps = 0; |
| uint32_t dispFps = EXYNOS_CAMERA_PREVIEW_FPS_REFERENCE; |
| uint32_t fvalid = 0; |
| uint32_t fcount = 0; |
| struct camera2_stream *shot_stream = NULL; |
| size_t callbackBufSize; |
| status_t statusRet = NO_ERROR; |
| int fps = 0; |
| int ae = 0; |
| int internalValue = 0; |
| |
| if (m_previewEnabled == false) { |
| CLOGD("DEBUG(%s):preview is stopped, thread stop", __FUNCTION__); |
| return false; |
| } |
| |
| ret = m_pipeFrameVisionDoneQ->waitAndPopProcessQ(&handleFrame); |
| if (ret < 0) { |
| /* TODO: We need to make timeout duration depends on FPS */ |
| if (ret == 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 (handleFrame == NULL) { |
| CLOGE("ERR(%s[%d]):handleFrame is NULL", __FUNCTION__, __LINE__); |
| return true; |
| } |
| |
| /* handle vision frame */ |
| entity = handleFrame->getFrameDoneEntity(); |
| if (entity == NULL) { |
| CLOGE("ERR(%s[%d]):current entity is NULL", __FUNCTION__, __LINE__); |
| /* TODO: doing exception handling */ |
| return true; |
| } |
| |
| pipeID = entity->getPipeId(); |
| |
| switch(entity->getPipeId()) { |
| case PIPE_FLITE: |
| ret = handleFrame->getDstBuffer(entity->getPipeId(), &bayerBuffer); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]):getDstBuffer fail, pipeId(%d), ret(%d)", |
| __FUNCTION__, __LINE__, entity->getPipeId(), ret); |
| return ret; |
| } |
| |
| #ifdef VISION_DUMP |
| char filePath[50]; |
| snprintf(filePath, sizeof(filePath), "/data/media/0/DCIM/Camera/vision%02d.raw", dumpIndex); |
| CLOGD("vision dump %s", filePath); |
| dumpToFile(filePath, (char *)bayerBuffer.addr[0], VISION_WIDTH * VISION_HEIGHT); |
| |
| dumpIndex ++; |
| if (dumpIndex > 4) |
| dumpIndex = 0; |
| #endif |
| |
| m_exynosCameraParameters->getFrameSkipCount(&frameSkipCount); |
| |
| if (frameSkipCount > 0) { |
| CLOGD("INFO(%s[%d]):frameSkipCount(%d)", __FUNCTION__, __LINE__, frameSkipCount); |
| } else { |
| /* callback */ |
| if (m_exynosCameraParameters->msgTypeEnabled(CAMERA_MSG_PREVIEW_FRAME)) { |
| ExynosCameraBuffer previewCbBuffer; |
| camera_memory_t *previewCallbackHeap = NULL; |
| char *srcAddr = NULL; |
| char *dstAddr = NULL; |
| int bufIndex = -2; |
| |
| m_previewCallbackBufferMgr->getBuffer(&bufIndex, EXYNOS_CAMERA_BUFFER_POSITION_IN_HAL, &previewCbBuffer); |
| previewCallbackHeap = m_getMemoryCb(previewCbBuffer.fd[0], previewCbBuffer.size[0], 1, m_callbackCookie); |
| if (!previewCallbackHeap || previewCallbackHeap->data == MAP_FAILED) { |
| CLOGE("ERR(%s[%d]):m_getMemoryCb(fd:%d, size:%d) fail", __FUNCTION__, __LINE__, previewCbBuffer.fd[0], previewCbBuffer.size[0]); |
| |
| return INVALID_OPERATION; |
| } |
| |
| for (int plane = 0; plane < 1; plane++) { |
| srcAddr = bayerBuffer.addr[plane]; |
| dstAddr = (char *)previewCallbackHeap->data; |
| memcpy(dstAddr, srcAddr, previewCbBuffer.size[plane]); |
| } |
| #if 0 |
| // Getting the buffer size for current preview size. |
| callbackBufSize = m_getCurrentPreviewSizeBytes(); |
| if (callbackBufSize <= 0) { |
| CLOGE("ERR(%s[%d]): m_getCurrentPreviewSizeBytes fail, ret(%d)", __FUNCTION__, __LINE__, callbackBufSize); |
| statusRet = INVALID_OPERATION; |
| // goto done; |
| } |
| |
| // Comparing newely updated preview buffer size against previewCallbackHeap. |
| // If size is different, it means that the preview size has changed |
| // during the memory transfer or GSC operations. So we have to drop this |
| // preview callback buffer to prevent malfunctioning of user application |
| if (previewCallbackHeap->size != callbackBufSize) { |
| CLOGW("WARN(%s[%d]): Preview size changed during operation. " \ |
| "Initial=[%d], Current=[%d]. Current preview frame[%d] will be dropped." |
| , __FUNCTION__, __LINE__, previewCallbackHeap->size, callbackBufSize, handleFrame->getFrameCount()); |
| // goto done; |
| } |
| #endif |
| setBit(&m_callbackState, CALLBACK_STATE_PREVIEW_FRAME, true); |
| m_dataCb(CAMERA_MSG_PREVIEW_FRAME, previewCallbackHeap, 0, NULL, m_callbackCookie); |
| clearBit(&m_callbackState, CALLBACK_STATE_PREVIEW_FRAME, true); |
| |
| previewCallbackHeap->release(previewCallbackHeap); |
| |
| m_previewCallbackBufferMgr->putBuffer(bufIndex, EXYNOS_CAMERA_BUFFER_POSITION_NONE); |
| } |
| } |
| |
| ret = m_putBuffers(m_bayerBufferMgr, bayerBuffer.index); |
| |
| ret = generateFrameVision(m_fliteFrameCount, &newFrame); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]):generateFrame fail", __FUNCTION__, __LINE__); |
| return ret; |
| } |
| |
| ret = m_setupEntity(PIPE_FLITE, newFrame); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]):setupEntity fail", __FUNCTION__, __LINE__); |
| break; |
| } |
| |
| m_visionFrameFactory->pushFrameToPipe(&newFrame, PIPE_FLITE); |
| m_visionFrameFactory->setOutputFrameQToPipe(m_pipeFrameVisionDoneQ, PIPE_FLITE); |
| m_fliteFrameCount++; |
| |
| break; |
| default: |
| break; |
| } |
| |
| ret = handleFrame->setEntityState(entity->getPipeId(), ENTITY_STATE_COMPLETE); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]):setEntityState fail, pipeId(%d), state(%d), ret(%d)", |
| __FUNCTION__, __LINE__, entity->getPipeId(), ENTITY_STATE_COMPLETE, ret); |
| return ret; |
| } |
| |
| CLOGV("DEBUG(%s[%d]):frame complete, count(%d)", __FUNCTION__, __LINE__, handleFrame->getFrameCount()); |
| ret = m_removeFrameFromList(&m_processList, handleFrame); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]):remove frame from processList fail, ret(%d)", __FUNCTION__, __LINE__, ret); |
| } |
| |
| handleFrame->decRef(); |
| m_frameMgr->deleteFrame(handleFrame); |
| handleFrame = NULL; |
| |
| #if 1 |
| fps = m_exynosCameraParameters->getVisionModeFps(); |
| if (m_visionFps != fps) { |
| ret = m_visionFrameFactory->setControl(V4L2_CID_SENSOR_SET_FRAME_RATE, fps, PIPE_FLITE); |
| if (ret < 0) |
| CLOGE("ERR(%s[%d]):FLITE setControl fail, ret(%d)", __FUNCTION__, __LINE__, ret); |
| |
| m_visionFps = fps; |
| CLOGD("DEBUG(%s[%d]):(%d)(%d)", __FUNCTION__, __LINE__, m_visionFps, fps); |
| } |
| #if 0 |
| if (0 < m_visionAeTarget) { |
| if (m_visionAeTarget != m_exynosVision->getAeTarget()) { |
| if (m_exynosVision->setAeTarget(m_visionAeTarget) == false) { |
| CLOGE("ERR(%s): Fail to setAeTarget(%d)", __func__, m_visionAeTarget); |
| |
| goto err; |
| } |
| } |
| } |
| #endif |
| |
| ae = m_exynosCameraParameters->getVisionModeAeTarget(); |
| if (ae != m_visionAe) { |
| switch(ae) { |
| case 1: |
| internalValue = 0x2A; |
| break; |
| case 2: |
| internalValue = 0x8A; |
| break; |
| default: |
| internalValue = 0x2A; |
| break; |
| } |
| |
| ret = m_visionFrameFactory->setControl(V4L2_CID_SENSOR_SET_AE_TARGET, internalValue, PIPE_FLITE); |
| if (ret < 0) |
| CLOGE("ERR(%s[%d]):FLITE setControl fail, ret(%d)", __FUNCTION__, __LINE__, ret); |
| |
| m_visionAe = ae; |
| CLOGD("DEBUG(%s[%d]):(%d)(%d)", __FUNCTION__, __LINE__, m_visionAe, internalValue); |
| } |
| #endif |
| |
| |
| |
| return true; |
| } |
| |
| 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_exynosCameraParameters->getCameraId()); |
| CLOGD("DEBUG(%s[%d]):= getDualMode : %d", __FUNCTION__, __LINE__, m_exynosCameraParameters->getDualMode()); |
| CLOGD("DEBUG(%s[%d]):= getScalableSensorMode : %d", __FUNCTION__, __LINE__, m_exynosCameraParameters->getScalableSensorMode()); |
| CLOGD("DEBUG(%s[%d]):= getRecordingHint : %d", __FUNCTION__, __LINE__, m_exynosCameraParameters->getRecordingHint()); |
| CLOGD("DEBUG(%s[%d]):= getDualRecordingHint : %d", __FUNCTION__, __LINE__, m_exynosCameraParameters->getDualRecordingHint()); |
| CLOGD("DEBUG(%s[%d]):= getAdaptiveCSCRecording : %d", __FUNCTION__, __LINE__, m_exynosCameraParameters->getAdaptiveCSCRecording()); |
| CLOGD("DEBUG(%s[%d]):= doCscRecording : %d", __FUNCTION__, __LINE__, m_exynosCameraParameters->doCscRecording()); |
| CLOGD("DEBUG(%s[%d]):= needGSCForCapture : %d", __FUNCTION__, __LINE__, needGSCForCapture(getCameraId())); |
| CLOGD("DEBUG(%s[%d]):= getShotMode : %d", __FUNCTION__, __LINE__, m_exynosCameraParameters->getShotMode()); |
| CLOGD("DEBUG(%s[%d]):= getTpuEnabledMode : %d", __FUNCTION__, __LINE__, m_exynosCameraParameters->getTpuEnabledMode()); |
| CLOGD("DEBUG(%s[%d]):= getHWVdisMode : %d", __FUNCTION__, __LINE__, m_exynosCameraParameters->getHWVdisMode()); |
| CLOGD("DEBUG(%s[%d]):= get3dnrMode : %d", __FUNCTION__, __LINE__, m_exynosCameraParameters->get3dnrMode()); |
| |
| CLOGD("DEBUG(%s[%d]):============= Internal setting ====================", __FUNCTION__, __LINE__); |
| CLOGD("DEBUG(%s[%d]):= isFlite3aaOtf : %d", __FUNCTION__, __LINE__, m_exynosCameraParameters->isFlite3aaOtf()); |
| CLOGD("DEBUG(%s[%d]):= is3aaIspOtf : %d", __FUNCTION__, __LINE__, m_exynosCameraParameters->is3aaIspOtf()); |
| CLOGD("DEBUG(%s[%d]):= isReprocessing : %d", __FUNCTION__, __LINE__, m_exynosCameraParameters->isReprocessing()); |
| CLOGD("DEBUG(%s[%d]):= isReprocessing3aaIspOTF : %d", __FUNCTION__, __LINE__, m_exynosCameraParameters->isReprocessing3aaIspOTF()); |
| CLOGD("DEBUG(%s[%d]):= getUsePureBayerReprocessing : %d", __FUNCTION__, __LINE__, m_exynosCameraParameters->getUsePureBayerReprocessing()); |
| |
| int reprocessingBayerMode = m_exynosCameraParameters->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_exynosCameraParameters->isSccCapture()); |
| |
| CLOGD("DEBUG(%s[%d]):============= size setting =======================", __FUNCTION__, __LINE__); |
| m_exynosCameraParameters->getMaxSensorSize(&w, &h); |
| CLOGD("DEBUG(%s[%d]):= getMaxSensorSize : %d x %d", __FUNCTION__, __LINE__, w, h); |
| |
| m_exynosCameraParameters->getHwSensorSize(&w, &h); |
| CLOGD("DEBUG(%s[%d]):= getHwSensorSize : %d x %d", __FUNCTION__, __LINE__, w, h); |
| |
| m_exynosCameraParameters->getBnsSize(&w, &h); |
| CLOGD("DEBUG(%s[%d]):= getBnsSize : %d x %d", __FUNCTION__, __LINE__, w, h); |
| |
| m_exynosCameraParameters->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_exynosCameraParameters->getPreviewBdsSize(&dstRect); |
| CLOGD("DEBUG(%s[%d]):= getPreviewBdsSize : (%d, %d, %d, %d)", __FUNCTION__, __LINE__, |
| dstRect.x, dstRect.y, dstRect.w, dstRect.h); |
| |
| m_exynosCameraParameters->getHwPreviewSize(&w, &h); |
| CLOGD("DEBUG(%s[%d]):= getHwPreviewSize : %d x %d", __FUNCTION__, __LINE__, w, h); |
| |
| m_exynosCameraParameters->getPreviewSize(&w, &h); |
| CLOGD("DEBUG(%s[%d]):= getPreviewSize : %d x %d", __FUNCTION__, __LINE__, w, h); |
| |
| m_exynosCameraParameters->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_exynosCameraParameters->getPictureBdsSize(&dstRect); |
| CLOGD("DEBUG(%s[%d]):= getPictureBdsSize : (%d, %d, %d, %d)", __FUNCTION__, __LINE__, |
| dstRect.x, dstRect.y, dstRect.w, dstRect.h); |
| |
| m_exynosCameraParameters->getHwPictureSize(&w, &h); |
| CLOGD("DEBUG(%s[%d]):= getHwPictureSize : %d x %d", __FUNCTION__, __LINE__, w, h); |
| |
| m_exynosCameraParameters->getPictureSize(&w, &h); |
| CLOGD("DEBUG(%s[%d]):= getPictureSize : %d x %d", __FUNCTION__, __LINE__, w, h); |
| |
| CLOGD("DEBUG(%s[%d]):===================================================", __FUNCTION__, __LINE__); |
| } |
| |
| }; /* namespace android */ |