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