| /* |
| * Copyright (C) 2014, Samsung Electronics Co. LTD |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| /* #define LOG_NDEBUG 0 */ |
| #define LOG_TAG "ExynosCamera3" |
| #include <cutils/log.h> |
| #include <ui/Fence.h> |
| |
| #include "ExynosCamera3.h" |
| |
| namespace android { |
| |
| #ifdef MONITOR_LOG_SYNC |
| uint32_t ExynosCamera3::cameraSyncLogId = 0; |
| #endif |
| ExynosCamera3::ExynosCamera3(int cameraId, camera_metadata_t **info): |
| m_requestMgr(NULL), |
| m_parameters(NULL), |
| m_streamManager(NULL), |
| m_activityControl(NULL) |
| { |
| BUILD_DATE(); |
| m_cameraId = cameraId; |
| |
| memset(m_name, 0x00, sizeof(m_name)); |
| |
| /* Initialize pointer variables */ |
| m_ionAllocator = NULL; |
| |
| m_bayerBufferMgr= NULL; |
| m_fliteBufferMgr= NULL; |
| m_3aaBufferMgr = NULL; |
| m_ispBufferMgr = NULL; |
| m_yuvCaptureBufferMgr = NULL; |
| m_vraBufferMgr = NULL; |
| m_gscBufferMgr = NULL; |
| m_internalScpBufferMgr = NULL; |
| m_ispReprocessingBufferMgr = NULL; |
| m_thumbnailBufferMgr = NULL; |
| m_skipBufferMgr = NULL; |
| m_yuvCaptureReprocessingBufferMgr = NULL; |
| m_captureSelector = NULL; |
| m_sccCaptureSelector = NULL; |
| m_captureZslSelector = NULL; |
| |
| /* Create related classes */ |
| m_parameters = new ExynosCamera3Parameters(m_cameraId); |
| m_use_companion = m_parameters->isCompanion(cameraId); |
| m_activityControl = m_parameters->getActivityControl(); |
| |
| ExynosCameraActivityUCTL *uctlMgr = m_activityControl->getUCTLMgr(); |
| if (uctlMgr != NULL) |
| uctlMgr->setDeviceRotation(m_parameters->getFdOrientation()); |
| |
| m_metadataConverter = new ExynosCamera3MetadataConverter(cameraId, (ExynosCameraParameters *)m_parameters); |
| m_requestMgr = new ExynosCameraRequestManager(cameraId, (ExynosCameraParameters *)m_parameters); |
| m_requestMgr->setMetaDataConverter(m_metadataConverter); |
| |
| #ifdef SAMSUNG_COMPANION |
| m_companionNode = NULL; |
| m_companionThread = NULL; |
| CLOGI2("use_companion(%d)", cameraId, m_use_companion); |
| |
| if (m_use_companion == true) { |
| m_companionThread = new mainCameraThread(this, &ExynosCamera3::m_companionThreadFunc, |
| "companionshotThread", PRIORITY_URGENT_DISPLAY); |
| if (m_companionThread != NULL) { |
| m_companionThread->run(); |
| CLOGD2("companionThread starts"); |
| } else { |
| CLOGE2("failed the m_companionThread."); |
| } |
| } |
| #endif |
| |
| #if defined(SAMSUNG_EEPROM) |
| m_eepromThread = NULL; |
| if ((m_use_companion == false) && (isEEprom(getCameraId()) == true)) { |
| m_eepromThread = new mainCameraThread(this, &ExynosCamera3::m_eepromThreadFunc, |
| "cameraeepromThread", PRIORITY_URGENT_DISPLAY); |
| if (m_eepromThread != NULL) { |
| m_eepromThread->run(); |
| CLOGD2("eepromThread starts"); |
| } else { |
| CLOGE2("failed the m_eepromThread"); |
| } |
| } |
| #endif |
| |
| /* Create managers */ |
| m_createManagers(); |
| |
| /* Create threads */ |
| m_createThreads(); |
| |
| /* Create queue for preview path. If you want to control pipeDone in ExynosCamera3, try to create frame queue here */ |
| m_shotDoneQ = new ExynosCameraList<uint32_t>(); |
| for (int i = 0; i < MAX_PIPE_NUM; i++) { |
| switch (i) { |
| case PIPE_FLITE: |
| case PIPE_3AA: |
| case PIPE_ISP: |
| case PIPE_VRA: |
| m_pipeFrameDoneQ[i] = new frame_queue_t; |
| break; |
| default: |
| m_pipeFrameDoneQ[i] = NULL; |
| break; |
| } |
| } |
| |
| /* Create queue for capture path */ |
| m_pipeCaptureFrameDoneQ = new frame_queue_t(m_captureStreamThread); |
| m_pipeCaptureFrameDoneQ->setWaitTime(2000000000); |
| |
| m_duplicateBufferDoneQ = new frame_queue_t; |
| |
| /* Create queue for capture path */ |
| m_reprocessingDoneQ = new frame_queue_t; |
| m_reprocessingDoneQ->setWaitTime(2000000000); |
| |
| m_frameFactoryQ = new framefactory3_queue_t; |
| m_selectBayerQ = new frame_queue_t(); |
| m_captureQ = new frame_queue_t(m_captureThread); |
| |
| /* construct static meta data information */ |
| if (ExynosCamera3MetadataConverter::constructStaticInfo(cameraId, info)) |
| CLOGE2("Create static meta data failed!!"); |
| |
| m_metadataConverter->setStaticInfo(cameraId, *info); |
| |
| m_streamManager->setYuvStreamMaxCount(m_parameters->getYuvStreamMaxNum()); |
| |
| m_setFrameManager(); |
| |
| m_setConfigInform(); |
| |
| m_constructFrameFactory(); |
| |
| /* Setup FrameFactory to RequestManager*/ |
| m_setupFrameFactoryToRequest(); |
| |
| /* HACK : check capture stream */ |
| isCaptureConfig = false; |
| isRestarted = false; |
| |
| isRecordingConfig = false; |
| recordingEnabled = false; |
| m_checkConfigStream = false; |
| m_flushFlag = false; |
| m_factoryStartFlag = false; |
| m_flushWaitEnable = false; |
| m_frameFactoryStartDone = false; |
| m_internalFrameCount = 0; |
| m_isNeedInternalFrame = false; |
| m_isNeedRequestFrame = false; |
| m_currentShot = new struct camera2_shot_ext; |
| memset(m_currentShot, 0x00, sizeof(struct camera2_shot_ext)); |
| m_internalFrameDoneQ = new frame_queue_t(m_internalFrameThread); |
| m_captureCount = 0; |
| #ifdef MONITOR_LOG_SYNC |
| m_syncLogDuration = 0; |
| #endif |
| #ifdef USE_FASTEN_AE_STABLE |
| m_flagRunFastAE = false; |
| #endif |
| m_flagStartFrameFactory = false; |
| m_flagStartReprocessingFrameFactory = false; |
| m_flagBayerRequest = false; |
| m_prepareFliteCnt = 0; |
| m_lastFrametime = 0; |
| } |
| |
| status_t ExynosCamera3::m_setConfigInform() { |
| struct ExynosConfigInfo exynosConfig; |
| memset((void *)&exynosConfig, 0x00, sizeof(exynosConfig)); |
| |
| exynosConfig.mode = CONFIG_MODE::NORMAL; |
| |
| /* Internal buffers */ |
| exynosConfig.info[CONFIG_MODE::NORMAL].bufInfo.num_sensor_buffers = NUM_SENSOR_BUFFERS; |
| exynosConfig.info[CONFIG_MODE::NORMAL].bufInfo.num_3aa_buffers = NUM_3AA_BUFFERS; |
| exynosConfig.info[CONFIG_MODE::NORMAL].bufInfo.num_hwdis_buffers = NUM_HW_DIS_BUFFERS; |
| exynosConfig.info[CONFIG_MODE::NORMAL].bufInfo.num_vra_buffers = NUM_VRA_BUFFERS; |
| exynosConfig.info[CONFIG_MODE::NORMAL].bufInfo.num_reprocessing_buffers = NUM_REPROCESSING_BUFFERS; |
| exynosConfig.info[CONFIG_MODE::NORMAL].bufInfo.num_fastaestable_buffer = NUM_FASTAESTABLE_BUFFERS; |
| exynosConfig.info[CONFIG_MODE::NORMAL].bufInfo.reprocessing_bayer_hold_count = REPROCESSING_BAYER_HOLD_COUNT; |
| /* Service buffers */ |
| #if 1 /* Consumer's buffer counts are not fixed */ |
| exynosConfig.info[CONFIG_MODE::NORMAL].bufInfo.num_bayer_buffers = VIDEO_MAX_FRAME - NUM_SENSOR_BUFFERS; |
| exynosConfig.info[CONFIG_MODE::NORMAL].bufInfo.num_preview_buffers = VIDEO_MAX_FRAME; |
| exynosConfig.info[CONFIG_MODE::NORMAL].bufInfo.num_preview_cb_buffers = VIDEO_MAX_FRAME; |
| exynosConfig.info[CONFIG_MODE::NORMAL].bufInfo.num_recording_buffers = VIDEO_MAX_FRAME; |
| exynosConfig.info[CONFIG_MODE::NORMAL].bufInfo.num_picture_buffers = VIDEO_MAX_FRAME; |
| #else |
| exynosConfig.info[CONFIG_MODE::NORMAL].bufInfo.num_bayer_buffers = NUM_REQUEST_RAW_BUFFER + NUM_SERVICE_RAW_BUFFER; |
| exynosConfig.info[CONFIG_MODE::NORMAL].bufInfo.num_preview_buffers = NUM_REQUEST_PREVIEW_BUFFER + NUM_SERVICE_PREVIEW_BUFFER; |
| exynosConfig.info[CONFIG_MODE::NORMAL].bufInfo.num_preview_cb_buffers = NUM_REQUEST_CALLBACK_BUFFER + NUM_SERVICE_CALLBACK_BUFFER; |
| exynosConfig.info[CONFIG_MODE::NORMAL].bufInfo.num_recording_buffers = NUM_REQUEST_VIDEO_BUFFER + NUM_SERVICE_VIDEO_BUFFER; |
| exynosConfig.info[CONFIG_MODE::NORMAL].bufInfo.num_picture_buffers = NUM_REQUEST_JPEG_BUFFER + NUM_SERVICE_JPEG_BUFFER; |
| #endif |
| exynosConfig.info[CONFIG_MODE::NORMAL].bufInfo.num_request_raw_buffers = NUM_REQUEST_RAW_BUFFER; |
| exynosConfig.info[CONFIG_MODE::NORMAL].bufInfo.num_request_preview_buffers = NUM_REQUEST_PREVIEW_BUFFER; |
| exynosConfig.info[CONFIG_MODE::NORMAL].bufInfo.num_request_callback_buffers = NUM_REQUEST_CALLBACK_BUFFER; |
| exynosConfig.info[CONFIG_MODE::NORMAL].bufInfo.num_request_video_buffers = NUM_REQUEST_VIDEO_BUFFER; |
| exynosConfig.info[CONFIG_MODE::NORMAL].bufInfo.num_request_jpeg_buffers = NUM_REQUEST_JPEG_BUFFER; |
| /* Blocking request */ |
| exynosConfig.info[CONFIG_MODE::NORMAL].bufInfo.num_min_block_request = NUM_REQUEST_BLOCK_MIN; |
| exynosConfig.info[CONFIG_MODE::NORMAL].bufInfo.num_max_block_request = NUM_REQUEST_BLOCK_MAX; |
| /* Prepare buffers */ |
| exynosConfig.info[CONFIG_MODE::NORMAL].pipeInfo.prepare[PIPE_FLITE] = PIPE_FLITE_PREPARE_COUNT; |
| exynosConfig.info[CONFIG_MODE::NORMAL].pipeInfo.prepare[PIPE_3AA] = PIPE_3AA_PREPARE_COUNT; |
| |
| #if (USE_HIGHSPEED_RECORDING) |
| /* Config HIGH_SPEED 60 buffer & pipe info */ |
| exynosConfig.info[CONFIG_MODE::HIGHSPEED_60].bufInfo.num_sensor_buffers = (getCameraId() == CAMERA_ID_BACK) ? FPS60_NUM_SENSOR_BUFFERS : FPS60_FRONT_NUM_BAYER_BUFFERS; |
| exynosConfig.info[CONFIG_MODE::HIGHSPEED_60].bufInfo.num_bayer_buffers = FPS60_NUM_NUM_BAYER_BUFFERS; |
| exynosConfig.info[CONFIG_MODE::HIGHSPEED_60].bufInfo.init_bayer_buffers = FPS60_NUM_NUM_BAYER_BUFFERS; |
| exynosConfig.info[CONFIG_MODE::HIGHSPEED_60].bufInfo.num_3aa_buffers = FPS60_NUM_NUM_BAYER_BUFFERS; |
| exynosConfig.info[CONFIG_MODE::HIGHSPEED_60].bufInfo.num_hwdis_buffers = FPS60_NUM_HW_DIS_BUFFERS; |
| exynosConfig.info[CONFIG_MODE::HIGHSPEED_60].bufInfo.num_vra_buffers = FPS60_NUM_VRA_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 = FPS60_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.front_num_bayer_buffers = FPS60_FRONT_NUM_BAYER_BUFFERS; |
| exynosConfig.info[CONFIG_MODE::HIGHSPEED_60].bufInfo.front_num_picture_buffers = FPS60_FRONT_NUM_PICTURE_BUFFERS; |
| exynosConfig.info[CONFIG_MODE::HIGHSPEED_60].bufInfo.preview_buffer_margin = FPS60_NUM_PREVIEW_BUFFERS_MARGIN; |
| exynosConfig.info[CONFIG_MODE::HIGHSPEED_60].bufInfo.num_min_block_request = FPS60_NUM_REQUEST_BLOCK_MIN; |
| exynosConfig.info[CONFIG_MODE::HIGHSPEED_60].bufInfo.num_max_block_request = FPS60_NUM_REQUEST_BLOCK_MAX; |
| exynosConfig.info[CONFIG_MODE::HIGHSPEED_60].pipeInfo.prepare[PIPE_FLITE] = FPS60_PIPE_FLITE_PREPARE_COUNT; |
| exynosConfig.info[CONFIG_MODE::HIGHSPEED_60].pipeInfo.prepare[PIPE_3AA] = FPS60_PIPE_3AA_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 */ |
| |
| /* Internal buffers */ |
| exynosConfig.info[CONFIG_MODE::HIGHSPEED_120].bufInfo.num_sensor_buffers = FPS120_NUM_SENSOR_BUFFERS; |
| exynosConfig.info[CONFIG_MODE::HIGHSPEED_120].bufInfo.num_3aa_buffers = FPS120_NUM_3AA_BUFFERS; |
| exynosConfig.info[CONFIG_MODE::HIGHSPEED_120].bufInfo.num_hwdis_buffers = FPS120_NUM_HW_DIS_BUFFERS; |
| exynosConfig.info[CONFIG_MODE::HIGHSPEED_120].bufInfo.num_vra_buffers = FPS120_NUM_VRA_BUFFERS; |
| exynosConfig.info[CONFIG_MODE::HIGHSPEED_120].bufInfo.num_reprocessing_buffers = FPS120_NUM_REPROCESSING_BUFFERS; |
| exynosConfig.info[CONFIG_MODE::HIGHSPEED_120].bufInfo.num_fastaestable_buffer = FPS120_NUM_FASTAESTABLE_BUFFERS; |
| exynosConfig.info[CONFIG_MODE::HIGHSPEED_120].bufInfo.reprocessing_bayer_hold_count = FPS120_REPROCESSING_BAYER_HOLD_COUNT; |
| |
| /* Service buffers */ |
| #if 1 |
| exynosConfig.info[CONFIG_MODE::HIGHSPEED_120].bufInfo.num_bayer_buffers = VIDEO_MAX_FRAME - FPS120_NUM_SENSOR_BUFFERS; |
| exynosConfig.info[CONFIG_MODE::HIGHSPEED_120].bufInfo.num_preview_buffers = VIDEO_MAX_FRAME; |
| exynosConfig.info[CONFIG_MODE::HIGHSPEED_120].bufInfo.num_preview_cb_buffers = VIDEO_MAX_FRAME; |
| exynosConfig.info[CONFIG_MODE::HIGHSPEED_120].bufInfo.num_recording_buffers = VIDEO_MAX_FRAME; |
| exynosConfig.info[CONFIG_MODE::HIGHSPEED_120].bufInfo.num_picture_buffers = VIDEO_MAX_FRAME; |
| #else |
| exynosConfig.info[CONFIG_MODE::HIGHSPEED_120].bufInfo.num_bayer_buffers = FPS120_NUM_REQUEST_RAW_BUFFER + FPS120_NUM_SERVICE_RAW_BUFFER; |
| exynosConfig.info[CONFIG_MODE::HIGHSPEED_120].bufInfo.num_preview_buffers = FPS120_NUM_REQUEST_PREVIEW_BUFFER + FPS120_NUM_SERVICE_PREVIEW_BUFFER; |
| exynosConfig.info[CONFIG_MODE::HIGHSPEED_120].bufInfo.num_preview_cb_buffers = FPS120_NUM_REQUEST_CALLBACK_BUFFER + FPS120_NUM_SERVICE_CALLBACK_BUFFER; |
| exynosConfig.info[CONFIG_MODE::HIGHSPEED_120].bufInfo.num_recording_buffers = FPS120_NUM_REQUEST_VIDEO_BUFFER + FPS120_NUM_SERVICE_VIDEO_BUFFER; |
| exynosConfig.info[CONFIG_MODE::HIGHSPEED_120].bufInfo.num_picture_buffers = FPS120_NUM_REQUEST_JPEG_BUFFER + FPS120_NUM_SERVICE_JPEG_BUFFER; |
| #endif |
| exynosConfig.info[CONFIG_MODE::HIGHSPEED_120].bufInfo.num_request_raw_buffers = FPS120_NUM_REQUEST_RAW_BUFFER; |
| exynosConfig.info[CONFIG_MODE::HIGHSPEED_120].bufInfo.num_request_preview_buffers = FPS120_NUM_REQUEST_PREVIEW_BUFFER; |
| exynosConfig.info[CONFIG_MODE::HIGHSPEED_120].bufInfo.num_request_callback_buffers = FPS120_NUM_REQUEST_CALLBACK_BUFFER; |
| exynosConfig.info[CONFIG_MODE::HIGHSPEED_120].bufInfo.num_request_video_buffers = FPS120_NUM_REQUEST_VIDEO_BUFFER; |
| exynosConfig.info[CONFIG_MODE::HIGHSPEED_120].bufInfo.num_request_jpeg_buffers = FPS120_NUM_REQUEST_JPEG_BUFFER; |
| /* Blocking request */ |
| exynosConfig.info[CONFIG_MODE::HIGHSPEED_120].bufInfo.num_min_block_request = FPS120_NUM_REQUEST_BLOCK_MIN; |
| exynosConfig.info[CONFIG_MODE::HIGHSPEED_120].bufInfo.num_max_block_request = FPS120_NUM_REQUEST_BLOCK_MAX; |
| /* Prepare buffers */ |
| exynosConfig.info[CONFIG_MODE::HIGHSPEED_120].pipeInfo.prepare[PIPE_FLITE] = FPS120_PIPE_FLITE_PREPARE_COUNT; |
| exynosConfig.info[CONFIG_MODE::HIGHSPEED_120].pipeInfo.prepare[PIPE_3AA] = FPS120_PIPE_3AA_PREPARE_COUNT; |
| #endif |
| |
| m_parameters->setConfig(&exynosConfig); |
| |
| m_exynosconfig = m_parameters->getConfig(); |
| |
| return NO_ERROR; |
| } |
| |
| status_t ExynosCamera3::m_setupFrameFactoryToRequest() |
| { |
| status_t ret = NO_ERROR; |
| const char *intentName = NULL; |
| const char *streamIDName = NULL; |
| ExynosCamera3FrameFactory *factory = NULL; |
| |
| factory = m_frameFactory[FRAME_FACTORY_TYPE_CAPTURE_PREVIEW]; |
| #if defined(ENABLE_FULL_FRAME) |
| if (factory != NULL) { |
| m_requestMgr->setRequestsInfo(HAL_STREAM_ID_PREVIEW, factory); |
| m_requestMgr->setRequestsInfo(HAL_STREAM_ID_VIDEO, factory); |
| m_requestMgr->setRequestsInfo(HAL_STREAM_ID_CALLBACK, factory); |
| m_requestMgr->setRequestsInfo(HAL_STREAM_ID_RAW, factory); |
| m_requestMgr->setRequestsInfo(HAL_STREAM_ID_JPEG, factory); |
| m_requestMgr->setRequestsInfo(HAL_STREAM_ID_ZSL_OUTPUT, factory); |
| } else { |
| CLOGE2("FRAME_FACTORY_TYPE_CAPTURE_PREVIEW factory is NULL!!!!"); |
| } |
| #else |
| if (factory != NULL) { |
| m_requestMgr->setRequestsInfo(HAL_STREAM_ID_PREVIEW, factory); |
| m_requestMgr->setRequestsInfo(HAL_STREAM_ID_VIDEO, factory); |
| m_requestMgr->setRequestsInfo(HAL_STREAM_ID_CALLBACK, factory); |
| m_requestMgr->setRequestsInfo(HAL_STREAM_ID_RAW, factory); |
| m_requestMgr->setRequestsInfo(HAL_STREAM_ID_ZSL_OUTPUT, factory); |
| |
| /* Set reprocessing frameFactory */ |
| if (m_parameters->isReprocessing() == true) { |
| if (m_frameFactory[FRAME_FACTORY_TYPE_REPROCESSING] != NULL) |
| factory = m_frameFactory[FRAME_FACTORY_TYPE_REPROCESSING]; |
| else |
| CLOGE2("FRAME_FACTORY_TYPE_REPROCESSING factory is NULL!!!!"); |
| } |
| |
| m_requestMgr->setRequestsInfo(HAL_STREAM_ID_JPEG, factory); |
| } else { |
| CLOGE2("FRAME_FACTORY_TYPE_CAPTURE_PREVIEW factory is NULL!!!!"); |
| } |
| #endif |
| |
| return ret; |
| } |
| |
| status_t ExynosCamera3::m_setStreamInfo(camera3_stream_configuration *streamList) |
| { |
| int ret = OK; |
| int id = 0; |
| |
| CLOGD2("In"); |
| |
| /* sanity check */ |
| if (streamList == NULL) { |
| CLOGE2("NULL stream configuration"); |
| return BAD_VALUE; |
| } |
| |
| if (streamList->streams == NULL) { |
| CLOGE2("NULL stream list"); |
| return BAD_VALUE; |
| } |
| |
| if (streamList->num_streams < 1) { |
| CLOGE2("Bad number of streams requested: %d", streamList->num_streams); |
| return BAD_VALUE; |
| } |
| |
| /* check input stream */ |
| camera3_stream_t *inputStream = NULL; |
| for (size_t i = 0; i < streamList->num_streams; i++) { |
| camera3_stream_t *newStream = streamList->streams[i]; |
| if (newStream == NULL) { |
| CLOGE2("Stream index %zu was NULL", i); |
| return BAD_VALUE; |
| } |
| // for debug |
| CLOGD2("Stream(%p), ID(%zu), type(%d), usage(%#x) format(%#x) w(%d),h(%d)", |
| newStream, i, newStream->stream_type, newStream->usage, newStream->format, newStream->width, newStream->height); |
| |
| if ((newStream->stream_type == CAMERA3_STREAM_INPUT) || |
| (newStream->stream_type == CAMERA3_STREAM_BIDIRECTIONAL)) { |
| if (inputStream != NULL) { |
| CLOGE2("Multiple input streams requested!"); |
| return BAD_VALUE; |
| } |
| inputStream = newStream; |
| } |
| |
| /* HACK : check capture stream */ |
| if (newStream->format == 0x21) |
| isCaptureConfig = true; |
| |
| /* HACK : check recording stream */ |
| if ((newStream->format == HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED) |
| && (newStream->usage & GRALLOC_USAGE_HW_VIDEO_ENCODER)) { |
| CLOGI2("recording stream checked"); |
| isRecordingConfig = true; |
| } |
| |
| // TODO: format validation |
| } |
| |
| /* 1. Invalidate all current streams */ |
| List<int> keylist; |
| List<int>::iterator iter; |
| ExynosCameraStream *stream = NULL; |
| keylist.clear(); |
| m_streamManager->getStreamKeys(&keylist); |
| for (iter = keylist.begin(); iter != keylist.end(); iter++) { |
| m_streamManager->getStream(*iter, &stream); |
| stream->setRegisterStream(EXYNOS_STREAM::HAL_STREAM_STS_INVALID); |
| stream->setRegisterBuffer(EXYNOS_STREAM::HAL_STREAM_STS_UNREGISTERED); |
| } |
| |
| /* 2. Remove dead streams */ |
| keylist.clear(); |
| stream = NULL; |
| id = 0; |
| EXYNOS_STREAM::STATE registerStream = EXYNOS_STREAM::HAL_STREAM_STS_INIT; |
| m_streamManager->getStreamKeys(&keylist); |
| for (iter = keylist.begin(); iter != keylist.end(); iter++) { |
| m_streamManager->getStream(*iter, &stream); |
| ret = stream->getRegisterStream(®isterStream); |
| if (registerStream == EXYNOS_STREAM::HAL_STREAM_STS_INVALID){ |
| ret = stream->getID(&id); |
| if (id < 0) { |
| CLOGE2("getID failed id(%d)", id); |
| continue; |
| } |
| m_streamManager->deleteStream(id); |
| } |
| } |
| |
| /* 3. Update stream info */ |
| for (size_t i = 0; i < streamList->num_streams; i++) { |
| stream = NULL; |
| camera3_stream_t *newStream = streamList->streams[i]; |
| if (newStream->priv == NULL) { |
| /* new stream case */ |
| ret = m_enumStreamInfo(newStream); |
| if (ret) { |
| CLOGE2("Register stream failed %p", newStream); |
| return ret; |
| } |
| } else { |
| /* Existing stream, reuse current stream */ |
| stream = static_cast<ExynosCameraStream*>(newStream->priv); |
| stream->setRegisterStream(EXYNOS_STREAM::HAL_STREAM_STS_VALID); |
| } |
| } |
| |
| /* 4. Debug */ |
| CLOGD2("Out"); |
| return ret; |
| } |
| |
| status_t ExynosCamera3::m_enumStreamInfo(camera3_stream_t *stream) |
| { |
| CLOGD2("In"); |
| int ret = OK; |
| ExynosCameraStream *newStream = NULL; |
| int id = 0; |
| int actualFormat = 0; |
| int planeCount = 0; |
| int requestBuffer = 0; |
| int outputPortId = 0; |
| EXYNOS_STREAM::STATE registerStream; |
| EXYNOS_STREAM::STATE registerBuffer; |
| |
| registerStream = EXYNOS_STREAM::HAL_STREAM_STS_VALID; |
| registerBuffer = EXYNOS_STREAM::HAL_STREAM_STS_UNREGISTERED; |
| |
| if (stream == NULL) { |
| CLOGE2("stream is NULL."); |
| return INVALID_OPERATION; |
| } |
| |
| /* Update gralloc usage */ |
| switch (stream->stream_type) { |
| case CAMERA3_STREAM_INPUT: |
| stream->usage |= GRALLOC_USAGE_HW_CAMERA_READ; |
| break; |
| case CAMERA3_STREAM_OUTPUT: |
| stream->usage |= GRALLOC_USAGE_HW_CAMERA_WRITE; |
| break; |
| case CAMERA3_STREAM_BIDIRECTIONAL: |
| stream->usage |= (GRALLOC_USAGE_HW_CAMERA_READ | GRALLOC_USAGE_HW_CAMERA_WRITE); |
| break; |
| default: |
| CLOGE2("Invalid stream_type %d", stream->stream_type); |
| break; |
| } |
| |
| switch (stream->stream_type) { |
| case CAMERA3_STREAM_OUTPUT: |
| // TODO: split this routine to function |
| switch (stream->format) { |
| case HAL_PIXEL_FORMAT_BLOB: |
| CLOGD2("HAL_PIXEL_FORMAT_BLOB format(%#x) usage(%#x) stream_type(%#x)", stream->format, stream->usage, stream->stream_type); |
| id = HAL_STREAM_ID_JPEG; |
| actualFormat = HAL_PIXEL_FORMAT_BLOB; |
| planeCount = 1; |
| outputPortId = 0; |
| requestBuffer = m_exynosconfig->current->bufInfo.num_request_jpeg_buffers; |
| break; |
| case HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED: |
| if (stream->usage & GRALLOC_USAGE_HW_TEXTURE || stream->usage & GRALLOC_USAGE_HW_COMPOSER) { |
| CLOGD2("GRALLOC_USAGE_HW_TEXTURE foramt(%#x) usage(%#x) stream_type(%#x)", stream->format, stream->usage, stream->stream_type); |
| id = HAL_STREAM_ID_PREVIEW; |
| actualFormat = HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP_M; |
| planeCount = 2; |
| outputPortId = m_streamManager->getYuvStreamCount(); |
| requestBuffer = m_exynosconfig->current->bufInfo.num_request_preview_buffers; |
| } else if(stream->usage & GRALLOC_USAGE_HW_VIDEO_ENCODER) { |
| CLOGD2("GRALLOC_USAGE_HW_VIDEO_ENCODER format(%#x) usage(%#x) stream_type(%#x)", stream->format, stream->usage, stream->stream_type); |
| id = HAL_STREAM_ID_VIDEO; |
| actualFormat = HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP_M; /* NV12M */ |
| planeCount = 2; |
| outputPortId = m_streamManager->getYuvStreamCount(); |
| requestBuffer = m_exynosconfig->current->bufInfo.num_request_video_buffers; |
| } else if(stream->usage & GRALLOC_USAGE_HW_CAMERA_ZSL) { |
| CLOGD2("GRALLOC_USAGE_HW_CAMERA_ZSL format(%#x) usage(%#x) stream_type(%#x)", stream->format, stream->usage, stream->stream_type); |
| id = HAL_STREAM_ID_ZSL_OUTPUT; |
| actualFormat = HAL_PIXEL_FORMAT_RAW16; |
| planeCount = 1; |
| requestBuffer = m_exynosconfig->current->bufInfo.num_request_raw_buffers; |
| } else { |
| CLOGE2("HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED unknown usage(%#x) format(%#x) stream_type(%#x)", stream->usage, stream->format, stream->stream_type); |
| ret = BAD_VALUE; |
| goto func_err; |
| break; |
| } |
| break; |
| case HAL_PIXEL_FORMAT_YCbCr_420_888: |
| CLOGD2("HAL_PIXEL_FORMAT_YCbCr_420_888 format(%#x) usage(%#x) stream_type(%#x)", stream->format, stream->usage, stream->stream_type); |
| id = HAL_STREAM_ID_CALLBACK; |
| actualFormat = HAL_PIXEL_FORMAT_YCrCb_420_SP; |
| planeCount = 1; |
| outputPortId = m_streamManager->getYuvStreamCount(); |
| requestBuffer = m_exynosconfig->current->bufInfo.num_request_callback_buffers; |
| break; |
| /* case HAL_PIXEL_FORMAT_RAW_SENSOR: */ |
| case HAL_PIXEL_FORMAT_RAW16: |
| CLOGD2("HAL_PIXEL_FORMAT_RAW_XXX format(%#x) usage(%#x) stream_type(%#x)", stream->format, stream->usage, stream->stream_type); |
| id = HAL_STREAM_ID_RAW; |
| actualFormat = HAL_PIXEL_FORMAT_RAW16; |
| planeCount = 1; |
| outputPortId = 0; |
| requestBuffer = m_exynosconfig->current->bufInfo.num_request_raw_buffers; |
| break; |
| default: |
| CLOGE2("Not supported image format(%#x) usage(%#x) stream_type(%#x)", stream->format, stream->usage, stream->stream_type); |
| ret = BAD_VALUE; |
| goto func_err; |
| break; |
| } |
| break; |
| case CAMERA3_STREAM_INPUT: |
| case CAMERA3_STREAM_BIDIRECTIONAL: |
| switch (stream->format) { |
| /* case HAL_PIXEL_FORMAT_RAW_SENSOR: */ |
| case HAL_PIXEL_FORMAT_RAW16: |
| case HAL_PIXEL_FORMAT_RAW_OPAQUE: |
| CLOGD2("HAL_PIXEL_FORMAT_RAW_XXX format(%#x) usage(%#x) stream_type(%#x)", stream->format, stream->usage, stream->stream_type); |
| id = HAL_STREAM_ID_RAW; |
| actualFormat = HAL_PIXEL_FORMAT_RAW16; |
| planeCount = 1; |
| requestBuffer = m_exynosconfig->current->bufInfo.num_request_raw_buffers; |
| break; |
| case HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED: |
| if (stream->usage & GRALLOC_USAGE_HW_CAMERA_ZSL) { |
| CLOGD2("GRALLOC_USAGE_HW_CAMERA_ZSL foramt(%#x) usage(%#x) stream_type(%#x)", stream->format, stream->usage, stream->stream_type); |
| id = HAL_STREAM_ID_ZSL_INPUT; |
| actualFormat = HAL_PIXEL_FORMAT_RAW16; |
| planeCount = 1; |
| requestBuffer = m_exynosconfig->current->bufInfo.num_request_raw_buffers; |
| break; |
| } else { |
| CLOGE2("HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED unknown usage(%#x) format(%#x) stream_type(%#x)", stream->usage, stream->format, stream->stream_type); |
| ret = BAD_VALUE; |
| goto func_err; |
| } |
| break; |
| default: |
| CLOGE2("Not supported image format(%#x) usage(%#x) stream_type(%#x)", stream->format, stream->usage, stream->stream_type); |
| goto func_err; |
| } |
| break; |
| default: |
| CLOGE2("Unknown stream_type(%#x) format(%#x) usage(%#x)", stream->stream_type, stream->format, stream->usage); |
| ret = BAD_VALUE; |
| goto func_err; |
| } |
| |
| newStream = m_streamManager->createStream(id, stream); |
| if (newStream == NULL) { |
| CLOGE2("createStream is NULL id(%d)", id); |
| goto func_err; |
| } |
| |
| newStream->setRegisterStream(registerStream); |
| newStream->setRegisterBuffer(registerBuffer); |
| newStream->setFormat(actualFormat); |
| newStream->setPlaneCount(planeCount); |
| newStream->setOutputPortId(outputPortId); |
| newStream->setRequestBuffer(requestBuffer); |
| |
| func_err: |
| CLOGD2("Out"); |
| |
| return ret; |
| |
| } |
| |
| void ExynosCamera3::m_createManagers(void) |
| { |
| if (!m_streamManager) { |
| m_streamManager = new ExynosCameraStreamManager(m_cameraId); |
| CLOGD2("Stream Manager created"); |
| } |
| |
| /* Create buffer manager */ |
| if (!m_fliteBufferMgr) |
| m_createInternalBufferManager(&m_fliteBufferMgr, "INTERNAL_BAYER_BUF"); |
| if (!m_3aaBufferMgr) |
| m_createInternalBufferManager(&m_3aaBufferMgr, "3AA_IN_BUF"); |
| if (!m_ispBufferMgr) |
| m_createInternalBufferManager(&m_ispBufferMgr, "ISP_IN_BUF"); |
| if (!m_yuvCaptureBufferMgr) |
| m_createInternalBufferManager(&m_yuvCaptureBufferMgr, "YUV_CAPTURE_IN_BUF"); |
| if (!m_internalScpBufferMgr) |
| m_createInternalBufferManager(&m_internalScpBufferMgr, "INTERNAL_SCP_BUF"); |
| if (!m_vraBufferMgr) |
| m_createInternalBufferManager(&m_vraBufferMgr, "VRA_BUF"); |
| if (!m_gscBufferMgr) |
| m_createInternalBufferManager(&m_gscBufferMgr, "GSC_BUF"); |
| if (!m_ispReprocessingBufferMgr) |
| m_createInternalBufferManager(&m_ispReprocessingBufferMgr, "ISP_RE_BUF"); |
| if (!m_yuvCaptureReprocessingBufferMgr) |
| m_createInternalBufferManager(&m_yuvCaptureReprocessingBufferMgr, "YUV_CAPTURE_RE_BUF"); |
| if (!m_thumbnailBufferMgr) |
| m_createInternalBufferManager(&m_thumbnailBufferMgr, "THUMBNAIL_BUF"); |
| |
| } |
| |
| void ExynosCamera3::m_createThreads(void) |
| { |
| m_mainThread = new mainCameraThread(this, &ExynosCamera3::m_mainThreadFunc, "m_mainThreadFunc"); |
| CLOGD2("DEBUG(%s):Main thread created", __FUNCTION__); |
| |
| /* m_previewStreamXXXThread is for seperated frameDone each own handler */ |
| m_previewStreamBayerThread = new mainCameraThread(this, &ExynosCamera3::m_previewStreamBayerPipeThreadFunc, "PreviewBayerThread"); |
| CLOGD2("Bayer Preview stream thread created"); |
| |
| m_previewStream3AAThread = new mainCameraThread(this, &ExynosCamera3::m_previewStream3AAPipeThreadFunc, "Preview3AAThread"); |
| CLOGD2("3AA Preview stream thread created"); |
| |
| m_previewStreamVRAThread = new mainCameraThread(this, &ExynosCamera3::m_previewStreamVRAPipeThreadFunc, "PreviewVRAThread"); |
| CLOGD2("VRA Preview stream thread created"); |
| |
| m_duplicateBufferThread = new mainCameraThread(this, &ExynosCamera3::m_duplicateBufferThreadFunc, "DuplicateThread"); |
| CLOGD2("Duplicate buffer thread created"); |
| |
| m_captureStreamThread = new mainCameraThread(this, &ExynosCamera3::m_captureStreamThreadFunc, "CaptureThread"); |
| CLOGD2("Capture stream thread created"); |
| |
| m_setBuffersThread = new mainCameraThread(this, &ExynosCamera3::m_setBuffersThreadFunc, "setBuffersThread"); |
| CLOGD2("Buffer allocation thread created"); |
| |
| m_framefactoryCreateThread = new mainCameraThread(this, &ExynosCamera3::m_frameFactoryCreateThreadFunc, "FrameFactoryInitThread"); |
| CLOGD2("FrameFactoryInitThread created"); |
| |
| m_selectBayerThread = new mainCameraThread(this, &ExynosCamera3::m_selectBayerThreadFunc, "SelectBayerThreadFunc"); |
| CLOGD2("SelectBayerThread created"); |
| |
| m_captureThread = new mainCameraThread(this, &ExynosCamera3::m_captureThreadFunc, "m_captureThreadFunc"); |
| CLOGD2("FrameFactoryInitThread created"); |
| |
| m_reprocessingFrameFactoryStartThread = new mainCameraThread(this, &ExynosCamera3::m_reprocessingFrameFactoryStartThreadFunc, "m_reprocessingFrameFactoryStartThread"); |
| CLOGD2("m_reprocessingFrameFactoryStartThread created"); |
| |
| m_startPictureBufferThread = new mainCameraThread(this, &ExynosCamera3::m_startPictureBufferThreadFunc, "startPictureBufferThread"); |
| CLOGD2("startPictureBufferThread created"); |
| |
| m_frameFactoryStartThread = new mainCameraThread(this, &ExynosCamera3::m_frameFactoryStartThreadFunc, "FrameFactoryStartThread"); |
| CLOGD2("FrameFactoryStartThread created"); |
| |
| m_internalFrameThread = new mainCameraThread(this, &ExynosCamera3::m_internalFrameThreadFunc, "InternalFrameThread"); |
| CLOGD2("Internal Frame Handler Thread created"); |
| |
| m_monitorThread = new mainCameraThread(this, &ExynosCamera3::m_monitorThreadFunc, "MonitorThread"); |
| CLOGD2("MonitorThread created"); |
| } |
| |
| ExynosCamera3::~ExynosCamera3() |
| { |
| this->release(); |
| } |
| |
| void ExynosCamera3::release() |
| { |
| CLOGI2("-IN-"); |
| int ret = 0; |
| // m_mainFrameThread->requestExitAndWait(); |
| |
| m_releaseBuffers(); |
| |
| if (m_fliteBufferMgr!= NULL) { |
| delete m_fliteBufferMgr; |
| m_fliteBufferMgr = NULL; |
| } |
| |
| if (m_3aaBufferMgr != NULL) { |
| delete m_3aaBufferMgr; |
| m_3aaBufferMgr = NULL; |
| } |
| |
| if (m_ispBufferMgr != NULL) { |
| delete m_ispBufferMgr; |
| m_ispBufferMgr = NULL; |
| } |
| |
| if (m_yuvCaptureBufferMgr != NULL) { |
| delete m_yuvCaptureBufferMgr; |
| m_yuvCaptureBufferMgr = NULL; |
| } |
| |
| if (m_vraBufferMgr != NULL) { |
| delete m_vraBufferMgr; |
| m_vraBufferMgr = NULL; |
| } |
| |
| if (m_gscBufferMgr != NULL) { |
| delete m_gscBufferMgr; |
| m_gscBufferMgr = NULL; |
| } |
| |
| if (m_yuvCaptureReprocessingBufferMgr != NULL) { |
| delete m_yuvCaptureReprocessingBufferMgr; |
| m_yuvCaptureReprocessingBufferMgr = NULL; |
| } |
| |
| if (m_internalScpBufferMgr != NULL) { |
| delete m_internalScpBufferMgr; |
| m_internalScpBufferMgr = NULL; |
| } |
| |
| if (m_ispReprocessingBufferMgr != NULL) { |
| delete m_ispReprocessingBufferMgr; |
| m_ispReprocessingBufferMgr = NULL; |
| } |
| |
| if (m_thumbnailBufferMgr != NULL) { |
| delete m_thumbnailBufferMgr; |
| m_thumbnailBufferMgr = NULL; |
| } |
| |
| if (m_skipBufferMgr != NULL) { |
| delete m_skipBufferMgr; |
| m_skipBufferMgr = NULL; |
| } |
| |
| if (m_ionAllocator != NULL) { |
| delete m_ionAllocator; |
| m_ionAllocator = NULL; |
| } |
| |
| if (m_shotDoneQ != NULL) { |
| delete m_shotDoneQ; |
| m_shotDoneQ = NULL; |
| } |
| |
| for (int i = 0; i < MAX_PIPE_NUM; i++) { |
| if (m_pipeFrameDoneQ[i] != NULL) { |
| delete m_pipeFrameDoneQ[i]; |
| m_pipeFrameDoneQ[i] = NULL; |
| } |
| } |
| |
| if (m_duplicateBufferDoneQ != NULL) { |
| delete m_duplicateBufferDoneQ; |
| m_duplicateBufferDoneQ = NULL; |
| } |
| |
| /* 4. release queues*/ |
| if (m_pipeCaptureFrameDoneQ != NULL) { |
| delete m_pipeCaptureFrameDoneQ; |
| m_pipeCaptureFrameDoneQ = NULL; |
| } |
| |
| if (m_reprocessingDoneQ != NULL) { |
| delete m_reprocessingDoneQ; |
| m_reprocessingDoneQ = NULL; |
| } |
| |
| if (m_internalFrameDoneQ != NULL) { |
| delete m_internalFrameDoneQ; |
| m_internalFrameDoneQ = NULL; |
| } |
| |
| if (m_frameFactoryQ != NULL) { |
| delete m_frameFactoryQ; |
| m_frameFactoryQ = NULL; |
| } |
| |
| if (m_selectBayerQ != NULL) { |
| delete m_selectBayerQ; |
| m_selectBayerQ = NULL; |
| } |
| |
| if (m_captureQ != NULL) { |
| delete m_captureQ; |
| m_captureQ = NULL; |
| } |
| |
| if (m_frameMgr != NULL) { |
| delete m_frameMgr; |
| m_frameMgr = NULL; |
| } |
| |
| if (m_streamManager != NULL) { |
| delete m_streamManager; |
| m_streamManager = NULL; |
| } |
| |
| if (m_requestMgr!= NULL) { |
| delete m_requestMgr; |
| m_requestMgr = NULL; |
| } |
| |
| m_deinitFrameFactory(); |
| |
| #if 1 |
| if (m_parameters != NULL) { |
| delete m_parameters; |
| m_parameters = NULL; |
| } |
| |
| if (m_metadataConverter != NULL) { |
| delete m_parameters; |
| m_parameters = NULL; |
| } |
| |
| if (m_captureSelector != NULL) { |
| delete m_captureSelector; |
| m_captureSelector = NULL; |
| } |
| |
| if (m_captureZslSelector != NULL) { |
| delete m_captureZslSelector; |
| m_captureZslSelector = NULL; |
| } |
| |
| if (m_sccCaptureSelector != NULL) { |
| delete m_sccCaptureSelector; |
| m_sccCaptureSelector = NULL; |
| } |
| #endif |
| |
| // TODO: clean up |
| // m_resultBufferVectorSet |
| // m_processList |
| // m_postProcessList |
| // m_pipeFrameDoneQ |
| CLOGI2("-OUT-"); |
| } |
| |
| status_t ExynosCamera3::initilizeDevice(const camera3_callback_ops *callbackOps) |
| { |
| status_t ret = NO_ERROR; |
| CLOGD2("-IN-"); |
| |
| /* set callback ops */ |
| m_requestMgr->setCallbackOps(callbackOps); |
| |
| if (m_parameters->isReprocessing() == true) { |
| ExynosCameraBufferManager *bufMgr = NULL; |
| if (m_parameters->isUseYuvReprocessing() == true |
| && m_parameters->isUsing3acForIspc() == true) |
| bufMgr = m_yuvCaptureBufferMgr; |
| else |
| bufMgr = m_fliteBufferMgr; |
| |
| if (m_captureSelector == NULL) { |
| m_captureSelector = new ExynosCameraFrameSelector(m_parameters, bufMgr, m_frameMgr); |
| ret = m_captureSelector->setFrameHoldCount(REPROCESSING_BAYER_HOLD_COUNT); |
| if (ret < 0) |
| CLOGE2("m_captureSelector setFrameHoldCount(%d) is fail", REPROCESSING_BAYER_HOLD_COUNT); |
| } |
| |
| if (m_captureZslSelector == NULL) { |
| m_captureZslSelector = new ExynosCameraFrameSelector(m_parameters, m_bayerBufferMgr, m_frameMgr); |
| ret = m_captureZslSelector->setFrameHoldCount(REPROCESSING_BAYER_HOLD_COUNT); |
| if (ret < 0) |
| CLOGE2("m_captureZslSelector setFrameHoldCount(%d) is fail", REPROCESSING_BAYER_HOLD_COUNT); |
| } |
| } else { |
| if (m_sccCaptureSelector == NULL) { |
| ExynosCameraBufferManager *bufMgr = NULL; |
| |
| if (m_parameters->isSccCapture() == true |
| || m_parameters->isUsing3acForIspc() == true) { |
| /* TODO: Dynamic select buffer manager for capture */ |
| bufMgr = m_yuvCaptureBufferMgr; |
| } |
| |
| m_sccCaptureSelector = new ExynosCameraFrameSelector(m_parameters, bufMgr, m_frameMgr); |
| } |
| } |
| |
| m_framefactoryCreateThread->run(); |
| m_frameMgr->start(); |
| |
| m_startPictureBufferThread->run(); |
| |
| /* |
| * NOTICE: Join is to avoid dual scanario's problem. |
| * The problem is that back camera's EOS was not finished, but front camera opened. |
| * Two instance was actually different but driver accepts same instance. |
| */ |
| m_framefactoryCreateThread->join(); |
| return ret; |
| } |
| |
| status_t ExynosCamera3::releaseDevice(void) |
| { |
| status_t ret = NO_ERROR; |
| CLOGD("DEBUG(%s[%d])", __FUNCTION__, __LINE__); |
| |
| m_setBuffersThread->requestExitAndWait(); |
| m_framefactoryCreateThread->requestExitAndWait(); |
| m_monitorThread->requestExitAndWait(); |
| m_previewStreamBayerThread->requestExitAndWait(); |
| m_previewStream3AAThread->requestExitAndWait(); |
| m_previewStreamVRAThread->requestExitAndWait(); |
| m_duplicateBufferThread->requestExitAndWait(); |
| m_internalFrameThread->requestExitAndWait(); |
| m_mainThread->requestExitAndWait(); |
| m_selectBayerThread->requestExitAndWait(); |
| |
| if (m_shotDoneQ != NULL) |
| m_shotDoneQ->release(); |
| |
| if (m_flushFlag == false) |
| flush(); |
| |
| ret = m_clearList(&m_processList, &m_processLock); |
| if (ret < 0) { |
| CLOGE2("m_clearList fail"); |
| return ret; |
| } |
| |
| /* initialize frameQ */ |
| for (int i = 0; i < MAX_PIPE_NUM; i++) { |
| if (m_pipeFrameDoneQ[i] != NULL) { |
| m_pipeFrameDoneQ[i]->release(); |
| m_pipeFrameDoneQ[i] = NULL; |
| } |
| } |
| m_reprocessingDoneQ->release(); |
| m_pipeCaptureFrameDoneQ->release(); |
| m_duplicateBufferDoneQ->release(); |
| |
| /* internal frame */ |
| m_internalFrameDoneQ->release(); |
| |
| m_frameMgr->stop(); |
| m_frameMgr->deleteAllFrame(); |
| |
| return ret; |
| } |
| |
| status_t ExynosCamera3::construct_default_request_settings(camera_metadata_t **request, int type) |
| { |
| Mutex::Autolock l(m_requestLock); |
| factory_handler_t frameCreateHandler; |
| factory_donehandler_t frameDoneHandler; |
| ExynosCamera3FrameFactory *factory = NULL; |
| |
| CLOGD2("Type(%d)", type); |
| if ((type < 0) || (type >= CAMERA3_TEMPLATE_COUNT)) { |
| CLOGE2("Unknown request settings template: %d", type); |
| return -ENODEV; |
| } |
| |
| m_requestMgr->constructDefaultRequestSettings(type, request); |
| |
| CLOGI2("-OUT-"); |
| return OK; |
| } |
| |
| status_t ExynosCamera3::configureStreams(camera3_stream_configuration *stream_list) |
| { |
| Mutex::Autolock l(m_requestLock); |
| |
| status_t ret = NO_ERROR; |
| EXYNOS_STREAM::STATE registerStream = EXYNOS_STREAM::HAL_STREAM_STS_INIT; |
| EXYNOS_STREAM::STATE registerbuffer = EXYNOS_STREAM::HAL_STREAM_STS_INIT; |
| exynos_camera_buffer_type_t type = EXYNOS_CAMERA_BUFFER_ION_NONCACHED_TYPE; |
| buffer_manager_allocation_mode_t allocMode = BUFFER_MANAGER_ALLOCATION_ATONCE; |
| int id = 0; |
| unsigned int bytesPerLine[EXYNOS_CAMERA_BUFFER_MAX_PLANES] = {0}; |
| unsigned int planeSize[EXYNOS_CAMERA_BUFFER_MAX_PLANES] = {0}; |
| int planeCount, width, height, maxBufferCount, startIndex; |
| CameraParameters parameter; |
| bool updateSize = true; |
| int streamPixelFormat = 0; |
| int streamPlaneCount = 0; |
| int outputPortId = 0; |
| int currentConfigMode = m_parameters->getConfigMode(); |
| |
| /* prepare flite count init */ |
| m_prepareFliteCnt = 0; |
| |
| CLOGD2("-IN-"); |
| |
| /* sanity check for stream_list */ |
| if (stream_list == NULL) { |
| CLOGE2("NULL stream configuration"); |
| return BAD_VALUE; |
| } |
| |
| if (stream_list->streams == NULL) { |
| CLOGE2("NULL stream list"); |
| return BAD_VALUE; |
| } |
| |
| if (stream_list->num_streams < 1) { |
| CLOGE2("Bad number of streams requested: %d", stream_list->num_streams); |
| return BAD_VALUE; |
| } |
| |
| if (stream_list->operation_mode == CAMERA3_STREAM_CONFIGURATION_CONSTRAINED_HIGH_SPEED_MODE) { |
| ALOGI("INFO(%s[%d]):High speed mode is configured. StreamCount %d", |
| __FUNCTION__, __LINE__, stream_list->num_streams); |
| m_parameters->setConfigMode(CONFIG_MODE::HIGHSPEED_120); |
| m_exynosconfig = m_parameters->getConfig(); |
| m_flagBayerRequest = false; |
| } else { |
| m_parameters->setConfigMode(CONFIG_MODE::NORMAL); |
| m_exynosconfig = m_parameters->getConfig(); |
| m_flagBayerRequest = false; |
| } |
| |
| /* start allocation of internal buffers */ |
| if (m_checkConfigStream == false) { |
| m_setBuffersThread->run(PRIORITY_DEFAULT); |
| } |
| |
| ret = m_streamManager->setConfig(m_exynosconfig); |
| if (ret) { |
| CLOGE2("setMaxBuffers() failed!!"); |
| return ret; |
| } |
| ret = m_setStreamInfo(stream_list); |
| if (ret) { |
| CLOGE2("setStreams() failed!!"); |
| return ret; |
| } |
| |
| /* flush request Mgr */ |
| m_requestMgr->flush(); |
| |
| /* HACK :: restart frame factory */ |
| if (m_checkConfigStream == true || |
| ((isCaptureConfig == true) && (stream_list->num_streams == 1)) |
| || ((isRecordingConfig == true) && (recordingEnabled == false)) |
| || ((isRecordingConfig == false) && (recordingEnabled == true))) { |
| CLOGI2("restart frame factory isCaptureConfig(%d), isRecordingConfig(%d), stream_list->num_streams(%d)", |
| isCaptureConfig, isRecordingConfig, stream_list->num_streams); |
| |
| isCaptureConfig = false; |
| /* In case of preview with Recording, enter this block even if not restart */ |
| if (m_checkConfigStream == true) |
| isRestarted = true; |
| |
| recordingEnabled = false; |
| isRecordingConfig = false; |
| |
| if (m_flagStartReprocessingFrameFactory == true) |
| m_stopReprocessingFrameFactory(m_frameFactory[FRAME_FACTORY_TYPE_REPROCESSING]); |
| |
| if (m_flagStartFrameFactory == true) { |
| m_stopFrameFactory(m_frameFactory[FRAME_FACTORY_TYPE_CAPTURE_PREVIEW]); |
| m_removeInternalFrames(&m_processList, &m_processLock); |
| m_clearList(&m_captureProcessList, &m_captureProcessLock); |
| } |
| |
| if (m_parameters->isReprocessing() == true) { |
| m_captureSelector->release(); |
| m_captureZslSelector->release(); |
| } else { |
| m_sccCaptureSelector->release(); |
| } |
| |
| /* restart frame manager */ |
| m_frameMgr->stop(); |
| m_frameMgr->deleteAllFrame(); |
| m_frameMgr->start(); |
| |
| /* Pull all internal buffers */ |
| for (int bufIndex = 0; bufIndex < m_fliteBufferMgr->getAllocatedBufferCount(); bufIndex++) |
| ret = m_putBuffers(m_fliteBufferMgr, bufIndex); |
| for (int bufIndex = 0; bufIndex < m_3aaBufferMgr->getAllocatedBufferCount(); bufIndex++) |
| ret = m_putBuffers(m_3aaBufferMgr, bufIndex); |
| for (int bufIndex = 0; bufIndex < m_internalScpBufferMgr->getAllocatedBufferCount(); bufIndex++) |
| ret = m_putBuffers(m_internalScpBufferMgr, bufIndex); |
| for (int bufIndex = 0; bufIndex < m_yuvCaptureBufferMgr->getAllocatedBufferCount(); bufIndex++) |
| ret = m_putBuffers(m_yuvCaptureBufferMgr, bufIndex); |
| for (int bufIndex = 0; bufIndex < m_vraBufferMgr->getAllocatedBufferCount(); bufIndex++) |
| ret = m_putBuffers(m_vraBufferMgr, bufIndex); |
| for (int bufIndex = 0; bufIndex < m_gscBufferMgr->getAllocatedBufferCount(); bufIndex++) |
| ret = m_putBuffers(m_gscBufferMgr, bufIndex); |
| for (int bufIndex = 0; bufIndex < m_ispBufferMgr->getAllocatedBufferCount(); bufIndex++) |
| ret = m_putBuffers(m_ispBufferMgr, bufIndex); |
| |
| if (currentConfigMode != m_parameters->getConfigMode()) { |
| CLOGI("INFO(%s[%d]):ConfigMode is changed. Reallocate the internal buffers. currentConfigMode %d newConfigMode %d", |
| __FUNCTION__, __LINE__, |
| currentConfigMode, m_parameters->getConfigMode()); |
| ret = m_releaseBuffers(); |
| if (ret != NO_ERROR) |
| CLOGE("ERR(%s[%d]):Failed to releaseBuffers. ret %d", |
| __FUNCTION__, __LINE__, ret); |
| |
| m_setBuffersThread->run(PRIORITY_DEFAULT); |
| } |
| } |
| |
| /* clear previous settings */ |
| ret = m_requestMgr->clearPrevRequest(); |
| if (ret) { |
| CLOGE2("clearPrevRequest() failed!!"); |
| return ret; |
| } |
| |
| ret = m_requestMgr->clearPrevShot(); |
| if (ret < 0) { |
| CLOGE2("clearPrevShot() failed!! status(%d)", ret); |
| } |
| |
| /* check flag update size */ |
| updateSize = m_streamManager->findStream(HAL_STREAM_ID_PREVIEW); |
| |
| m_parameters->setSetfileYuvRange(); |
| |
| /* Create service buffer manager at each stream */ |
| for (size_t i = 0; i < stream_list->num_streams; i++) { |
| registerStream = EXYNOS_STREAM::HAL_STREAM_STS_INIT; |
| registerbuffer = EXYNOS_STREAM::HAL_STREAM_STS_INIT; |
| id = -1; |
| |
| camera3_stream_t *newStream = stream_list->streams[i]; |
| ExynosCameraStream *privStreamInfo = static_cast<ExynosCameraStream*>(newStream->priv); |
| privStreamInfo->getID(&id); |
| |
| CLOGI2("list_index(%zu), streamId(%d)", i, id); |
| CLOGD2("stream_type(%d), usage(%x), format(%x), width(%d), height(%d), max_buffers(%d)", |
| newStream->stream_type, newStream->usage, newStream->format, |
| newStream->width, newStream->height, newStream->max_buffers); |
| |
| privStreamInfo->getRegisterBuffer(®isterbuffer); |
| privStreamInfo->getPlaneCount(&streamPlaneCount); |
| privStreamInfo->getFormat(&streamPixelFormat); |
| if (registerbuffer != EXYNOS_STREAM::HAL_STREAM_STS_UNREGISTERED) { |
| CLOGE2("privStreamInfo->registerBuffer state error!!"); |
| return BAD_VALUE; |
| } |
| |
| width = newStream->width; |
| height = newStream->height; |
| |
| privStreamInfo->getRegisterStream(®isterStream); |
| if (registerStream == EXYNOS_STREAM::HAL_STREAM_STS_INVALID) { |
| privStreamInfo->getID(&id); |
| CLOGE2("Invalid stream index(%zu) id(%d)", i, id); |
| ret = BAD_VALUE; |
| break; |
| } |
| |
| privStreamInfo->getRegisterBuffer(®isterbuffer); |
| |
| CLOGD2("streamID(%d) registerStream(%d) registerbuffer(%d)", id, registerStream, registerbuffer); |
| |
| if ((registerStream == EXYNOS_STREAM::HAL_STREAM_STS_VALID) && |
| (registerbuffer == EXYNOS_STREAM::HAL_STREAM_STS_UNREGISTERED)) { |
| ExynosCameraBufferManager *bufferMgr = NULL; |
| switch (id % HAL_STREAM_ID_MAX) { |
| case HAL_STREAM_ID_RAW: |
| CLOGD2("Create buffer manager(RAW)"); |
| ret = m_createServiceBufferManager(&m_bayerBufferMgr, "RAW_STREAM_BUF"); |
| if (ret < 0) { |
| CLOGE2("m_createBufferManager() failed!!"); |
| return ret; |
| } |
| |
| planeCount = streamPlaneCount + 1; |
| planeSize[0] = width * height * 2; |
| CLOGD2("planeCount(%d)+1", streamPlaneCount); |
| CLOGD2("planeSize[0](%d)", planeSize[0]); |
| CLOGD2("bytesPerLine[0](%d)", bytesPerLine[0]); |
| |
| /* set startIndex as the next internal buffer index */ |
| startIndex = m_exynosconfig->current->bufInfo.num_sensor_buffers; |
| maxBufferCount = m_exynosconfig->current->bufInfo.num_bayer_buffers; |
| CLOGD2("(RAW)- maxBufferCount(%d)", maxBufferCount); |
| |
| m_bayerBufferMgr->setAllocator(newStream); |
| m_allocBuffers(m_bayerBufferMgr, planeCount, planeSize, bytesPerLine, startIndex, maxBufferCount, true, false); |
| |
| privStreamInfo->setRegisterBuffer(EXYNOS_STREAM::HAL_STREAM_STS_REGISTERED); |
| privStreamInfo->setBufferManager(m_bayerBufferMgr); |
| CLOGD2("m_bayerBufferMgr - %p", m_bayerBufferMgr); |
| break; |
| case HAL_STREAM_ID_ZSL_OUTPUT: |
| CLOGD2("DEBUG(%s[%d]):Create buffer manager(ZSL)", __FUNCTION__, __LINE__); |
| |
| planeCount = streamPlaneCount + 1; |
| planeSize[0] = width * height * 2; |
| |
| CLOGD2("planeCount %d+1", streamPlaneCount); |
| CLOGD2("planeSize[0] %d", planeSize[0]); |
| CLOGD2("bytesPerLine[0] %d", bytesPerLine[0]); |
| |
| /* set startIndex as the next internal buffer index */ |
| startIndex = NUM_BAYER_BUFFERS; |
| maxBufferCount = m_exynosconfig->current->bufInfo.num_bayer_buffers; |
| |
| privStreamInfo->setRegisterBuffer(EXYNOS_STREAM::HAL_STREAM_STS_REGISTERED); |
| break; |
| case HAL_STREAM_ID_ZSL_INPUT: |
| planeCount = streamPlaneCount + 1; |
| planeSize[0] = width * height * 2; |
| |
| ALOGD("DEBUG(%s[%d]):planeCount %d+1", |
| __FUNCTION__, __LINE__, streamPlaneCount); |
| ALOGD("DEBUG(%s[%d]):planeSize[0] %d", |
| __FUNCTION__, __LINE__, planeSize[0]); |
| ALOGD("DEBUG(%s[%d]):bytesPerLine[0] %d", |
| __FUNCTION__, __LINE__, bytesPerLine[0]); |
| |
| privStreamInfo->setRegisterBuffer(EXYNOS_STREAM::HAL_STREAM_STS_REGISTERED); |
| break; |
| case HAL_STREAM_ID_PREVIEW: |
| |
| ret = privStreamInfo->getOutputPortId(&outputPortId); |
| if (ret != NO_ERROR) { |
| CLOGE("ERR(%s[%d]):Failed to getOutputPortId for PREVIEW stream", |
| __FUNCTION__, __LINE__); |
| return ret; |
| } |
| |
| ret = m_parameters->checkYuvSize(width, height, outputPortId); |
| if (ret != NO_ERROR) { |
| CLOGE("ERR(%s[%d]):Failed to checkYuvSize for PREVIEW stream. size %dx%d outputPortId %d", |
| __FUNCTION__, __LINE__, width, height, outputPortId); |
| return ret; |
| } |
| |
| ret = m_parameters->checkYuvFormat(streamPixelFormat, outputPortId); |
| if (ret != NO_ERROR) { |
| CLOGE("ERR(%s[%d]):Failed to checkYuvFormat for PREVIEW stream. format %x outputPortId %d", |
| __FUNCTION__, __LINE__, streamPixelFormat, outputPortId); |
| return ret; |
| } |
| |
| maxBufferCount = m_exynosconfig->current->bufInfo.num_preview_buffers; |
| CLOGD2("(PREVIEW)- maxBufferCount(%d)", maxBufferCount); |
| ret = m_parameters->setYuvBufferCount(maxBufferCount, outputPortId); |
| if (ret != NO_ERROR) { |
| CLOGE("ERR(%s[%d]):Failed to setYuvBufferCount for PREVIEW stream. maxBufferCount %d outputPortId %d", |
| __FUNCTION__, __LINE__, maxBufferCount, outputPortId); |
| return ret; |
| } |
| |
| CLOGD2("Create buffer manager(PREVIEW)"); |
| ret = m_createServiceBufferManager(&bufferMgr, "PREVIEW_STREAM_BUF"); |
| if (ret != NO_ERROR) { |
| CLOGE2("m_createBufferManager() failed!!"); |
| return ret; |
| } |
| |
| planeCount = streamPlaneCount + 1; |
| planeSize[0] = width * height; |
| planeSize[1] = width * height / 2; |
| CLOGD2("planeCount(%d)+1", streamPlaneCount); |
| CLOGD2("planeSize[0](%d), planeSize[1](%d)", planeSize[0], planeSize[1]); |
| CLOGD2("bytesPerLine[0](%d)", bytesPerLine[0]); |
| |
| bufferMgr->setAllocator(newStream); |
| m_allocBuffers(bufferMgr, planeCount, planeSize, bytesPerLine, maxBufferCount, true, false); |
| |
| privStreamInfo->setRegisterBuffer(EXYNOS_STREAM::HAL_STREAM_STS_REGISTERED); |
| privStreamInfo->setBufferManager(bufferMgr); |
| CLOGD2("previewBufferMgr - %p", bufferMgr); |
| break; |
| case HAL_STREAM_ID_VIDEO: |
| |
| ret = privStreamInfo->getOutputPortId(&outputPortId); |
| if (ret != NO_ERROR) { |
| CLOGE("ERR(%s[%d]):Failed to getOutputPortId for VIDEO stream", |
| __FUNCTION__, __LINE__); |
| return ret; |
| } |
| |
| ret = m_parameters->checkYuvSize(width, height, outputPortId); |
| if (ret != NO_ERROR) { |
| CLOGE("ERR(%s[%d]):Failed to checkYuvSize for VIDEO stream. size %dx%d outputPortId %d", |
| __FUNCTION__, __LINE__, width, height, outputPortId); |
| return ret; |
| } |
| |
| ret = m_parameters->checkYuvFormat(streamPixelFormat, outputPortId); |
| if (ret != NO_ERROR) { |
| CLOGE("ERR(%s[%d]):Failed to checkYuvFormat for VIDEO stream. format %x outputPortId %d", |
| __FUNCTION__, __LINE__, streamPixelFormat, outputPortId); |
| return ret; |
| } |
| |
| maxBufferCount = m_exynosconfig->current->bufInfo.num_recording_buffers; |
| CLOGD2("(VIDEO)- maxBufferCount(%d)", maxBufferCount); |
| ret = m_parameters->setYuvBufferCount(maxBufferCount, outputPortId); |
| if (ret != NO_ERROR) { |
| CLOGE("ERR(%s[%d]):Failed to setYuvBufferCount for VIDEO stream. maxBufferCount %d outputPortId %d", |
| __FUNCTION__, __LINE__, maxBufferCount, outputPortId); |
| return ret; |
| } |
| CLOGD2("Create buffer manager(VIDEO)"); |
| ret = m_createServiceBufferManager(&bufferMgr, "RECORDING_STREAM_BUF"); |
| if (ret != NO_ERROR) { |
| CLOGE2("m_createBufferManager() failed!!"); |
| return ret; |
| } |
| |
| planeCount = streamPlaneCount + 1; |
| planeSize[0] = width * height; |
| planeSize[1] = width * height / 2; |
| |
| bufferMgr->setAllocator(newStream); |
| m_allocBuffers(bufferMgr, planeCount, planeSize, bytesPerLine, maxBufferCount, false, false); |
| |
| privStreamInfo->setRegisterBuffer(EXYNOS_STREAM::HAL_STREAM_STS_REGISTERED); |
| privStreamInfo->setBufferManager(bufferMgr); |
| CLOGD2("recBufferMgr - %p", bufferMgr); |
| break; |
| |
| case HAL_STREAM_ID_JPEG: |
| |
| ret = m_parameters->checkPictureSize(width, height); |
| if (ret != NO_ERROR) { |
| CLOGE("ERR(%s[%d]):Failed to checkPictureSize for JPEG stream. size %dx%d", |
| __FUNCTION__, __LINE__, width, height); |
| return ret; |
| } |
| |
| maxBufferCount = m_exynosconfig->current->bufInfo.num_picture_buffers; |
| CLOGD2("Create buffer manager(JPEG)"); |
| ret = m_createServiceBufferManager(&bufferMgr, "JPEG_STREAM_BUF"); |
| if (ret < 0) { |
| CLOGE2("m_createBufferManager() failed!!"); |
| return ret; |
| } |
| |
| planeCount = streamPlaneCount; |
| planeSize[0] = width * height * 2; |
| |
| CLOGD2("planeCount(%d), planeSize[0](%d), bytesPerLine[0](%d)", |
| streamPlaneCount, planeSize[0], bytesPerLine[0]); |
| |
| bufferMgr->setAllocator(newStream); |
| m_allocBuffers(bufferMgr, planeCount, planeSize, bytesPerLine, maxBufferCount, false, false); |
| |
| CLOGD2("JPEG stream size = %d", planeSize[0]); |
| privStreamInfo->setRegisterBuffer(EXYNOS_STREAM::HAL_STREAM_STS_REGISTERED); |
| privStreamInfo->setBufferManager(bufferMgr); |
| CLOGD2("JpegBufferMgr - %p", bufferMgr); |
| |
| break; |
| case HAL_STREAM_ID_CALLBACK: |
| |
| ret = privStreamInfo->getOutputPortId(&outputPortId); |
| if (ret != NO_ERROR) { |
| CLOGE("ERR(%s[%d]):Failed to getOutputPortId for CALLBACK stream", |
| __FUNCTION__, __LINE__); |
| return ret; |
| } |
| |
| ret = m_parameters->checkYuvSize(width, height, outputPortId); |
| if (ret != NO_ERROR) { |
| CLOGE("ERR(%s[%d]):Failed to checkYuvSize for CALLBACK stream. size %dx%d outputPortId %d", |
| __FUNCTION__, __LINE__, width, height, outputPortId); |
| return ret; |
| } |
| |
| ret = m_parameters->checkYuvFormat(streamPixelFormat, outputPortId); |
| if (ret != NO_ERROR) { |
| CLOGE("ERR(%s[%d]):Failed to checkYuvFormat for CALLBACK stream. format %x outputPortId %d", |
| __FUNCTION__, __LINE__, streamPixelFormat, outputPortId); |
| return ret; |
| } |
| |
| maxBufferCount = m_exynosconfig->current->bufInfo.num_preview_cb_buffers; |
| ret = m_parameters->setYuvBufferCount(maxBufferCount, outputPortId); |
| if (ret != NO_ERROR) { |
| CLOGE("ERR(%s[%d]):Failed to setYuvBufferCount for CALLBACK stream. maxBufferCount %d outputPortId %d", |
| __FUNCTION__, __LINE__, maxBufferCount, outputPortId); |
| return ret; |
| } |
| CLOGD2("Create buffer manager(PREVIEW_CB)"); |
| |
| ret = m_createServiceBufferManager(&bufferMgr, "PREVIEW_CB_STREAM_BUF"); |
| if (ret < 0) { |
| CLOGE2("m_createBufferManager() failed!!"); |
| return ret; |
| } |
| |
| planeCount = streamPlaneCount + 1; |
| planeSize[0] = (width * height * 3) / 2; |
| |
| CLOGD2("planeCount %d", streamPlaneCount); |
| CLOGD2("planeSize[0] %d",planeSize[0]); |
| CLOGD2("bytesPerLine[0] %d",bytesPerLine[0]); |
| |
| bufferMgr->setAllocator(newStream); |
| m_allocBuffers(bufferMgr, planeCount, planeSize, bytesPerLine, maxBufferCount, true, false); |
| privStreamInfo->setRegisterBuffer(EXYNOS_STREAM::HAL_STREAM_STS_REGISTERED); |
| privStreamInfo->setBufferManager(bufferMgr); |
| CLOGD2("preivewCallbackBufferMgr - %p", bufferMgr); |
| |
| break; |
| |
| default: |
| CLOGE2("privStreamInfo->id is invalid !! id(%d)", id); |
| ret = BAD_VALUE; |
| break; |
| } |
| } |
| } |
| |
| /* Do pure bayer always reprocessing */ |
| m_checkConfigStream = true; |
| |
| CLOGD2("-OUT-"); |
| return ret; |
| } |
| |
| status_t ExynosCamera3::registerStreamBuffers(const camera3_stream_buffer_set_t *buffer_set) |
| { |
| /* deprecated function */ |
| if (buffer_set == NULL) { |
| CLOGE2("buffer_set is NULL"); |
| return INVALID_OPERATION; |
| } |
| |
| return NO_ERROR; |
| } |
| |
| status_t ExynosCamera3::processCaptureRequest(camera3_capture_request *request) |
| { |
| Mutex::Autolock l(m_requestLock); |
| ExynosCameraBuffer *buffer = NULL; |
| ExynosCameraFrame *newFrame = NULL; |
| ExynosCameraBuffer dstBuf; |
| ExynosCameraStream *streamInfo = NULL; |
| uint32_t timeOutNs = 60 * 1000000; /* timeout default value is 60ms based on 15fps */ |
| uint32_t waitMaxBlockCnt = 0; |
| status_t ret = NO_ERROR; |
| camera3_stream_t *stream = NULL; |
| EXYNOS_STREAM::STATE registerBuffer = EXYNOS_STREAM::HAL_STREAM_STS_UNREGISTERED; |
| uint32_t minBlockReqCount = 0; |
| uint32_t maxBlockReqCount = 0; |
| CameraMetadata meta; |
| camera_metadata_entry_t entry; |
| |
| CLOGV2("Capture request (%d) #out(%d)", request->frame_number, request->num_output_buffers); |
| |
| /* 1. Wait for allocation completion of internal buffers and creation of frame factory */ |
| m_setBuffersThread->join(); |
| m_framefactoryCreateThread->join(); |
| |
| /* 2. Check the validation of request */ |
| if (request == NULL) { |
| ALOGE("ERR(%s[%d]):NULL request!", __FUNCTION__, __LINE__); |
| ret = BAD_VALUE; |
| goto req_err; |
| } |
| |
| /* m_streamManager->dumpCurrentStreamList(); */ |
| |
| /* 3. Check NULL for service metadata */ |
| if ((request->settings == NULL) && (m_requestMgr->isPrevRequest())) { |
| CLOGE2("Request%d: NULL and no prev request!!", request->frame_number); |
| ret = BAD_VALUE; |
| goto req_err; |
| } |
| |
| /* 4. Check the registeration of input buffer on stream */ |
| if (request->input_buffer != NULL){ |
| stream = request->input_buffer->stream; |
| streamInfo = static_cast<ExynosCameraStream*>(stream->priv); |
| streamInfo->getRegisterBuffer(®isterBuffer); |
| |
| if (registerBuffer != EXYNOS_STREAM::HAL_STREAM_STS_REGISTERED) { |
| CLOGE2("Request %d: Input buffer not from input stream!", request->frame_number); |
| CLOGE2("Bad Request %p, type(%d), format(%x)", request->input_buffer->stream, |
| request->input_buffer->stream->stream_type, request->input_buffer->stream->format); |
| ret = BAD_VALUE; |
| goto req_err; |
| } |
| } |
| |
| /* 5. Check the output buffer count */ |
| if ((request->num_output_buffers < 1) || (request->output_buffers == NULL)) { |
| CLOGE2("Request %d: No output buffers provided!", request->frame_number); |
| ret = BAD_VALUE; |
| goto req_err; |
| } |
| |
| CLOGV2("request->num_output_buffers(%d) frame_number(%d)", |
| request->num_output_buffers, request->frame_number); |
| |
| /* 6. Store request settings |
| * Caution : All information must be copied into internal data structure |
| * before receiving another request from service |
| */ |
| ret = m_pushRequest(request); |
| ret = m_registerStreamBuffers(request); |
| |
| /* 7. Calculate the timeout value for processing request based on actual fps setting */ |
| meta = request->settings; |
| if (request->settings != NULL && meta.exists(ANDROID_CONTROL_AE_TARGET_FPS_RANGE)) { |
| uint32_t minFps = 0, maxFps = 0; |
| entry = meta.find(ANDROID_CONTROL_AE_TARGET_FPS_RANGE); |
| minFps = entry.data.i32[0]; |
| maxFps = entry.data.i32[1]; |
| m_parameters->checkPreviewFpsRange(minFps, maxFps); |
| timeOutNs = (1000 / ((minFps == 0) ? 15 : minFps)) * 1000000; |
| } |
| |
| /* 8. Process initial requests for preparing the stream */ |
| if (request->frame_number == 0 || m_flushFlag == true || isRestarted == true) { |
| isRestarted = false; |
| m_flushFlag = false; |
| m_prepareFliteCnt = m_exynosconfig->current->pipeInfo.prepare[PIPE_FLITE]; |
| m_factoryStartFlag = true; |
| |
| ALOGV("DEBUG(%s[%d]):Start FrameFactory requestKey(%d) m_flushFlag(%d/%d)", |
| __FUNCTION__, __LINE__, request->frame_number, isRestarted, m_flushFlag); |
| m_frameFactoryStartDone = false; |
| m_frameFactoryStartThread->run(); |
| |
| if (m_parameters->isReprocessing() == true && |
| m_flagStartReprocessingFrameFactory == false) { |
| m_frameFactoryStartThread->join(); |
| m_reprocessingFrameFactoryStartThread->run(); |
| } |
| } |
| |
| m_flushWaitEnable = true; |
| |
| minBlockReqCount = m_exynosconfig->current->bufInfo.num_min_block_request; |
| maxBlockReqCount = m_exynosconfig->current->bufInfo.num_max_block_request; |
| waitMaxBlockCnt = minBlockReqCount * 10; |
| |
| /* |
| * Blocked this func if request counts(in HAL) is over than MIN request count. |
| * So we keeps MIN request counts in HAL. |
| * If HAL received too many requests, there are some late reactive problem in case of stopping, appling effects .. etc. |
| * MAX request count is not used now. But it will be used in case that HAL want to receive request as many as MAX request count |
| */ |
| while (m_requestMgr->getRequestCount() > minBlockReqCount && m_flushFlag == false && waitMaxBlockCnt > 0) { |
| if (m_frameFactoryStartDone == false) { |
| m_frameFactoryStartThread->join(); |
| } |
| if (m_parameters->isReprocessing() == true) |
| m_reprocessingFrameFactoryStartThread->join(); |
| status_t waitRet = NO_ERROR; |
| m_captureResultDoneLock.lock(); |
| waitRet = m_captureResultDoneCondition.waitRelative(m_captureResultDoneLock, timeOutNs); |
| if (waitRet == TIMED_OUT) |
| CLOGV2("time out (m_processList:%zu / totalRequestCnt:%d / " |
| "blockReqCount = min:%u, max:%u / waitcnt:%u)", |
| m_processList.size(), m_requestMgr->getRequestCount(), |
| minBlockReqCount, maxBlockReqCount, waitMaxBlockCnt); |
| |
| m_captureResultDoneLock.unlock(); |
| waitMaxBlockCnt--; |
| } |
| |
| req_err: |
| return ret; |
| } |
| |
| void ExynosCamera3::get_metadata_vendor_tag_ops(const camera3_device_t *, vendor_tag_query_ops_t *ops) |
| { |
| ALOGD("DEBUG(%s[%d])", __FUNCTION__, __LINE__); |
| |
| if (ops == NULL) { |
| CLOGE2("ops is NULL"); |
| return; |
| } |
| } |
| |
| status_t ExynosCamera3::flush() |
| { |
| camera3_stream_buffer_t streamBuffer; |
| CameraMetadata result; |
| ExynosCamera3FrameFactory *frameFactory = NULL; |
| ExynosCameraRequest* request = NULL; |
| ResultRequest resultRequest = NULL; |
| ExynosCameraStream *stream = NULL; |
| ExynosCameraBuffer buffer; |
| List<ExynosCameraFrame *> *list = &m_processList; |
| ExynosCameraFrame *curFrame = NULL; |
| List<ExynosCameraFrame *>::iterator r; |
| List<request_info_t *>::iterator requestInfoR; |
| request_info_t *requestInfo = NULL; |
| int bufferIndex; |
| int requestIndex = -1; |
| status_t ret = NO_ERROR; |
| ExynosCameraBufferManager *bufferMgr = NULL; |
| |
| /* |
| * This flag should be set before stoping all pipes, |
| * because other func(like processCaptureRequest) must know call state about flush() entry level |
| */ |
| m_flushFlag = true; |
| m_captureResultDoneCondition.signal(); |
| |
| List<int> *outputStreamId; |
| List<int>::iterator outputStreamIdIter; |
| |
| int streamId = 0; |
| |
| Mutex::Autolock l(m_resultLock); |
| CLOGD2("IN+++", __FUNCTION__, __LINE__); |
| CLOGV2("ProcessListCount(%d)", list->size()); |
| |
| if (m_flushWaitEnable == false) { |
| CLOGD2("No need to wait & flush"); |
| m_stopCompanion(); |
| goto func_exit; |
| } |
| |
| /* Wait for finishing frameFactoryStartThread */ |
| m_frameFactoryStartThread->requestExitAndWait(); |
| m_internalFrameThread->requestExit(); |
| m_mainThread->requestExitAndWait(); |
| |
| m_captureThread->requestExit(); |
| if (m_sccCaptureSelector != NULL) |
| m_sccCaptureSelector->wakeselectDynamicFrames(); |
| m_captureThread->requestExitAndWait(); |
| |
| /* close companion node */ |
| m_stopCompanion(); |
| |
| |
| /* Create frame for the waiting request */ |
| while (m_requestWaitingList.size() > 0) { |
| requestInfoR = m_requestWaitingList.begin(); |
| requestInfo = *requestInfoR; |
| request = requestInfo->request; |
| |
| m_createRequestFrameFunc(request); |
| |
| m_requestWaitingList.erase(requestInfoR); |
| } |
| |
| /* Stop pipeline */ |
| for (int i = 0; i < FRAME_FACTORY_TYPE_MAX; i++) { |
| if (m_frameFactory[i] != NULL) { |
| frameFactory = m_frameFactory[i]; |
| |
| for (int k = i + 1; k < FRAME_FACTORY_TYPE_MAX; k++) { |
| if (frameFactory == m_frameFactory[k]) { |
| CLOGD2("m_frameFactory index(%d) and index(%d) are same instance, set index(%d) = NULL", i, k, k); |
| m_frameFactory[k] = NULL; |
| } |
| } |
| |
| ret = m_stopFrameFactory(m_frameFactory[i]); |
| if (ret < 0) |
| CLOGE2("m_frameFactory[%d] stopPipes fail", i); |
| |
| CLOGD2("m_frameFactory[%d] stopPipes", i); |
| } |
| } |
| |
| m_flagStartReprocessingFrameFactory = false; |
| |
| if (m_captureSelector != NULL) |
| m_captureSelector->release(); |
| if (m_sccCaptureSelector != NULL) |
| m_sccCaptureSelector->release(); |
| |
| /* Wait until duplicateBufferThread stop */ |
| m_duplicateBufferThread->requestExitAndWait(); |
| |
| /* Wait until previewStream3AA/ISPThread stop */ |
| m_previewStreamVRAThread->requestExitAndWait(); |
| m_previewStream3AAThread->requestExitAndWait(); |
| m_previewStreamBayerThread->requestExitAndWait(); |
| |
| /* Check queued requests from camera service */ |
| CLOGV2("ProcessListCount(%d)", list->size()); |
| |
| do { |
| Mutex::Autolock l(m_processLock); |
| while (!list->empty()) { |
| r = list->begin()++; |
| curFrame = *r; |
| if (curFrame == NULL) { |
| CLOGE2("curFrame is empty"); |
| break; |
| } |
| |
| if (curFrame->getFrameType() == FRAME_TYPE_INTERNAL) { |
| m_releaseInternalFrame(curFrame); |
| list->erase(r); |
| curFrame = NULL; |
| |
| continue; |
| } |
| |
| request = m_requestMgr->getServiceRequest(curFrame->getFrameCount()); |
| |
| if (request == NULL) { |
| CLOGE2("request is empty"); |
| list->erase(r); |
| curFrame->decRef(); |
| m_frameMgr->deleteFrame(curFrame); |
| curFrame = NULL; |
| continue; |
| } |
| CLOGV2("framecount(%d)", curFrame->getFrameCount()); |
| |
| /* handle notify */ |
| camera3_notify_msg_t notify; |
| uint64_t timeStamp = 0L; |
| timeStamp = request->getSensorTimestamp(); |
| if (timeStamp == 0L) |
| timeStamp = m_lastFrametime + 15000000; /* set dummy frame time */ |
| notify.type = CAMERA3_MSG_SHUTTER; |
| notify.message.shutter.frame_number = request->getKey(); |
| notify.message.shutter.timestamp = timeStamp; |
| resultRequest = m_requestMgr->createResultRequest(curFrame->getFrameCount(), EXYNOS_REQUEST_RESULT::CALLBACK_NOTIFY_ONLY, NULL, ¬ify); |
| m_requestMgr->callbackSequencerLock(); |
| m_requestMgr->callbackRequest(resultRequest); |
| m_requestMgr->callbackSequencerUnlock(); |
| |
| request = m_requestMgr->getServiceRequest(curFrame->getFrameCount()); |
| if (request == NULL) { |
| CLOGW("WARN(%s[%d]):request is empty", __FUNCTION__, __LINE__); |
| list->erase(r); |
| curFrame->decRef(); |
| m_frameMgr->deleteFrame(curFrame); |
| curFrame = NULL; |
| continue; |
| } |
| |
| CLOGV2("framecount(%d)", curFrame->getFrameCount()); |
| result = request->getResultMeta(); |
| result.update(ANDROID_SENSOR_TIMESTAMP, (int64_t *)&timeStamp, 1); |
| request->setResultMeta(result); |
| |
| request->getAllRequestOutputStreams(&outputStreamId); |
| CLOGI2("outputStreamID->size(%d)", outputStreamId->size()); |
| |
| if (outputStreamId->size() > 0) { |
| outputStreamIdIter = outputStreamId->begin(); |
| bufferIndex = 0; |
| CLOGI("INFO(%s[%d]):outputStreamId->size(%zu)", |
| __FUNCTION__, __LINE__, outputStreamId->size()); |
| for (int i = outputStreamId->size(); i > 0; i--) { |
| CLOGI("INFO(%s[%d]):i(%d) *outputStreamIdIter(%d)", |
| __FUNCTION__, __LINE__, i, *outputStreamIdIter); |
| if (*outputStreamIdIter < 0) |
| break; |
| |
| m_streamManager->getStream(*outputStreamIdIter, &stream); |
| |
| if (stream == NULL) { |
| CLOGE2("stream is NULL"); |
| ret = INVALID_OPERATION; |
| return ret; |
| } |
| |
| stream->getID(&streamId); |
| |
| ret = stream->getStream(&streamBuffer.stream); |
| if (ret < 0) { |
| CLOGE2("getStream is failed, from exynoscamerastream. Id error:HAL_STREAM_ID_PREVIEW"); |
| return ret; |
| } |
| |
| requestIndex = -1; |
| stream->getBufferManager(&bufferMgr); |
| ret = bufferMgr->getBuffer(&requestIndex, EXYNOS_CAMERA_BUFFER_POSITION_IN_HAL, &buffer); |
| if (ret != NO_ERROR) { |
| CLOGE2("Buffer manager getBuffer fail, frameCount(%d), ret(%d)", curFrame->getFrameCount(), ret); |
| } |
| |
| ret = bufferMgr->getHandleByIndex(&streamBuffer.buffer, buffer.index); |
| if (ret != OK) { |
| CLOGE2("Buffer index error(%d)!!", buffer.index); |
| return ret; |
| } |
| |
| /* handle stream buffers */ |
| streamBuffer.status = CAMERA3_BUFFER_STATUS_OK; |
| streamBuffer.acquire_fence = -1; |
| streamBuffer.release_fence = -1; |
| |
| resultRequest = m_requestMgr->createResultRequest(curFrame->getFrameCount(), EXYNOS_REQUEST_RESULT::CALLBACK_BUFFER_ONLY, NULL, NULL); |
| resultRequest->pushStreamBuffer(&streamBuffer); |
| m_requestMgr->callbackSequencerLock(); |
| request->increaseCompleteBufferCount(); |
| m_requestMgr->callbackRequest(resultRequest); |
| m_requestMgr->callbackSequencerUnlock(); |
| |
| bufferIndex++; |
| outputStreamIdIter++; |
| |
| } |
| |
| } |
| |
| CLOGV2("frameCount(%d), request->getNumOfOutputBuffer(%d), result num_output_buffers(%d)", |
| request->getFrameCount(), request->getNumOfOutputBuffer(), bufferIndex); |
| |
| /* frame to complete callback should be removed */ |
| list->erase(r); |
| |
| curFrame->decRef(); |
| |
| m_frameMgr->deleteFrame(curFrame); |
| |
| curFrame = NULL; |
| } |
| } while(0); |
| |
| /* Pull all internal buffers */ |
| for (int bufIndex = 0; bufIndex < m_fliteBufferMgr->getAllocatedBufferCount(); bufIndex++) |
| ret = m_putBuffers(m_fliteBufferMgr, bufIndex); |
| for (int bufIndex = 0; bufIndex < m_3aaBufferMgr->getAllocatedBufferCount(); bufIndex++) |
| ret = m_putBuffers(m_3aaBufferMgr, bufIndex); |
| for (int bufIndex = 0; bufIndex < m_internalScpBufferMgr->getAllocatedBufferCount(); bufIndex++) |
| ret = m_putBuffers(m_internalScpBufferMgr, bufIndex); |
| for (int bufIndex = 0; bufIndex < m_yuvCaptureBufferMgr->getAllocatedBufferCount(); bufIndex++) |
| ret = m_putBuffers(m_yuvCaptureBufferMgr, bufIndex); |
| for (int bufIndex = 0; bufIndex < m_vraBufferMgr->getAllocatedBufferCount(); bufIndex++) |
| ret = m_putBuffers(m_vraBufferMgr, bufIndex); |
| for (int bufIndex = 0; bufIndex < m_gscBufferMgr->getAllocatedBufferCount(); bufIndex++) |
| ret = m_putBuffers(m_gscBufferMgr, bufIndex); |
| for (int bufIndex = 0; bufIndex < m_ispBufferMgr->getAllocatedBufferCount(); bufIndex++) |
| ret = m_putBuffers(m_ispBufferMgr, bufIndex); |
| |
| func_exit: |
| CLOGD2("-OUT-"); |
| return ret; |
| } |
| |
| void ExynosCamera3::dump() |
| { |
| CLOGD("DEBUG(%s[%d])", __FUNCTION__, __LINE__); |
| } |
| |
| int ExynosCamera3::getCameraId() const |
| { |
| return m_cameraId; |
| } |
| |
| #ifdef USE_FASTEN_AE_STABLE |
| status_t ExynosCamera3::m_fastenAeStable(ExynosCamera3FrameFactory *factory) |
| { |
| int ret = 0; |
| ExynosCameraBuffer fastenAeBuffer[NUM_FASTAESTABLE_BUFFERS]; |
| ExynosCameraBufferManager *skipBufferMgr = NULL; |
| m_createInternalBufferManager(&skipBufferMgr, "SKIP_BUF"); |
| |
| unsigned int planeSize[EXYNOS_CAMERA_BUFFER_MAX_PLANES] = {0}; |
| unsigned int bytesPerLine[EXYNOS_CAMERA_BUFFER_MAX_PLANES] = {0}; |
| planeSize[0] = 32 * 64 * 2; |
| int planeCount = 2; |
| int bufferCount = NUM_FASTAESTABLE_BUFFERS; |
| |
| if (skipBufferMgr == NULL) { |
| CLOGE2("ERR(%s[%d]):createBufferManager failed"); |
| goto func_exit; |
| } |
| |
| ret = m_allocBuffers(skipBufferMgr, planeCount, planeSize, bytesPerLine, bufferCount, true, false); |
| if (ret < 0) { |
| CLOGE2("ERR(%s[%d]):m_3aaBufferMgr m_allocBuffers(bufferCount=%d) fail", bufferCount); |
| goto done; |
| } |
| |
| for (int i = 0; i < bufferCount; i++) { |
| int index = i; |
| ret = skipBufferMgr->getBuffer(&index, EXYNOS_CAMERA_BUFFER_POSITION_IN_HAL, &fastenAeBuffer[i]); |
| if (ret < 0) { |
| CLOGE2("getBuffer fail"); |
| goto done; |
| } |
| } |
| |
| ret = factory->fastenAeStable(bufferCount, fastenAeBuffer); |
| if (ret < 0) { |
| ret = INVALID_OPERATION; |
| CLOGE2("fastenAeStable fail(%d)", ret); |
| } |
| |
| done: |
| if (skipBufferMgr != NULL) { |
| skipBufferMgr->deinit(); |
| delete skipBufferMgr; |
| skipBufferMgr = NULL; |
| } |
| func_exit: |
| return ret; |
| } |
| #endif |
| |
| bool ExynosCamera3::m_mainThreadFunc(void) |
| { |
| ExynosCameraRequest *request = NULL; |
| uint32_t frameCount = 0; |
| status_t ret = NO_ERROR; |
| |
| /* 1. Wait the shot done with the latest framecount */ |
| ret = m_shotDoneQ->waitAndPopProcessQ(&frameCount); |
| if (ret < 0) { |
| if (ret == TIMED_OUT) |
| CLOGW("WARN(%s[%d]):wait timeout", __FUNCTION__, __LINE__); |
| else |
| CLOGE("ERR(%s[%d]):wait and pop fail, ret(%d)", __FUNCTION__, __LINE__, ret); |
| return true; |
| } |
| |
| if (isRestarted == true) { |
| CLOGI("INFO(%s[%d]):wait configure stream", __FUNCTION__, __LINE__); |
| usleep(1); |
| |
| return true; |
| } |
| |
| ret = m_createFrameFunc(); |
| if (ret != NO_ERROR) |
| CLOGE("ERR(%s[%d]):Failed to createFrameFunc. Shotdone framecount %d", |
| __FUNCTION__, __LINE__, frameCount); |
| |
| return true; |
| } |
| |
| void ExynosCamera3::m_updateCurrentShot(void) |
| { |
| List<request_info_t *>::iterator r; |
| request_info_t *requestInfo = NULL; |
| ExynosCameraRequest *request = NULL; |
| struct camera2_shot_ext temp_shot_ext; |
| status_t ret = NO_ERROR; |
| int controlInterval = 0; |
| |
| /* 1. Get the request info from the back of the list (the newest request) */ |
| r = m_requestWaitingList.end(); |
| r--; |
| requestInfo = *r; |
| request = requestInfo->request; |
| |
| /* 2. Get the metadata from request */ |
| ret = request->getServiceShot(&temp_shot_ext); |
| if (ret != NO_ERROR) { |
| ALOGE("ERR(%s[%d]):Get service shot fail, requestKey(%d), ret(%d)", |
| __FUNCTION__, __LINE__, request->getKey(), ret); |
| } |
| |
| /* 3. Store the frameCount that the sensor control is going to be delivered */ |
| if (requestInfo->sensorControledFrameCount == 0) |
| requestInfo->sensorControledFrameCount = m_internalFrameCount; |
| |
| /* 4. Get the request info from the front of the list (the oldest request) */ |
| r = m_requestWaitingList.begin(); |
| requestInfo = *r; |
| request = requestInfo->request; |
| |
| /* 5. Update the entire shot_ext structure */ |
| ret = request->getServiceShot(m_currentShot); |
| if (ret != NO_ERROR) { |
| CLOGV("ERR(%s[%d]):Get service shot fail, requestKey(%d), ret(%d)", |
| __FUNCTION__, __LINE__, request->getKey(), ret); |
| } |
| |
| /* 6. Overwrite the sensor control metadata to m_currentShot */ |
| m_currentShot->shot.ctl.sensor.exposureTime = temp_shot_ext.shot.ctl.sensor.exposureTime; |
| m_currentShot->shot.ctl.sensor.frameDuration = temp_shot_ext.shot.ctl.sensor.frameDuration; |
| m_currentShot->shot.ctl.sensor.sensitivity = temp_shot_ext.shot.ctl.sensor.sensitivity; |
| m_currentShot->shot.ctl.lens = temp_shot_ext.shot.ctl.lens; |
| m_currentShot->shot.ctl.aa.aeMode = temp_shot_ext.shot.ctl.aa.aeMode; |
| m_currentShot->shot.ctl.aa.aeLock = temp_shot_ext.shot.ctl.aa.aeLock; |
| m_currentShot->shot.ctl.aa.vendor_isoValue = temp_shot_ext.shot.ctl.aa.vendor_isoValue; |
| m_currentShot->shot.ctl.aa.vendor_isoMode = temp_shot_ext.shot.ctl.aa.vendor_isoMode; |
| m_currentShot->shot.ctl.aa.aeExpCompensation = temp_shot_ext.shot.ctl.aa.aeExpCompensation; |
| |
| controlInterval = m_internalFrameCount - requestInfo->sensorControledFrameCount; |
| |
| /* 7. Decide to make the internal frame */ |
| if (controlInterval < SENSOR_CONTROL_DELAY) { |
| m_isNeedInternalFrame = true; |
| m_isNeedRequestFrame = false; |
| } else if (request->getNeedInternalFrame() == true) { |
| m_isNeedInternalFrame = true; |
| m_isNeedRequestFrame = true; |
| } else { |
| m_isNeedInternalFrame = false; |
| m_isNeedRequestFrame = true; |
| } |
| |
| CLOGV2("INFO(%s[%d]):framecount %d needRequestFrame %d needInternalFrame %d", |
| __FUNCTION__, __LINE__, |
| m_internalFrameCount, m_isNeedRequestFrame, m_isNeedInternalFrame); |
| |
| return; |
| } |
| |
| status_t ExynosCamera3::m_previewframeHandler(ExynosCameraRequest *request, ExynosCamera3FrameFactory *targetfactory) |
| { |
| status_t ret = NO_ERROR; |
| ExynosCameraFrame *newFrame = NULL; |
| uint32_t bufferCnt = 0; |
| uint32_t requestKey = 0; |
| int32_t bufIndex = -1; |
| ExynosCameraBuffer buffer; |
| bool captureFlag = false; |
| bool rawStreamFlag = false; |
| bool zslStreamFlag = false; |
| bool needDynamicBayer = false; |
| bool usePureBayer = false; |
| uint32_t frameCount = 0; |
| int32_t reprocessingBayerMode = m_parameters->getReprocessingBayerMode(); |
| |
| /* set buffers belonged to each stream as available */ |
| // TODO: acquire fence |
| |
| frameCount = request->getFrameCount(); |
| requestKey = request->getKey(); |
| |
| /* Initialize the request flags in framefactory */ |
| targetfactory->setRequestFLITE(false); |
| targetfactory->setRequest3AC(false); |
| targetfactory->setRequestSCC(false); |
| targetfactory->setRequestSCP(false); |
| |
| m_flagBayerRequest = false; |
| |
| /* To decide the dynamic bayer request flag for JPEG capture */ |
| switch (reprocessingBayerMode) { |
| case REPROCESSING_BAYER_MODE_NONE : |
| needDynamicBayer = false; |
| break; |
| case REPROCESSING_BAYER_MODE_PURE_ALWAYS_ON : |
| targetfactory->setRequest(PIPE_FLITE, true); |
| needDynamicBayer = false; |
| usePureBayer = true; |
| break; |
| case REPROCESSING_BAYER_MODE_DIRTY_ALWAYS_ON : |
| targetfactory->setRequest(PIPE_3AC, true); |
| needDynamicBayer = false; |
| usePureBayer = false; |
| break; |
| case REPROCESSING_BAYER_MODE_PURE_DYNAMIC : |
| needDynamicBayer = true; |
| usePureBayer = true; |
| break; |
| case REPROCESSING_BAYER_MODE_DIRTY_DYNAMIC : |
| needDynamicBayer = true; |
| usePureBayer = false; |
| break; |
| default : |
| break; |
| } |
| |
| /* Setting DMA-out request flag based on stream configuration */ |
| bufferCnt = request->getNumOfOutputBuffer(); |
| |
| for (size_t i = 0; i < bufferCnt; i++) { |
| int id = -1; |
| id = request->getStreamId(i); |
| |
| switch (id % HAL_STREAM_ID_MAX) { |
| case HAL_STREAM_ID_RAW: |
| CLOGD2("request(%d) outputBuffer-Index(%zu) buffer-StreamType(HAL_STREAM_ID_RAW) ", request->getKey(), i); |
| targetfactory->setRequestFLITE(true); |
| m_flagBayerRequest = true; |
| rawStreamFlag = true; |
| |
| break; |
| case HAL_STREAM_ID_ZSL_OUTPUT: |
| CLOGD2("request(%d) outputBuffer-Index(%zu) buffer-StreamType(HAL_STREAM_ID_ZSL)", request->getKey(), i); |
| if (usePureBayer == true) |
| targetfactory->setRequest(PIPE_FLITE, true); |
| else |
| targetfactory->setRequest(PIPE_3AC, true); |
| zslStreamFlag = true; |
| |
| break; |
| case HAL_STREAM_ID_VIDEO: |
| recordingEnabled = true; |
| case HAL_STREAM_ID_PREVIEW: |
| case HAL_STREAM_ID_CALLBACK: |
| CLOGV2("request(%d) outputBuffer-Index(%zu) buffer-StreamType(%d) ", request->getKey(), i, id); |
| targetfactory->setRequestSCP(true); |
| |
| break; |
| case HAL_STREAM_ID_JPEG: |
| CLOGD2("request(%d) outputBuffer-Index %zu buffer-StreamType(HAL_STREAM_ID_JPEG)", request->getKey(), i); |
| captureFlag = true; |
| if (m_parameters->isReprocessing() == false) { |
| targetfactory->setRequest(PIPE_3AC, true); |
| } else if (needDynamicBayer == true) { |
| if(m_parameters->getUsePureBayerReprocessing() == true) |
| targetfactory->setRequest(PIPE_FLITE, true); |
| else |
| targetfactory->setRequest(PIPE_3AC, true); |
| } |
| |
| break; |
| default: |
| CLOGE2("Invalid stream ID %d", id); |
| break; |
| } |
| } |
| |
| if (m_currentShot == NULL) { |
| CLOGE2("m_currentShot is NULL. requestKey %d ret %d", request->getKey(), ret); |
| request->getServiceShot(m_currentShot); |
| } |
| |
| m_updateCropRegion(m_currentShot); |
| |
| /* Set framecount into request */ |
| if (frameCount == 0) { |
| m_requestMgr->setFrameCount(m_internalFrameCount++, request->getKey()); |
| frameCount = request->getFrameCount(); |
| } |
| |
| ret = m_generateFrame(frameCount, targetfactory, &m_processList, &m_processLock, &newFrame); |
| if (ret != NO_ERROR) { |
| CLOGE2("Failed to generateRequestFrame. framecount %d", frameCount); |
| goto CLEAN; |
| } else if (newFrame == NULL) { |
| CLOGE2("newFrame is NULL. framecount %d", frameCount); |
| goto CLEAN; |
| } |
| |
| CLOGV2("frameCount:%d , requestKey:%d", frameCount, request->getKey()); |
| |
| ret = newFrame->setMetaData(m_currentShot); |
| if (ret != NO_ERROR) { |
| CLOGE2("Set metadata to frame fail, Frame count(%d), ret(%d)", frameCount, ret); |
| } |
| |
| newFrame->setFrameCapture(captureFlag); |
| newFrame->setFrameZsl(zslStreamFlag); |
| |
| /* newFrame->printEntity(); */ |
| if (m_parameters->isFlite3aaOtf() == true) { |
| /* It is assumed that flite is first, So use newFrame->getFristEntity(). */ |
| /* TODO: If you want location of flite entity isn't first. Don't use this. */ |
| if (m_flagBayerRequest == true) { |
| int bayerPipeId = m_getBayerPipeId(); |
| |
| if ((rawStreamFlag == true) && (zslStreamFlag != true)) { |
| CLOGD2("flite buffer(%d) use Service Bayer buffer", frameCount); |
| |
| ret = m_bayerBufferMgr->getBuffer(&bufIndex, EXYNOS_CAMERA_BUFFER_POSITION_IN_HAL, &buffer); |
| if (ret != NO_ERROR) { |
| CLOGE2("Failed to get Service Bayer Buffer. framecount %d availableBuffer %d", |
| frameCount, m_bayerBufferMgr->getNumOfAvailableBuffer()); |
| } else { |
| newFrame->setFrameServiceBayer(true); |
| } |
| } else { |
| CLOGD2("flite buffer use Internal Bayer buffer"); |
| |
| ret = m_fliteBufferMgr->getBuffer(&bufIndex, EXYNOS_CAMERA_BUFFER_POSITION_IN_HAL, &buffer); |
| if (ret != NO_ERROR) { |
| CLOGE2("getBuffer fail, pipeId(%d), frameCount(%d), ret(%d)", bayerPipeId, frameCount, ret); |
| } |
| |
| CLOGV2("Use Internal Bayer Buffer. framecount %d bufferIndex %d", frameCount, buffer.index); |
| } |
| |
| if (bufIndex < 0) { |
| CLOGW2("Invalid bayer buffer index %d. Skip to pushFrame", bufIndex); |
| ret = newFrame->setEntityState(bayerPipeId, ENTITY_STATE_COMPLETE); |
| if (ret != NO_ERROR) |
| CLOGE2("Failed to setEntityState with COMPLETE to FLITE. framecount %d", frameCount); |
| } else { |
| ret = m_setupEntity(bayerPipeId, newFrame, NULL, &buffer); |
| if (ret != NO_ERROR) { |
| CLOGE2("Failed to setupEntity with bayer buffer. framecount %d bufferIndex %d", |
| frameCount, buffer.index); |
| } else { |
| CLOGD2("PushFrametoPipe PIPE_FLITE framecount(%d)", frameCount); |
| targetfactory->setOutputFrameQToPipe(m_pipeFrameDoneQ[bayerPipeId], bayerPipeId); |
| targetfactory->pushFrameToPipe(&newFrame, bayerPipeId); |
| } |
| } |
| } |
| |
| m_setupEntity(PIPE_3AA, newFrame); |
| if (m_parameters->isMcscVraOtf() == true) { |
| targetfactory->setOutputFrameQToPipe(m_pipeFrameDoneQ[PIPE_3AA], PIPE_3AA); |
| } else { |
| targetfactory->setFrameDoneQToPipe(m_pipeFrameDoneQ[PIPE_3AA], PIPE_3AA); |
| targetfactory->setOutputFrameQToPipe(m_pipeFrameDoneQ[PIPE_VRA], PIPE_VRA); |
| } |
| targetfactory->pushFrameToPipe(&newFrame, PIPE_3AA); |
| } else { /* TODO: Implement M2M Path */ |
| m_setupEntity(PIPE_FLITE_FRONT, newFrame); |
| targetfactory->pushFrameToPipe(&newFrame, PIPE_FLITE_FRONT); |
| |
| m_setupEntity(PIPE_3AA_FRONT, newFrame); |
| m_setupEntity(PIPE_ISP_FRONT, newFrame); |
| targetfactory->setOutputFrameQToPipe(m_pipeFrameDoneQ[INDEX(PIPE_ISP_FRONT)], PIPE_ISP_FRONT); |
| |
| m_setupEntity(PIPE_SCC_FRONT, newFrame); |
| targetfactory->pushFrameToPipe(&newFrame, PIPE_SCC_FRONT); |
| targetfactory->setOutputFrameQToPipe(m_pipeFrameDoneQ[INDEX(PIPE_SCC_FRONT)], PIPE_SCC_FRONT); |
| |
| m_setupEntity(PIPE_SCP_FRONT, newFrame); |
| targetfactory->pushFrameToPipe(&newFrame, PIPE_SCP_FRONT); |
| targetfactory->setOutputFrameQToPipe(m_pipeFrameDoneQ[INDEX(PIPE_SCP_FRONT)], PIPE_SCP_FRONT); |
| } |
| |
| if (captureFlag == true |
| && m_parameters->isReprocessing() == false) { |
| m_captureCount++; |
| CLOGI2("setFrameCapture(true), frameCount(%d) m_captureCount(%d) isRunningstate(%d)", |
| frameCount, m_captureCount, m_captureThread->isRunning()); |
| m_captureQ->pushProcessQ(&newFrame); |
| } |
| |
| if (m_flagBayerRequest == true && m_frameFactoryStartDone == true) { |
| /* HAL 3.2 on 8MP Full concept is dynamic bayer */ |
| if (targetfactory->checkPipeThreadRunning(m_getBayerPipeId()) == false) { |
| m_previewStreamBayerThread->run(PRIORITY_DEFAULT); |
| targetfactory->startThread(m_getBayerPipeId()); |
| } |
| targetfactory->setRequestFLITE(false); |
| } |
| |
| CLEAN: |
| return ret; |
| } |
| |
| status_t ExynosCamera3::m_captureframeHandler(ExynosCameraRequest *request, ExynosCamera3FrameFactory *targetfactory) |
| { |
| status_t ret = NO_ERROR; |
| ExynosCameraFrame *newFrame = NULL; |
| struct camera2_shot_ext shot_ext; |
| uint32_t bufferCnt = 0; |
| uint32_t requestKey = 0; |
| uint32_t frameCount = 0; |
| bool captureFlag = false; |
| bool rawStreamFlag = false; |
| bool zslFlag = false; |
| bool isNeedThumbnail = false; |
| |
| frameCount = request->getFrameCount(); |
| |
| CLOGD2("Capture request. requestKey %d frameCount %d", |
| request->getKey(), frameCount); |
| |
| if (targetfactory == NULL) { |
| CLOGE2("targetfactory is NULL"); |
| return INVALID_OPERATION; |
| } |
| |
| /* set buffers belonged to each stream as available */ |
| /* wait for reprocessing instance of capture */ |
| if (m_parameters->isReprocessing() == true) { |
| if (m_flagStartReprocessingFrameFactory == false) |
| m_reprocessingFrameFactoryStartThread->join(); |
| m_startPictureBufferThread->join(); |
| } |
| |
| requestKey = request->getKey(); |
| |
| targetfactory->setRequest(PIPE_MCSC0_REPROCESSING, false); |
| if (m_parameters->isHWFCEnabled() == true) { |
| targetfactory->setRequest(PIPE_HWFC_JPEG_SRC_REPROCESSING, false); |
| targetfactory->setRequest(PIPE_HWFC_THUMB_SRC_REPROCESSING, false); |
| } |
| |
| /* set input buffers belonged to each stream as available */ |
| bufferCnt = request->getNumOfInputBuffer(); |
| |
| for (size_t i = 0; i < bufferCnt ; i++) { |
| int id = request->getStreamId(i); |
| switch (id % HAL_STREAM_ID_MAX) { |
| case HAL_STREAM_ID_ZSL_INPUT: |
| CLOGD2("requestKey %d buffer-StreamType(HAL_STREAM_ID_ZSL_INPUT)", request->getKey()); |
| zslFlag = true; |
| break; |
| case HAL_STREAM_ID_JPEG: |
| case HAL_STREAM_ID_PREVIEW: |
| case HAL_STREAM_ID_VIDEO: |
| case HAL_STREAM_ID_CALLBACK: |
| case HAL_STREAM_ID_MAX: |
| CLOGE2("frameCount %d requestKey %d Invalid buffer-StreamType(%d)", |
| frameCount, request->getKey(), id); |
| break; |
| default: |
| break; |
| } |
| } |
| |
| /* set output buffers belonged to each stream as available */ |
| bufferCnt = request->getNumOfOutputBuffer(); |
| |
| for (size_t i = 0; i < bufferCnt; i++) { |
| int id = request->getStreamId(i); |
| switch (id % HAL_STREAM_ID_MAX) { |
| case HAL_STREAM_ID_JPEG: |
| CLOGD2("frameCount %d requestKey %d buffer-StreamType(HAL_STREAM_ID_JPEG)", |
| frameCount, request->getKey()); |
| targetfactory->setRequest(PIPE_MCSC0_REPROCESSING, true); |
| |
| request->getServiceShot(&shot_ext); |
| isNeedThumbnail = (shot_ext.shot.ctl.jpeg.thumbnailSize[0] > 0 |
| && shot_ext.shot.ctl.jpeg.thumbnailSize[1] > 0) ? true : false; |
| |
| if (m_parameters->isHWFCEnabled() == true) { |
| if (m_parameters->isUseYuvReprocessingForThumbnail() == false) { |
| targetfactory->setRequest(PIPE_HWFC_JPEG_SRC_REPROCESSING, true); |
| } else if (isNeedThumbnail == false) { |
| targetfactory->setRequest(PIPE_HWFC_JPEG_SRC_REPROCESSING, true); |
| targetfactory->setRequest(PIPE_HWFC_THUMB_SRC_REPROCESSING, true); |
| } |
| } |
| |
| captureFlag = true; |
| break; |
| case HAL_STREAM_ID_RAW: |
| CLOGV2("frameCount %d requestKey %d buffer-StreamType(HAL_STREAM_ID_RAW)", |
| frameCount, request->getKey()); |
| |
| rawStreamFlag = true; |
| break; |
| case HAL_STREAM_ID_PREVIEW: |
| case HAL_STREAM_ID_VIDEO: |
| case HAL_STREAM_ID_CALLBACK: |
| case HAL_STREAM_ID_MAX: |
| CLOGE2("frameCount %d requestKey %d Invalid buffer-StreamType(%d)", |
| frameCount, request->getKey()); |
| break; |
| default: |
| break; |
| } |
| } |
| |
| if (m_currentShot == NULL) { |
| CLOGW2("requestKey(%d) m_currentShot is NULL. Use request metadata.", request->getKey()); |
| request->getServiceShot(m_currentShot); |
| } |
| |
| m_updateCropRegion(m_currentShot); |
| m_updateJpegControlInfo(m_currentShot); |
| |
| /* Set framecount into request */ |
| if (request->getNeedInternalFrame() == true) |
| /* Must use the same framecount with internal frame */ |
| m_internalFrameCount--; |
| |
| if (frameCount == 0) { |
| m_requestMgr->setFrameCount(m_internalFrameCount++, request->getKey()); |
| frameCount = request->getFrameCount(); |
| } |
| |
| ret = m_generateFrame(frameCount, targetfactory, &m_captureProcessList, &m_captureProcessLock, &newFrame); |
| if (ret != NO_ERROR) { |
| CLOGE2("m_generateFrame fail"); |
| return INVALID_OPERATION; |
| } else if (newFrame == NULL) { |
| CLOGE2("new frame is NULL"); |
| return INVALID_OPERATION; |
| } |
| |
| CLOGV2("generate request framecount %d requestKey %d", frameCount, request->getKey()); |
| |
| ret = newFrame->setMetaData(m_currentShot); |
| if (ret != NO_ERROR) |
| CLOGE2("Set metadata to frame fail, Frame count(%d), ret(%d)", |
| frameCount, ret); |
| |
| newFrame->setFrameServiceBayer(rawStreamFlag); |
| newFrame->setFrameCapture(captureFlag); |
| newFrame->setFrameZsl(zslFlag); |
| |
| m_selectBayerQ->pushProcessQ(&newFrame); |
| |
| if(m_selectBayerThread != NULL |
| && m_selectBayerThread->isRunning() == false) { |
| m_selectBayerThread->run(); |
| CLOGI2("Initiate selectBayerThread (%d)", m_selectBayerThread->getTid()); |
| } |
| |
| return ret; |
| } |
| |
| status_t ExynosCamera3::m_createRequestFrameFunc(ExynosCameraRequest *request) |
| { |
| int32_t factoryAddrIndex = 0; |
| bool removeDupFlag = false; |
| |
| ExynosCamera3FrameFactory *factory = NULL; |
| ExynosCamera3FrameFactory *factoryAddr[100] ={NULL,}; |
| FrameFactoryList factorylist; |
| FrameFactoryListIterator factorylistIter; |
| factory_handler_t frameCreateHandler; |
| |
| // TODO: acquire fence |
| /* 1. Remove the duplicated frame factory in request */ |
| factoryAddrIndex = 0; |
| factorylist.clear(); |
| |
| request->getFrameFactoryList(&factorylist); |
| for (factorylistIter = factorylist.begin(); factorylistIter != factorylist.end(); ) { |
| removeDupFlag = false; |
| factory = *factorylistIter; |
| ALOGV("DEBUG(%s[%d]):list Factory(%p) ", __FUNCTION__, __LINE__, factory); |
| |
| for (int i = 0; i < factoryAddrIndex ; i++) { |
| if (factoryAddr[i] == factory) { |
| removeDupFlag = true; |
| break; |
| } |
| } |
| |
| if (removeDupFlag) { |
| ALOGV("DEBUG(%s[%d]):remove duplicate Factory factoryAddrIndex(%d)", |
| __FUNCTION__, __LINE__, factoryAddrIndex); |
| factorylist.erase(factorylistIter++); |
| } else { |
| ALOGV("DEBUG(%s[%d]):add frame factory, factoryAddrIndex(%d)", |
| __FUNCTION__, __LINE__, factoryAddrIndex); |
| factoryAddr[factoryAddrIndex] = factory; |
| factoryAddrIndex++; |
| factorylistIter++; |
| } |
| |
| } |
| |
| /* 2. Call the frame create handler for each frame factory */ |
| for (int i = 0; i < factoryAddrIndex; i++) { |
| ALOGV("DEBUG(%s[%d]):framefactory index(%d) maxIndex(%d) (%p)", |
| __FUNCTION__, __LINE__, i, factoryAddrIndex, factoryAddr[i]); |
| frameCreateHandler = factoryAddr[i]->getFrameCreateHandler(); |
| (this->*frameCreateHandler)(request, factoryAddr[i]); |
| } |
| |
| ALOGV("DEBUG(%s[%d]):- OUT - (F:%d)", __FUNCTION__, __LINE__, request->getKey()); |
| return NO_ERROR; |
| } |
| |
| status_t ExynosCamera3::m_createInternalFrameFunc(void) |
| { |
| status_t ret = NO_ERROR; |
| uint32_t waitTime = 15 * 1000000; /* 15 msec as a default */ |
| uint32_t maxFps = 0; |
| ExynosCameraBufferManager *bufferMgr = NULL; |
| ExynosCamera3FrameFactory *factory = NULL; |
| ExynosCameraFrame *newFrame = NULL; |
| short retryCount = 4; |
| |
| /* 1. Generate the internal frame */ |
| factory = m_frameFactory[FRAME_FACTORY_TYPE_CAPTURE_PREVIEW]; |
| if (m_parameters->isFlite3aaOtf() == true) { |
| factory->setRequestFLITE(false); |
| } else |
| factory->setRequestFLITE(true); |
| |
| ret = m_generateInternalFrame(m_internalFrameCount++, factory, &m_processList, &m_processLock, &newFrame); |
| if (ret != NO_ERROR) { |
| ALOGE("ERR(%s[%d]):m_generateFrame failed", __FUNCTION__, __LINE__); |
| return ret; |
| } else if (newFrame == NULL) { |
| ALOGE("ERR(%s[%d]):newFrame is NULL", __FUNCTION__, __LINE__); |
| return INVALID_OPERATION; |
| } |
| |
| ALOGV("INFO(%s[%d]):generate internal framecount %d", |
| __FUNCTION__, __LINE__, |
| newFrame->getFrameCount()); |
| |
| /* 2. Set DMA-out request flag into frame |
| * 3AP, 3AC, ISP, ISPP, ISPC, SCC, DIS, SCP */ |
| newFrame->setRequest(false, false, false, false, false, false, false, false); |
| |
| switch (m_parameters->getReprocessingBayerMode()) { |
| case REPROCESSING_BAYER_MODE_PURE_ALWAYS_ON : |
| newFrame->setRequest(PIPE_FLITE, true); |
| break; |
| case REPROCESSING_BAYER_MODE_DIRTY_ALWAYS_ON: |
| newFrame->setRequest(PIPE_3AC, true); |
| break; |
| default: |
| break; |
| } |
| |
| /* 3. Update the metadata with m_currentShot into frame */ |
| if (m_currentShot == NULL) { |
| CLOGE2("ERR(%s[%d]):m_currentShot is NULL", __FUNCTION__, __LINE__); |
| return INVALID_OPERATION; |
| } |
| ret = newFrame->setMetaData(m_currentShot); |
| if (ret != NO_ERROR) { |
| CLOGE2("ERR(%s[%d]):Failed to setMetaData with m_currehtShot. framecount %d ret %d", |
| __FUNCTION__, __LINE__, |
| newFrame->getFrameCount(), ret); |
| return ret; |
| } |
| |
| /* 4. Attach the buffers into frame */ |
| maxFps = m_currentShot->shot.ctl.aa.aeTargetFpsRange[1]; |
| if (maxFps > 0) |
| waitTime = (1000 / maxFps) * 1000000 / 2; // Wait for the half of MIN frame duration(MAX fps) |
| while (retryCount-- > 0) { |
| if (m_parameters->isFlite3aaOtf() == false) { |
| ret = m_setupEntity(PIPE_FLITE, newFrame); |
| if (ret != NO_ERROR) { |
| ALOGW("WARN(%s[%d]):Get FLITE buffer failed!, framecount(%d), availableFLITEBuffer(%d), sleep(%d ns/%d fps(MAX)), retryCount(%d)", |
| __FUNCTION__, __LINE__, newFrame->getFrameCount(), |
| m_fliteBufferMgr->getNumOfAvailableBuffer(), waitTime, maxFps, retryCount); |
| usleep(waitTime); |
| continue; |
| } |
| } else { |
| ret = m_setupEntity(PIPE_3AA, newFrame); |
| if (ret != NO_ERROR) { |
| ret = m_getBufferManager(PIPE_3AA, &bufferMgr, SRC_BUFFER_DIRECTION); |
| if (ret != NO_ERROR) { |
| CLOGE("ERR(%s[%d]):Failed to getBufferManager for 3AA. framecount %d", |
| __FUNCTION__, __LINE__, newFrame->getFrameCount()); |
| return ret; |
| } |
| |
| ALOGW("WARN(%s[%d]):Get 3AA buffer failed!, framecount(%d), available3AABuffer(%d), sleep(%d ns/%d fps(MAX)), retryCount(%d)", |
| __FUNCTION__, __LINE__, newFrame->getFrameCount(), |
| m_3aaBufferMgr->getNumOfAvailableBuffer(), waitTime, maxFps, retryCount); |
| |
| usleep(waitTime); |
| continue; |
| } |
| } |
| break; |
| } |
| if (retryCount == 0 && ret != NO_ERROR) { |
| ALOGE("ERR(%s[%d]):Get 3AA buffer finally failed!, framecount(%d), available3AABuffer(%d)", |
| __FUNCTION__, __LINE__, newFrame->getFrameCount(), |
| m_3aaBufferMgr->getNumOfAvailableBuffer()); |
| return ret; |
| } |
| |
| /* 5. Push the frame to 3AA */ |
| if (m_parameters->isFlite3aaOtf() == false) { |
| factory->setOutputFrameQToPipe(m_pipeFrameDoneQ[PIPE_FLITE], PIPE_FLITE); |
| factory->pushFrameToPipe(&newFrame, PIPE_FLITE); |
| } else { |
| if (m_parameters->isMcscVraOtf() == true) { |
| factory->setOutputFrameQToPipe(m_pipeFrameDoneQ[PIPE_3AA], PIPE_3AA); |
| } else { |
| factory->setFrameDoneQToPipe(m_pipeFrameDoneQ[PIPE_3AA], PIPE_3AA); |
| factory->setOutputFrameQToPipe(m_pipeFrameDoneQ[PIPE_VRA], PIPE_VRA); |
| } |
| factory->pushFrameToPipe(&newFrame, PIPE_3AA); |
| } |
| |
| return ret; |
| } |
| |
| status_t ExynosCamera3::m_createPrepareFrameFunc(ExynosCameraRequest *request) |
| { |
| status_t ret = NO_ERROR; |
| short retryCount = 4; |
| uint32_t waitTime = 15 * 1000000; /* 15 msec as as defatul */ |
| uint32_t maxFps = 0; |
| uint32_t pipeId = MAX_PIPE_NUM; |
| uint32_t flitePrepareCnt = m_prepareFliteCnt; |
| uint32_t taaPrepareCnt = m_exynosconfig->current->pipeInfo.prepare[PIPE_3AA]; |
| ExynosCamera3FrameFactory *factory = NULL; |
| ExynosCameraFrame *newFrame = NULL; |
| ExynosCameraStream *stream = NULL; |
| |
| ExynosCameraBufferManager *taaBufferManager[MAX_NODE]; |
| ExynosCameraBufferManager *ispBufferManager[MAX_NODE]; |
| ExynosCameraBufferManager *disBufferManager[MAX_NODE]; |
| ExynosCameraBufferManager *vraBufferManager[MAX_NODE]; |
| |
| for (int i = 0; i < MAX_NODE; i++) { |
| taaBufferManager[i] = NULL; |
| ispBufferManager[i] = NULL; |
| disBufferManager[i] = NULL; |
| vraBufferManager[i] = NULL; |
| } |
| factory = m_frameFactory[FRAME_FACTORY_TYPE_CAPTURE_PREVIEW]; |
| |
| if (m_factoryStartFlag == true) { |
| m_factoryStartFlag = false; |
| |
| #ifdef USE_FASTEN_AE_STABLE |
| /* for FAST AE Stable */ |
| if (request->getKey()== 0 && |
| m_parameters->getUseFastenAeStable() == true && |
| m_parameters->getCameraId() == CAMERA_ID_BACK && |
| m_parameters->getDualMode() == false && |
| m_parameters->getRecordingHint() == false && |
| m_flagRunFastAE == false) { |
| m_flagRunFastAE = true; |
| m_fastenAeStable(factory); |
| } |
| #endif |
| |
| ret = factory->initPipes(); |
| if (ret != NO_ERROR) { |
| ALOGE("ERR(%s[%d]):m_previewFrameFactory->initPipes() failed", __FUNCTION__, __LINE__); |
| return ret; |
| } |
| |
| if (m_parameters->getTpuEnabledMode() == true) { |
| #if 0 |
| factory->setRequestISPP(true); |
| factory->setRequestDIS(true); |
| |
| if (m_parameters->is3aaIspOtf() == true) { |
| taaBufferManager[factory->getNodeType(PIPE_3AA)] = m_3aaBufferMgr; |
| taaBufferManager[factory->getNodeType(PIPE_3AC)] = m_fliteBufferMgr; |
| taaBufferManager[factory->getNodeType(PIPE_ISPP)] = m_hwDisBufferMgr; |
| |
| disBufferManager[factory->getNodeType(PIPE_DIS)] = m_hwDisBufferMgr; |
| disBufferManager[factory->getNodeType(PIPE_SCP)] = scpBufferMgr; |
| } else { |
| taaBufferManager[factory->getNodeType(PIPE_3AA)] = m_3aaBufferMgr; |
| taaBufferManager[factory->getNodeType(PIPE_3AC)] = m_fliteBufferMgr; |
| taaBufferManager[factory->getNodeType(PIPE_3AP)] = m_ispBufferMgr; |
| |
| ispBufferManager[factory->getNodeType(PIPE_ISP)] = m_ispBufferMgr; |
| ispBufferManager[factory->getNodeType(PIPE_ISPP)] = m_hwDisBufferMgr; |
| |
| disBufferManager[factory->getNodeType(PIPE_DIS)] = m_hwDisBufferMgr; |
| disBufferManager[factory->getNodeType(PIPE_SCP)] = scpBufferMgr; |
| } |
| #endif |
| } else { |
| factory->setRequestISPP(false); |
| factory->setRequestDIS(false); |
| |
| if (m_parameters->is3aaIspOtf() == true) { |
| if (m_parameters->getDualMode() == true && getCameraId() == CAMERA_ID_FRONT) { |
| factory->setRequestFLITE(true); |
| factory->setRequestISPC(true); |
| |
| taaBufferManager[factory->getNodeType(PIPE_3AA)] = m_fliteBufferMgr; |
| taaBufferManager[factory->getNodeType(PIPE_ISPC)] = m_yuvCaptureBufferMgr; |
| } else { |
| |
| taaBufferManager[factory->getNodeType(PIPE_3AA)] = m_3aaBufferMgr; |
| if (m_parameters->isUsing3acForIspc() == true) |
| taaBufferManager[factory->getNodeType(PIPE_3AC)] = m_yuvCaptureBufferMgr; |
| #ifndef RAWDUMP_CAPTURE |
| else |
| taaBufferManager[factory->getNodeType(PIPE_3AC)] = m_fliteBufferMgr; |
| #endif |
| taaBufferManager[factory->getNodeType(PIPE_SCP)] = m_internalScpBufferMgr; |
| } |
| } else { |
| taaBufferManager[factory->getNodeType(PIPE_3AA)] = m_3aaBufferMgr; |
| taaBufferManager[factory->getNodeType(PIPE_3AC)] = m_fliteBufferMgr; |
| taaBufferManager[factory->getNodeType(PIPE_3AP)] = m_ispBufferMgr; |
| |
| ispBufferManager[factory->getNodeType(PIPE_ISP)] = m_ispBufferMgr; |
| ispBufferManager[factory->getNodeType(PIPE_SCP)] = m_internalScpBufferMgr; |
| } |
| } |
| |
| if (m_parameters->isMcscVraOtf() == false) { |
| vraBufferManager[OUTPUT_NODE] = m_vraBufferMgr; |
| |
| ret = factory->setBufferManagerToPipe(vraBufferManager, PIPE_VRA); |
| if (ret != NO_ERROR) { |
| CLOGE2("m_previewFrameFactory->setBufferManagerToPipe(vraBufferManager, %d) failed", PIPE_VRA); |
| return ret; |
| } |
| } |
| |
| for (int i = 0; i < MAX_NODE; i++) { |
| /* If even one buffer slot is valid. call setBufferManagerToPipe() */ |
| if (taaBufferManager[i] != NULL) { |
| ret = factory->setBufferManagerToPipe(taaBufferManager, PIPE_3AA); |
| if (ret != NO_ERROR) { |
| CLOGE2("m_previewFrameFactory->setBufferManagerToPipe(taaBufferManager, %d) failed", PIPE_3AA); |
| return ret; |
| } |
| break; |
| } |
| } |
| |
| for (int i = 0; i < MAX_NODE; i++) { |
| /* If even one buffer slot is valid. call setBufferManagerToPipe() */ |
| if (ispBufferManager[i] != NULL) { |
| ret = factory->setBufferManagerToPipe(ispBufferManager, PIPE_ISP); |
| if (ret != NO_ERROR) { |
| CLOGE2("m_previewFrameFactory->setBufferManagerToPipe(ispBufferManager, %d) failed", PIPE_ISP); |
| return ret; |
| } |
| break; |
| } |
| } |
| |
| if (m_parameters->getHWVdisMode()) { |
| for (int i = 0; i < MAX_NODE; i++) { |
| /* If even one buffer slot is valid. call setBufferManagerToPipe() */ |
| if (disBufferManager[i] != NULL) { |
| ret = factory->setBufferManagerToPipe(disBufferManager, PIPE_DIS); |
| if (ret != NO_ERROR) { |
| CLOGE2("m_previewFrameFactory->setBufferManagerToPipe(disBufferManager, %d) failed", PIPE_DIS); |
| return ret; |
| } |
| break; |
| } |
| } |
| } |
| |
| } |
| |
| /* 1. Generate the internal frame */ |
| if (m_parameters->isFlite3aaOtf() == true) { |
| factory->setRequestFLITE(false); |
| pipeId = PIPE_3AA; |
| } else { |
| factory->setRequestFLITE(true); |
| pipeId = PIPE_FLITE; |
| } |
| ret = m_generateInternalFrame(m_internalFrameCount++, factory, &m_processList, &m_processLock, &newFrame); |
| if (ret != NO_ERROR) { |
| ALOGE("ERR(%s[%d]):m_generateFrame failed", __FUNCTION__, __LINE__); |
| return ret; |
| } else if (newFrame == NULL) { |
| ALOGE("ERR(%s[%d]):newFrame is NULL", __FUNCTION__, __LINE__); |
| return INVALID_OPERATION; |
| } |
| |
| /* newFrame->dump(); */ |
| |
| ALOGI("INFO(%s[%d]):generate prepare framecount %d", |
| __FUNCTION__, __LINE__, |
| newFrame->getFrameCount()); |
| |
| /* 2. Set DMA-out request flag into frame |
| * 3AP, 3AC, ISP, ISPP, ISPC, SCC, DIS, SCP */ |
| /* newFrame->setRequest(false, false, false, false, false, false, false, false); */ |
| #if 0 |
| if (m_parameters->is3aaIspOtf() == false) { |
| newFrame->setRequest(PIPE_3AP, true); |
| taaBufferManager[OUTPUT_NODE] = m_3aaBufferMgr; |
| taaBufferManager[SUB_NODE] = m_ispBufferMgr; |
| ret = factory->setBufferManagerToPipe(taaBufferManager, PIPE_3AA); |
| if (ret < 0) { |
| ALOGE("ERR(%s):m_previewFrameFactory->setBufferManagerToPipe() failed", __FUNCTION__); |
| return ret; |
| } |
| } |
| #endif |
| |
| /* 3. Update the metadata with m_currentShot into frame */ |
| ret = newFrame->setMetaData(m_currentShot); |
| |
| /* 4. Attach the buffers into frame */ |
| maxFps = m_currentShot->shot.ctl.aa.aeTargetFpsRange[1]; |
| if (maxFps > 0) |
| waitTime = (1000 / maxFps) * 1000000 / 2; // Wait for the half of MIN frame duration(MAX fps) |
| while (retryCount-- > 0) { |
| ret = m_setupEntity(pipeId, newFrame); |
| if (ret != NO_ERROR) { |
| ALOGW("WARN(%s[%d]):Get %s buffer failed!, framecount(%d), availableFLITEBuffer(%d), sleep(%d ns/%d fps(MAX)), retryCount(%d)", |
| __FUNCTION__, __LINE__, |
| (pipeId == PIPE_FLITE)?"PIPE_FLITE":"PIPE_3AA", |
| newFrame->getFrameCount(), |
| m_fliteBufferMgr->getNumOfAvailableBuffer(), waitTime, maxFps, retryCount); |
| usleep(waitTime); |
| continue; |
| } |
| break; |
| } |
| if (retryCount == 0 && ret != NO_ERROR) { |
| ALOGE("ERR(%s[%d]):Get %s buffer finally failed!, framecount(%d), available3AABuffer(%d)", |
| __FUNCTION__, __LINE__, |
| (pipeId == PIPE_FLITE)?"PIPE_FLITE":"PIPE_3AA", |
| newFrame->getFrameCount(), |
| m_3aaBufferMgr->getNumOfAvailableBuffer()); |
| return ret; |
| } |
| |
| /* 5. Push the frame to 3AA */ |
| if (m_parameters->isMcscVraOtf() == true) { |
| factory->setOutputFrameQToPipe(m_pipeFrameDoneQ[PIPE_3AA], PIPE_3AA); |
| } else { |
| factory->setFrameDoneQToPipe(m_pipeFrameDoneQ[PIPE_3AA], PIPE_3AA); |
| factory->setOutputFrameQToPipe(m_pipeFrameDoneQ[PIPE_VRA], PIPE_VRA); |
| } |
| factory->pushFrameToPipe(&newFrame, pipeId); |
| |
| /* before starting framefactory, we should set bayer prepare buffer count (max prepare count depend on 3aa count) */ |
| if ((factory->checkPipeThreadRunning(m_getBayerPipeId()) == false) && |
| (taaPrepareCnt - 1) >= (newFrame->getFrameCount()) && |
| m_parameters->isFlite3aaOtf() == false && |
| m_flagBayerRequest == true) { |
| flitePrepareCnt++; |
| if (flitePrepareCnt != m_prepareFliteCnt) |
| ALOGI("INFO(%s[%d]):adjust PIPE_FLITE prepare count(%d => %d)", __FUNCTION__, __LINE__, |
| m_prepareFliteCnt, flitePrepareCnt); |
| m_prepareFliteCnt = flitePrepareCnt; |
| } |
| |
| return ret; |
| } |
| |
| status_t ExynosCamera3::m_createFrameFunc(void) |
| { |
| status_t ret = NO_ERROR; |
| ExynosCameraRequest *request = NULL; |
| int key = 0; |
| /* 1. Get new service request from request manager */ |
| #ifdef USE_SKIP_FIRST_FRAME |
| /* HACK : Skip to update metadata for 2nd frame (fCount == 2) |
| * AE library does NOT refer to the 1st shot. |
| * To get the normal dynamic metadata for the 1st request from user, |
| * HAL must create the two frame which have the same control metadata. |
| * Therefore, the frame that has the frameCount 1 must not be updated |
| * with new request. |
| */ |
| if (m_requestMgr->getServiceRequestCount() > 0 && m_internalFrameCount != 1) { |
| #else |
| if (m_requestMgr->getServiceRequestCount() > 0) { |
| #endif |
| m_popRequest(&request); |
| key = request->getKey(); |
| } |
| ALOGV("Service Request Count(%d) Total Request Count(%d)", |
| m_requestMgr->getServiceRequestCount(),m_requestMgr->getRequestCount()); |
| |
| /* 2. Push back the new service request into m_requestWaitingList */ |
| /* Warning : |
| * The List APIs for 'm_requestWaitingList' are called sequencially. |
| * So the mutex is not required. |
| * If the 'm_requestWaitingList' will be accessed by another thread, |
| * using mutex must be considered. |
| */ |
| if (request != NULL) { |
| request_info_t *requestInfo = new request_info_t; |
| requestInfo->request = request; |
| requestInfo->sensorControledFrameCount = 0; |
| m_requestWaitingList.push_back(requestInfo); |
| } |
| |
| /* 3. Update the current shot */ |
| if (m_requestWaitingList.size() > 0) |
| m_updateCurrentShot(); |
| |
| ALOGV("DEBUG(%s[%d]):Create New Frame %d Key %d needRequestFrame %d needInternalFrame %d waitingSize %d", |
| __FUNCTION__, __LINE__, |
| m_internalFrameCount, key, m_isNeedRequestFrame, m_isNeedInternalFrame, m_requestWaitingList.size()); |
| |
| /* 4. Select the frame creation logic between request frame and internal frame */ |
| if (m_isNeedInternalFrame == true || m_requestWaitingList.empty() == true) { |
| |
| m_createInternalFrameFunc(); |
| } |
| if (m_isNeedRequestFrame == true && m_requestWaitingList.empty() == false) { |
| List<request_info_t *>::iterator r; |
| request_info_t *requestInfo = NULL; |
| |
| r = m_requestWaitingList.begin(); |
| requestInfo = *r; |
| request = requestInfo->request; |
| |
| m_createRequestFrameFunc(request); |
| |
| m_requestWaitingList.erase(r); |
| delete requestInfo; |
| } |
| |
| return ret; |
| } |
| |
| status_t ExynosCamera3::m_sendRawCaptureResult(ExynosCameraFrame *frame, uint32_t pipeId, bool isSrc) |
| { |
| status_t ret = NO_ERROR; |
| ExynosCameraStream *stream = NULL; |
| ExynosCameraRequest *request = NULL; |
| ExynosCameraBuffer buffer; |
| camera3_stream_buffer_t streamBuffer; |
| ResultRequest resultRequest = NULL; |
| |
| /* 1. Get stream object for RAW */ |
| ret = m_streamManager->getStream(HAL_STREAM_ID_RAW, &stream); |
| if (ret < 0) { |
| ALOGE("ERR(%s[%d]):getStream is failed, from streammanager. Id error:HAL_STREAM_ID_RAW", |
| __FUNCTION__, __LINE__); |
| return ret; |
| } |
| |
| /* 2. Get camera3_stream structure from stream object */ |
| ret = stream->getStream(&streamBuffer.stream); |
| if (ret < 0) { |
| ALOGE("ERR(%s[%d]):getStream is failed, from exynoscamerastream. Id error:HAL_STREAM_ID_RAW", |
| __FUNCTION__, __LINE__); |
| return ret; |
| } |
| |
| /* 3. Get the bayer buffer from frame */ |
| if (isSrc == true) |
| ret = frame->getSrcBuffer(pipeId, &buffer); |
| else |
| ret = frame->getDstBuffer(pipeId, &buffer); |
| if (ret < 0) { |
| ALOGE("ERR(%s[%d]):Get bayer buffer failed, framecount(%d), isSrc(%d), pipeId(%d)", |
| __FUNCTION__, __LINE__, |
| frame->getFrameCount(), isSrc, pipeId); |
| return ret; |
| } |
| |
| /* 4. Get the service buffer handle from buffer manager */ |
| ret = m_bayerBufferMgr->getHandleByIndex(&(streamBuffer.buffer), buffer.index); |
| if (ret < 0) { |
| ALOGE("ERR(%s[%d]):Buffer index error(%d)!!", __FUNCTION__, __LINE__, buffer.index); |
| return ret; |
| } |
| |
| /* 5. Update the remained buffer info */ |
| streamBuffer.status = CAMERA3_BUFFER_STATUS_OK; |
| streamBuffer.acquire_fence = -1; |
| streamBuffer.release_fence = -1; |
| |
| /* 6. Create new result for RAW buffer */ |
| request = m_requestMgr->getServiceRequest(frame->getFrameCount()); |
| resultRequest = m_requestMgr->createResultRequest(frame->getFrameCount(), EXYNOS_REQUEST_RESULT::CALLBACK_BUFFER_ONLY, NULL, NULL); |
| resultRequest->pushStreamBuffer(&streamBuffer); |
| |
| /* 7. Request to callback the result to request manager */ |
| m_requestMgr->callbackSequencerLock(); |
| request->increaseCompleteBufferCount(); |
| m_requestMgr->callbackRequest(resultRequest); |
| m_requestMgr->callbackSequencerUnlock(); |
| |
| #if 0 |
| /* 8. Send the bayer buffer to frame selector */ |
| if (frame->getFrameCapture() == true) { |
| ALOGD("DEBUG(%s[%d]):Send the service bayer buffer to m_sccCaptureSelector. frameCount(%d)", |
| __FUNCTION__, __LINE__, frame->getFrameCount()); |
| ret = m_sccCaptureSelector->manageFrameHoldList(frame, pipeId, isSrc); |
| if (ret < 0) { |
| ALOGE("ERR(%s[%d]):manageFrameHoldList failed, frameCount(%d)", |
| __FUNCTION__, __LINE__, frame->getFrameCount()); |
| return ret; |
| } |
| } |
| #endif |
| ALOGE("DEBUG(%s[%d]):request->frame_number(%d), request->getNumOfOutputBuffer(%d) request->getCompleteBufferCount(%d) frame->getFrameCapture(%d)", |
| __FUNCTION__, __LINE__, |
| request->getKey(), |
| request->getNumOfOutputBuffer(), |
| request->getCompleteBufferCount(), |
| frame->getFrameCapture()); |
| |
| ALOGV("DEBUG(%s[%d]):streamBuffer info: stream (%p), handle(%p)", |
| __FUNCTION__, __LINE__, |
| streamBuffer.stream, streamBuffer.buffer); |
| |
| return ret; |
| } |
| |
| status_t ExynosCamera3::m_sendZSLCaptureResult(ExynosCameraFrame *frame, __unused uint32_t pipeId, __unused bool isSrc) |
| { |
| status_t ret = NO_ERROR; |
| ExynosCameraStream *stream = NULL; |
| ExynosCameraRequest *request = NULL; |
| camera3_stream_buffer_t streamBuffer; |
| ResultRequest resultRequest = NULL; |
| const camera3_stream_buffer_t *buffer; |
| const camera3_stream_buffer_t *bufferList; |
| int streamId = 0; |
| uint32_t bufferCount = 0; |
| |
| |
| /* 1. Get stream object for ZSL */ |
| ret = m_streamManager->getStream(HAL_STREAM_ID_ZSL_OUTPUT, &stream); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]):getStream is failed, from streammanager. Id error:HAL_STREAM_ID_ZSL", |
| __FUNCTION__, __LINE__); |
| return ret; |
| } |
| |
| /* 2. Get camera3_stream structure from stream object */ |
| ret = stream->getStream(&streamBuffer.stream); |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]):getStream is failed, from exynoscamerastream. Id error:HAL_STREAM_ID_RAW", |
| __FUNCTION__, __LINE__); |
| return ret; |
| } |
| |
| /* 3. Get zsl buffer */ |
| request = m_requestMgr->getServiceRequest(frame->getFrameCount()); |
| bufferCount = request->getNumOfOutputBuffer(); |
| bufferList = request->getOutputBuffers(); |
| |
| for (uint32_t index = 0; index < bufferCount; index++) { |
| buffer = &(bufferList[index]); |
| stream = static_cast<ExynosCameraStream *>(bufferList[index].stream->priv); |
| stream->getID(&streamId); |
| |
| if ((streamId % HAL_STREAM_ID_MAX) == HAL_STREAM_ID_ZSL_OUTPUT) { |
| streamBuffer.buffer = bufferList[index].buffer; |
| } |
| } |
| |
| /* 4. Update the remained buffer info */ |
| streamBuffer.status = CAMERA3_BUFFER_STATUS_OK; |
| streamBuffer.acquire_fence = -1; |
| streamBuffer.release_fence = -1; |
| |
| /* 5. Create new result for ZSL buffer */ |
| resultRequest = m_requestMgr->createResultRequest(frame->getFrameCount(), EXYNOS_REQUEST_RESULT::CALLBACK_BUFFER_ONLY, NULL, NULL); |
| resultRequest->pushStreamBuffer(&streamBuffer); |
| |
| /* 6. Request to callback the result to request manager */ |
| m_requestMgr->callbackSequencerLock(); |
| request->increaseCompleteBufferCount(); |
| m_requestMgr->callbackRequest(resultRequest); |
| m_requestMgr->callbackSequencerUnlock(); |
| |
| CLOGE("DEBUG(%s[%d]):request->frame_number(%d), request->getNumOfOutputBuffer(%d) request->getCompleteBufferCount(%d) frame->getFrameCapture(%d)", |
| __FUNCTION__, __LINE__, |
| request->getKey(), |
| request->getNumOfOutputBuffer(), |
| request->getCompleteBufferCount(), |
| frame->getFrameCapture()); |
| |
| CLOGV("DEBUG(%s[%d]):streamBuffer info: stream (%p), handle(%p)", |
| __FUNCTION__, __LINE__, |
| streamBuffer.stream, streamBuffer.buffer); |
| |
| return ret; |
| |
| } |
| |
| |
| status_t ExynosCamera3::m_sendNotify(uint32_t frameNumber, int type) |
| { |
| camera3_notify_msg_t notify; |
| ResultRequest resultRequest = NULL; |
| ExynosCameraRequest *request = NULL; |
| uint32_t frameCount = 0; |
| nsecs_t timeStamp = m_lastFrametime; |
| |
| status_t ret = OK; |
| request = m_requestMgr->getServiceRequest(frameNumber); |
| frameCount = request->getKey(); |
| timeStamp = request->getSensorTimestamp(); |
| |
| CLOGV2("(%d)frame t(%lld), key : %d", frameCount, timeStamp, frameCount); |
| switch (type) { |
| case CAMERA3_MSG_ERROR: |
| notify.type = CAMERA3_MSG_ERROR; |
| notify.message.error.frame_number = frameCount; |
| notify.message.error.error_code = CAMERA3_MSG_ERROR_BUFFER; |
| // TODO: how can handle this? |
| //msg.message.error.error_stream = j->stream; |
| resultRequest = m_requestMgr->createResultRequest(frameNumber, EXYNOS_REQUEST_RESULT::CALLBACK_NOTIFY_ONLY, NULL, ¬ify); |
| m_requestMgr->callbackSequencerLock(); |
| m_requestMgr->callbackRequest(resultRequest); |
| m_requestMgr->callbackSequencerUnlock(); |
| break; |
| case CAMERA3_MSG_SHUTTER: |
| CLOGV2("SHUTTER (%d)frame t(%lld)", frameNumber, timeStamp); |
| notify.type = CAMERA3_MSG_SHUTTER; |
| notify.message.shutter.frame_number = frameCount; |
| notify.message.shutter.timestamp = timeStamp; |
| resultRequest = m_requestMgr->createResultRequest(frameNumber, EXYNOS_REQUEST_RESULT::CALLBACK_NOTIFY_ONLY, NULL, ¬ify); |
| /* keep current frame time for flush ops */ |
| m_requestMgr->callbackSequencerLock(); |
| m_requestMgr->callbackRequest(resultRequest); |
| m_requestMgr->callbackSequencerUnlock(); |
| m_captureResultDoneCondition.signal(); |
| break; |
| default: |
| CLOGE2("Msg type is invalid (%d)", type); |
| ret = BAD_VALUE; |
| break; |
| } |
| |
| return ret; |
| } |
| |
| status_t ExynosCamera3::m_searchFrameFromList(List<ExynosCameraFrame *> *list, Mutex *listLock, uint32_t frameCount, ExynosCameraFrame **frame) |
| { |
| ExynosCameraFrame *curFrame = NULL; |
| List<ExynosCameraFrame *>::iterator r; |
| |
| Mutex::Autolock l(listLock); |
| if (list->empty()) { |
| CLOGD2("list is empty"); |
| return NO_ERROR; |
| } |
| |
| r = list->begin()++; |
| |
| do { |
| curFrame = *r; |
| if (curFrame == NULL) { |
| CLOGE2("curFrame is empty"); |
| return INVALID_OPERATION; |
| } |
| |
| if (frameCount == curFrame->getFrameCount()) { |
| CLOGV2("frame count match: expected(%d)", frameCount); |
| *frame = curFrame; |
| return NO_ERROR; |
| } |
| r++; |
| } while (r != list->end()); |
| |
| CLOGV2("Cannot find match frame, frameCount(%d)", frameCount); |
| |
| return OK; |
| } |
| |
| status_t ExynosCamera3::m_removeFrameFromList(List<ExynosCameraFrame *> *list, Mutex *listLock, ExynosCameraFrame *frame) |
| { |
| ExynosCameraFrame *curFrame = NULL; |
| int frameCount = 0; |
| int curFrameCount = 0; |
| List<ExynosCameraFrame *>::iterator r; |
| |
| if (frame == NULL) { |
| CLOGE2("frame is NULL"); |
| return BAD_VALUE; |
| } |
| |
| Mutex::Autolock l(listLock); |
| if (list->empty()) { |
| CLOGE2("list is empty"); |
| return INVALID_OPERATION; |
| } |
| |
| frameCount = frame->getFrameCount(); |
| r = list->begin()++; |
| |
| do { |
| curFrame = *r; |
| if (curFrame == NULL) { |
| CLOGE2("curFrame is empty"); |
| return INVALID_OPERATION; |
| } |
| |
| curFrameCount = curFrame->getFrameCount(); |
| if (frameCount == curFrameCount) { |
| CLOGV2("frame count match: expected(%d), current(%d)", frameCount, curFrameCount); |
| list->erase(r); |
| return NO_ERROR; |
| } |
| CLOGW2("frame count mismatch: expected(%d), current(%d)", frameCount, curFrameCount); |
| /* curFrame->printEntity(); */ |
| r++; |
| } while (r != list->end()); |
| |
| CLOGE2("Cannot find match frame!!!"); |
| |
| return INVALID_OPERATION; |
| } |
| |
| status_t ExynosCamera3::m_clearList(List<ExynosCameraFrame *> *list, Mutex *listLock) |
| { |
| ExynosCameraFrame *curFrame = NULL; |
| List<ExynosCameraFrame *>::iterator r; |
| |
| CLOGD2("remaining frame(%zu), we remove them all", list->size()); |
| |
| Mutex::Autolock l(listLock); |
| while (!list->empty()) { |
| r = list->begin()++; |
| curFrame = *r; |
| if (curFrame != NULL) { |
| CLOGV2("remove frame count(%d)", curFrame->getFrameCount()); |
| curFrame->decRef(); |
| m_frameMgr->deleteFrame(curFrame); |
| } |
| list->erase(r); |
| } |
| |
| return OK; |
| } |
| |
| status_t ExynosCamera3::m_removeInternalFrames(List<ExynosCameraFrame *> *list, Mutex *listLock) |
| { |
| ExynosCameraFrame *curFrame = NULL; |
| List<ExynosCameraFrame *>::iterator r; |
| |
| ALOGD("DEBUG(%s[%d]):remaining frame(%zu), we remove internal frames", |
| __FUNCTION__, __LINE__, list->size()); |
| |
| Mutex::Autolock l(listLock); |
| while (!list->empty()) { |
| r = list->begin()++; |
| curFrame = *r; |
| if (curFrame != NULL) { |
| if (curFrame->getFrameType() == FRAME_TYPE_INTERNAL) { |
| ALOGV("DEBUG(%s[%d]):remove internal frame(%d)", |
| __FUNCTION__, __LINE__, curFrame->getFrameCount()); |
| m_releaseInternalFrame(curFrame); |
| } else { |
| ALOGW("WARN(%s[%d]):frame(%d) is NOT internal frame and will be remained in List", |
| __FUNCTION__, __LINE__, curFrame->getFrameCount()); |
| } |
| } |
| list->erase(r); |
| curFrame = NULL; |
| } |
| |
| return OK; |
| } |
| |
| status_t ExynosCamera3::m_releaseInternalFrame(ExynosCameraFrame *frame) |
| { |
| status_t ret = NO_ERROR; |
| ExynosCameraBuffer buffer; |
| ExynosCameraBufferManager *bufferMgr = NULL; |
| |
| if (frame == NULL) { |
| ALOGE("ERR(%s[%d]):frame is NULL", __FUNCTION__, __LINE__); |
| return BAD_VALUE; |
| } |
| if (frame->getFrameType() != FRAME_TYPE_INTERNAL) { |
| ALOGE("ERR(%s[%d]):frame(%d) is NOT internal frame", |
| __FUNCTION__, __LINE__, frame->getFrameCount()); |
| return BAD_VALUE; |
| } |
| |
| /* Return bayer buffer */ |
| if (m_parameters->isFlite3aaOtf() == false) { |
| ret = frame->getDstBuffer(PIPE_FLITE, &buffer); |
| if (ret != NO_ERROR) { |
| ALOGE("ERR(%s[%d]):getDstBuffer failed. PIPE_FLITE, ret %d", |
| __FUNCTION__, __LINE__, ret); |
| } else if (buffer.index >= 0) { |
| ret = m_getBufferManager(PIPE_FLITE, &bufferMgr, DST_BUFFER_DIRECTION); |
| if (ret != NO_ERROR) { |
| ALOGE("ERR(%s[%d]):Failed to getBufferManager for FLITE", |
| __FUNCTION__, __LINE__); |
| } else { |
| ret = m_putBuffers(bufferMgr, buffer.index); |
| if (ret != NO_ERROR) |
| ALOGE("ERR(%s[%d]):Failed to putBuffer for FLITE. index %d", |
| __FUNCTION__, __LINE__, buffer.index); |
| } |
| } |
| } |
| |
| /* Return 3AS buffer */ |
| ret = frame->getSrcBuffer(PIPE_3AA, &buffer); |
| if (ret != NO_ERROR) { |
| ALOGE("ERR(%s[%d]):getSrcBuffer failed. PIPE_3AA, ret(%d)", |
| __FUNCTION__, __LINE__, ret); |
| } else if (buffer.index >= 0) { |
| ret = m_getBufferManager(PIPE_3AA, &bufferMgr, SRC_BUFFER_DIRECTION); |
| if (ret != NO_ERROR) { |
| ALOGE("ERR(%s[%d]):Failed to getBufferManager for 3AS", |
| __FUNCTION__, __LINE__); |
| } else { |
| ret = m_putBuffers(bufferMgr, buffer.index); |
| if (ret != NO_ERROR) |
| ALOGE("ERR(%s[%d]):Failed to putBuffer for 3AS. index %d", |
| __FUNCTION__, __LINE__, buffer.index); |
| } |
| } |
| |
| /* Return 3AP buffer */ |
| if (frame->getRequest(PIPE_3AP) == true) { |
| ret = frame->getDstBuffer(PIPE_3AA, &buffer); |
| if (ret != NO_ERROR) { |
| ALOGE("ERR(%s[%d]):getDstBuffer failed. PIPE_3AA, ret %d", |
| __FUNCTION__, __LINE__, ret); |
| } else if (buffer.index >= 0) { |
| ret = m_getBufferManager(PIPE_3AA, &bufferMgr, DST_BUFFER_DIRECTION); |
| if (ret != NO_ERROR) { |
| ALOGE("ERR(%s[%d]):Failed to getBufferManager for 3AP", |
| __FUNCTION__, __LINE__); |
| } else { |
| ret = m_putBuffers(bufferMgr, buffer.index); |
| if (ret != NO_ERROR) |
| ALOGE("ERR(%s[%d]):Failed to putBuffer for 3AP. index %d", |
| __FUNCTION__, __LINE__, buffer.index); |
| } |
| } |
| } |
| |
| frame->decRef(); |
| m_frameMgr->deleteFrame(frame); |
| frame = NULL; |
| |
| return ret; |
| } |
| |
| status_t ExynosCamera3::m_setFrameManager() |
| { |
| sp<FrameWorker> worker; |
| m_frameMgr = new ExynosCameraFrameManager("FRAME MANAGER", m_cameraId, FRAMEMGR_OPER::SLIENT, 50, 100); |
| |
| worker = new CreateWorker("CREATE FRAME WORKER", m_cameraId, FRAMEMGR_OPER::SLIENT, 40); |
| m_frameMgr->setWorker(FRAMEMGR_WORKER::CREATE, worker); |
| |
| worker = new DeleteWorker("DELETE FRAME WORKER", m_cameraId, FRAMEMGR_OPER::SLIENT); |
| m_frameMgr->setWorker(FRAMEMGR_WORKER::DELETE, worker); |
| |
| sp<KeyBox> key = new KeyBox("FRAME KEYBOX", m_cameraId); |
| |
| m_frameMgr->setKeybox(key); |
| |
| return NO_ERROR; |
| } |
| |
| bool ExynosCamera3::m_frameFactoryCreateThreadFunc(void) |
| { |
| |
| #ifdef DEBUG |
| ExynosCameraAutoTimer autoTimer(__FUNCTION__); |
| #endif |
| bool loop = false; |
| status_t ret = NO_ERROR; |
| |
| ExynosCamera3FrameFactory *framefactory = NULL; |
| |
| ret = m_frameFactoryQ->waitAndPopProcessQ(&framefactory); |
| if (ret < 0) { |
| CLOGE2("wait and pop fail, ret(%d)", ret); |
| goto func_exit; |
| } |
| |
| if (framefactory == NULL) { |
| CLOGE2("framefactory is NULL"); |
| goto func_exit; |
| } |
| |
| if (framefactory->isCreated() == false) { |
| CLOGD2("framefactory create"); |
| framefactory->create(); |
| } else { |
| CLOGD2("framefactory already create"); |
| } |
| |
| func_exit: |
| if (0 < m_frameFactoryQ->getSizeOfProcessQ()) { |
| loop = true; |
| } |
| |
| return loop; |
| } |
| |
| bool ExynosCamera3::m_frameFactoryStartThreadFunc(void) |
| { |
| #ifdef DEBUG |
| ExynosCameraAutoTimer autoTimer(__FUNCTION__); |
| #endif |
| status_t ret = NO_ERROR; |
| ExynosCamera3FrameFactory *factory = NULL; |
| ExynosCameraRequest *request = NULL; |
| uint32_t prepare = 1; |
| |
| if (m_requestMgr->getServiceRequestCount() < 1) { |
| ALOGE("ERR(%s[%d]):There is NO available request!!! \"processCaptureRequest()\" must be called, first!!!", __FUNCTION__, __LINE__); |
| return false; |
| } |
| |
| /* 1. Get the first request from the request manager */ |
| m_popRequest(&request); |
| if (request == NULL) { |
| ALOGE("ERR(%s[%d]):request is NULL", __FUNCTION__, __LINE__); |
| } else { |
| request_info_t *requestInfo = new request_info_t; |
| requestInfo->request = request; |
| requestInfo->sensorControledFrameCount = 0; |
| m_requestWaitingList.push_back(requestInfo); |
| } |
| |
| /* 2. Get the initial metadata from request */ |
| ret = request->getServiceShot(m_currentShot); |
| if (ret != NO_ERROR) { |
| ALOGE("ERR(%s[%d]):Failed to getServiceShot. requestKey %d ret %d", |
| __FUNCTION__, __LINE__, request->getKey(), ret); |
| return false; |
| } |
| |
| m_internalFrameCount = 0; |
| prepare = m_exynosconfig->current->pipeInfo.prepare[PIPE_3AA]; |
| |
| ALOGD("DEBUG(%s[%d]):prepare %d", __FUNCTION__, __LINE__, prepare); |
| |
| /* 3. Push the prepare frame into 3AA Pipe |
| * - call initPipes() |
| */ |
| m_createPrepareFrameFunc(request); |
| for (uint32_t i = 0; i < prepare; i++) { |
| ret = m_createFrameFunc(); |
| if (ret != NO_ERROR) |
| ALOGE("ERR(%s[%d]):Failed to createFrameFunc for preparing frame. prepareCount %d/%d", |
| __FUNCTION__, __LINE__, i, prepare); |
| } |
| |
| factory = m_frameFactory[FRAME_FACTORY_TYPE_CAPTURE_PREVIEW]; |
| if (factory != NULL) { |
| /* - call preparePipes(); |
| * - call startPipes() |
| * - call startInitialThreads() |
| */ |
| if (m_flagStartFrameFactory == false) |
| m_startFrameFactory(factory); |
| |
| if (m_shotDoneQ != NULL) |
| m_shotDoneQ->release(); |
| |
| for (int i = 0; i < MAX_PIPE_NUM; i++) { |
| if (m_pipeFrameDoneQ[i] != NULL) { |
| m_pipeFrameDoneQ[i]->release(); |
| } |
| } |
| m_reprocessingDoneQ->release(); |
| m_pipeCaptureFrameDoneQ->release(); |
| m_mainThread->run(PRIORITY_URGENT_DISPLAY); |
| |
| m_previewStream3AAThread->run(PRIORITY_DEFAULT); |
| if (m_parameters->isMcscVraOtf() == false) |
| m_previewStreamVRAThread->run(PRIORITY_DEFAULT); |
| if (m_flagBayerRequest == true) |
| m_previewStreamBayerThread->run(PRIORITY_DEFAULT); |
| m_duplicateBufferThread->run(PRIORITY_DEFAULT); |
| m_monitorThread->run(PRIORITY_DEFAULT); |
| |
| m_internalFrameThread->run(PRIORITY_DEFAULT); |
| |
| #ifdef USE_INTERNAL_FRAME |
| /* internal frame */ |
| m_internalFrameHandlerThread->run(PRIORITY_DEFAULT); |
| #endif /* #ifdef USE_INTERNAL_FRAME */ |
| if (m_flagBayerRequest == true |
| && factory->checkPipeThreadRunning(m_getBayerPipeId()) == false) |
| factory->startThread(m_getBayerPipeId()); |
| } else { |
| CLOGE2("Can't start FrameFactory!!!! FrameFactory is NULL!! Prepare(%d), Request(%d)", |
| prepare, m_requestMgr != NULL ? m_requestMgr->getRequestCount(): 0); |
| return false; |
| } |
| m_frameFactoryStartDone = true; |
| |
| return false; |
| } |
| |
| status_t ExynosCamera3::m_constructFrameFactory(void) |
| { |
| CLOGI2("-IN-"); |
| |
| ExynosCameraAutoTimer autoTimer(__FUNCTION__); |
| status_t ret = NO_ERROR; |
| ExynosCamera3FrameFactory *factory = NULL; |
| |
| for(int i = 0; i < FRAME_FACTORY_TYPE_MAX; i++) |
| m_frameFactory[i] = NULL; |
| |
| factory = new ExynosCamera3FrameFactoryPreview(m_cameraId, m_parameters); |
| factory->setFrameCreateHandler(&ExynosCamera3::m_previewframeHandler); |
| m_frameFactory[FRAME_FACTORY_TYPE_CAPTURE_PREVIEW] = factory; |
| m_frameFactory[FRAME_FACTORY_TYPE_RECORDING_PREVIEW] = factory; |
| |
| m_frameFactory[FRAME_FACTORY_TYPE_DUAL_PREVIEW] = factory; |
| |
| if (m_parameters->isReprocessing() == true) { |
| factory = new ExynosCamera3FrameReprocessingFactory(m_cameraId, m_parameters); |
| factory->setFrameCreateHandler(&ExynosCamera3::m_captureframeHandler); |
| m_frameFactory[FRAME_FACTORY_TYPE_REPROCESSING] = factory; |
| } |
| |
| m_waitCompanionThreadEnd(); |
| |
| /* |
| #if defined(SAMSUNG_EEPROM) |
| m_parameters->setRomReadThreadDone(true); |
| #endif |
| */ |
| |
| for (int i = 0; i < FRAME_FACTORY_TYPE_MAX; i++) { |
| factory = m_frameFactory[i]; |
| if ((factory != NULL) && (factory->isCreated() == false)) { |
| factory->setFrameManager(m_frameMgr); |
| m_frameFactoryQ->pushProcessQ(&factory); |
| } |
| } |
| |
| CLOGI2("-OUT-"); |
| |
| return ret; |
| } |
| |
| status_t ExynosCamera3::m_startFrameFactory(ExynosCamera3FrameFactory *factory) |
| { |
| status_t ret = OK; |
| |
| uint32_t flitePrepareCnt = m_prepareFliteCnt; |
| CLOGD2("flitePrepareCnt:%d", flitePrepareCnt); |
| |
| /* prepare pipes */ |
| #if !defined(ENABLE_FULL_FRAME) |
| ret = factory->preparePipes(flitePrepareCnt); |
| #else |
| ret = factory->preparePipes(); |
| #endif |
| |
| if (ret < 0) { |
| CLOGW("ERR(%s[%d]):Failed to prepare FLITE", __FUNCTION__, __LINE__); |
| } |
| |
| /* s_ctrl HAL version for selecting dvfs table */ |
| ret = factory->setControl(V4L2_CID_IS_HAL_VERSION, IS_HAL_VER_3_2, PIPE_3AA); |
| |
| if (ret < 0) |
| CLOGW2("V4L2_CID_IS_HAL_VERSION is fail"); |
| |
| /* stream on pipes */ |
| ret = factory->startPipes(); |
| if (ret < 0) { |
| CLOGE2("startPipe fail"); |
| return ret; |
| } |
| |
| /* start all thread */ |
| ret = factory->startInitialThreads(); |
| if (ret < 0) { |
| CLOGE2("startInitialThreads fail"); |
| return ret; |
| } |
| |
| m_flagStartFrameFactory = true; |
| |
| return ret; |
| } |
| |
| status_t ExynosCamera3::m_stopFrameFactory(ExynosCamera3FrameFactory *factory) |
| { |
| int ret = 0; |
| |
| CLOGD("DEBUG(%s[%d])", __FUNCTION__, __LINE__); |
| if (factory != NULL && factory->isCreated()) { |
| ret = factory->stopPipes(); |
| if (ret < 0) { |
| CLOGE2("stopPipe fail"); |
| return ret; |
| } |
| } |
| |
| m_flagStartFrameFactory = false; |
| |
| return ret; |
| } |
| |
| status_t ExynosCamera3::m_deinitFrameFactory() |
| { |
| CLOGI2("-IN-"); |
| |
| ExynosCameraAutoTimer autoTimer(__FUNCTION__); |
| |
| status_t ret = NO_ERROR; |
| ExynosCamera3FrameFactory *frameFactory = NULL; |
| |
| for (int i = 0; i < FRAME_FACTORY_TYPE_MAX; i++) { |
| if (m_frameFactory[i] != NULL) { |
| frameFactory = m_frameFactory[i]; |
| |
| for (int k = i + 1; k < FRAME_FACTORY_TYPE_MAX; k++) { |
| if (frameFactory == m_frameFactory[k]) { |
| CLOGD2("m_frameFactory index(%d) and index(%d) are same instance, set index(%d) = NULL", i, k, k); |
| m_frameFactory[k] = NULL; |
| } |
| } |
| |
| ret = m_frameFactory[i]->destroy(); |
| if (ret < 0) |
| CLOGE2("m_frameFactory[%d] destroy fail", i); |
| |
| SAFE_DELETE(m_frameFactory[i]); |
| |
| CLOGD2("m_frameFactory[%d] destroyed", i); |
| } |
| } |
| |
| CLOGI2("-OUT-"); |
| |
| return ret; |
| |
| } |
| |
| status_t ExynosCamera3::m_setupReprocessingPipeline(void) |
| { |
| status_t ret = NO_ERROR; |
| uint32_t pipeId = MAX_PIPE_NUM; |
| ExynosCamera3FrameFactory *factory = m_frameFactory[FRAME_FACTORY_TYPE_REPROCESSING]; |
| ExynosCameraStream *stream = NULL; |
| ExynosCameraBufferManager *bufferMgr = NULL; |
| ExynosCameraBufferManager *taaBufferManager[MAX_NODE]; |
| ExynosCameraBufferManager *ispBufferManager[MAX_NODE]; |
| ExynosCameraBufferManager *mcscBufferManager[MAX_NODE]; |
| ExynosCameraBufferManager **tempBufferManager; |
| |
| for (int i = 0; i < MAX_NODE; i++) { |
| taaBufferManager[i] = NULL; |
| ispBufferManager[i] = NULL; |
| mcscBufferManager[i] = NULL; |
| } |
| |
| /* Setting bufferManager based on H/W pipeline */ |
| tempBufferManager = taaBufferManager; |
| pipeId = PIPE_3AA_REPROCESSING; |
| |
| tempBufferManager[factory->getNodeType(PIPE_3AA_REPROCESSING)] = m_fliteBufferMgr; |
| tempBufferManager[factory->getNodeType(PIPE_3AP_REPROCESSING)] = m_ispReprocessingBufferMgr; |
| |
| if (m_parameters->isReprocessing3aaIspOTF() == false) { |
| ret = factory->setBufferManagerToPipe(tempBufferManager, pipeId); |
| if (ret != NO_ERROR) { |
| CLOGE2("Failed to setBufferManagerToPipe into pipeId %d", pipeId); |
| return ret; |
| } |
| tempBufferManager = ispBufferManager; |
| pipeId = PIPE_ISP_REPROCESSING; |
| } |
| |
| tempBufferManager[factory->getNodeType(PIPE_ISP_REPROCESSING)] = m_ispReprocessingBufferMgr; |
| tempBufferManager[factory->getNodeType(PIPE_ISPC_REPROCESSING)] = m_yuvCaptureBufferMgr; |
| |
| if (m_parameters->isReprocessingIspMcscOTF() == false) { |
| ret = factory->setBufferManagerToPipe(tempBufferManager, pipeId); |
| if (ret != NO_ERROR) { |
| CLOGE2("Failed to setBufferManagerToPipe into pipeId %d", pipeId); |
| return ret; |
| } |
| tempBufferManager = mcscBufferManager; |
| pipeId = PIPE_MCSC_REPROCESSING; |
| } |
| |
| tempBufferManager[factory->getNodeType(PIPE_MCSC0_REPROCESSING)] = m_yuvCaptureReprocessingBufferMgr; |
| tempBufferManager[factory->getNodeType(PIPE_HWFC_JPEG_SRC_REPROCESSING)] = m_yuvCaptureReprocessingBufferMgr; |
| tempBufferManager[factory->getNodeType(PIPE_HWFC_THUMB_SRC_REPROCESSING)] = m_thumbnailBufferMgr; |
| /* Dummy buffer manager */ |
| tempBufferManager[factory->getNodeType(PIPE_HWFC_THUMB_DST_REPROCESSING)] = m_thumbnailBufferMgr; |
| |
| if (m_streamManager->findStream(HAL_STREAM_ID_JPEG) == true) { |
| ret = m_streamManager->getStream(HAL_STREAM_ID_JPEG, &stream); |
| if (ret != NO_ERROR) |
| CLOGE2("Failed to getStream from streamMgr. HAL_STREAM_ID_JPEG"); |
| |
| ret = stream->getBufferManager(&bufferMgr); |
| if (ret != NO_ERROR) |
| CLOGE2("Failed to getBufferMgr. HAL_STREAM_ID_JPEG"); |
| |
| tempBufferManager[factory->getNodeType(PIPE_HWFC_JPEG_DST_REPROCESSING)] = bufferMgr; |
| } |
| |
| ret = factory->setBufferManagerToPipe(tempBufferManager, pipeId); |
| if (ret != NO_ERROR) { |
| CLOGE2("Failed to setBufferManagerToPipe into pipeId %d", pipeId); |
| return ret; |
| } |
| |
| /* Setting OutputFrameQ/FrameDoneQ to Pipe */ |
| if(m_parameters->getUsePureBayerReprocessing()) { |
| // Pure bayer reprocessing |
| pipeId = PIPE_3AA_REPROCESSING; |
| } else if (m_parameters->isUseYuvReprocessing() == true) { |
| // YUV reprocessing |
| pipeId = PIPE_MCSC_REPROCESSING; |
| } else { |
| // Dirty bayer reprocessing |
| pipeId = PIPE_ISP_REPROCESSING; |
| } |
| |
| /* TODO : Consider the M2M Reprocessing Scenario */ |
| if (m_parameters->isUseYuvReprocessingForThumbnail() == true) { |
| factory->setOutputFrameQToPipe(m_reprocessingDoneQ, pipeId); |
| } else { |
| factory->setOutputFrameQToPipe(m_pipeCaptureFrameDoneQ, pipeId); |
| factory->setFrameDoneQToPipe(m_reprocessingDoneQ, pipeId); |
| } |
| |
| return ret; |
| } |
| |
| void ExynosCamera3::m_updateCropRegion(struct camera2_shot_ext *shot_ext) |
| { |
| int sensorMaxW = 0, sensorMaxH = 0; |
| |
| m_parameters->getMaxSensorSize(&sensorMaxW, &sensorMaxH); |
| |
| shot_ext->shot.ctl.scaler.cropRegion[0] = ALIGN_DOWN(shot_ext->shot.ctl.scaler.cropRegion[0], 2); |
| shot_ext->shot.ctl.scaler.cropRegion[1] = ALIGN_DOWN(shot_ext->shot.ctl.scaler.cropRegion[1], 2); |
| shot_ext->shot.ctl.scaler.cropRegion[2] = ALIGN_UP(shot_ext->shot.ctl.scaler.cropRegion[2], 2); |
| shot_ext->shot.ctl.scaler.cropRegion[3] = ALIGN_UP(shot_ext->shot.ctl.scaler.cropRegion[3], 2); |
| |
| /* 1. Check the validation of the crop size(width x height). |
| * The crop size must be smaller than sensor max size. |
| */ |
| if (sensorMaxW < (int) shot_ext->shot.ctl.scaler.cropRegion[2] |
| || sensorMaxH < (int)shot_ext->shot.ctl.scaler.cropRegion[3]) { |
| CLOGE2("Invalid Crop Size(%d, %d), sensorMax(%d, %d)", |
| shot_ext->shot.ctl.scaler.cropRegion[2], |
| shot_ext->shot.ctl.scaler.cropRegion[3], |
| sensorMaxW, sensorMaxH); |
| shot_ext->shot.ctl.scaler.cropRegion[2] = sensorMaxW; |
| shot_ext->shot.ctl.scaler.cropRegion[3] = sensorMaxH; |
| } |
| |
| /* 2. Check the validation of the crop offset. |
| * Offset coordinate + width or height must be smaller than sensor max size. |
| */ |
| if ((int)(shot_ext->shot.ctl.scaler.cropRegion[0]) < 0) { |
| CLOGE2("Invalid Crop Region, offsetX(%d), Change to 0", |
| shot_ext->shot.ctl.scaler.cropRegion[0]); |
| shot_ext->shot.ctl.scaler.cropRegion[0] = 0; |
| } |
| |
| if ((int)(shot_ext->shot.ctl.scaler.cropRegion[1]) < 0) { |
| CLOGE2("Invalid Crop Region, offsetX(%d), Change to 0", |
| shot_ext->shot.ctl.scaler.cropRegion[1]); |
| shot_ext->shot.ctl.scaler.cropRegion[1] = 0; |
| } |
| |
| if (sensorMaxW < (int) shot_ext->shot.ctl.scaler.cropRegion[0] |
| + (int) shot_ext->shot.ctl.scaler.cropRegion[2]) { |
| CLOGE2("Invalid Crop Region, offsetX(%d), width(%d) sensorMaxW(%d)", |
| shot_ext->shot.ctl.scaler.cropRegion[0], |
| shot_ext->shot.ctl.scaler.cropRegion[2], |
| sensorMaxW); |
| shot_ext->shot.ctl.scaler.cropRegion[0] = sensorMaxW - shot_ext->shot.ctl.scaler.cropRegion[2]; |
| } |
| |
| if (sensorMaxH < (int) shot_ext->shot.ctl.scaler.cropRegion[1] |
| + (int) shot_ext->shot.ctl.scaler.cropRegion[3]) { |
| CLOGE2("Invalid Crop Region, offsetY(%d), height(%d) sensorMaxH(%d)", |
| shot_ext->shot.ctl.scaler.cropRegion[1], |
| shot_ext->shot.ctl.scaler.cropRegion[3], |
| sensorMaxH); |
| shot_ext->shot.ctl.scaler.cropRegion[1] = sensorMaxH - shot_ext->shot.ctl.scaler.cropRegion[3]; |
| } |
| |
| m_parameters->setCropRegion( |
| shot_ext->shot.ctl.scaler.cropRegion[0], |
| shot_ext->shot.ctl.scaler.cropRegion[1], |
| shot_ext->shot.ctl.scaler.cropRegion[2], |
| shot_ext->shot.ctl.scaler.cropRegion[3]); |
| } |
| |
| status_t ExynosCamera3::m_updateJpegControlInfo(const struct camera2_shot_ext *shot_ext) |
| { |
| status_t ret = NO_ERROR; |
| if (shot_ext == NULL) { |
| CLOGE("ERR(%s[%d]):shot_ext is NULL", __FUNCTION__, __LINE__); |
| return BAD_VALUE; |
| } |
| ret = m_parameters->checkJpegQuality(shot_ext->shot.ctl.jpeg.quality); |
| if (ret != NO_ERROR) |
| CLOGE("ERR(%s[%d]):Failed to checkJpegQuality. quality %d", |
| __FUNCTION__, __LINE__, shot_ext->shot.ctl.jpeg.quality); |
| ret = m_parameters->checkThumbnailSize( |
| shot_ext->shot.ctl.jpeg.thumbnailSize[0], |
| shot_ext->shot.ctl.jpeg.thumbnailSize[1]); |
| if (ret != NO_ERROR) |
| CLOGE("ERR(%s[%d]):Failed to checkThumbnailSize. size %dx%d", |
| __FUNCTION__, __LINE__, |
| shot_ext->shot.ctl.jpeg.thumbnailSize[0], |
| shot_ext->shot.ctl.jpeg.thumbnailSize[1]); |
| ret = m_parameters->checkThumbnailQuality(shot_ext->shot.ctl.jpeg.thumbnailQuality); |
| if (ret != NO_ERROR) |
| CLOGE("ERR(%s[%d]):Failed to checkThumbnailQuality. quality %d", |
| __FUNCTION__, __LINE__, |
| shot_ext->shot.ctl.jpeg.thumbnailQuality); |
| return ret; |
| } |
| status_t ExynosCamera3::m_generateFrame(int32_t frameCount, ExynosCamera3FrameFactory *factory, List<ExynosCameraFrame *> *list, Mutex *listLock, ExynosCameraFrame **newFrame) |
| { |
| status_t ret = OK; |
| *newFrame = NULL; |
| |
| CLOGV2("(%d)", frameCount); |
| if (frameCount >= 0) { |
| ret = m_searchFrameFromList(list, listLock, frameCount, newFrame); |
| if (ret < 0) { |
| CLOGE2("searchFrameFromList fail"); |
| return INVALID_OPERATION; |
| } |
| } |
| |
| if (*newFrame == NULL) { |
| *newFrame = factory->createNewFrame(frameCount); |
| if (*newFrame == NULL) { |
| CLOGE2("newFrame is NULL"); |
| return UNKNOWN_ERROR; |
| } |
| listLock->lock(); |
| list->push_back(*newFrame); |
| listLock->unlock(); |
| } |
| |
| return ret; |
| } |
| |
| status_t ExynosCamera3::m_setupEntity(uint32_t pipeId, ExynosCameraFrame *newFrame, ExynosCameraBuffer *srcBuf, ExynosCameraBuffer *dstBuf) |
| { |
| status_t ret = OK; |
| entity_buffer_state_t entityBufferState; |
| |
| CLOGV2("pipeId : %d", pipeId); |
| /* set SRC buffer */ |
| ret = newFrame->getSrcBufferState(pipeId, &entityBufferState); |
| if (ret < 0) { |
| CLOGE2("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) { |
| CLOGE2("m_setSrcBuffer fail, pipeId(%d), ret(%d)", pipeId, ret); |
| return ret; |
| } |
| } |
| |
| /* set DST buffer */ |
| ret = newFrame->getDstBufferState(pipeId, &entityBufferState); |
| if (ret < 0) { |
| CLOGE2("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) { |
| CLOGE2("m_setDstBuffer fail, pipeId(%d), ret(%d)", pipeId, ret); |
| return ret; |
| } |
| } |
| |
| ret = newFrame->setEntityState(pipeId, ENTITY_STATE_PROCESSING); |
| if (ret < 0) { |
| CLOGE2("setEntityState(ENTITY_STATE_PROCESSING) fail, pipeId(%d), ret(%d)", pipeId, ret); |
| return ret; |
| } |
| |
| return ret; |
| } |
| |
| status_t ExynosCamera3::m_setSrcBuffer(uint32_t pipeId, ExynosCameraFrame *newFrame, ExynosCameraBuffer *buffer) |
| { |
| status_t ret = OK; |
| int bufIndex = -1; |
| ExynosCameraBufferManager *bufferMgr = NULL; |
| ExynosCameraBuffer srcBuf; |
| |
| CLOGV2("pipeId : %d", pipeId); |
| if (buffer == NULL) { |
| buffer = &srcBuf; |
| |
| ret = m_getBufferManager(pipeId, &bufferMgr, SRC_BUFFER_DIRECTION); |
| if (ret < 0) { |
| CLOGE2("getBufferManager(SRC) fail, pipeId(%d), ret(%d)", pipeId, ret); |
| return ret; |
| } |
| |
| if (bufferMgr == NULL) { |
| CLOGE2("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) { |
| CLOGE2("getBuffer fail, pipeId(%d), frameCount(%d), ret(%d)", pipeId, newFrame->getFrameCount(), ret); |
| return ret; |
| } |
| } |
| |
| /* set buffers */ |
| ret = newFrame->setSrcBuffer(pipeId, *buffer); |
| if (ret < 0) { |
| CLOGE2("setSrcBuffer fail, pipeId(%d), ret(%d)", pipeId, ret); |
| return ret; |
| } |
| |
| return ret; |
| } |
| |
| status_t ExynosCamera3::m_setDstBuffer(uint32_t pipeId, ExynosCameraFrame *newFrame, ExynosCameraBuffer *buffer) |
| { |
| status_t ret = OK; |
| int bufIndex = -1; |
| ExynosCameraBufferManager *bufferMgr = NULL; |
| ExynosCameraBuffer dstBuf; |
| |
| CLOGV2("pipeId : %d", pipeId); |
| if (buffer == NULL) { |
| buffer = &dstBuf; |
| |
| ret = m_getBufferManager(pipeId, &bufferMgr, DST_BUFFER_DIRECTION); |
| if (ret < 0) { |
| CLOGE2("getBufferManager(DST) fail, pipeId(%d), ret(%d)", pipeId, ret); |
| return ret; |
| } |
| |
| if (bufferMgr == NULL) { |
| CLOGE2("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) { |
| CLOGE2("getBuffer fail, pipeId(%d), frameCount(%d), ret(%d)", pipeId, newFrame->getFrameCount(), ret); |
| return ret; |
| } |
| } |
| |
| /* set buffers */ |
| ret = newFrame->setDstBuffer(pipeId, *buffer); |
| if (ret < 0) { |
| CLOGE2("setDstBuffer fail, pipeId(%d), ret(%d)", pipeId, ret); |
| return ret; |
| } |
| |
| return ret; |
| } |
| |
| status_t ExynosCamera3::m_setSrcBuffer(uint32_t pipeId, ExynosCameraFrame *newFrame, ExynosCameraBuffer *buffer, ExynosCameraBufferManager *bufMgr) |
| { |
| status_t ret = OK; |
| int bufIndex = -1; |
| ExynosCameraBuffer srcBuf; |
| |
| CLOGV2("pipeId : %d", pipeId); |
| if (bufMgr == NULL) { |
| |
| ret = m_getBufferManager(pipeId, &bufMgr, SRC_BUFFER_DIRECTION); |
| if (ret < 0) { |
| CLOGE2("getBufferManager(SRC) fail, pipeId(%d), ret(%d)", pipeId, ret); |
| return ret; |
| } |
| |
| if (bufMgr == NULL) { |
| CLOGE2("buffer manager is NULL, pipeId(%d)", pipeId); |
| return BAD_VALUE; |
| } |
| |
| } |
| |
| /* get buffers */ |
| ret = bufMgr->getBuffer(&bufIndex, EXYNOS_CAMERA_BUFFER_POSITION_IN_HAL, buffer); |
| if (ret < 0) { |
| CLOGE2("getBuffer fail, pipeId(%d), frameCount(%d), ret(%d)", pipeId, newFrame->getFrameCount(), ret); |
| return ret; |
| } |
| |
| /* set buffers */ |
| ret = newFrame->setSrcBuffer(pipeId, *buffer); |
| if (ret < 0) { |
| CLOGE2("setSrcBuffer fail, pipeId(%d), ret(%d)", pipeId, ret); |
| return ret; |
| } |
| |
| return ret; |
| } |
| |
| status_t ExynosCamera3::m_setDstBuffer(uint32_t pipeId, ExynosCameraFrame *newFrame, ExynosCameraBuffer *buffer, ExynosCameraBufferManager *bufMgr) |
| { |
| status_t ret = OK; |
| int bufIndex = -1; |
| ExynosCameraBuffer dstBuf; |
| |
| CLOGD2("pipeId : %d", pipeId); |
| if (bufMgr == NULL) { |
| |
| ret = m_getBufferManager(pipeId, &bufMgr, DST_BUFFER_DIRECTION); |
| if (ret < 0) { |
| CLOGE2("getBufferManager(DST) fail, pipeId(%d), ret(%d)", pipeId, ret); |
| return ret; |
| } |
| |
| if (bufMgr == NULL) { |
| CLOGE2("buffer manager is NULL, pipeId(%d)", pipeId); |
| return BAD_VALUE; |
| } |
| } |
| |
| /* get buffers */ |
| ret = bufMgr->getBuffer(&bufIndex, EXYNOS_CAMERA_BUFFER_POSITION_IN_HAL, buffer); |
| if (ret < 0) { |
| CLOGE2("getBuffer fail, pipeId(%d), frameCount(%d), ret(%d)", pipeId, newFrame->getFrameCount(), ret); |
| return ret; |
| } |
| |
| /* set buffers */ |
| ret = newFrame->setDstBuffer(pipeId, *buffer); |
| if (ret < 0) { |
| CLOGE2("setDstBuffer fail, pipeId(%d), ret(%d)", pipeId, ret); |
| return ret; |
| } |
| |
| return ret; |
| } |
| |
| /* This function reset buffer state of pipeId. |
| * Some pipes are shared by multi stream. In this case, we need reset buffer for using PIPE again. |
| */ |
| status_t ExynosCamera3::m_resetBufferState(uint32_t pipeId, ExynosCameraFrame *frame) |
| { |
| status_t ret = NO_ERROR; |
| entity_buffer_state_t bufState = ENTITY_BUFFER_STATE_NOREQ; |
| |
| if (frame == NULL) { |
| CLOGE2("frame is NULL"); |
| ret = BAD_VALUE; |
| goto ERR; |
| } |
| |
| ret = frame->getSrcBufferState(pipeId, &bufState); |
| if (ret < 0) { |
| CLOGE2("getSrcBufferState fail, pipeId(%d), ret(%d)", pipeId, ret); |
| goto ERR; |
| } |
| |
| if (bufState != ENTITY_BUFFER_STATE_NOREQ && bufState != ENTITY_BUFFER_STATE_INVALID) { |
| frame->setSrcBufferState(pipeId, ENTITY_BUFFER_STATE_REQUESTED); |
| } else { |
| CLOGW2("SrcBufferState is not COMPLETE, fail to reset buffer state, pipeId(%d), state(%d)", pipeId, bufState); |
| ret = INVALID_OPERATION; |
| goto ERR; |
| } |
| |
| |
| ret = frame->getDstBufferState(pipeId, &bufState); |
| if (ret < 0) { |
| CLOGE2("getDstBufferState fail, pipeId(%d), ret(%d)", pipeId, ret); |
| goto ERR; |
| } |
| |
| if (bufState != ENTITY_BUFFER_STATE_NOREQ && bufState != ENTITY_BUFFER_STATE_INVALID) { |
| ret = frame->setDstBufferState(pipeId, ENTITY_BUFFER_STATE_REQUESTED); |
| if (ret != NO_ERROR) |
| CLOGE2("setDstBufferState fail, pipeId(%d), ret(%d)", pipeId, ret); |
| } else { |
| CLOGW2("DstBufferState is not COMPLETE, fail to reset buffer state, pipeId(%d), state(%d)", pipeId, bufState); |
| ret = INVALID_OPERATION; |
| goto ERR; |
| } |
| |
| ERR: |
| return ret; |
| } |
| |
| status_t ExynosCamera3::m_getBufferManager(uint32_t pipeId, ExynosCameraBufferManager **bufMgr, uint32_t direction) |
| { |
| status_t ret = NO_ERROR; |
| ExynosCameraBufferManager **bufMgrList[2] = {NULL}; |
| |
| switch (pipeId) { |
| case PIPE_FLITE: |
| bufMgrList[0] = NULL; |
| bufMgrList[1] = &m_bayerBufferMgr; |
| break; |
| case PIPE_3AA_ISP: |
| bufMgrList[0] = &m_3aaBufferMgr; |
| bufMgrList[1] = &m_ispBufferMgr; |
| break; |
| case PIPE_3AA: |
| bufMgrList[0] = &m_3aaBufferMgr; |
| bufMgrList[1] = &m_ispBufferMgr; |
| break; |
| case PIPE_3AC: |
| bufMgrList[0] = NULL; |
| bufMgrList[1] = &m_bayerBufferMgr; |
| break; |
| case PIPE_ISP: |
| bufMgrList[0] = &m_ispBufferMgr; |
| bufMgrList[1] = &m_internalScpBufferMgr; |
| break; |
| case PIPE_SCP: |
| bufMgrList[0] = NULL; |
| bufMgrList[1] = &m_internalScpBufferMgr; |
| break; |
| case PIPE_VRA: |
| bufMgrList[0] = &m_vraBufferMgr; |
| bufMgrList[1] = NULL; |
| break; |
| case PIPE_GSC: |
| bufMgrList[0] = &m_internalScpBufferMgr; |
| bufMgrList[1] = NULL; |
| break; |
| case PIPE_GSC_VIDEO: |
| bufMgrList[0] = &m_internalScpBufferMgr; |
| bufMgrList[1] = NULL; |
| break; |
| case PIPE_GSC_PICTURE: |
| bufMgrList[0] = &m_yuvCaptureBufferMgr; |
| bufMgrList[1] = &m_gscBufferMgr; |
| break; |
| case PIPE_JPEG: |
| case PIPE_JPEG_REPROCESSING: |
| bufMgrList[0] = NULL; |
| bufMgrList[1] = NULL; |
| break; |
| case PIPE_3AA_REPROCESSING: |
| bufMgrList[0] = &m_fliteBufferMgr; |
| bufMgrList[1] = &m_ispReprocessingBufferMgr; |
| break; |
| case PIPE_ISP_REPROCESSING: |
| bufMgrList[0] = &m_ispReprocessingBufferMgr; |
| bufMgrList[1] = &m_yuvCaptureReprocessingBufferMgr; |
| break; |
| case PIPE_ISPC_REPROCESSING: |
| case PIPE_SCC_REPROCESSING: |
| bufMgrList[0] = NULL; |
| bufMgrList[1] = &m_yuvCaptureReprocessingBufferMgr; |
| break; |
| case PIPE_MCSC_REPROCESSING: |
| bufMgrList[0] = &m_yuvCaptureBufferMgr; |
| bufMgrList[1] = &m_yuvCaptureReprocessingBufferMgr; |
| break; |
| case PIPE_GSC_REPROCESSING: |
| bufMgrList[0] = &m_yuvCaptureReprocessingBufferMgr; |
| bufMgrList[1] = &m_gscBufferMgr; |
| break; |
| |
| default: |
| CLOGE2("Unknown pipeId(%d)", pipeId); |
| bufMgrList[0] = NULL; |
| bufMgrList[1] = NULL; |
| ret = BAD_VALUE; |
| break; |
| } |
| |
| *bufMgr = *bufMgrList[direction]; |
| return ret; |
| } |
| |
| status_t ExynosCamera3::m_createIonAllocator(ExynosCameraIonAllocator **allocator) |
| { |
| status_t ret = NO_ERROR; |
| int retry = 0; |
| do { |
| retry++; |
| CLOGI2("try(%d) to create IonAllocator", retry); |
| *allocator = new ExynosCameraIonAllocator(); |
| ret = (*allocator)->init(false); |
| if (ret < 0) |
| CLOGE2("create IonAllocator fail (retryCount=%d)", retry); |
| else { |
| CLOGD2("m_createIonAllocator success (allocator=%p)", *allocator); |
| break; |
| } |
| } while ((ret < 0) && (retry < 3)); |
| |
| if ((ret < 0) && (retry >=3)) { |
| CLOGE2("create IonAllocator fail (retryCount=%d)", retry); |
| ret = INVALID_OPERATION; |
| } |
| |
| return ret; |
| } |
| |
| status_t ExynosCamera3::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) |
| CLOGE2("m_createIonAllocator fail"); |
| else |
| CLOGD2("m_createIonAllocator success"); |
| } |
| |
| *bufferManager = ExynosCameraBufferManager::createBufferManager(type); |
| (*bufferManager)->create(name, m_cameraId, m_ionAllocator); |
| |
| CLOGD2("BufferManager(%s) created", name); |
| |
| return ret; |
| } |
| |
| status_t ExynosCamera3::m_createInternalBufferManager(ExynosCameraBufferManager **bufferManager, const char *name) |
| { |
| return m_createBufferManager(bufferManager, name, BUFFER_MANAGER_ION_TYPE); |
| } |
| |
| status_t ExynosCamera3::m_createServiceBufferManager(ExynosCameraBufferManager **bufferManager, const char *name) |
| { |
| return m_createBufferManager(bufferManager, name, BUFFER_MANAGER_SERVICE_GRALLOC_TYPE); |
| } |
| |
| status_t ExynosCamera3::m_convertingStreamToShotExt(ExynosCameraBuffer *buffer, struct camera2_node_output *outputInfo) |
| { |
| /* TODO: HACK: Will be removed, this is driver's job */ |
| status_t ret = NO_ERROR; |
| int bayerFrameCount = 0; |
| camera2_shot_ext *shot_ext = NULL; |
| camera2_stream *shot_stream = NULL; |
| |
| shot_stream = (struct camera2_stream *)buffer->addr[1]; |
| bayerFrameCount = shot_stream->fcount; |
| outputInfo->cropRegion[0] = shot_stream->output_crop_region[0]; |
| outputInfo->cropRegion[1] = shot_stream->output_crop_region[1]; |
| outputInfo->cropRegion[2] = shot_stream->output_crop_region[2]; |
| outputInfo->cropRegion[3] = shot_stream->output_crop_region[3]; |
| |
| memset(buffer->addr[1], 0x0, sizeof(struct camera2_shot_ext)); |
| |
| shot_ext = (struct camera2_shot_ext *)buffer->addr[1]; |
| shot_ext->shot.dm.request.frameCount = bayerFrameCount; |
| |
| return ret; |
| } |
| |
| bool ExynosCamera3::m_selectBayerThreadFunc() |
| { |
| ExynosCameraAutoTimer autoTimer(__FUNCTION__); |
| |
| status_t ret = NO_ERROR; |
| ExynosCameraFrame *frame = NULL; |
| ExynosCameraBuffer bayerBuffer; |
| ExynosCameraBufferManager *bufferMgr = NULL; |
| camera2_shot_ext *shot_ext = NULL; |
| camera2_shot_ext updateDmShot; |
| struct camera2_node_output output_crop_info; |
| camera2_node_group node_group_info; |
| uint32_t pipeID = 0; |
| uint32_t frameCount = 0; |
| ExynosRect ratioCropSize; |
| int pictureW = 0, pictureH = 0; |
| |
| ret = m_selectBayerQ->waitAndPopProcessQ(&frame); |
| if (ret != NO_ERROR) { |
| if (ret == TIMED_OUT) |
| CLOGW2("Wait timeout"); |
| else |
| CLOGE2("Failed to waitAndPopProcessQ. ret %d", ret); |
| |
| goto CLEAN; |
| } else if (frame == NULL) { |
| CLOGE2("frame is NULL!!"); |
| goto CLEAN; |
| } |
| |
| frameCount = frame->getFrameCount(); |
| |
| if (frame->getFrameCapture() == false) { |
| CLOGW2("frame is not capture frame. frameCount %d", frameCount); |
| goto CLEAN; |
| } |
| |
| CLOGV2("Start to select Bayer. frameCount %d", frameCount); |
| |
| /* Get bayer buffer based on current reprocessing mode */ |
| switch(m_parameters->getReprocessingBayerMode()) { |
| case REPROCESSING_BAYER_MODE_PURE_ALWAYS_ON: |
| case REPROCESSING_BAYER_MODE_PURE_DYNAMIC: |
| CLOGD2("REPROCESSING_BAYER_MODE_PURE. isRawCapture %d", |
| frame->getFrameServiceBayer()); |
| |
| if (frame->getFrameZsl() || frame->getFrameServiceBayer()) |
| ret = m_getBayerServiceBuffer(frame, &bayerBuffer); |
| else |
| ret = m_getBayerBuffer(m_getBayerPipeId(), frameCount, &bayerBuffer, m_captureSelector); |
| if (ret != NO_ERROR) { |
| CLOGE2("Failed to get bayer buffer. frameCount %d useServiceBayerBuffer %d", |
| frameCount, frame->getFrameZsl()); |
| goto CLEAN; |
| } |
| |
| shot_ext = (struct camera2_shot_ext *)(bayerBuffer.addr[bayerBuffer.planeCount-1]); |
| if (shot_ext == NULL) { |
| CLOGE2("shot_ext from pure bayer buffer is NULL"); |
| break; |
| } |
| |
| ret = frame->storeDynamicMeta(shot_ext); |
| if (ret < 0) { |
| CLOGE2("storeDynamicMeta fail ret(%d)", ret); |
| goto CLEAN; |
| } |
| |
| ret = frame->storeUserDynamicMeta(shot_ext); |
| if (ret < 0) { |
| CLOGE2("storeUserDynamicMeta fail ret(%d)", ret); |
| goto CLEAN; |
| } |
| |
| break; |
| case REPROCESSING_BAYER_MODE_DIRTY_ALWAYS_ON: |
| case REPROCESSING_BAYER_MODE_DIRTY_DYNAMIC: |
| CLOGD2("REPROCESSING_BAYER_MODE_DIRTY%s. isRawCapture %d", |
| (m_parameters->getReprocessingBayerMode() |
| == REPROCESSING_BAYER_MODE_DIRTY_DYNAMIC) ? "_DYNAMIC" : "_ALWAYS_ON", |
| frame->getFrameServiceBayer()); |
| |
| if (frame->getFrameZsl()/* || frame->getFrameServiceBayer()*/) |
| ret = m_getBayerServiceBuffer(frame, &bayerBuffer); |
| else |
| ret = m_getBayerBuffer(PIPE_3AA, frameCount, &bayerBuffer, m_captureSelector, &updateDmShot); |
| if (ret != NO_ERROR) { |
| CLOGE2("Failed to get bayer buffer. frameCount %d useServiceBayerBuffer %d", |
| frameCount, frame->getFrameZsl()); |
| goto CLEAN; |
| } |
| |
| /* Set perframe size of dirty reprocessing */ |
| /* TODO: HACK: Will be removed, this is driver's job */ |
| ret = m_convertingStreamToShotExt(&bayerBuffer, &output_crop_info); |
| if (ret != NO_ERROR) { |
| CLOGE2("shot_stream to shot_ext converting fail, ret(%d)", ret); |
| goto CLEAN; |
| } |
| |
| memset(&node_group_info, 0x0, sizeof(camera2_node_group)); |
| if (m_parameters->isUseYuvReprocessingForThumbnail() == true) { |
| m_parameters->getThumbnailSize(&pictureW, &pictureH); |
| if (pictureW <= 0 || pictureH <= 0) |
| m_parameters->getPictureSize(&pictureW, &pictureH); |
| } else { |
| m_parameters->getPictureSize(&pictureW, &pictureH); |
| } |
| |
| if (m_parameters->isUseYuvReprocessing() == true) |
| frame->getNodeGroupInfo(&node_group_info, PERFRAME_INFO_YUV_REPROCESSING_MCSC); |
| else |
| frame->getNodeGroupInfo(&node_group_info, PERFRAME_INFO_DIRTY_REPROCESSING_ISP); |
| |
| /* Leader */ |
| setLeaderSizeToNodeGroupInfo(&node_group_info, |
| output_crop_info.cropRegion[0], |
| output_crop_info.cropRegion[1], |
| ALIGN_UP(output_crop_info.cropRegion[2], CAMERA_ISP_ALIGN), |
| output_crop_info.cropRegion[3]); |
| |
| /* Capture */ |
| ret = getCropRectAlign( |
| node_group_info.leader.input.cropRegion[2], |
| node_group_info.leader.input.cropRegion[3], |
| pictureW, pictureH, |
| &ratioCropSize.x, &ratioCropSize.y, &ratioCropSize.w, &ratioCropSize.h, |
| CAMERA_MCSC_ALIGN, 2, 0, 1.0); |
| if (ret != NO_ERROR) { |
| CLOGE2("getCropRectAlign failed. MCSC in_crop %dx%d, MCSC(picture) out_size %dx%d", |
| node_group_info.leader.input.cropRegion[2], |
| node_group_info.leader.input.cropRegion[3], |
| pictureW, pictureH); |
| |
| ratioCropSize.x = 0; |
| ratioCropSize.y = 0; |
| ratioCropSize.w = node_group_info.leader.input.cropRegion[2]; |
| ratioCropSize.h = node_group_info.leader.input.cropRegion[3]; |
| } |
| |
| setCaptureCropNScaleSizeToNodeGroupInfo(&node_group_info, |
| PERFRAME_REPROCESSING_SCC_POS, |
| ratioCropSize.x, ratioCropSize.y, |
| ratioCropSize.w, ratioCropSize.h, |
| pictureW, pictureH); |
| |
| if (m_parameters->isUseYuvReprocessing() == true) |
| frame->storeNodeGroupInfo(&node_group_info, PERFRAME_INFO_YUV_REPROCESSING_MCSC); |
| else |
| frame->storeNodeGroupInfo(&node_group_info, PERFRAME_INFO_DIRTY_REPROCESSING_ISP); |
| |
| ret = frame->storeDynamicMeta(&updateDmShot); |
| if (ret < 0) { |
| CLOGE2("storeDynamicMeta fail ret(%d)", ret); |
| goto CLEAN; |
| } |
| |
| ret = frame->storeUserDynamicMeta(&updateDmShot); |
| if (ret < 0) { |
| CLOGE2("storeUserDynamicMeta fail ret(%d)", ret); |
| goto CLEAN; |
| } |
| |
| shot_ext = (struct camera2_shot_ext *)(bayerBuffer.addr[bayerBuffer.planeCount-1]); |
| frame->getMetaData(shot_ext); |
| |
| break; |
| default: |
| CLOGE2("bayer mode is not valid(%d)", m_parameters->getReprocessingBayerMode()); |
| goto CLEAN; |
| } |
| |
| CLOGD2("meta_shot_ext->shot.dm.request.frameCount : %d", getMetaDmRequestFrameCount(shot_ext)); |
| |
| /* Get pipeId for the first entity in reprocessing frame */ |
| pipeID = frame->getFirstEntity()->getPipeId(); |
| CLOGD2("Reprocessing stream first pipe ID %d", pipeID); |
| |
| /* Check available buffer */ |
| ret = m_getBufferManager(pipeID, &bufferMgr, DST_BUFFER_DIRECTION); |
| if (ret != NO_ERROR) { |
| CLOGE2("Failed to getBufferManager, ret %d", ret); |
| goto CLEAN; |
| } else if (bufferMgr == NULL) { |
| CLOGE2("BufferMgr is NULL. pipeId %d", pipeID); |
| goto CLEAN; |
| } |
| |
| ret = m_checkBufferAvailable(pipeID, bufferMgr); |
| if (ret != NO_ERROR) { |
| CLOGE2("Waiting buffer timeout, PipeID %d, ret %d", pipeID, ret); |
| goto CLEAN; |
| } |
| |
| ret = m_setupEntity(pipeID, frame, &bayerBuffer, NULL); |
| if (ret < 0) { |
| CLOGE2("setupEntity fail, bayerPipeId(%d), ret(%d)", pipeID, ret); |
| goto CLEAN; |
| } |
| |
| m_captureQ->pushProcessQ(&frame); |
| |
| return true; |
| |
| CLEAN: |
| if (frame != NULL) { |
| frame->frameUnlock(); |
| ret = m_removeFrameFromList(&m_captureProcessList, &m_captureProcessLock, frame); |
| if (ret != NO_ERROR) |
| CLOGE2("Failed to remove frame from m_captureProcessList. frameCount %d ret %d", |
| frame->getFrameCount(), ret); |
| |
| frame->printEntity(); |
| CLOGD2("Delete frame from m_captureProcessList. frameCount %d", frame->getFrameCount()); |
| frame->decRef(); |
| m_frameMgr->deleteFrame(frame); |
| frame = NULL; |
| } |
| return true; |
| |
| } |
| |
| bool ExynosCamera3::m_captureThreadFunc() |
| { |
| ExynosCameraAutoTimer autoTimer(__FUNCTION__); |
| |
| status_t ret = NO_ERROR; |
| ExynosCameraFrame *frame = NULL; |
| ExynosCameraFrame *newFrame = NULL; |
| ExynosCameraRequest *request = NULL; |
| ExynosCamera3FrameFactory *factory = NULL; |
| |
| int pipeId = 0; |
| int bufPipeId = 0; |
| bool isSrc = false; |
| int retryCount = 3; |
| uint32_t frameCount = 0; |
| |
| ret = m_captureQ->waitAndPopProcessQ(&frame); |
| if (ret != NO_ERROR) { |
| /* TODO: We need to make timeout duration depends on FPS */ |
| if (ret == TIMED_OUT) { |
| CLOGW2("Wait timeout"); |
| } else { |
| CLOGE2("Failed to wait&pop captureQ, ret %d", ret); |
| /* TODO: doing exception handling */ |
| } |
| goto CLEAN; |
| } else if (frame == NULL) { |
| CLOGE2("frame is NULL!!"); |
| goto CLEAN; |
| } |
| |
| m_captureStreamThread->run(PRIORITY_DEFAULT); |
| |
| frameCount = frame->getFrameCount(); |
| |
| CLOGV2("frame frameCount(%d)", frameCount); |
| |
| request = m_requestMgr->getServiceRequest(frameCount); |
| factory = request->getFrameFactory(HAL_STREAM_ID_JPEG); |
| |
| if (m_parameters->isReprocessing() == true) { |
| if (m_parameters->isUseYuvReprocessingForThumbnail() == true) { |
| ret = m_handleThumbnailReprocessingFrame(frame); |
| if (ret != NO_ERROR) { |
| CLOGE2("m_handleThumbnailReprocessingFrame fail, ret(%d)", ret); |
| goto CLEAN; |
| } |
| } else { |
| pipeId = frame->getFirstEntity()->getPipeId(); |
| |
| factory->pushFrameToPipe(&frame, pipeId); |
| factory->startThread(pipeId); |
| |
| /* Wait reprocesisng done */ |
| CLOGI2("Wait reprocessing done. frameCount %d", frameCount); |
| do { |
| ret = m_reprocessingDoneQ->waitAndPopProcessQ(&frame); |
| } while (ret == TIMED_OUT && retryCount-- > 0); |
| |
| if (ret != NO_ERROR) |
| CLOGW2("Failed to waitAndPopProcessQ to reprocessingDoneQ. ret %d", ret); |
| } |
| } else { |
| if (m_parameters->is3aaIspOtf() == true) { |
| pipeId = PIPE_3AA; |
| if (m_parameters->isUsing3acForIspc() == true) |
| bufPipeId = PIPE_3AC; |
| else |
| bufPipeId = PIPE_ISPC; |
| } else { |
| pipeId = PIPE_ISP; |
| bufPipeId = PIPE_ISPC; |
| } |
| |
| newFrame = m_sccCaptureSelector->selectDynamicFrames(1, pipeId, isSrc, retryCount, factory->getNodeType(bufPipeId)); |
| |
| if (newFrame == NULL) { |
| CLOGE2("newFrame is NULL"); |
| goto CLEAN; |
| } |
| |
| if (frameCount != newFrame->getFrameCount()) |
| CLOGW2("Selected frame count is not match! frame(%d), selected(%d)", |
| frameCount, newFrame->getFrameCount()); |
| |
| m_captureProcessList.push_back(newFrame); |
| |
| ret = m_handleIsChainDone(newFrame); |
| if (ret != NO_ERROR) { |
| CLOGE2("m_handleIsChainDone fail, ret(%d)", ret); |
| goto CLEAN; |
| } |
| } |
| |
| if (m_captureQ->getSizeOfProcessQ() > 0) |
| return true; |
| else |
| return false; |
| |
| CLEAN: |
| if (frame != NULL) { |
| if (m_parameters->isReprocessing() == true) { |
| frame->frameUnlock(); |
| ret = m_removeFrameFromList(&m_captureProcessList, &m_captureProcessLock, frame); |
| if (ret != NO_ERROR) |
| CLOGE2("remove frame from m_captureProcessList fail, ret(%d)", ret); |
| } |
| |
| frame->printEntity(); |
| CLOGD2("Picture frame delete(%d)", frame->getFrameCount()); |
| frame->decRef(); |
| m_frameMgr->deleteFrame(frame); |
| frame = NULL; |
| } |
| |
| CLOGI2("captureThreadFunc fail, remaining count(%d)", m_sccCaptureSelector->getHoldCount()); |
| |
| if (m_captureQ->getSizeOfProcessQ() > 0) |
| return true; |
| else |
| return false; |
| } |
| |
| status_t ExynosCamera3::m_getBayerServiceBuffer(ExynosCameraFrame *frame, ExynosCameraBuffer *buffer) |
| { |
| status_t ret = NO_ERROR; |
| ExynosCameraRequest *request = NULL; |
| ExynosCameraBufferManager *bufferMgr = NULL; |
| |
| request = m_requestMgr->getServiceRequest(frame->getFrameCount()); |
| if (request != NULL) { |
| camera3_stream_buffer_t *stream_buffer = request->getInputBuffer(); |
| buffer_handle_t *handle = stream_buffer->buffer; |
| int bufIndex = -1; |
| |
| m_bayerBufferMgr->getIndexByHandle(handle, &bufIndex); |
| if (bufIndex < 0) { |
| CLOGE2("getIndexByHandle is fail(fcount:%d / handle:%p)", frame->getFrameCount(), handle); |
| ret = BAD_VALUE; |
| } else { |
| ret = m_bayerBufferMgr->getBuffer(&bufIndex, EXYNOS_CAMERA_BUFFER_POSITION_IN_SERVICE, buffer); |
| CLOGI2("service bayer selected(fcount:%d / handle:%p / idx:%d / ret:%d)", frame->getFrameCount(), handle, bufIndex, ret); |
| } |
| } else { |
| CLOGE2("request if NULL(fcount:%d)", frame->getFrameCount()); |
| ret = BAD_VALUE; |
| } |
| |
| return ret; |
| } |
| |
| status_t ExynosCamera3::m_getBayerBuffer(uint32_t pipeId, uint32_t frameCount, ExynosCameraBuffer *buffer, ExynosCameraFrameSelector *selector, camera2_shot_ext *updateDmShot) |
| { |
| status_t ret = NO_ERROR; |
| bool isSrc = false; |
| int retryCount = 30; /* 200ms x 30 */ |
| camera2_shot_ext *shot_ext = NULL; |
| camera2_stream *shot_stream = NULL; |
| ExynosCameraFrame *inListFrame = NULL; |
| ExynosCameraFrame *bayerFrame = NULL; |
| |
| if (m_parameters->isReprocessing() == false || selector == NULL) { |
| CLOGE2("INVALID_OPERATION, isReprocessing(%s) or bayerFrame is NULL", |
| m_parameters->isReprocessing() ? "True" : "False"); |
| ret = INVALID_OPERATION; |
| goto CLEAN; |
| } |
| |
| selector->setWaitTime(200000000); |
| bayerFrame = selector->selectCaptureFrames(1, frameCount, pipeId, isSrc, retryCount, 0); |
| if (bayerFrame == NULL) { |
| CLOGE2("bayerFrame is NULL"); |
| ret = INVALID_OPERATION; |
| goto CLEAN; |
| } |
| |
| ret = bayerFrame->getDstBuffer(pipeId, buffer); |
| if (ret < 0) { |
| CLOGE2("getDstBuffer fail, pipeId(%d), ret(%d)", pipeId, ret); |
| goto CLEAN; |
| } |
| |
| if (m_parameters->getReprocessingBayerMode() == REPROCESSING_BAYER_MODE_PURE_ALWAYS_ON || |
| m_parameters->getReprocessingBayerMode() == REPROCESSING_BAYER_MODE_PURE_DYNAMIC) { |
| shot_ext = (struct camera2_shot_ext *)buffer->addr[1]; |
| CLOGD2("Selected frame count(hal : %d / driver : %d)", |
| bayerFrame->getFrameCount(), shot_ext->shot.dm.request.frameCount); |
| } else if (m_parameters->getReprocessingBayerMode() == REPROCESSING_BAYER_MODE_DIRTY_ALWAYS_ON || |
| m_parameters->getReprocessingBayerMode() == REPROCESSING_BAYER_MODE_DIRTY_DYNAMIC) { |
| if (updateDmShot == NULL) { |
| CLOGE2("updateDmShot is NULL"); |
| goto CLEAN; |
| } |
| |
| while(retryCount > 0) { |
| if(bayerFrame->getMetaDataEnable() == false) { |
| CLOGD2("Waiting for update jpeg metadata failed (%d), retryCount(%d)", ret, retryCount); |
| } else { |
| break; |
| } |
| retryCount--; |
| usleep(DM_WAITING_TIME); |
| } |
| |
| /* update meta like pure bayer */ |
| bayerFrame->getUserDynamicMeta(updateDmShot); |
| bayerFrame->getDynamicMeta(updateDmShot); |
| |
| shot_stream = (struct camera2_stream *)buffer->addr[1]; |
| CLOGD2("Selected fcount(hal : %d / driver : %d)", bayerFrame->getFrameCount(), shot_stream->fcount); |
| } else { |
| CLOGE2("reprocessing is not valid pipeId(%d), ret(%d)", pipeId, ret); |
| goto CLEAN; |
| } |
| |
| CLEAN: |
| |
| if (bayerFrame != NULL) { |
| bayerFrame->frameUnlock(); |
| |
| ret = m_searchFrameFromList(&m_processList, &m_processLock, bayerFrame->getFrameCount(), &inListFrame); |
| if (ret < 0) { |
| CLOGE2("searchFrameFromList fail"); |
| } else { |
| CLOGD2("Selected frame(%d) complete, Delete", bayerFrame->getFrameCount()); |
| bayerFrame->decRef(); |
| m_frameMgr->deleteFrame(bayerFrame); |
| bayerFrame = NULL; |
| } |
| } |
| |
| return ret; |
| } |
| |
| bool ExynosCamera3::m_captureStreamThreadFunc(void) |
| { |
| status_t ret = 0; |
| ExynosCameraFrame *frame = NULL; |
| ExynosCameraFrameEntity *entity = NULL; |
| ExynosCameraBuffer buffer; |
| ExynosCameraRequest* request = NULL; |
| struct camera2_shot_ext *shot_ext = NULL; |
| uint32_t frameCount = 0; |
| int pipeId = -1; |
| |
| ret = m_pipeCaptureFrameDoneQ->waitAndPopProcessQ(&frame); |
| if (ret != NO_ERROR) { |
| /* TODO: We need to make timeout duration depends on FPS */ |
| if (ret == TIMED_OUT) { |
| CLOGW2("wait timeout"); |
| } else { |
| CLOGE2("wait and pop fail, ret(%d)", ret); |
| /* TODO: doing exception handling */ |
| } |
| goto FUNC_EXIT; |
| } |
| |
| if (frame == NULL) { |
| CLOGE2("frame is NULL"); |
| goto FUNC_EXIT; |
| } |
| |
| entity = frame->getFrameDoneEntity(); |
| if (entity == NULL) { |
| CLOGE2("current entity is NULL"); |
| /* TODO: doing exception handling */ |
| goto FUNC_EXIT; |
| } |
| |
| frameCount = frame->getFrameCount(); |
| pipeId = entity->getPipeId(); |
| |
| CLOGD2("captureStream frame->frameCnt(%d), entityID(%d)", frameCount, pipeId); |
| |
| switch(pipeId) { |
| case PIPE_3AA_REPROCESSING: |
| case PIPE_ISP_REPROCESSING: |
| case PIPE_MCSC_REPROCESSING: |
| ret = frame->getSrcBuffer(pipeId, &buffer); |
| if (ret != NO_ERROR) { |
| CLOGE2("Failed to getSrcBuffer, pipeId %d, ret %d", pipeId, ret); |
| goto FUNC_EXIT; |
| } |
| |
| shot_ext = (struct camera2_shot_ext *) buffer.addr[buffer.planeCount - 1]; |
| if (shot_ext == NULL) { |
| CLOGE2("shot_ext is NULL. pipeId %d frameCount %d", pipeId, frameCount); |
| goto FUNC_EXIT; |
| } |
| |
| if (m_parameters->getUsePureBayerReprocessing() == true) { |
| ret = m_pushResult(frameCount, shot_ext); |
| if (ret != NO_ERROR) { |
| CLOGE2("Failed to pushResult. framecount %d ret %d", frameCount, ret); |
| goto FUNC_EXIT; |
| } |
| } else { |
| // In dirty bayer case, the meta is updated if the current request |
| // is reprocessing only(i.e. Internal frame is created on preview path). |
| // Preview path will update the meta if the current request have preview frame |
| ExynosCameraRequest* request = m_requestMgr->getServiceRequest(frameCount); |
| if (request == NULL) { |
| CLOGE2("getServiceRequest failed"); |
| } else { |
| if(request->getNeedInternalFrame() == true) { |
| ret = m_pushResult(frameCount, shot_ext); |
| if (ret != NO_ERROR) { |
| CLOGE2("Failed to pushResult. framecount %d ret %d", frameCount, ret); |
| goto FUNC_EXIT; |
| } |
| } |
| } |
| } |
| |
| ret = frame->storeDynamicMeta(shot_ext); |
| if (ret != NO_ERROR) { |
| CLOGE2("Failed to storeUserDynamicMeta, requestKey %d, ret %d", request->getKey(), ret); |
| goto FUNC_EXIT; |
| } |
| |
| ret = frame->storeUserDynamicMeta(shot_ext); |
| if (ret != NO_ERROR) { |
| CLOGE2("Failed to storeUserDynamicMeta, requestKey %d, ret %d", request->getKey(), ret); |
| goto FUNC_EXIT; |
| } |
| |
| CLOGV2("REPROCESSING Done. dm.request.frameCount %d frameCount %d", |
| getMetaDmRequestFrameCount(shot_ext), frameCount); |
| |
| if (m_parameters->isUseYuvReprocessing() == true) { |
| ret = m_putBuffers(m_yuvCaptureBufferMgr, buffer.index); |
| if (ret != NO_ERROR) |
| CLOGE2("Failed to putBuffer to yuvCaptureBufferMgr, bufferIndex %d", buffer.index); |
| } else if (frame->getFrameServiceBayer() == false) { |
| ret = m_putBuffers(m_fliteBufferMgr, buffer.index); |
| if (ret != NO_ERROR) |
| CLOGE2("Failed to putBuffer to fliteBufferMgr, bufferIndex %d", buffer.index); |
| } |
| |
| /* Handle yuv capture buffer */ |
| ret = m_handleYuvCaptureFrame(frame); |
| if (ret != NO_ERROR) { |
| CLOGE2("Failed to handleYuvCaptureFrame. pipeId %d ret %d", pipeId, ret); |
| goto FUNC_EXIT; |
| } |
| |
| /* Continue to JPEG processing stage in HWFC mode */ |
| if (m_parameters->isHWFCEnabled() == false) |
| break; |
| case PIPE_JPEG: |
| case PIPE_JPEG_REPROCESSING: |
| ret = m_handleJpegFrame(frame); |
| if (ret != NO_ERROR) { |
| CLOGE2("m_handleJpegFrame fail, pipeId(%d), ret(%d)", pipeId, ret); |
| goto FUNC_EXIT; |
| } |
| break; |
| case PIPE_GSC: |
| case PIPE_GSC_VIDEO: |
| case PIPE_GSC_PICTURE: |
| case PIPE_GSC_REPROCESSING: |
| ret = m_handleScalerDone(frame); |
| if (ret != NO_ERROR) { |
| CLOGE2("m_handleScalerDone fail, pipeId(%d) ret(%d)", pipeId, ret); |
| goto FUNC_EXIT; |
| } |
| break; |
| default: |
| CLOGE2("Invalid pipe ID (%d)", pipeId); |
| break; |
| } |
| |
| ret = frame->setEntityState(pipeId, ENTITY_STATE_COMPLETE); |
| if (ret < 0) { |
| CLOGE2("setEntityState fail, pipeId(%d), state(%d), ret(%d)", |
| pipeId, ENTITY_STATE_COMPLETE, ret); |
| goto FUNC_EXIT; |
| } |
| |
| if ((pipeId == PIPE_JPEG |
| || m_parameters->isHWFCEnabled() == true |
| || pipeId == PIPE_JPEG_REPROCESSING) |
| && frame->isComplete() == true) { |
| List<ExynosCameraFrame *> *list = NULL; |
| Mutex *listLock = NULL; |
| #if defined(ENABLE_FULL_FRAME) |
| list = &m_processList; |
| listLock = &m_processLock; |
| #else |
| list = &m_captureProcessList; |
| listLock = &m_captureProcessLock; |
| #endif |
| // TODO:decide proper position |
| CLOGV2("frame complete, count(%d)", frameCount); |
| ret = m_removeFrameFromList(list, listLock, frame); |
| if (ret < 0) { |
| CLOGE2("remove frame from processList fail, ret(%d)", ret); |
| } |
| |
| frame->decRef(); |
| m_frameMgr->deleteFrame(frame); |
| frame = NULL; |
| } |
| |
| FUNC_EXIT: |
| Mutex::Autolock l(m_captureProcessLock); |
| if (m_captureProcessList.size() > 0) |
| return true; |
| else |
| return false; |
| } |
| |
| status_t ExynosCamera3::m_handleIsChainDone(ExynosCameraFrame *frame) |
| { |
| status_t ret = 0; |
| ExynosCameraRequest* request = NULL; |
| ExynosCameraBufferManager *bufferMgr = NULL; |
| ExynosCameraBuffer srcBuffer; |
| ExynosCameraBuffer dstBuffer; |
| int bufIndex = -1; |
| ExynosCamera3FrameFactory *factory = NULL; |
| int pipeId_src = -1; |
| int pipeId_gsc = -1; |
| int pipeId_jpeg = -1; |
| |
| bool isSrc = false; |
| float zoomRatio = 0.0F; |
| struct camera2_stream *shot_stream = NULL; |
| int pictureW = 0, pictureH = 0, pictureFormat = 0; |
| ExynosRect srcRect, dstRect; |
| int type = CAMERA3_MSG_SHUTTER; |
| struct camera2_shot_ext *temp_ext = new struct camera2_shot_ext; |
| struct camera2_shot_ext *result_ext = new struct camera2_shot_ext; |
| |
| memset(temp_ext, 0x00, sizeof(struct camera2_shot_ext)); |
| memset(result_ext, 0x00, sizeof(struct camera2_shot_ext)); |
| |
| request = m_requestMgr->getServiceRequest(frame->getFrameCount()); |
| factory = request->getFrameFactory(HAL_STREAM_ID_JPEG); |
| |
| zoomRatio = m_parameters->getZoomRatio(m_parameters->getZoomLevel()) / 1000; |
| |
| /////////////////////////////////////////////////////////// |
| if (m_parameters->isReprocessing() == true) { |
| /* We are using only PIPE_ISP_REPROCESSING */ |
| pipeId_src = PIPE_ISP_REPROCESSING; |
| pipeId_gsc = PIPE_GSC_REPROCESSING; |
| pipeId_jpeg = PIPE_JPEG_REPROCESSING; |
| isSrc = true; |
| } else if(m_parameters->isUsing3acForIspc() == true){ |
| pipeId_src = PIPE_3AA; |
| pipeId_gsc = PIPE_GSC_PICTURE; |
| pipeId_jpeg = PIPE_JPEG; |
| } else { |
| #if defined(ENABLE_FULL_FRAME) |
| pipeId_src = PIPE_ISP; |
| pipeId_gsc = PIPE_GSC_PICTURE; |
| pipeId_jpeg = PIPE_JPEG; |
| #else |
| switch (getCameraId()) { |
| case CAMERA_ID_FRONT: |
| pipeId_src = PIPE_ISP; |
| pipeId_gsc = PIPE_GSC_PICTURE; |
| break; |
| default: |
| CLOGE2("Current picture mode is not yet supported, CameraId(%d), reprocessing(%d)", |
| getCameraId(), m_parameters->isReprocessing()); |
| break; |
| } |
| pipeId_jpeg = PIPE_JPEG; |
| #endif |
| } |
| /////////////////////////////////////////////////////////// |
| |
| if (m_parameters->needGSCForCapture(getCameraId()) == true) { |
| if (m_parameters->isReprocessing() == true) |
| ret = frame->getDstBuffer(pipeId_src, &srcBuffer, factory->getNodeType(PIPE_ISPC_REPROCESSING)); |
| else if (m_parameters->isUsing3acForIspc() == true) |
| ret = frame->getDstBuffer(pipeId_src, &srcBuffer, factory->getNodeType(PIPE_3AC)); |
| else |
| ret = frame->getDstBuffer(pipeId_src, &srcBuffer, factory->getNodeType(PIPE_ISPC)); |
| |
| if (ret < 0) |
| CLOGE2("getDstBuffer fail, pipeId(%d), ret(%d)", pipeId_src, ret); |
| |
| shot_stream = (struct camera2_stream *)(srcBuffer.addr[srcBuffer.planeCount-1]); |
| if (shot_stream != NULL) { |
| CLOGD2("fcount(%d), rcount(%d), findex(%d), fvalid(%d)", |
| shot_stream->fcount, shot_stream->rcount, shot_stream->findex, shot_stream->fvalid); |
| |
| CLOGD2("(%d %d %d %d)(%d %d %d %d)", |
| shot_stream->input_crop_region[0], |
| shot_stream->input_crop_region[1], |
| shot_stream->input_crop_region[2], |
| shot_stream->input_crop_region[3], |
| shot_stream->output_crop_region[0], |
| shot_stream->output_crop_region[1], |
| shot_stream->output_crop_region[2], |
| shot_stream->output_crop_region[3]); |
| } else { |
| CLOGE2("shot_stream is NULL"); |
| return INVALID_OPERATION; |
| } |
| |
| /* should change size calculation code in pure bayer */ |
| #if 0 |
| if (shot_stream != NULL) { |
| ret = m_calcPictureRect(&srcRect, &dstRect); |
| ret = newFrame->setSrcRect(pipeId_gsc, &srcRect); |
| ret = newFrame->setDstRect(pipeId_gsc, &dstRect); |
| } |
| #else |
| m_parameters->getPictureSize(&pictureW, &pictureH); |
| #if defined(ENABLE_FULL_FRAME) |
| pictureFormat = m_parameters->getHwPreviewFormat(); |
| #else |
| pictureFormat = m_parameters->getHwPictureFormat(); |
| #endif |
| |
| 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]; |
| srcRect.fullW = shot_stream->output_crop_region[2]; |
| srcRect.fullH = shot_stream->output_crop_region[3]; |
| srcRect.colorFormat = pictureFormat; |
| #if 0 |
| dstRect.x = 0; |
| dstRect.y = 0; |
| dstRect.w = srcRect.w; |
| dstRect.h = srcRect.h; |
| dstRect.fullW = srcRect.fullW; |
| dstRect.fullH = srcRect.fullH; |
| dstRect.colorFormat = JPEG_INPUT_COLOR_FMT; |
| |
| #else |
| dstRect.x = 0; |
| dstRect.y = 0; |
| dstRect.w = pictureW; |
| dstRect.h = pictureH; |
| dstRect.fullW = pictureW; |
| dstRect.fullH = pictureH; |
| dstRect.colorFormat = JPEG_INPUT_COLOR_FMT; |
| #endif |
| ret = getCropRectAlign(srcRect.w, srcRect.h, |
| pictureW, pictureH, |
| &srcRect.x, &srcRect.y, |
| &srcRect.w, &srcRect.h, |
| 2, 2, 0, zoomRatio); |
| |
| ret = frame->setSrcRect(pipeId_gsc, &srcRect); |
| ret = frame->setDstRect(pipeId_gsc, &dstRect); |
| #endif |
| |
| CLOGD2("srcRect size (%d, %d, %d, %d %d %d)", |
| srcRect.x, srcRect.y, srcRect.w, srcRect.h, srcRect.fullW, srcRect.fullH); |
| CLOGD2("dstRect size (%d, %d, %d, %d %d %d)", |
| dstRect.x, dstRect.y, dstRect.w, dstRect.h, dstRect.fullW, dstRect.fullH); |
| |
| ret = m_setupEntity(pipeId_gsc, frame, &srcBuffer, NULL); |
| |
| if (ret < 0) { |
| CLOGE2("setupEntity fail, pipeId(%d), ret(%d)", pipeId_jpeg, ret); |
| } |
| |
| // Update frame's exposureTime from request result's exposureTime |
| frame->getMetaData(temp_ext); |
| if ((temp_ext->shot.dm.sensor.exposureTime) == 0) { |
| request = m_requestMgr->getServiceRequest(frame->getFrameCount()); |
| ret = request->getResultShot(result_ext); |
| if (ret < 0) { |
| CLOGE2("getResultShot fail, pipeId(%d), ret(%d)", pipeId_jpeg, ret); |
| } |
| temp_ext->shot.dm.sensor.exposureTime = result_ext->shot.dm.sensor.exposureTime; |
| frame->setMetaData(temp_ext); |
| } |
| |
| factory->pushFrameToPipe(&frame, pipeId_gsc); |
| factory->setOutputFrameQToPipe(m_pipeCaptureFrameDoneQ, pipeId_gsc); |
| |
| } else { /* m_parameters->needGSCForCapture(getCameraId()) == false */ |
| ret = frame->getDstBuffer(pipeId_src, &srcBuffer); |
| #if defined(ENABLE_FULL_FRAME) |
| if (ret < 0) |
| CLOGE2("getDstBuffer fail, pipeId(%d), ret(%d)", pipeId_src, ret); |
| |
| ret = m_setupEntity(pipeId_jpeg, frame, &srcBuffer, NULL); |
| if (ret < 0) { |
| CLOGE2("setupEntity fail, pipeId(%d), ret(%d)", pipeId_jpeg, ret); |
| } |
| #else |
| if (ret < 0) { |
| CLOGE2("getDstBuffer fail, pipeId(%d), ret(%d)", pipeId_src, ret); |
| } else { |
| /* getting jpeg buffer from service buffer */ |
| ExynosCameraStream *stream = NULL; |
| |
| int streamId = 0; |
| m_streamManager->getStream(HAL_STREAM_ID_JPEG, &stream); |
| |
| if (stream == NULL) { |
| CLOGE2("stream is NULL"); |
| return INVALID_OPERATION; |
| } |
| |
| stream->getID(&streamId); |
| stream->getBufferManager(&bufferMgr); |
| CLOGV2("streamId(%d), bufferMgr(%p)", streamId, bufferMgr); |
| /* bufferMgr->printBufferQState(); */ |
| ret = bufferMgr->getBuffer(&bufIndex, EXYNOS_CAMERA_BUFFER_POSITION_IN_HAL, &dstBuffer); |
| if (ret < 0) { |
| CLOGE2("bufferMgr getBuffer fail, frameCount(%d), ret(%d)", frame->getFrameCount(), ret); |
| } |
| } |
| ret = m_setupEntity(pipeId_jpeg, frame, &srcBuffer, &dstBuffer); |
| if (ret < 0) { |
| CLOGE2("setupEntity fail, pipeId(%d), ret(%d)", pipeId_jpeg, ret); |
| } |
| #endif |
| factory->setOutputFrameQToPipe(m_pipeCaptureFrameDoneQ, pipeId_jpeg); |
| factory->pushFrameToPipe(&frame, pipeId_jpeg); |
| } |
| |
| return ret; |
| } |
| |
| status_t ExynosCamera3::m_handleScalerDone(ExynosCameraFrame *frame) |
| { |
| status_t ret = 0; |
| ExynosCameraRequest* request = NULL; |
| int pipeId_gsc = -1; |
| int pipeId_dst = -1; |
| ExynosCameraBufferManager *bufferMgr = NULL; |
| ExynosCameraBuffer buffer; |
| ExynosCameraBuffer srcBuffer; |
| ExynosCameraBuffer dstBuffer; |
| int bufIndex = -1; |
| ExynosCamera3FrameFactory *factory = NULL; |
| |
| unsigned int completeBufferCount = 0; |
| |
| request = m_requestMgr->getServiceRequest(frame->getFrameCount()); |
| factory = request->getFrameFactory(HAL_STREAM_ID_JPEG); |
| |
| ////////////////////////////////////////////////////////// |
| /* TODO: Need to decision pipeId both current and next */ |
| if (m_parameters->isReprocessing() == true) { |
| if (m_parameters->needGSCForCapture(getCameraId()) == true) { |
| pipeId_gsc = PIPE_GSC_REPROCESSING; |
| } else { |
| pipeId_gsc = (m_parameters->isOwnScc(getCameraId()) == true) ? PIPE_SCC_REPROCESSING : PIPE_ISPC_REPROCESSING; |
| } |
| pipeId_dst = PIPE_JPEG_REPROCESSING; |
| } else { |
| if (m_parameters->needGSCForCapture(getCameraId()) == true) { |
| pipeId_gsc = PIPE_GSC_PICTURE; |
| } else { |
| if (m_parameters->isOwnScc(getCameraId()) == true) { |
| pipeId_gsc = PIPE_SCC; |
| } else { |
| pipeId_gsc = PIPE_ISPC; |
| } |
| } |
| pipeId_dst = PIPE_JPEG; |
| } |
| ////////////////////////////////////////////////////////// |
| |
| #if !defined(ENABLE_FULL_FRAME) |
| /* handle src buffer of gsc */ |
| ret = m_getBufferManager(pipeId_gsc, &bufferMgr, SRC_BUFFER_DIRECTION); |
| if (ret < 0) { |
| CLOGE2("getBufferManager(DST) fail, pipeId(%d), ret(%d)", pipeId_gsc, ret); |
| return ret; |
| } |
| |
| ret = frame->getSrcBuffer(pipeId_gsc, &buffer); |
| if (ret < 0) { |
| CLOGE2("getSrcBuffer fail, pipeId(%d), ret(%d)", pipeId_gsc, ret); |
| } |
| |
| ret = m_putBuffers(bufferMgr, buffer.index); |
| if (ret < 0) { |
| CLOGE2("m_putBuffers fail, ret(%d)", ret); |
| /* TODO: doing exception handling */ |
| } |
| #else |
| /* |
| * internal scp buffer should be return to buffer manager before creating jpeg output buffer. |
| * so, we should compare complete buffer count + 1 |
| */ |
| CLOGV2("request->getNumOfOutputBuffer(%d) request->getCompleteBuffers(%d)", request->getNumOfOutputBuffer(), request->getCompleteBufferCount()); |
| |
| request->increaseDuplicateBufferCount(); |
| completeBufferCount = request->getNumOfOutputBuffer(); |
| if (frame->getFrameCapture() == true) |
| completeBufferCount --; |
| if (frame->getFrameServiceBayer() == true) |
| completeBufferCount --; |
| |
| if(completeBufferCount == (unsigned int)request->getDuplicateBufferCount()) { |
| /* handle src buffer of gsc */ |
| ret = m_getBufferManager(pipeId_gsc, &bufferMgr, SRC_BUFFER_DIRECTION); |
| if (ret < 0) { |
| CLOGE2("getBufferManager(DST) fail, pipeId(%d), ret(%d)", pipeId_gsc, ret); |
| return ret; |
| } |
| |
| ret = frame->getSrcBuffer(pipeId_gsc, &buffer); |
| if (ret < 0) { |
| CLOGE2("getSrcBuffer fail, pipeId(%d), ret(%d)", pipeId_gsc, ret); |
| } |
| |
| CLOGV2("Internal Scp Buffer is returned index(%d)frameCount(%d)", buffer.index, frame->getFrameCount()); |
| |
| ret = m_putBuffers(bufferMgr, buffer.index); |
| if (ret < 0) { |
| CLOGE2("m_putBuffers fail, ret(%d)", ret); |
| /* TODO: doing exception handling */ |
| } |
| m_captureResultDoneCondition.signal(); |
| } |
| #endif |
| |
| /* |
| * handle dst buffer of gsc |
| * - pipeId_dst : Indicate to pipe ID for next pipe. |
| * -1 means final result for this stream. |
| */ |
| if (pipeId_dst >= 0) { |
| ExynosCameraStream *stream = NULL; |
| |
| int streamId = 0; |
| m_streamManager->getStream(HAL_STREAM_ID_JPEG, &stream); |
| |
| if (stream == NULL) { |
| CLOGE2("stream is NULL"); |
| return INVALID_OPERATION; |
| } |
| |
| stream->getID(&streamId); |
| CLOGD2("streamID(%d)", streamId); |
| |
| stream->getBufferManager(&bufferMgr); |
| CLOGV2("bufferMgr(%p)", bufferMgr); |
| /* bufferMgr->printBufferQState(); */ |
| ret = bufferMgr->getBuffer(&bufIndex, EXYNOS_CAMERA_BUFFER_POSITION_IN_HAL, &dstBuffer); |
| if (ret < 0) { |
| CLOGE2("bufferMgr getBuffer fail, frameCount(%d), ret(%d)", frame->getFrameCount(), ret); |
| } |
| ret = m_getBufferManager(pipeId_gsc, &bufferMgr, DST_BUFFER_DIRECTION); |
| if (ret < 0) { |
| CLOGE2("getBufferManager(DST) fail, pipeId(%d), ret(%d)", pipeId_gsc, ret); |
| return ret; |
| } |
| /* bufferMgr->printBufferQState(); */ |
| ret = frame->getDstBuffer(pipeId_gsc, &srcBuffer); |
| if (ret < 0) { |
| CLOGE2("getDstBuffer fail, pipeId(%d), ret(%d)", pipeId_gsc, ret); |
| } |
| |
| ret = m_putBuffers(bufferMgr, srcBuffer.index); |
| if (ret < 0) { |
| CLOGE2("m_putBuffers fail, ret(%d)", ret); |
| /* TODO: doing exception handling */ |
| } |
| |
| ret = m_setupEntity(pipeId_dst, frame, &srcBuffer, &dstBuffer); |
| if (ret < 0) { |
| CLOGE2("setupEntity fail, pipeId(%d), ret(%d)", pipeId_dst, ret); |
| } |
| factory->setOutputFrameQToPipe(m_pipeCaptureFrameDoneQ, pipeId_dst); |
| factory->pushFrameToPipe(&frame, pipeId_dst); |
| } else { |
| // TODO: send result |
| } |
| |
| return ret; |
| } |
| |
| status_t ExynosCamera3::m_handleThumbnailReprocessingFrame(ExynosCameraFrame *frame) |
| { |
| status_t ret = NO_ERROR; |
| |
| ExynosCameraRequest *request = NULL; |
| ExynosCamera3FrameFactory *factory = NULL; |
| |
| ExynosCameraBufferManager *bufferMgr = NULL; |
| ExynosCameraBuffer srcBuffer; |
| ExynosCameraBuffer yuvReprocessingBuffer; |
| ExynosCameraBuffer thumbnailBuffer; |
| struct camera2_shot_ext shot_ext; |
| struct camera2_node_output output_crop_info; |
| camera2_node_group node_group_info; |
| |
| int bufferIndex = -2; |
| int pipeId = 0; |
| int retryCount = 3; |
| uint32_t frameCount = 0; |
| bool isNeedThumbnail = false; |
| ExynosRect ratioCropSize; |
| int pictureW = 0, pictureH = 0; |
| |
| srcBuffer.index = -2; |
| yuvReprocessingBuffer.index = -2; |
| thumbnailBuffer.index = -2; |
| |
| frameCount = frame->getFrameCount(); |
| request = m_requestMgr->getServiceRequest(frameCount); |
| factory = request->getFrameFactory(HAL_STREAM_ID_JPEG); |
| |
| pipeId = frame->getFirstEntity()->getPipeId(); |
| |
| factory->pushFrameToPipe(&frame, pipeId); |
| factory->startThread(pipeId); |
| |
| /* Wait reprocesisng done */ |
| CLOGI2("Wait reprocessing done. frameCount %d", frameCount); |
| do { |
| ret = m_reprocessingDoneQ->waitAndPopProcessQ(&frame); |
| } while (ret == TIMED_OUT && retryCount-- > 0); |
| |
| if (ret != NO_ERROR) |
| CLOGW2("Failed to waitAndPopProcessQ to reprocessingDoneQ. ret %d", ret); |
| |
| frame->getMetaData(&shot_ext); |
| isNeedThumbnail = (shot_ext.shot.ctl.jpeg.thumbnailSize[0] > 0 |
| && shot_ext.shot.ctl.jpeg.thumbnailSize[1] > 0) ? true : false; |
| |
| if (isNeedThumbnail == false) { |
| m_pipeCaptureFrameDoneQ->pushProcessQ(&frame); |
| return ret; |
| } |
| |
| ret = frame->setEntityState(pipeId, ENTITY_STATE_COMPLETE); |
| if (ret != NO_ERROR) { |
| CLOGE2("setEntityState(ENTITY_STATE_PROCESSING) fail, pipeId(%d), ret(%d)", pipeId, ret); |
| return ret; |
| } |
| |
| CLOGI2("Thumbnail Reprocessing done"); |
| |
| frame->setMetaDataEnable(true); |
| |
| /* Copy thumbnail image to thumbnail buffer */ |
| ret = frame->getDstBuffer(pipeId, &yuvReprocessingBuffer, factory->getNodeType(PIPE_MCSC0_REPROCESSING)); |
| if (ret != NO_ERROR) { |
| CLOGE2("getDstBuffer fail, pipeId(%d), ret(%d)", pipeId, ret); |
| goto CLEAN; |
| } |
| |
| ret = m_thumbnailBufferMgr->getBuffer(&bufferIndex, EXYNOS_CAMERA_BUFFER_POSITION_IN_HAL, &thumbnailBuffer); |
| if (ret != NO_ERROR) { |
| CLOGE2("get thumbnail Buffer fail, ret(%d)", ret); |
| goto CLEAN; |
| } |
| |
| memcpy(thumbnailBuffer.addr[0], yuvReprocessingBuffer.addr[0], thumbnailBuffer.size[0]); |
| |
| /* Put buffers */ |
| ret = m_putBuffers(m_thumbnailBufferMgr, thumbnailBuffer.index); |
| if (ret != NO_ERROR) { |
| CLOGE2("ThumbnailBuffer putBuffer fail, index(%d), ret(%d)", thumbnailBuffer.index, ret); |
| goto CLEAN; |
| } |
| |
| /* Put reprocessing dst buffer */ |
| ret = m_getBufferManager(pipeId, &bufferMgr, DST_BUFFER_DIRECTION); |
| if (ret != NO_ERROR) { |
| CLOGE2("getBufferManager fail, ret(%d)", ret); |
| goto CLEAN; |
| } |
| |
| if (bufferMgr != NULL) { |
| ret = m_putBuffers(bufferMgr, yuvReprocessingBuffer.index); |
| if (ret != NO_ERROR) { |
| CLOGE2("DstBuffer putBuffer fail, index(%d), ret(%d)", yuvReprocessingBuffer.index, ret); |
| goto CLEAN; |
| } |
| } |
| |
| /* get src buffer */ |
| ret = frame->getSrcBuffer(pipeId, &srcBuffer); |
| if (ret != NO_ERROR) { |
| CLOGE2("getSrcBuffer fail, pipeId(%d), ret(%d)", pipeId, ret); |
| goto CLEAN; |
| } |
| |
| memset(&node_group_info, 0x0, sizeof(camera2_node_group)); |
| frame->getNodeGroupInfo(&node_group_info, PERFRAME_INFO_YUV_REPROCESSING_MCSC); |
| |
| /* Delete new frame */ |
| CLOGI2("Reprocessing frame for thumbnail delete(%d)", frame->getFrameCount()); |
| |
| ret = m_removeFrameFromList(&m_captureProcessList, &m_captureProcessLock, frame); |
| if (ret != 0) |
| CLOGE2("remove frame from processList fail, ret(%d)", ret); |
| |
| frame->decRef(); |
| m_frameMgr->deleteFrame(frame); |
| frame = NULL; |
| |
| ret = m_generateFrame(frameCount, factory, &m_captureProcessList, &m_captureProcessLock, &frame); |
| if (ret != NO_ERROR) { |
| CLOGE2("m_generateFrame fail"); |
| return INVALID_OPERATION; |
| } else if (frame == NULL) { |
| CLOGE2("frame is NULL"); |
| return INVALID_OPERATION; |
| } |
| |
| /* Set JPEG request true */ |
| frame->setRequest(PIPE_MCSC0_REPROCESSING, true); |
| if (m_parameters->isHWFCEnabled() == true) { |
| frame->setRequest(PIPE_HWFC_JPEG_SRC_REPROCESSING, true); |
| frame->setRequest(PIPE_HWFC_JPEG_DST_REPROCESSING, true); |
| frame->setRequest(PIPE_HWFC_THUMB_SRC_REPROCESSING, true); |
| } |
| |
| CLOGV2("generate request framecount %d requestKey %d", frameCount, request->getKey()); |
| |
| ret = frame->setMetaData(&shot_ext); |
| if (ret != NO_ERROR) |
| CLOGE2("Set metadata to frame fail, Frame count(%d), ret(%d)", |
| frameCount, ret); |
| |
| m_parameters->getPictureSize(&pictureW, &pictureH); |
| |
| /* Capture */ |
| ret = getCropRectAlign( |
| node_group_info.leader.input.cropRegion[2], |
| node_group_info.leader.input.cropRegion[3], |
| pictureW, pictureH, |
| &ratioCropSize.x, &ratioCropSize.y, &ratioCropSize.w, &ratioCropSize.h, |
| CAMERA_MCSC_ALIGN, 2, 0, 1.0); |
| if (ret != NO_ERROR) { |
| CLOGE2("getCropRectAlign failed. MCSC in_crop %dx%d, MCSC(picture) out_size %dx%d", |
| node_group_info.leader.input.cropRegion[2], |
| node_group_info.leader.input.cropRegion[3], |
| pictureW, pictureH); |
| |
| ratioCropSize.x = 0; |
| ratioCropSize.y = 0; |
| ratioCropSize.w = node_group_info.leader.input.cropRegion[2]; |
| ratioCropSize.h = node_group_info.leader.input.cropRegion[3]; |
| } |
| |
| setCaptureCropNScaleSizeToNodeGroupInfo(&node_group_info, |
| PERFRAME_REPROCESSING_SCC_POS, |
| ratioCropSize.x, ratioCropSize.y, |
| ratioCropSize.w, ratioCropSize.h, |
| pictureW, pictureH); |
| |
| frame->storeNodeGroupInfo(&node_group_info, PERFRAME_INFO_YUV_REPROCESSING_MCSC); |
| |
| /* Get pipeId for the first entity in reprocessing frame */ |
| pipeId = frame->getFirstEntity()->getPipeId(); |
| CLOGD2("Reprocessing stream first pipe ID %d", pipeId); |
| |
| /* Check available buffer */ |
| ret = m_getBufferManager(pipeId, &bufferMgr, DST_BUFFER_DIRECTION); |
| if (ret != NO_ERROR) { |
| CLOGE2("Failed to getBufferManager, ret %d", ret); |
| goto CLEAN; |
| } else if (bufferMgr == NULL) { |
| CLOGE2("BufferMgr is NULL. pipeId %d", pipeId); |
| goto CLEAN; |
| } |
| |
| ret = m_checkBufferAvailable(pipeId, bufferMgr); |
| if (ret != NO_ERROR) { |
| CLOGE2("Waiting buffer timeout, PipeID %d, ret %d", pipeId, ret); |
| goto CLEAN; |
| } |
| |
| ret = m_setupEntity(pipeId, frame, &srcBuffer, NULL); |
| if (ret != NO_ERROR) { |
| CLOGE2("setupEntity fail, bayerPipeId(%d), ret(%d)", pipeId, ret); |
| goto CLEAN; |
| } |
| |
| factory->pushFrameToPipe(&frame, pipeId); |
| factory->startThread(pipeId); |
| |
| /* Wait reprocesisng done */ |
| CLOGI2("Wait reprocessing done. frameCount %d", frameCount); |
| do { |
| ret = m_reprocessingDoneQ->waitAndPopProcessQ(&frame); |
| } while (ret == TIMED_OUT && retryCount-- > 0); |
| |
| if (ret != NO_ERROR) |
| CLOGW2("Failed to waitAndPopProcessQ to reprocessingDoneQ. ret %d", ret); |
| |
| PUSH_FRAME: |
| m_pipeCaptureFrameDoneQ->pushProcessQ(&frame); |
| |
| CLEAN: |
| return ret; |
| } |
| |
| status_t ExynosCamera3::m_handleYuvCaptureFrame(ExynosCameraFrame *frame) |
| { |
| status_t ret = NO_ERROR; |
| ExynosCameraRequest* request = NULL; |
| ExynosCameraBufferManager *bufferMgr = NULL; |
| ExynosCameraBuffer srcBuffer; |
| ExynosCameraBuffer dstBuffer; |
| int bufIndex = -1; |
| ExynosCamera3FrameFactory *factory = NULL; |
| int pipeId_src = -1; |
| int pipeId_gsc = -1; |
| int pipeId_jpeg = -1; |
| |
| bool isSrc = false; |
| float zoomRatio = 0.0F; |
| struct camera2_stream *shot_stream = NULL; |
| int pictureW = 0, pictureH = 0, pictureFormat = 0; |
| ExynosRect srcRect, dstRect; |
| |
| request = m_requestMgr->getServiceRequest(frame->getFrameCount()); |
| factory = request->getFrameFactory(HAL_STREAM_ID_JPEG); |
| |
| if (m_parameters->isHWFCEnabled() == true) { |
| ret = frame->getDstBuffer(PIPE_MCSC_REPROCESSING, &dstBuffer, factory->getNodeType(PIPE_MCSC0_REPROCESSING)); |
| if (ret != NO_ERROR) { |
| CLOGE2("Failed to getDstBuffer. pipeId %d node %d ret %d", |
| PIPE_MCSC_REPROCESSING, PIPE_MCSC0_REPROCESSING, ret); |
| return INVALID_OPERATION; |
| } |
| |
| ret = m_putBuffers(m_yuvCaptureReprocessingBufferMgr, dstBuffer.index); |
| if (ret != NO_ERROR) { |
| CLOGE2("Failed to putBuffer to m_yuvCaptureBufferMgr. bufferIndex %d", |
| dstBuffer.index); |
| return INVALID_OPERATION; |
| } |
| |
| #if 0 /* TODO : Why this makes error? */ |
| ret = frame->getDstBuffer(PIPE_MCSC_REPROCESSING, &dstBuffer, factory->getNodeType(PIPE_HWFC_THUMB_SRC_REPROCESSING)); |
| if (ret != NO_ERROR) { |
| CLOGE2("Failed to getDstBuffer. pipeId %d node %d ret %d", |
| PIPE_3AA_REPROCESSING, PIPE_MCSC4_REPROCESSING, ret); |
| return INVALID_OPERATION; |
| } |
| |
| ret = m_putBuffers(m_thumbnailBufferMgr, dstBuffer.index); |
| if (ret != NO_ERROR) { |
| CLOGE2("Failed to putBuffer to m_thumbnailBufferMgr. bufferIndex %d", |
| dstBuffer.index); |
| return INVALID_OPERATION; |
| } |
| #endif |
| } else { |
| zoomRatio = m_parameters->getZoomRatio(m_parameters->getZoomLevel()) / 1000; |
| |
| if (m_parameters->isReprocessing() == true) { |
| /* We are using only PIPE_ISP_REPROCESSING */ |
| pipeId_src = PIPE_ISP_REPROCESSING; |
| pipeId_gsc = PIPE_GSC_REPROCESSING; |
| pipeId_jpeg = PIPE_JPEG_REPROCESSING; |
| isSrc = true; |
| } else { |
| #if defined(ENABLE_FULL_FRAME) |
| pipeId_src = PIPE_ISP; |
| pipeId_gsc = PIPE_GSC_PICTURE; |
| pipeId_jpeg = PIPE_JPEG; |
| #else |
| switch (getCameraId()) { |
| case CAMERA_ID_FRONT: |
| pipeId_src = PIPE_ISP; |
| pipeId_gsc = PIPE_GSC_PICTURE; |
| break; |
| default: |
| CLOGE2("Current picture mode is not yet supported, CameraId(%d), reprocessing(%d)", |
| getCameraId(), m_parameters->isReprocessing()); |
| break; |
| } |
| pipeId_jpeg = PIPE_JPEG; |
| #endif |
| } |
| /////////////////////////////////////////////////////////// |
| |
| // Thumbnail image is currently not used |
| ret = frame->getDstBuffer(pipeId_src, &dstBuffer, factory->getNodeType(PIPE_MCSC4_REPROCESSING)); |
| if (ret != NO_ERROR) { |
| CLOGE2("Failed to getDstBuffer. pipeId %d node %d ret %d", |
| pipeId_src, PIPE_MCSC4_REPROCESSING, ret); |
| } else { |
| ret = m_putBuffers(m_thumbnailBufferMgr, dstBuffer.index); |
| if (ret != NO_ERROR) { |
| CLOGE2("Failed to putBuffer to m_thumbnailBufferMgr. bufferIndex %d", |
| dstBuffer.index); |
| } |
| CLOGI2("INFO(%s[%d]): Thumbnail image disposed at pipeId %d node %d, FrameCnt %d", |
| pipeId_src, PIPE_MCSC4_REPROCESSING, frame->getFrameCount()); |
| } |
| |
| if (m_parameters->needGSCForCapture(getCameraId()) == true) { |
| ret = frame->getDstBuffer(pipeId_src, &srcBuffer); |
| if (ret < 0) |
| CLOGE2("getDstBuffer fail, pipeId(%d), ret(%d)", pipeId_src, ret); |
| |
| shot_stream = (struct camera2_stream *)(srcBuffer.addr[srcBuffer.planeCount-1]); |
| if (shot_stream != NULL) { |
| CLOGD2("(%d %d %d %d)", |
| shot_stream->fcount, |
| shot_stream->rcount, |
| shot_stream->findex, |
| shot_stream->fvalid); |
| CLOGD2("(%d %d %d %d)(%d %d %d %d)", |
| shot_stream->input_crop_region[0], |
| shot_stream->input_crop_region[1], |
| shot_stream->input_crop_region[2], |
| shot_stream->input_crop_region[3], |
| shot_stream->output_crop_region[0], |
| shot_stream->output_crop_region[1], |
| shot_stream->output_crop_region[2], |
| shot_stream->output_crop_region[3]); |
| } else { |
| CLOGE2("shot_stream is NULL"); |
| return INVALID_OPERATION; |
| } |
| |
| /* should change size calculation code in pure bayer */ |
| #if 0 |
| if (shot_stream != NULL) { |
| ret = m_calcPictureRect(&srcRect, &dstRect); |
| ret = newFrame->setSrcRect(pipeId_gsc, &srcRect); |
| ret = newFrame->setDstRect(pipeId_gsc, &dstRect); |
| } |
| #else |
| m_parameters->getPictureSize(&pictureW, &pictureH); |
| #if defined(ENABLE_FULL_FRAME) |
| pictureFormat = m_parameters->getHwPreviewFormat(); |
| #else |
| pictureFormat = m_parameters->getHwPictureFormat(); |
| #endif |
| |
| 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]; |
| srcRect.fullW = shot_stream->output_crop_region[2]; |
| srcRect.fullH = shot_stream->output_crop_region[3]; |
| srcRect.colorFormat = pictureFormat; |
| #if 0 |
| dstRect.x = 0; |
| dstRect.y = 0; |
| dstRect.w = srcRect.w; |
| dstRect.h = srcRect.h; |
| dstRect.fullW = srcRect.fullW; |
| dstRect.fullH = srcRect.fullH; |
| dstRect.colorFormat = JPEG_INPUT_COLOR_FMT; |
| #else |
| dstRect.x = 0; |
| dstRect.y = 0; |
| dstRect.w = pictureW; |
| dstRect.h = pictureH; |
| dstRect.fullW = pictureW; |
| dstRect.fullH = pictureH; |
| dstRect.colorFormat = JPEG_INPUT_COLOR_FMT; |
| #endif |
| ret = getCropRectAlign(srcRect.w, srcRect.h, |
| pictureW, pictureH, |
| &srcRect.x, &srcRect.y, |
| &srcRect.w, &srcRect.h, |
| 2, 2, 0, zoomRatio); |
| |
| ret = frame->setSrcRect(pipeId_gsc, &srcRect); |
| ret = frame->setDstRect(pipeId_gsc, &dstRect); |
| #endif |
| |
| CLOGD2("size (%d, %d, %d, %d %d %d)", |
| srcRect.x, srcRect.y, srcRect.w, srcRect.h, srcRect.fullW, srcRect.fullH); |
| CLOGD2("size (%d, %d, %d, %d %d %d)", |
| dstRect.x, dstRect.y, dstRect.w, dstRect.h, dstRect.fullW, dstRect.fullH); |
| |
| ret = m_setupEntity(pipeId_gsc, frame, &srcBuffer, NULL); |
| |
| if (ret < 0) |
| CLOGE2("setupEntity fail, pipeId(%d), ret(%d)", pipeId_jpeg, ret); |
| |
| factory->pushFrameToPipe(&frame, pipeId_gsc); |
| factory->setOutputFrameQToPipe(m_pipeCaptureFrameDoneQ, pipeId_gsc); |
| |
| } else { /* m_parameters->needGSCForCapture(getCameraId()) == false */ |
| ret = frame->getDstBuffer(pipeId_src, &srcBuffer); |
| #if defined(ENABLE_FULL_FRAME) |
| if (ret < 0) |
| CLOGE2("getDstBuffer fail, pipeId(%d), ret(%d)", pipeId_src, ret); |
| |
| ret = m_setupEntity(pipeId_jpeg, frame, &srcBuffer, NULL); |
| if (ret < 0) { |
| CLOGE2("setupEntity fail, pipeId(%d), ret(%d)", |
| pipeId_jpeg, ret); |
| } |
| #else |
| if (ret < 0) { |
| CLOGE2("getDstBuffer fail, pipeId(%d), ret(%d)", pipeId_src, ret); |
| } else { |
| /* getting jpeg buffer from service buffer */ |
| ExynosCameraStream *stream = NULL; |
| |
| int streamId = 0; |
| m_streamManager->getStream(HAL_STREAM_ID_JPEG, &stream); |
| |
| if (stream == NULL) { |
| CLOGE2("stream is NULL"); |
| return INVALID_OPERATION; |
| } |
| |
| stream->getID(&streamId); |
| stream->getBufferManager(&bufferMgr); |
| CLOGV2("streamId(%d), bufferMgr(%p)", streamId, bufferMgr); |
| /* bufferMgr->printBufferQState(); */ |
| ret = bufferMgr->getBuffer(&bufIndex, EXYNOS_CAMERA_BUFFER_POSITION_IN_HAL, &dstBuffer); |
| if (ret < 0) { |
| CLOGE2("bufferMgr getBuffer fail, frameCount(%d), ret(%d)", |
| frame->getFrameCount(), ret); |
| } |
| } |
| ret = m_setupEntity(pipeId_jpeg, frame, &srcBuffer, &dstBuffer); |
| if (ret < 0) |
| CLOGE2("setupEntity fail, pipeId(%d), ret(%d)", pipeId_jpeg, ret); |
| #endif |
| factory->setOutputFrameQToPipe(m_pipeCaptureFrameDoneQ, pipeId_jpeg); |
| factory->pushFrameToPipe(&frame, pipeId_jpeg); |
| } |
| } |
| |
| return ret; |
| } |
| |
| status_t ExynosCamera3::m_handleJpegFrame(ExynosCameraFrame *frame) |
| { |
| status_t ret = 0; |
| int pipeId_jpeg = -1; |
| int pipeId_src = -1; |
| ExynosCameraRequest *request = NULL; |
| ExynosCamera3FrameFactory * factory = NULL; |
| ExynosCameraBufferManager *bufferMgr = NULL; |
| ExynosCameraBuffer buffer; |
| int jpegOutputSize = -1; |
| |
| request = m_requestMgr->getServiceRequest(frame->getFrameCount()); |
| factory = request->getFrameFactory(HAL_STREAM_ID_JPEG); |
| |
| ////////////////////////////////////////////////////////// |
| /* TODO: Need to decision pipeId both current and next */ |
| if (m_parameters->isReprocessing() == true) { |
| if (m_parameters->needGSCForCapture(getCameraId()) == true) { |
| pipeId_src = PIPE_GSC_REPROCESSING; |
| } else { |
| pipeId_src = (m_parameters->isOwnScc(getCameraId()) == true) ? PIPE_SCC_REPROCESSING : PIPE_ISPC_REPROCESSING; |
| } |
| pipeId_jpeg = PIPE_JPEG_REPROCESSING; |
| } else { |
| if (m_parameters->needGSCForCapture(getCameraId()) == true) { |
| pipeId_src = PIPE_GSC_PICTURE; |
| } else { |
| if (m_parameters->isOwnScc(getCameraId()) == true) { |
| pipeId_src = PIPE_SCC; |
| } else { |
| pipeId_src = PIPE_ISPC; |
| } |
| } |
| pipeId_jpeg = PIPE_JPEG; |
| } |
| ////////////////////////////////////////////////////////// |
| |
| if (m_parameters->isHWFCEnabled() == true) { |
| entity_buffer_state_t bufferState = ENTITY_BUFFER_STATE_NOREQ; |
| ret = frame->getDstBufferState(PIPE_MCSC_REPROCESSING, &bufferState, factory->getNodeType(PIPE_HWFC_JPEG_DST_REPROCESSING)); |
| if (ret != NO_ERROR) { |
| CLOGE2("Failed to getDstBufferState. frameCount %d pipeId %d node %d", |
| frame->getFrameCount(), PIPE_MCSC_REPROCESSING, PIPE_HWFC_JPEG_DST_REPROCESSING); |
| return INVALID_OPERATION; |
| } else if (bufferState == ENTITY_BUFFER_STATE_ERROR) { |
| CLOGE2("Invalid JPEG buffer state. frameCount %d bufferState %d", |
| frame->getFrameCount(), bufferState); |
| return INVALID_OPERATION; |
| } |
| |
| ret = frame->getDstBuffer(PIPE_MCSC_REPROCESSING, &buffer, factory->getNodeType(PIPE_HWFC_JPEG_DST_REPROCESSING)); |
| if (ret != NO_ERROR) { |
| CLOGE2("Failed to getDstBuffer. frameCount %d pipeId %d node %d", |
| frame->getFrameCount(), PIPE_MCSC_REPROCESSING, PIPE_HWFC_JPEG_DST_REPROCESSING); |
| return INVALID_OPERATION; |
| } |
| } else { |
| ret = frame->setEntityState(pipeId_jpeg, ENTITY_STATE_FRAME_DONE); |
| if (ret < 0) { |
| CLOGE2("set entity state fail, ret(%d)", ret); |
| /* TODO: doing exception handling */ |
| return OK; |
| } |
| |
| /* handle src buffer of jpeg */ |
| ret = m_getBufferManager(pipeId_src, &bufferMgr, DST_BUFFER_DIRECTION); |
| if (ret < 0) { |
| CLOGE2("getBufferManager(DST) fail, pipeId(%d), ret(%d)", pipeId_src, ret); |
| return ret; |
| } |
| |
| ret = frame->getSrcBuffer(pipeId_jpeg, &buffer); |
| if (ret < 0) { |
| CLOGE2("getSrcBuffer fail, pipeId(%d), ret(%d)", pipeId_jpeg, ret); |
| } |
| |
| ret = m_putBuffers(bufferMgr, buffer.index); |
| if (ret < 0) { |
| CLOGE2("bufferMgr(DST)->putBuffers() fail, pipeId(%d), ret(%d)", pipeId_src, ret); |
| } |
| |
| /* |
| * handle dst buffer of jpeg |
| * - JPEG image must be final result of stream. |
| */ |
| #if 0 |
| ret = m_getBufferManager(pipeId_jpeg, &bufferMgr, DST_BUFFER_DIRECTION); |
| if (ret < 0) { |
| CLOGE2("getBufferManager(DST) fail, pipeId(%d), ret(%d)", pipeId_jpeg, ret); |
| return ret; |
| } |
| #endif |
| |
| ret = frame->getDstBuffer(pipeId_jpeg, &buffer); |
| if (ret < 0) { |
| CLOGE2("getDstBuffer fail, pipeId(%d), ret(%d)", pipeId_jpeg, ret); |
| } |
| } |
| |
| jpegOutputSize = frame->getJpegSize(); |
| CLOGI2("jpeg output done, jpeg size(%d)", jpegOutputSize); |
| |
| if (jpegOutputSize <= 0) { |
| CLOGW2("jpegOutput size(%d) is invalid", jpegOutputSize); |
| jpegOutputSize = buffer.size[0]; |
| } |
| |
| /* frame->printEntity(); */ |
| m_pushJpegResult(frame, jpegOutputSize, &buffer); |
| m_captureCount--; |
| |
| return ret; |
| } |
| |
| status_t ExynosCamera3::m_handleBayerBuffer(ExynosCameraFrame *frame) |
| { |
| status_t ret = NO_ERROR; |
| uint32_t bufferDirection = INVALID_BUFFER_DIRECTION; |
| uint32_t pipeId = MAX_PIPE_NUM; |
| ExynosCameraBuffer buffer; |
| ExynosCameraBufferManager *bufferMgr = NULL; |
| ExynosCamera3FrameFactory *factory = NULL; |
| |
| if (frame == NULL) { |
| CLOGE("ERR(%s[%d]):Frame is NULL", __FUNCTION__, __LINE__); |
| return BAD_VALUE; |
| } |
| |
| /* Decide the bayer buffer position and pipe ID */ |
| if (m_parameters->isFlite3aaOtf() == true) { |
| pipeId = PIPE_FLITE; |
| bufferDirection = DST_BUFFER_DIRECTION; |
| ret = frame->getDstBuffer(pipeId, &buffer); |
| } else { |
| pipeId = PIPE_3AA; |
| bufferDirection = SRC_BUFFER_DIRECTION; |
| ret = frame->getSrcBuffer(pipeId, &buffer); |
| } |
| |
| if (ret != NO_ERROR) { |
| CLOGE("ERR(%s[%d]):Get bayer buffer failed, framecount(%d), direction(%d), pipeId(%d)", |
| __FUNCTION__, __LINE__, |
| frame->getFrameCount(), bufferDirection, pipeId); |
| return ret; |
| } |
| |
| /* Check the validation of bayer buffer */ |
| if (buffer.index < 0) { |
| CLOGE("ERR(%s[%d]):Invalid bayer buffer, framecount(%d), direction(%d), pipeId(%d)", |
| __FUNCTION__, __LINE__, |
| frame->getFrameCount(), bufferDirection, pipeId); |
| return INVALID_OPERATION; |
| } |
| |
| if (pipeId == PIPE_3AA) { |
| struct camera2_shot_ext *shot_ext = NULL; |
| |
| shot_ext = (struct camera2_shot_ext *) buffer.addr[buffer.planeCount -1]; |
| CLOGW("WRN(%s[%d]):Timestamp(%lld)", __FUNCTION__, __LINE__, shot_ext->shot.dm.sensor.timeStamp); |
| |
| ret = m_updateTimestamp(frame, &buffer); |
| if (ret != NO_ERROR) { |
| CLOGE("ERR(%s[%d]):Failed to update time stamp", __FUNCTION__, __LINE__); |
| return ret; |
| } |
| } |
| |
| /* Handle the bayer buffer */ |
| if (frame->getFrameServiceBayer() == true) { |
| /* Raw Capture Request */ |
| CLOGD("INFO(%s[%d]):Handle service bayer buffer. FLITE-3AA_OTF %d Bayer_Pipe_ID %d Framecount %d", |
| __FUNCTION__, __LINE__, |
| m_parameters->isFlite3aaOtf(), pipeId, frame->getFrameCount()); |
| ret = m_sendRawCaptureResult(frame, pipeId, (bufferDirection == SRC_BUFFER_DIRECTION)); |
| if (ret != NO_ERROR) { |
| CLOGE("ERR(%s[%d]):Failed to sendRawCaptureResult. frameCount %d bayerPipeId %d bufferIndex %d", |
| __FUNCTION__, __LINE__, |
| frame->getFrameCount(), pipeId, buffer.index); |
| return ret; |
| } |
| |
| if (m_parameters->isReprocessing() == true && frame->getFrameCapture() == true) { |
| CLOGD("DEBUG(%s[%d]):Hold service bayer buffer for reprocessing. frameCount %d bayerPipeId %d bufferIndex %d", |
| __FUNCTION__, __LINE__, |
| frame->getFrameCount(), pipeId, buffer.index); |
| ret = m_captureZslSelector->manageFrameHoldListForDynamicBayer(frame); |
| if (ret != NO_ERROR) { |
| CLOGE("ERR(%s[%d]):Failed to manageFrameHoldListForDynamicBayer to captureZslSelector. frameCount %d bayerPipeId %d bufferIndex %d", |
| __FUNCTION__, __LINE__, |
| frame->getFrameCount(), pipeId, buffer.index); |
| return ret; |
| } |
| } |
| } else if (frame->getFrameZsl() == true) { |
| /* ZSL Capture Request */ |
| CLOGV("INFO(%s[%d]):Handle ZSL buffer. FLITE-3AA_OTF %d Bayer_Pipe_ID %d Framecount %d", |
| __FUNCTION__, __LINE__, |
| m_parameters->isFlite3aaOtf(), pipeId, frame->getFrameCount()); |
| ret = m_sendZSLCaptureResult(frame, pipeId, (bufferDirection == SRC_BUFFER_DIRECTION)); |
| if (ret != NO_ERROR) { |
| CLOGE("ERR(%s[%d]):Failed to sendZslCaptureResult. frameCount %d bayerPipeId %d", |
| __FUNCTION__, __LINE__, |
| frame->getFrameCount(), pipeId); |
| } |
| } else if (m_parameters->isReprocessing() == true){ |
| /* For ZSL Reprocessing */ |
| CLOGV("INFO(%s[%d]):Hold internal bayer buffer for reprocessing. FLITE-3AA_OTF %d Bayer_Pipe_ID %d Framecount %d", |
| __FUNCTION__, __LINE__, |
| m_parameters->isFlite3aaOtf(), pipeId, frame->getFrameCount()); |
| ret = m_captureSelector->manageFrameHoldList(frame, pipeId, (bufferDirection == SRC_BUFFER_DIRECTION)); |
| } else { |
| /* No request for bayer image */ |
| CLOGV("INFO(%s[%d]):Return internal bayer buffer. FLITE-3AA_OTF %d Bayer_Pipe_ID %d Framecount %d", |
| __FUNCTION__, __LINE__, |
| m_parameters->isFlite3aaOtf(), pipeId, frame->getFrameCount()); |
| ret = m_getBufferManager(pipeId, &bufferMgr, bufferDirection); |
| if (ret != NO_ERROR) { |
| CLOGE("ERR(%s[%d]):getBufferManager failed, pipeId(%d), bufferDirection(%d), ret(%d)", |
| __FUNCTION__, __LINE__, pipeId, bufferDirection, ret); |
| return ret; |
| } |
| |
| ret = m_putBuffers(bufferMgr, buffer.index); |
| if (ret != NO_ERROR) { |
| CLOGE("ERR(%s[%d]):putBuffers failed, pipeId(%d), bufferDirection(%d), bufferIndex(%d), ret(%d)", |
| __FUNCTION__, __LINE__, pipeId, bufferDirection, buffer.index, ret); |
| return ret; |
| } |
| } |
| |
| if (ret != NO_ERROR) { |
| CLOGE("ERR(%s[%d]):Handling bayer buffer failed, isServiceBayer(%d), direction(%d), pipeId(%d)", |
| __FUNCTION__, __LINE__, |
| frame->getFrameServiceBayer(), |
| bufferDirection, pipeId); |
| } |
| |
| return ret; |
| } |
| |
| bool ExynosCamera3::m_previewStreamBayerPipeThreadFunc(void) |
| { |
| status_t ret = 0; |
| ExynosCameraFrame *newFrame = NULL; |
| |
| ret = m_pipeFrameDoneQ[PIPE_FLITE]->waitAndPopProcessQ(&newFrame); |
| if (ret < 0) { |
| /* TODO: We need to make timeout duration depends on FPS */ |
| if (ret == TIMED_OUT) { |
| /* CLOGW2("wait timeout"); */ |
| } else { |
| CLOGE2("wait and pop fail, ret(%d)", ret); |
| /* TODO: doing exception handling */ |
| } |
| return true; |
| } |
| return m_previewStreamFunc(newFrame, PIPE_FLITE); |
| } |
| |
| bool ExynosCamera3::m_previewStream3AAPipeThreadFunc(void) |
| { |
| status_t ret = 0; |
| ExynosCameraFrame *newFrame = NULL; |
| |
| ret = m_pipeFrameDoneQ[PIPE_3AA]->waitAndPopProcessQ(&newFrame); |
| if (ret < 0) { |
| /* TODO: We need to make timeout duration depends on FPS */ |
| if (ret == TIMED_OUT) { |
| CLOGW2("wait timeout"); |
| } else { |
| CLOGE2("wait and pop fail, ret(%d)", ret); |
| /* TODO: doing exception handling */ |
| } |
| return true; |
| } |
| return m_previewStreamFunc(newFrame, PIPE_3AA); |
| } |
| |
| bool ExynosCamera3::m_previewStreamISPPipeThreadFunc(void) |
| { |
| status_t ret = 0; |
| ExynosCameraFrame *newFrame = NULL; |
| |
| ret = m_pipeFrameDoneQ[PIPE_ISP]->waitAndPopProcessQ(&newFrame); |
| if (ret < 0) { |
| /* TODO: We need to make timeout duration depends on FPS */ |
| if (ret == TIMED_OUT) { |
| CLOGW2("wait timeout"); |
| } else { |
| CLOGE2("wait and pop fail, ret(%d)", ret); |
| /* TODO: doing exception handling */ |
| } |
| return true; |
| } |
| return m_previewStreamFunc(newFrame, PIPE_ISP); |
| } |
| |
| bool ExynosCamera3::m_previewStreamVRAPipeThreadFunc(void) |
| { |
| status_t ret = 0; |
| ExynosCameraFrame *newFrame = NULL; |
| |
| ret = m_pipeFrameDoneQ[PIPE_VRA]->waitAndPopProcessQ(&newFrame); |
| if (ret < 0) { |
| /* TODO: We need to make timeout duration depends on FPS */ |
| if (ret == TIMED_OUT) { |
| CLOGW2("wait timeout"); |
| } else { |
| CLOGE2("wait and pop fail, ret(%d)", ret); |
| /* TODO: doing exception handling */ |
| } |
| return true; |
| } |
| return m_previewStreamFunc(newFrame, PIPE_VRA); |
| } |
| |
| bool ExynosCamera3::m_previewStreamFunc(ExynosCameraFrame *newFrame, int pipeId) |
| { |
| status_t ret = 0; |
| int index = 0; |
| //result_info_t *resultInfo = NULL; |
| entity_state_t entityState = ENTITY_STATE_COMPLETE; |
| int type = CAMERA3_MSG_SHUTTER; |
| /* only trace */ |
| unsigned int halFrameCount = 0; |
| |
| if (newFrame != NULL) { |
| halFrameCount = newFrame->getFrameCount(); |
| } else { |
| CLOGE2("frame is NULL"); |
| return true; |
| } |
| CLOGV2("stream thread : frameCnt(%d) , pipeId(%d)", halFrameCount, pipeId); |
| |
| //newFrame->dump(); |
| |
| /* internal frame */ |
| if (newFrame->getFrameType() == FRAME_TYPE_INTERNAL) { |
| CLOGV2("push to m_internalFrameDoneQ handler : internalFrame frameCnt(%d)", newFrame->getFrameCount()); |
| m_internalFrameDoneQ->pushProcessQ(&newFrame); |
| return true; |
| } |
| |
| //CLOGV2("stream thread : frameCnt(%d) , pipeId(%d)", halFrameCount, pipeId); |
| |
| /* TODO: M2M path is also handled by this */ |
| ret = m_handlePreviewFrame(newFrame, pipeId); |
| if (ret < 0) { |
| CLOGE2("handle preview frame fail"); |
| return ret; |
| } |
| //CLOGD2("+++++++++++++++++++++++++++++++++++++++++++++"); |
| //newFrame->dump(); |
| //CLOGD2("---------------------------------------------"); |
| |
| if (newFrame->isComplete() == true) { |
| |
| m_sendNotify(newFrame->getFrameCount(), type); |
| |
| CLOGV2("newFrame->getFrameCount(%d)", newFrame->getFrameCount()); |
| |
| ret = m_removeFrameFromList(&m_processList, &m_processLock, newFrame); |
| |
| if (ret < 0) { |
| CLOGE2("remove frame from processList fail, ret(%d)", ret); |
| } |
| |
| CLOGV2("frame complete, count(%d)", newFrame->getFrameCount()); |
| newFrame->decRef(); |
| m_frameMgr->deleteFrame(newFrame); |
| newFrame = NULL; |
| m_captureResultDoneCondition.signal(); |
| } |
| |
| CLOGV2("stream thread : frameCnt(%d) , pipeId(%d)", halFrameCount, pipeId); |
| |
| return true; |
| } |
| |
| status_t ExynosCamera3::m_updateTimestamp(ExynosCameraFrame *frame, ExynosCameraBuffer *timestampBuffer, bool flagPushResult) |
| { |
| struct camera2_shot_ext *shot_ext = NULL; |
| status_t ret = NO_ERROR; |
| |
| /* handle meta data */ |
| shot_ext = (struct camera2_shot_ext *) timestampBuffer->addr[timestampBuffer->planeCount -1]; |
| if (shot_ext == NULL) { |
| CLOGE("ERR(%s[%d]):shot_ext is NULL. framecount %d buffer %d", |
| __FUNCTION__, __LINE__, frame->getFrameCount(), timestampBuffer->index); |
| return INVALID_OPERATION; |
| } |
| |
| #ifdef SAMSUNG_TIMESTAMP_BOOT |
| uint64_t timeStamp = shot_ext->shot.udm.sensor.timeStampBoot; |
| #else |
| uint64_t timeStamp = shot_ext->shot.dm.sensor.timeStamp; |
| #endif |
| uint64_t frameDuration = shot_ext->shot.dm.sensor.frameDuration; |
| |
| /* HACK: W/A for timeStamp reversion */ |
| if (timeStamp < (uint64_t)m_lastFrametime) { |
| CLOGW2("Timestamp is %lld!, m_lastFrametime(%lld)", |
| timeStamp, m_lastFrametime); |
| |
| if (frameDuration > 0) |
| timeStamp = m_lastFrametime + frameDuration; |
| else |
| timeStamp = m_lastFrametime + 15000000; |
| } |
| |
| if (m_lastFrametime > 0 |
| && timeStamp > (uint64_t)m_lastFrametime + 100000000) { /* 1sec */ |
| CLOGW2("Timestamp is %lld!, m_lastFrametime(%lld)", |
| timeStamp, m_lastFrametime); |
| } |
| |
| m_lastFrametime = timeStamp; |
| shot_ext->shot.udm.sensor.timeStampBoot = timeStamp; |
| |
| if (flagPushResult == true) |
| ret = m_pushResult(frame->getFrameCount(), shot_ext); |
| |
| return ret; |
| } |
| |
| status_t ExynosCamera3::m_handlePreviewFrame(ExynosCameraFrame *frame, int pipeId) |
| { |
| ExynosCameraFrameEntity *entity = NULL; |
| ExynosCameraFrame *newFrame = NULL; |
| ExynosCameraBuffer buffer; |
| ExynosCamera3FrameFactory *factory = NULL; |
| ExynosCameraBuffer t3acBuffer; |
| int32_t reprocessingBayerMode = m_parameters->getReprocessingBayerMode(); |
| |
| struct camera2_shot_ext *shot_ext; |
| struct camera2_shot_ext meta_shot_ext; |
| struct camera2_dm *dm = NULL; |
| entity_state_t entityState = ENTITY_STATE_COMPLETE; |
| status_t ret = NO_ERROR; |
| uint32_t framecount = 0; |
| |
| entity = frame->getFrameDoneFirstEntity(pipeId); |
| if (entity == NULL) { |
| CLOGE2("current entity is NULL pipeID(%d)", pipeId); |
| /* TODO: doing exception handling */ |
| return true; |
| } |
| |
| CLOGV2("handle preview frame : previewStream frameCnt(%d) entityID(%d)", frame->getFrameCount(), entity->getPipeId()); |
| |
| factory = m_frameFactory[FRAME_FACTORY_TYPE_CAPTURE_PREVIEW]; |
| |
| switch(pipeId) { |
| case PIPE_3AA_ISP: |
| ret = frame->getSrcBuffer(entity->getPipeId(), &buffer); |
| if (ret < 0) { |
| CLOGE2("getSrcBuffer fail, pipeId(%d), ret(%d)", entity->getPipeId(), ret); |
| return ret; |
| } |
| |
| /* handle meta data */ |
| shot_ext = (struct camera2_shot_ext *) buffer.addr[buffer.planeCount -1]; |
| memset(&meta_shot_ext, 0x00, sizeof(struct camera2_shot_ext)); |
| memcpy(&meta_shot_ext, shot_ext, sizeof(struct camera2_shot_ext)); |
| ret = m_pushResult(frame->getFrameCount(), &meta_shot_ext); |
| |
| ret = m_putBuffers(m_3aaBufferMgr, buffer.index); |
| if (ret < 0) { |
| CLOGE2("put Buffer fail"); |
| } |
| |
| CLOGV2("3AA_ISP frameCount(%d) frame.Count(%d)", |
| getMetaDmRequestFrameCount((struct camera2_shot_ext *)buffer.addr[buffer.planeCount-1]), |
| frame->getFrameCount()); |
| |
| ret = frame->getDstBuffer(entity->getPipeId(), &buffer); |
| if (ret < 0) { |
| CLOGE2("getDstBuffer fail, pipeId(%d), ret(%d)", entity->getPipeId(), ret); |
| return ret; |
| } |
| |
| ret = m_putBuffers(m_ispBufferMgr, buffer.index); |
| if (ret < 0) { |
| CLOGE2("put Buffer fail"); |
| break; |
| } |
| |
| frame->setMetaDataEnable(true); |
| dm = &(meta_shot_ext.shot.dm); |
| if (dm == NULL) { |
| CLOGE2("dm data is null"); |
| return INVALID_OPERATION; |
| } |
| |
| break; |
| case PIPE_3AA: |
| /* Notify ShotDone to mainThread */ |
| framecount = frame->getFrameCount(); |
| m_shotDoneQ->pushProcessQ(&framecount); |
| |
| /* 1. Handle the buffer from 3AA output node */ |
| if (m_parameters->isFlite3aaOtf() == true) { |
| ExynosCameraBufferManager *bufferMgr = NULL; |
| |
| /* Return the dummy buffer */ |
| ret = frame->getSrcBuffer(entity->getPipeId(), &buffer); |
| if (ret < 0) { |
| ALOGE("ERR(%s[%d]):getSrcBuffer fail, pipeId(%d), ret(%d)", |
| __FUNCTION__, __LINE__, entity->getPipeId(), ret); |
| return ret; |
| } else if (buffer.index < 0) { |
| ALOGE("ERR(%s[%d]):Invalid buffer index(%d), framecount(%d), pipeId(%d)", |
| __FUNCTION__, __LINE__, |
| buffer.index, frame->getFrameCount(), entity->getPipeId()); |
| return BAD_VALUE; |
| } |
| |
| if (m_parameters->is3aaIspOtf() == true) { |
| ret = m_updateTimestamp(frame, &buffer); |
| if (ret != NO_ERROR) { |
| CLOGE2("[F%d B%d]Failed to updateTimestamp", |
| frame->getFrameCount(), buffer.index); |
| return ret; |
| } |
| } |
| |
| ret = m_putBuffers(m_3aaBufferMgr, buffer.index); |
| if (ret < 0) { |
| CLOGE2("[F%d]Failed to put buffer %d to 3aaBufferMgr", |
| frame->getFrameCount(), buffer.index); |
| break; |
| } |
| } else { |
| ret = m_handleBayerBuffer(frame); |
| if (ret != NO_ERROR) { |
| ALOGE("ERR(%s[%d]):Failed to handle bayerBuffer. framecount %d pipeId %d ret %d", |
| __FUNCTION__, __LINE__, |
| frame->getFrameCount(), entity->getPipeId(), ret); |
| return ret; |
| } |
| } |
| |
| frame->setMetaDataEnable(true); |
| |
| if (frame->getFrameZsl() == true) { |
| /* ZSL Capture Request */ |
| CLOGD2("Handle ZSL buffer. FLITE-3AA_OTF %d Framecount %d", |
| m_parameters->isFlite3aaOtf(), frame->getFrameCount()); |
| ret = m_sendZSLCaptureResult(frame, PIPE_3AC, false); |
| if (ret != NO_ERROR) { |
| CLOGE2("Failed to sendZslCaptureResult. frameCount %d", |
| frame->getFrameCount()); |
| } |
| } |
| |
| t3acBuffer.index = -1; |
| |
| if (frame->getRequest(PIPE_3AC) == true) { |
| ret = frame->getDstBuffer(entity->getPipeId(), &t3acBuffer, factory->getNodeType(PIPE_3AC)); |
| if (ret != NO_ERROR) { |
| CLOGE2("getDstBuffer fail, pipeId(%d), ret(%d)", entity->getPipeId(), ret); |
| } |
| } |
| |
| if (m_parameters->isReprocessing() == true) { |
| if (m_captureSelector == NULL) { |
| CLOGE2("m_captureSelector is NULL"); |
| return INVALID_OPERATION; |
| } |
| } else { |
| if (m_sccCaptureSelector == NULL) { |
| CLOGE2("m_sccCaptureSelector is NULL"); |
| return INVALID_OPERATION; |
| } |
| } |
| |
| if (0 <= t3acBuffer.index) { |
| if (m_parameters->isUseYuvReprocessing() == true |
| || frame->getFrameCapture() == true) { |
| if (m_parameters->getHighSpeedRecording() == true) { |
| if (m_parameters->isUsing3acForIspc() == true) |
| ret = m_putBuffers(m_yuvCaptureBufferMgr, t3acBuffer.index); |
| else |
| ret = m_putBuffers(m_fliteBufferMgr, t3acBuffer.index); |
| |
| if (ret < 0) { |
| CLOGE2("m_putBuffers(m_fliteBufferMgr, %d) fail", t3acBuffer.index); |
| break; |
| } |
| } else { |
| entity_buffer_state_t bufferstate = ENTITY_BUFFER_STATE_NOREQ; |
| ret = frame->getDstBufferState(entity->getPipeId(), &bufferstate, factory->getNodeType(PIPE_3AC)); |
| if (ret == NO_ERROR && bufferstate != ENTITY_BUFFER_STATE_ERROR) { |
| if (m_parameters->isUseYuvReprocessing() == false |
| && m_parameters->isUsing3acForIspc() == true) |
| ret = m_sccCaptureSelector->manageFrameHoldListForDynamicBayer(frame); |
| else |
| ret = m_captureSelector->manageFrameHoldList(frame, entity->getPipeId(), false, factory->getNodeType(PIPE_3AC)); |
| |
| if (ret < 0) { |
| CLOGE2("manageFrameHoldList fail"); |
| return ret; |
| } |
| } else { |
| if (m_parameters->isUsing3acForIspc() == true) |
| ret = m_putBuffers(m_yuvCaptureBufferMgr, t3acBuffer.index); |
| else |
| ret = m_putBuffers(m_fliteBufferMgr, t3acBuffer.index); |
| |
| if (ret < 0) { |
| CLOGE2("m_putBuffers(m_fliteBufferMgr, %d) fail", t3acBuffer.index); |
| break; |
| } |
| } |
| } |
| } else { |
| if (reprocessingBayerMode == REPROCESSING_BAYER_MODE_DIRTY_ALWAYS_ON) { |
| CLOGW2("frame->getRequest(PIPE_3AC) == false. so, just m_putBuffers(t3acBuffer.index(%d)..., pipeId(%d), ret(%d)", |
| t3acBuffer.index, entity->getPipeId(), ret); |
| } |
| |
| if (m_parameters->isUsing3acForIspc() == true) |
| ret = m_putBuffers(m_yuvCaptureBufferMgr, t3acBuffer.index); |
| else |
| ret = m_putBuffers(m_fliteBufferMgr, t3acBuffer.index); |
| |
| if (ret < 0) { |
| CLOGE2("m_putBuffers(m_fliteBufferMgr, %d) fail", t3acBuffer.index); |
| break; |
| } |
| } |
| } |
| |
| case PIPE_SCP: |
| ret = frame->getDstBuffer(entity->getPipeId(), &buffer, factory->getNodeType(PIPE_SCP)); |
| if (ret < 0) { |
| CLOGE2("getDstBuffer fail, pipeId(%d), ret(%d)", entity->getPipeId(), ret); |
| return ret; |
| } |
| |
| CLOGV2("SCP frameCount(%d) frame.Count(%d) index(%d)", |
| ((struct camera2_stream *)buffer.addr[buffer.planeCount-1])->fcount, |
| frame->getFrameCount(), |
| buffer.index); |
| // TODO: extract this |
| |
| if (frame->getFrameCapture() == true) { |
| ret = frame->setEntityState(entity->getPipeId(), ENTITY_STATE_COMPLETE); |
| if (ret < 0) { |
| CLOGE2("setEntityState fail, pipeId(%d), state(%d), ret(%d)", |
| entity->getPipeId(), ENTITY_STATE_COMPLETE, ret); |
| return ret; |
| } |
| |
| CLOGI2("Capture frame(%d)", frame->getFrameCount()); |
| #if defined(ENABLE_FULL_FRAME) |
| ret = m_handleIsChainDone(frame); |
| if (ret < 0) |
| CLOGE2("ERR(%s[%d]):m_handleIsChainDone fail, ret(%d)", ret); |
| |
| m_captureStreamThread->run(PRIORITY_DEFAULT); |
| #endif |
| } |
| |
| m_generateDuplicateBuffers(frame, entity->getPipeId()); |
| |
| break; |
| case PIPE_VRA: |
| ret = frame->getDstBuffer(entity->getPipeId(), &buffer); |
| if (ret != NO_ERROR) { |
| CLOGE("ERR(%s[%d]):getDstBuffer fail, pipeId(%d), ret(%d)", |
| __FUNCTION__, __LINE__, entity->getPipeId(), ret); |
| return ret; |
| } |
| |
| if (buffer.index >= 0) { |
| if (entity->getDstBufState() != ENTITY_BUFFER_STATE_ERROR) { |
| /* Face detection update */ |
| m_pushResult(frame->getFrameCount(), (struct camera2_shot_ext*)buffer.addr[buffer.planeCount-1]); |
| } |
| |
| ret = m_vraBufferMgr->putBuffer(buffer.index, EXYNOS_CAMERA_BUFFER_POSITION_IN_HAL); |
| if (ret != NO_ERROR) |
| CLOGW("WARN(%s[%d]):Put VRA buffer fail, ret(%d)", __FUNCTION__, __LINE__, ret); |
| } |
| |
| break; |
| case PIPE_3AC: |
| case PIPE_FLITE: |
| /* 1. Handle bayer buffer */ |
| if (m_parameters->isFlite3aaOtf() == true) { |
| ret = m_handleBayerBuffer(frame); |
| if (ret < NO_ERROR) { |
| ALOGE("ERR(%s[%d]):Handle bayer buffer failed, framecount(%d), pipeId(%d), ret(%d)", |
| __FUNCTION__, __LINE__, frame->getFrameCount(), entity->getPipeId(), ret); |
| return ret; |
| } |
| } else { |
| /* Send the bayer buffer to 3AA Pipe */ |
| ret = frame->getDstBuffer(entity->getPipeId(), &buffer); |
| if (ret < 0) { |
| ALOGE("ERR(%s[%d]):getDstBuffer fail, pipeId(%d), ret(%d)", |
| __FUNCTION__, __LINE__, entity->getPipeId(), ret); |
| return ret; |
| } |
| |
| if (buffer.index < 0) { |
| ALOGE("ERR(%s[%d]):Invalid buffer index(%d), framecount(%d), pipeId(%d)", |
| __FUNCTION__, __LINE__, |
| buffer.index, frame->getFrameCount(), entity->getPipeId()); |
| return BAD_VALUE; |
| } |
| ALOGV("DEBUG(%s[%d]):Deliver Flite Buffer to 3AA. driver->framecount %d hal->framecount %d", |
| __FUNCTION__, __LINE__, |
| getMetaDmRequestFrameCount((struct camera2_shot_ext *)buffer.addr[buffer.planeCount-1]), |
| frame->getFrameCount()); |
| |
| ret = m_setupEntity(PIPE_3AA, frame, &buffer, NULL); |
| if (ret != NO_ERROR) { |
| ALOGE("ERR(%s[%d]):setSrcBuffer failed, pipeId(%d), ret(%d)", |
| __FUNCTION__, __LINE__, PIPE_3AA, ret); |
| return ret; |
| } |
| |
| factory = m_frameFactory[FRAME_FACTORY_TYPE_CAPTURE_PREVIEW]; |
| factory->setOutputFrameQToPipe(m_pipeFrameDoneQ[PIPE_3AA], PIPE_3AA); |
| factory->pushFrameToPipe(&frame, PIPE_3AA); |
| } |
| |
| break; |
| case PIPE_ISP: |
| ret = frame->getSrcBuffer(entity->getPipeId(), &buffer); |
| if (ret < 0) { |
| CLOGE2("getSrcBuffer fail, pipeId(%d), ret(%d)", entity->getPipeId(), ret); |
| return ret; |
| } |
| |
| if (buffer.index >= 0) { |
| ret = m_updateTimestamp(frame, &buffer); |
| if (ret != NO_ERROR) { |
| CLOGE2("[F%d B%d]Failed to updateTimestamp", |
| frame->getFrameCount(), buffer.index); |
| return ret; |
| } |
| |
| ret = m_putBuffers(m_ispBufferMgr, buffer.index); |
| if (ret < 0) { |
| CLOGE2("put Buffer fail"); |
| break; |
| } |
| } |
| |
| /* break; *//* MCpipe case */ |
| default: |
| CLOGE2("Invalid pipe ID"); |
| break; |
| } |
| |
| ret = frame->setEntityState(entity->getPipeId(), entityState); |
| if (ret < 0) { |
| CLOGE2("setEntityState fail, pipeId(%d), state(%d), ret(%d)", |
| entity->getPipeId(), ENTITY_STATE_COMPLETE, ret); |
| return ret; |
| } |
| |
| return ret; |
| } |
| |
| status_t ExynosCamera3::m_generateDuplicateBuffers(ExynosCameraFrame *frame, int pipeIdSrc) |
| { |
| status_t ret = NO_ERROR; |
| ExynosCameraRequest *halRequest = NULL; |
| camera3_capture_request *serviceRequest = NULL; |
| const camera3_stream_buffer_t *targetBuffer = NULL; |
| const camera3_stream_buffer_t *targetBufferList = NULL; |
| |
| ExynosCameraStream *stream = NULL; |
| int streamId = 0; |
| |
| List<int> keylist; |
| List<int>::iterator iter; |
| keylist.clear(); |
| |
| List<int> *outputStreamId; |
| List<int>::iterator outputStreamIdIter; |
| |
| if (frame == NULL) { |
| CLOGE2("frame is NULL"); |
| return INVALID_OPERATION; |
| } |
| |
| halRequest = m_requestMgr->getServiceRequest(frame->getFrameCount()); |
| if (halRequest == NULL) { |
| CLOGE2("halRequest is NULL"); |
| return INVALID_OPERATION; |
| } |
| |
| serviceRequest = halRequest->getService(); |
| if (serviceRequest == NULL) { |
| CLOGE2("serviceRequest is NULL"); |
| return INVALID_OPERATION; |
| } |
| |
| CLOGV2("frame->getFrameCount(%d) halRequest->getFrameCount(%d) serviceRequest->num_output_buffers(%d)", |
| frame->getFrameCount(), |
| halRequest->getFrameCount(), |
| serviceRequest->num_output_buffers); |
| |
| halRequest->getAllRequestOutputStreams(&outputStreamId); |
| |
| if (outputStreamId->size() > 0) { |
| for (outputStreamIdIter = outputStreamId->begin(); outputStreamIdIter != outputStreamId->end(); outputStreamIdIter++) { |
| m_streamManager->getStream(*outputStreamIdIter, &stream); |
| |
| if (stream == NULL) { |
| CLOGE2("stream is NULL"); |
| continue; |
| } |
| |
| stream->getID(&streamId); |
| |
| switch (streamId % HAL_STREAM_ID_MAX) { |
| case HAL_STREAM_ID_RAW: |
| break; |
| case HAL_STREAM_ID_PREVIEW: |
| m_doDestCSC(true, frame, pipeIdSrc, streamId, PIPE_GSC); |
| break; |
| case HAL_STREAM_ID_VIDEO: |
| m_doDestCSC(true, frame, pipeIdSrc, streamId, PIPE_GSC_VIDEO); |
| break; |
| case HAL_STREAM_ID_JPEG: |
| break; |
| case HAL_STREAM_ID_CALLBACK: |
| m_doDestCSC(true, frame, pipeIdSrc, streamId, PIPE_GSC); |
| break; |
| default: |
| break; |
| } |
| } |
| } |
| |
| return ret; |
| } |
| |
| bool ExynosCamera3::m_duplicateBufferThreadFunc(void) |
| { |
| status_t ret = 0; |
| int index = 0; |
| ExynosCameraFrame *newFrame= NULL; |
| dup_buffer_info_t dupBufferInfo; |
| ExynosCameraBuffer srcBuffer; |
| ExynosCameraBuffer dstBuffer; |
| ExynosCameraStream *stream = NULL; |
| camera3_stream_buffer_t streamBuffer; |
| ExynosCameraRequest *request = NULL; |
| ResultRequest resultRequest = NULL; |
| int actualFormat = 0; |
| int bufIndex = -1; |
| |
| unsigned int completeBufferCount = 0; |
| |
| ExynosCameraBufferManager *bufferMgr = NULL; |
| |
| ret = m_duplicateBufferDoneQ->waitAndPopProcessQ(&newFrame); |
| if (ret < 0) { |
| /* TODO: We need to make timeout duration depends on FPS */ |
| if (ret == TIMED_OUT) { |
| CLOGW2("wait timeout"); |
| } else { |
| CLOGE2("wait and pop fail, ret(%d)", ret); |
| /* TODO: doing exception handling */ |
| } |
| return true; |
| } |
| |
| if (newFrame == NULL) { |
| CLOGE2("frame is NULL"); |
| goto func_exit; |
| } |
| |
| CLOGV2("CSC done (frameCount(%d))", newFrame->getFrameCount()); |
| |
| dupBufferInfo = newFrame->getDupBufferInfo(); |
| CLOGV2("streamID(%d), extScalerPipeID(%d)", dupBufferInfo.streamID, dupBufferInfo.extScalerPipeID); |
| |
| ret = m_streamManager->getStream(dupBufferInfo.streamID, &stream); |
| if (ret < 0) { |
| CLOGE2("getStream is failed, from streammanager. Id error:HAL_STREAM_ID_PREVIEW"); |
| goto func_exit; |
| } |
| |
| ret = stream->getStream(&streamBuffer.stream); |
| if (ret < 0) { |
| CLOGE2("ERR(%s[%d]):getStream is failed, from exynoscamerastream. Id error:HAL_STREAM_ID_PREVIEW"); |
| goto func_exit; |
| } |
| |
| stream->getBufferManager(&bufferMgr); |
| CLOGV2("bufferMgr(%p)", bufferMgr); |
| |
| ret = newFrame->getDstBuffer(dupBufferInfo.extScalerPipeID, &dstBuffer); |
| if (ret < 0) { |
| CLOGE2("getDstBuffer fail, pipeId(%d), ret(%d)", dupBufferInfo.extScalerPipeID, ret); |
| goto func_exit; |
| } |
| |
| ret = bufferMgr->getHandleByIndex(&streamBuffer.buffer, dstBuffer.index); |
| if (ret != OK) { |
| CLOGE2("Buffer index error(%d)!!", dstBuffer.index); |
| goto func_exit; |
| } |
| |
| /* update output stream buffer information */ |
| streamBuffer.status = CAMERA3_BUFFER_STATUS_OK; |
| streamBuffer.acquire_fence = -1; |
| streamBuffer.release_fence = -1; |
| |
| request = m_requestMgr->getServiceRequest(newFrame->getFrameCount()); |
| |
| resultRequest = m_requestMgr->createResultRequest(newFrame->getFrameCount(), EXYNOS_REQUEST_RESULT::CALLBACK_BUFFER_ONLY, NULL, NULL); |
| resultRequest->pushStreamBuffer(&streamBuffer); |
| |
| m_requestMgr->callbackSequencerLock(); |
| request->increaseCompleteBufferCount(); |
| request->increaseDuplicateBufferCount(); |
| completeBufferCount = request->getNumOfOutputBuffer(); |
| if (newFrame->getFrameCapture() == true) |
| completeBufferCount --; |
| if (newFrame->getFrameServiceBayer() == true) |
| completeBufferCount --; |
| |
| CLOGV2("OutputBuffer(%d) CompleteBufferCount(%d) DuplicateBufferCount(%d) streamID(%d), extScaler(%d), frame: Count(%d), ServiceBayer(%d), Capture(%d) completeBufferCount(%d)", |
| request->getNumOfOutputBuffer(), |
| request->getCompleteBufferCount(), |
| request->getDuplicateBufferCount(), |
| dupBufferInfo.streamID, |
| dupBufferInfo.extScalerPipeID, |
| newFrame->getFrameCount(), |
| newFrame->getFrameServiceBayer(), |
| newFrame->getFrameCapture(), |
| completeBufferCount); |
| |
| if(completeBufferCount == (unsigned int)request->getDuplicateBufferCount()) { |
| ret = newFrame->getSrcBuffer(dupBufferInfo.extScalerPipeID, &srcBuffer); |
| if (srcBuffer.index >= 0) { |
| CLOGV2("Internal Scp Buffer is returned index(%d)frameCount(%d)", srcBuffer.index, newFrame->getFrameCount()); |
| ret = m_putBuffers(m_internalScpBufferMgr, srcBuffer.index); |
| if (ret < 0) { |
| CLOGE2("put Buffer fail"); |
| } |
| } |
| } |
| m_requestMgr->callbackRequest(resultRequest); |
| m_requestMgr->callbackSequencerUnlock(); |
| |
| func_exit: |
| if (newFrame != NULL ) { |
| newFrame->decRef(); |
| m_frameMgr->deleteFrame(newFrame);; |
| newFrame = NULL; |
| } |
| |
| return true; |
| } |
| |
| status_t ExynosCamera3::m_doDestCSC(bool enableCSC, ExynosCameraFrame *frame, int pipeIdSrc, int halStreamId, int pipeExtScalerId) |
| { |
| status_t ret = OK; |
| ExynosCameraFrame *newFrame = NULL; |
| ExynosRect srcRect, dstRect; |
| ExynosCamera3FrameFactory *factory = NULL; |
| ExynosCameraBuffer srcBuffer; |
| ExynosCameraBuffer dstBuffer; |
| ExynosCameraStream *stream = NULL; |
| camera3_stream_buffer_t streamBuffer; |
| ExynosCameraRequest *request = NULL; |
| ResultRequest resultRequest = NULL; |
| int actualFormat = 0; |
| int bufIndex = -1; |
| dup_buffer_info_t dupBufferInfo; |
| struct camera2_stream *meta = NULL; |
| uint32_t *output = NULL; |
| |
| ExynosCameraBufferManager *bufferMgr = NULL; |
| |
| |
| if (enableCSC == false) { |
| /* TODO: memcpy srcBuffer, dstBuffer */ |
| return NO_ERROR; |
| } |
| |
| request = m_requestMgr->getServiceRequest(frame->getFrameCount()); |
| factory = request->getFrameFactory(halStreamId); |
| ret = frame->getDstBuffer(pipeIdSrc, &srcBuffer, factory->getNodeType(PIPE_SCP)); |
| if (ret < 0) { |
| CLOGE2("getDstBuffer fail, pipeId(%d), ret(%d)", pipeIdSrc, ret); |
| return ret; |
| } |
| |
| ret = m_streamManager->getStream(halStreamId, &stream); |
| if (ret < 0) { |
| CLOGE2("getStream is failed, from streammanager. Id error:HAL_STREAM_ID_PREVIEW"); |
| return ret; |
| } |
| |
| ret = stream->getStream(&streamBuffer.stream); |
| if (ret < 0) { |
| CLOGE2("getStream is failed, from exynoscamerastream. Id error:HAL_STREAM_ID_PREVIEW"); |
| return ret; |
| } |
| |
| meta = (struct camera2_stream*)srcBuffer.addr[srcBuffer.planeCount-1]; |
| output = meta->output_crop_region; |
| |
| stream->getBufferManager(&bufferMgr); |
| CLOGV2("bufferMgr(%p)", bufferMgr); |
| |
| ret = bufferMgr->getBuffer(&bufIndex, EXYNOS_CAMERA_BUFFER_POSITION_IN_HAL, &dstBuffer); |
| if (ret < 0) { |
| CLOGE2("bufferMgr getBuffer fail, frameCount(%d), ret(%d)", frame->getFrameCount(), ret); |
| return ret; |
| } |
| |
| srcRect.x = 0; |
| srcRect.y = 0; |
| srcRect.w = output[2]; |
| srcRect.h = output[3]; |
| srcRect.fullW = output[2]; |
| srcRect.fullH = output[3]; |
| srcRect.colorFormat = m_parameters->getHwPreviewFormat(); |
| |
| dstRect.x = 0; |
| dstRect.y = 0; |
| dstRect.fullW = dstRect.w = streamBuffer.stream->width; |
| dstRect.fullH = dstRect.h = streamBuffer.stream->height; |
| stream->getFormat(&actualFormat); |
| dstRect.colorFormat = HAL_PIXEL_FORMAT_2_V4L2_PIX(actualFormat); |
| |
| ret = getCropRectAlign(srcRect.w, srcRect.h, |
| dstRect.w, dstRect.h, |
| &srcRect.x, &srcRect.y, |
| &srcRect.w, &srcRect.h, |
| 2, 2, |
| 0, 1); |
| |
| newFrame = factory->createNewFrameOnlyOnePipe(pipeExtScalerId, frame->getFrameCount()); |
| |
| ret = newFrame->setSrcRect(pipeExtScalerId, srcRect); |
| if (ret != NO_ERROR) { |
| CLOGE2("setSrcRect fail, frameCount(%d), ret(%d)", frame->getFrameCount(), ret); |
| return ret; |
| } |
| |
| ret = newFrame->setDstRect(pipeExtScalerId, dstRect); |
| if (ret != NO_ERROR) { |
| CLOGE2("setDstRect fail, frameCount(%d), ret(%d)", frame->getFrameCount(), ret); |
| return ret; |
| } |
| |
| CLOGV2("srcRect size (%d, %d, %d, %d %d %d)", |
| srcRect.x, srcRect.y, srcRect.w, srcRect.h, srcRect.fullW, srcRect.fullH); |
| CLOGV2("dstRect size (%d, %d, %d, %d %d %d)", |
| dstRect.x, dstRect.y, dstRect.w, dstRect.h, dstRect.fullW, dstRect.fullH); |
| |
| /* GSC can be shared by preview and previewCb. Make sure dstBuffer for previewCb buffer. */ |
| /* m_resetBufferState(pipeExtScalerId, frame); */ |
| m_resetBufferState(pipeExtScalerId, newFrame); |
| |
| ret = m_setupEntity(pipeExtScalerId, newFrame, &srcBuffer, &dstBuffer); |
| if (ret < 0) { |
| CLOGE2("setupEntity fail, pipeExtScalerId(%d), ret(%d)", pipeExtScalerId, ret); |
| } |
| |
| dupBufferInfo.streamID = halStreamId; |
| dupBufferInfo.extScalerPipeID = pipeExtScalerId; |
| newFrame->setDupBufferInfo(dupBufferInfo); |
| newFrame->setFrameCapture(frame->getFrameCapture()); |
| newFrame->setFrameServiceBayer(frame->getFrameServiceBayer()); |
| |
| factory->setOutputFrameQToPipe(m_duplicateBufferDoneQ, pipeExtScalerId); |
| factory->pushFrameToPipe(&newFrame, pipeExtScalerId); |
| |
| return ret; |
| } |
| |
| status_t ExynosCamera3::m_releaseBuffers(void) |
| { |
| CLOGI2("release buffer"); |
| int ret = 0; |
| enum EXYNOS_CAMERA_BUFFER_PERMISSION permission; |
| enum EXYNOS_CAMERA_BUFFER_POSITION position; |
| |
| /* Pull all internal buffers */ |
| for (int bufIndex = 0; bufIndex < m_fliteBufferMgr->getAllocatedBufferCount(); bufIndex++) |
| ret = m_putBuffers(m_fliteBufferMgr, bufIndex); |
| for (int bufIndex = 0; bufIndex < m_3aaBufferMgr->getAllocatedBufferCount(); bufIndex++) |
| ret = m_putBuffers(m_3aaBufferMgr, bufIndex); |
| for (int bufIndex = 0; bufIndex < m_internalScpBufferMgr->getAllocatedBufferCount(); bufIndex++) |
| ret = m_putBuffers(m_internalScpBufferMgr, bufIndex); |
| for (int bufIndex = 0; bufIndex < m_yuvCaptureBufferMgr->getAllocatedBufferCount(); bufIndex++) |
| ret = m_putBuffers(m_yuvCaptureBufferMgr, bufIndex); |
| for (int bufIndex = 0; bufIndex < m_vraBufferMgr->getAllocatedBufferCount(); bufIndex++) |
| ret = m_putBuffers(m_vraBufferMgr, bufIndex); |
| for (int bufIndex = 0; bufIndex < m_gscBufferMgr->getAllocatedBufferCount(); bufIndex++) |
| ret = m_putBuffers(m_gscBufferMgr, bufIndex); |
| for (int bufIndex = 0; bufIndex < m_ispBufferMgr->getAllocatedBufferCount(); bufIndex++) |
| ret = m_putBuffers(m_ispBufferMgr, bufIndex); |
| |
| if (m_bayerBufferMgr != NULL) { |
| m_bayerBufferMgr->deinit(); |
| } |
| |
| if (m_fliteBufferMgr != NULL) { |
| m_fliteBufferMgr->deinit(); |
| } |
| |
| if (m_3aaBufferMgr != NULL) { |
| m_3aaBufferMgr->deinit(); |
| } |
| if (m_ispBufferMgr != NULL) { |
| m_ispBufferMgr->deinit(); |
| } |
| if (m_internalScpBufferMgr != NULL) { |
| m_internalScpBufferMgr->deinit(); |
| } |
| if (m_ispReprocessingBufferMgr != NULL) { |
| m_ispReprocessingBufferMgr->deinit(); |
| } |
| if (m_yuvCaptureBufferMgr != NULL) { |
| m_yuvCaptureBufferMgr->deinit(); |
| } |
| if (m_vraBufferMgr != NULL) { |
| m_vraBufferMgr->deinit(); |
| } |
| if (m_gscBufferMgr != NULL) { |
| m_gscBufferMgr->deinit(); |
| } |
| if (m_yuvCaptureReprocessingBufferMgr != NULL) { |
| m_yuvCaptureReprocessingBufferMgr->deinit(); |
| } |
| if (m_thumbnailBufferMgr != NULL) |
| m_thumbnailBufferMgr->deinit(); |
| |
| if (m_skipBufferMgr != NULL) { |
| m_skipBufferMgr->deinit(); |
| } |
| |
| CLOGI2("free buffer done"); |
| |
| return NO_ERROR; |
| } |
| |
| /* m_registerStreamBuffers |
| * 1. Get the input buffers from the input request |
| * 2. Get the output buffers from the input request |
| * 3. Register each buffers into the matched buffer manager |
| * This operation must be done before another request is delivered from the service. |
| */ |
| status_t ExynosCamera3::m_registerStreamBuffers(camera3_capture_request *request) |
| { |
| status_t ret = NO_ERROR; |
| const camera3_stream_buffer_t *buffer; |
| const camera3_stream_buffer_t *bufferList; |
| uint32_t bufferCount = 0; |
| int streamId = -1; |
| uint32_t requestKey = 0; |
| ExynosCameraStream *stream = NULL; |
| ExynosCameraBufferManager *bufferMgr = NULL; |
| |
| /* 1. Get the information of input buffers from the input request */ |
| requestKey = request->frame_number; |
| buffer = request->input_buffer; |
| |
| /* 2. Register the each input buffers into the matched buffer manager */ |
| if (buffer != NULL) { |
| stream = static_cast<ExynosCameraStream *>(buffer->stream->priv); |
| stream->getID(&streamId); |
| |
| switch (streamId % HAL_STREAM_ID_MAX) { |
| case HAL_STREAM_ID_ZSL_INPUT: |
| m_registerBuffers(m_bayerBufferMgr, requestKey, buffer); |
| ALOGV("DEBUG(%s[%d]):request(%d) inputBuffer(%p) buffer-StreamType(HAL_STREAM_ID_RAW) size(%u x %u) ", |
| __FUNCTION__, __LINE__, |
| request->frame_number, buffer, |
| buffer->stream->width, |
| buffer->stream->height); |
| break; |
| case HAL_STREAM_ID_PREVIEW: |
| case HAL_STREAM_ID_VIDEO: |
| case HAL_STREAM_ID_JPEG: |
| case HAL_STREAM_ID_CALLBACK: |
| default: |
| ALOGE("ERR(%s[%d]):request(%d) inputBuffer(%p) buffer-stream type is inavlid(%d). size(%d x %d)", |
| __FUNCTION__, __LINE__, |
| requestKey, buffer, streamId, |
| buffer->stream->width, |
| buffer->stream->height); |
| break; |
| } |
| } |
| |
| /* 3. Get the information of output buffers from the input request */ |
| bufferCount = request->num_output_buffers; |
| bufferList = request->output_buffers; |
| |
| /* 4. Register the each output buffers into the matched buffer manager */ |
| for (uint32_t index = 0; index < bufferCount; index++) { |
| buffer = &(bufferList[index]); |
| stream = static_cast<ExynosCameraStream *>(bufferList[index].stream->priv); |
| stream->getID(&streamId); |
| stream->getBufferManager(&bufferMgr); |
| |
| switch (streamId % HAL_STREAM_ID_MAX) { |
| case HAL_STREAM_ID_RAW: |
| m_registerBuffers(m_bayerBufferMgr, requestKey, buffer); |
| ALOGV("DEBUG(%s[%d]):request(%d) outputBuffer(%p) buffer-StreamType(HAL_STREAM_ID_RAW) size(%u x %u) ", |
| __FUNCTION__, __LINE__, |
| request->frame_number, buffer, |
| bufferList[index].stream->width, |
| bufferList[index].stream->height); |
| break; |
| case HAL_STREAM_ID_ZSL_OUTPUT: |
| /* no buffer register */ |
| ALOGV("DEBUG(%s[%d]):request(%d) outputBuffer(%p) buffer-StreamType(HAL_STREAM_ID_ZSL_OUTPUT) size(%u x %u) ", |
| __FUNCTION__, __LINE__, |
| request->frame_number, buffer, |
| bufferList[index].stream->width, |
| bufferList[index].stream->height); |
| break; |
| case HAL_STREAM_ID_PREVIEW: |
| m_registerBuffers(bufferMgr, requestKey, buffer); |
| ALOGV("DEBUG(%s[%d]):request(%d) outputBuffer(%p) buffer-StreamType(HAL_STREAM_ID_PREVIEW) size(%u x %u) ", |
| __FUNCTION__, __LINE__, |
| request->frame_number, buffer, |
| bufferList[index].stream->width, |
| bufferList[index].stream->height); |
| break; |
| case HAL_STREAM_ID_VIDEO: |
| m_registerBuffers(bufferMgr, requestKey, buffer); |
| ALOGV("DEBUG(%s[%d]):request(%d) outputBuffer(%p) buffer-StreamType(HAL_STREAM_ID_VIDEO) size(%u x %u) ", |
| __FUNCTION__, __LINE__, |
| request->frame_number, buffer, |
| bufferList[index].stream->width, |
| bufferList[index].stream->height); |
| break; |
| case HAL_STREAM_ID_JPEG: |
| m_registerBuffers(bufferMgr, requestKey, buffer); |
| ALOGD("DEBUG(%s[%d]):request(%d) outputBuffer(%p) buffer-StreamType(HAL_STREAM_ID_JPEG) size(%u x %u) ", |
| __FUNCTION__, __LINE__, |
| request->frame_number, buffer, |
| bufferList[index].stream->width, |
| bufferList[index].stream->height); |
| break; |
| case HAL_STREAM_ID_CALLBACK: |
| m_registerBuffers(bufferMgr, requestKey, buffer); |
| ALOGV("DEBUG(%s[%d]):request(%d) outputBuffer(%p) buffer-StreamType(HAL_STREAM_ID_CALLBACK) size(%u x %u) ", |
| __FUNCTION__, __LINE__, |
| request->frame_number, buffer, |
| bufferList[index].stream->width, |
| bufferList[index].stream->height); |
| break; |
| default: |
| ALOGE("ERR(%s[%d]):request(%d) outputBuffer(%p) buffer-StreamType is invalid(%d) size(%d x %d) ", |
| __FUNCTION__, __LINE__, |
| request->frame_number, buffer, streamId, |
| bufferList[index].stream->width, |
| bufferList[index].stream->height); |
| break; |
| } |
| } |
| |
| return ret; |
| } |
| |
| status_t ExynosCamera3::m_registerBuffers( |
| ExynosCameraBufferManager *bufManager, |
| int requestKey, |
| const camera3_stream_buffer_t *streamBuffer) |
| { |
| status_t ret = OK; |
| buffer_handle_t *handle = streamBuffer->buffer; |
| int acquireFence = streamBuffer->acquire_fence; |
| int releaseFence = streamBuffer->release_fence; |
| |
| if (bufManager != NULL) { |
| ret = bufManager->registerBuffer( |
| requestKey, |
| handle, |
| acquireFence, |
| releaseFence, |
| EXYNOS_CAMERA_BUFFER_POSITION_NONE); |
| if (ret < 0) { |
| CLOGE2("putBuffer(%d) fail(%d)", requestKey, ret); |
| return BAD_VALUE; |
| } |
| } |
| |
| return ret; |
| } |
| |
| status_t ExynosCamera3::m_putBuffers(ExynosCameraBufferManager *bufManager, int bufIndex) |
| { |
| status_t ret = NO_ERROR; |
| if (bufManager != NULL) |
| ret = bufManager->putBuffer(bufIndex, EXYNOS_CAMERA_BUFFER_POSITION_NONE); |
| |
| return ret; |
| } |
| |
| status_t ExynosCamera3::m_allocBuffers( |
| ExynosCameraBufferManager *bufManager, |
| int planeCount, |
| unsigned int *planeSize, |
| unsigned int *bytePerLine, |
| int startIndex, |
| int reqBufCount, |
| bool createMetaPlane, |
| bool needMmap) |
| { |
| int ret = 0; |
| |
| ret = bufManager->setInfo( |
| planeCount, |
| planeSize, |
| bytePerLine, |
| startIndex, |
| reqBufCount, |
| createMetaPlane, |
| needMmap); |
| if (ret < 0) { |
| CLOGE2("setInfo fail"); |
| goto func_exit; |
| } |
| |
| ret = bufManager->alloc(); |
| if (ret < 0) { |
| CLOGE2("alloc fail"); |
| goto func_exit; |
| } |
| |
| func_exit: |
| |
| return ret; |
| } |
| |
| status_t ExynosCamera3::m_allocBuffers( |
| ExynosCameraBufferManager *bufManager, |
| int planeCount, |
| unsigned int *planeSize, |
| unsigned int *bytePerLine, |
| int reqBufCount, |
| bool createMetaPlane, |
| bool needMmap) |
| { |
| int ret = 0; |
| |
| ret = bufManager->setInfo( |
| planeCount, |
| planeSize, |
| bytePerLine, |
| reqBufCount, |
| createMetaPlane, |
| needMmap); |
| if (ret < 0) { |
| CLOGE2("setInfo fail"); |
| goto func_exit; |
| } |
| |
| ret = bufManager->alloc(); |
| if (ret < 0) { |
| CLOGE2("alloc fail"); |
| goto func_exit; |
| } |
| |
| func_exit: |
| |
| return ret; |
| } |
| |
| status_t ExynosCamera3::m_allocBuffers( |
| ExynosCameraBufferManager *bufManager, |
| int planeCount, |
| unsigned int *planeSize, |
| unsigned int *bytePerLine, |
| int minBufCount, |
| int maxBufCount, |
| exynos_camera_buffer_type_t type, |
| bool createMetaPlane, |
| bool needMmap) |
| { |
| int ret = 0; |
| |
| ret = m_allocBuffers( |
| bufManager, |
| planeCount, |
| planeSize, |
| bytePerLine, |
| minBufCount, |
| maxBufCount, |
| type, |
| BUFFER_MANAGER_ALLOCATION_ONDEMAND, |
| createMetaPlane, |
| needMmap); |
| if (ret < 0) { |
| CLOGE2("m_allocBuffers(minBufCount=%d, maxBufCount=%d, type=%d) fail", minBufCount, maxBufCount, type); |
| } |
| |
| return ret; |
| } |
| |
| status_t ExynosCamera3::m_allocBuffers( |
| ExynosCameraBufferManager *bufManager, |
| int planeCount, |
| unsigned int *planeSize, |
| unsigned int *bytePerLine, |
| int minBufCount, |
| int maxBufCount, |
| exynos_camera_buffer_type_t type, |
| buffer_manager_allocation_mode_t allocMode, |
| bool createMetaPlane, |
| bool needMmap) |
| { |
| int ret = 0; |
| |
| CLOGI2("setInfo(planeCount=%d, minBufCount=%d, maxBufCount=%d, type=%d, allocMode=%d)", |
| planeCount, minBufCount, maxBufCount, (int)type, (int)allocMode); |
| |
| ret = bufManager->setInfo( |
| planeCount, |
| planeSize, |
| bytePerLine, |
| 0, |
| minBufCount, |
| maxBufCount, |
| type, |
| allocMode, |
| createMetaPlane, |
| needMmap); |
| if (ret < 0) { |
| CLOGE2("setInfo fail"); |
| goto func_exit; |
| } |
| |
| ret = bufManager->alloc(); |
| if (ret < 0) { |
| CLOGE2("alloc fail"); |
| goto func_exit; |
| } |
| |
| func_exit: |
| |
| return ret; |
| } |
| |
| status_t ExynosCamera3::m_setBuffers(void) |
| { |
| ExynosCameraAutoTimer autoTimer(__FUNCTION__); |
| int ret = OK; |
| unsigned int bytesPerLine[EXYNOS_CAMERA_BUFFER_MAX_PLANES] = {0}; |
| unsigned int planeSize[EXYNOS_CAMERA_BUFFER_MAX_PLANES] = {0}; |
| int planeCount = 1; |
| int bufferCount = 1; |
| int previewMaxW, previewMaxH; |
| int sensorMaxW, sensorMaxH; |
| |
| int hwPreviewW, hwPreviewH; |
| int hwSensorW, hwSensorH; |
| int hwPictureW, hwPictureH; |
| int sensorMarginW, sensorMarginH; |
| exynos_camera_buffer_type_t type = EXYNOS_CAMERA_BUFFER_ION_NONCACHED_TYPE; |
| |
| int minBufferCount = 1; |
| int maxBufferCount = 1; |
| |
| CLOGI2("alloc buffer - camera ID: %d", m_cameraId); |
| |
| // TODO: get this value from metadata class |
| m_parameters->getHwPreviewSize(&hwPreviewW, &hwPreviewH); |
| CLOGI2("HW Preview width x height = %dx%d", hwPreviewW, hwPreviewH); |
| m_parameters->getHwSensorSize(&hwSensorW, &hwSensorH); |
| CLOGI2("HW Sensor width x height = %dx%d", hwSensorW, hwSensorH); |
| m_parameters->getHwPictureSize(&hwPictureW, &hwPictureH); |
| CLOGI2("HW Picture width x height = %dx%d", hwPictureW, hwPictureH); |
| |
| m_parameters->getMaxSensorSize(&sensorMaxW, &sensorMaxH); |
| CLOGI2("HW Sensor MAX width x height = %dx%d", sensorMaxW, sensorMaxH); |
| m_parameters->getMaxPreviewSize(&previewMaxW, &previewMaxH); |
| CLOGI2("HW Preview MAX width x height = %dx%d", previewMaxW, previewMaxH); |
| |
| m_parameters->getSensorMargin(&sensorMarginW, &sensorMarginH); |
| |
| /* For preview stream */ |
| /* FLITE -> need bayer buffer for non zsl capture. */ |
| |
| if (m_parameters->isFlite3aaOtf() == false) { |
| #if !defined(ENABLE_FULL_FRAME) |
| #ifdef CAMERA_PACKED_BAYER_ENABLE |
| #ifdef DEBUG_RAWDUMP |
| if (m_parameters->checkBayerDumpEnable()) { |
| bytesPerLine[0] = (sensorMaxW + sensorMarginW) * 2; |
| planeSize[0] = (sensorMaxW + sensorMarginW) * (sensorMaxH + sensorMarginH) * 2; |
| } else |
| #endif /* DEBUG_RAWDUMP */ |
| { |
| bytesPerLine[0] = ROUND_UP((sensorMaxW + sensorMarginW), 10) * 8 / 5; |
| planeSize[0] = bytesPerLine[0] * (sensorMaxH + sensorMarginH); |
| } |
| #else |
| planeSize[0] = (sensorMaxW + sensorMarginW) * (sensorMaxH + sensorMarginH) * 2; |
| #endif |
| planeCount = 2; |
| |
| /* TO DO : make num of buffers samely */ |
| maxBufferCount = NUM_BAYER_BUFFERS; |
| |
| ret = m_allocBuffers(m_fliteBufferMgr, planeCount, planeSize, bytesPerLine, maxBufferCount, maxBufferCount, type, true, false); |
| if (ret < 0) { |
| CLOGE2("ERR(%s[%d]):bayerBuffer m_allocBuffers(bufferCount=%d) fail", maxBufferCount); |
| return ret; |
| } |
| #endif |
| } |
| |
| /* Buffers of FLITE is given by service for ZSL*/ |
| // TODO: consider non-zsl case |
| /* 3AA */ |
| planeSize[0] = 32 * 64 * 2; |
| planeCount = 2; |
| bufferCount = m_exynosconfig->current->bufInfo.num_3aa_buffers; |
| ret = m_allocBuffers(m_3aaBufferMgr, planeCount, planeSize, bytesPerLine, bufferCount, true); |
| if (ret < 0) { |
| CLOGE2("m_3aaBufferMgr m_allocBuffers(bufferCount=%d) fail", bufferCount); |
| return ret; |
| } |
| |
| /* ISP */ |
| // TODO: packed bayer? |
| if (m_parameters->is3aaIspOtf() == false) { |
| if (m_parameters->isFlite3aaOtf() == true) |
| planeSize[0] = previewMaxW * previewMaxH * 2; |
| else |
| planeSize[0] = sensorMaxW * sensorMaxH * 2; |
| planeCount = 2; |
| bufferCount = 1; |
| ret = m_allocBuffers(m_ispBufferMgr, planeCount, planeSize, bytesPerLine, bufferCount, true); |
| if (ret < 0) { |
| CLOGE2("m_ispBufferMgr m_allocBuffers(bufferCount=%d) fail", bufferCount); |
| return ret; |
| } |
| } |
| |
| /* SCC */ |
| /* planeSize[0] = ALIGN_UP(hwPictureW, GSCALER_IMG_ALIGN) * ALIGN_UP(hwPictureH, GSCALER_IMG_ALIGN) * 2; */ |
| planeSize[0] = sensorMaxW * sensorMaxH * 2; |
| planeCount = 2; |
| // TODO: Need dynamic buffer allocation. reduce SCC buffer |
| bufferCount = NUM_PICTURE_BUFFERS; |
| |
| ret = m_allocBuffers(m_yuvCaptureBufferMgr, planeCount, planeSize, bytesPerLine, bufferCount, true); |
| if (ret < 0) { |
| CLOGE2("m_yuvCaptureBufferMgr m_allocBuffers(bufferCount=%d) fail", bufferCount); |
| return ret; |
| } |
| |
| /* VRA buffers */ |
| if (m_parameters->isMcscVraOtf() == false) { |
| int vraWidth = 0, vraHeight = 0; |
| m_parameters->getHwVraInputSize(&vraWidth, &vraHeight); |
| |
| bytesPerLine[0] = ROUND_UP((vraWidth * 3 / 2), CAMERA_16PX_ALIGN); |
| planeSize[0] = bytesPerLine[0] * vraHeight; |
| planeCount = 2; |
| |
| maxBufferCount = m_exynosconfig->current->bufInfo.num_vra_buffers; |
| |
| type = EXYNOS_CAMERA_BUFFER_ION_CACHED_TYPE; |
| |
| ret = m_allocBuffers(m_vraBufferMgr, planeCount, planeSize, bytesPerLine, maxBufferCount, maxBufferCount, type, true, true); |
| if (ret < 0) { |
| CLOGE2("m_vraBufferMgr m_allocBuffers(bufferCount=%d) fail", maxBufferCount); |
| return ret; |
| } |
| } |
| |
| ret = m_setInternalScpBuffer(); |
| if (ret < 0) { |
| CLOGE2("m_setReprocessing Buffer fail"); |
| return ret; |
| } |
| |
| CLOGI2("alloc buffer done - camera ID: %d", m_cameraId); |
| return ret; |
| } |
| |
| status_t ExynosCamera3::m_setInternalScpBuffer(void) |
| { |
| int ret = 0; |
| int hwPreviewW = 0, hwPreviewH = 0; |
| unsigned int planeSize[EXYNOS_CAMERA_BUFFER_MAX_PLANES] = {0}; |
| unsigned int bytesPerLine[EXYNOS_CAMERA_BUFFER_MAX_PLANES] = {0}; |
| int planeCount = 0; |
| int bufferCount = 0; |
| int minBufferCount = NUM_REPROCESSING_BUFFERS; |
| int maxBufferCount = NUM_PREVIEW_BUFFERS; |
| exynos_camera_buffer_type_t type = EXYNOS_CAMERA_BUFFER_ION_NONCACHED_TYPE; |
| buffer_manager_allocation_mode_t allocMode = BUFFER_MANAGER_ALLOCATION_ONDEMAND; |
| |
| m_parameters->getHwPreviewSize(&hwPreviewW, &hwPreviewH); |
| CLOGI2("HW Picture MAX width x height = %dx%d", hwPreviewW, hwPreviewH); |
| |
| bytesPerLine[0] = 0; |
| planeSize[0] = ALIGN_UP(hwPreviewW, GSCALER_IMG_ALIGN) * ALIGN_UP(hwPreviewH, GSCALER_IMG_ALIGN); |
| planeSize[1] = (ALIGN_UP(hwPreviewW, GSCALER_IMG_ALIGN) * ALIGN_UP(hwPreviewH, GSCALER_IMG_ALIGN)) / 2; |
| planeCount = 3; |
| minBufferCount = m_exynosconfig->current->bufInfo.num_request_preview_buffers; |
| maxBufferCount = m_exynosconfig->current->bufInfo.num_preview_buffers; |
| |
| allocMode = BUFFER_MANAGER_ALLOCATION_ONDEMAND; |
| |
| ret = m_allocBuffers(m_internalScpBufferMgr, planeCount, planeSize, bytesPerLine, minBufferCount, maxBufferCount, type, allocMode, true, false); |
| if (ret < 0) { |
| CLOGE2("m_internalScpBufferMgr m_allocBuffers(minBufferCount=%d, maxBufferCount=%d) fail", minBufferCount, maxBufferCount); |
| return ret; |
| } |
| |
| return NO_ERROR; |
| } |
| |
| bool ExynosCamera3::m_setBuffersThreadFunc(void) |
| { |
| int ret; |
| |
| ret = m_setBuffers(); |
| if (ret < 0) { |
| CLOGE2("m_setBuffers failed"); |
| // TODO: Need release buffers and error exit |
| return false; |
| } |
| |
| return false; |
| } |
| |
| uint32_t ExynosCamera3::m_getBayerPipeId(void) |
| { |
| uint32_t pipeId = 0; |
| // TODO: implement it |
| |
| pipeId = PIPE_FLITE; |
| |
| return pipeId; |
| } |
| |
| status_t ExynosCamera3::m_pushRequest(camera3_capture_request *request) |
| { |
| ExynosCameraRequest* req = NULL; |
| |
| CLOGV2("m_pushRequest frameCnt(%d)", request->frame_number); |
| |
| req = m_requestMgr->registerServiceRequest(request); |
| if(req == NULL) { |
| return INVALID_OPERATION; |
| } else { |
| return OK; |
| } |
| } |
| |
| status_t ExynosCamera3::m_popRequest(ExynosCameraRequest **request) |
| { |
| status_t ret = OK; |
| |
| CLOGV2("m_popRequest "); |
| |
| *request = m_requestMgr->createServiceRequest(); |
| if (*request == NULL) { |
| CLOGE2("createRequest failed "); |
| ret = INVALID_OPERATION; |
| } |
| return ret; |
| } |
| |
| |
| /* m_needNotify is for reprocessing */ |
| bool ExynosCamera3::m_needNotify(ExynosCameraRequest *request) |
| { |
| camera3_stream_buffer_t *output_buffers; |
| List<int> *outputStreamId = NULL; |
| List<int>::iterator outputStreamIdIter; |
| ExynosCameraStream *stream = NULL; |
| int streamId = 0; |
| |
| request->getAllRequestOutputStreams(&outputStreamId); |
| bool notifyFlag = true; |
| |
| /* HACK: can't send notify cause of one request including render, video */ |
| if (outputStreamId != NULL) { |
| for (outputStreamIdIter = outputStreamId->begin(); outputStreamIdIter != outputStreamId->end(); outputStreamIdIter++) { |
| |
| m_streamManager->getStream(*outputStreamIdIter, &stream); |
| if (stream == NULL) { |
| CLOGE2("stream is NULL"); |
| break; |
| } |
| stream->getID(&streamId); |
| |
| switch (streamId % HAL_STREAM_ID_MAX) { |
| case HAL_STREAM_ID_RAW: |
| case HAL_STREAM_ID_PREVIEW: |
| case HAL_STREAM_ID_VIDEO: |
| case HAL_STREAM_ID_CALLBACK: |
| notifyFlag = false; |
| break; |
| default: |
| break; |
| }; |
| } |
| } |
| |
| return notifyFlag; |
| } |
| |
| |
| status_t ExynosCamera3::m_pushResult(uint32_t frameCount, struct camera2_shot_ext *src_ext) |
| { |
| status_t ret = OK; |
| ExynosCameraRequest *request = NULL; |
| struct camera2_shot_ext dst_ext; |
| uint8_t currentPipelineDepth = 0; |
| |
| request = m_requestMgr->getServiceRequest(frameCount); |
| if (request == NULL) { |
| CLOGE2("getRequest failed "); |
| return INVALID_OPERATION; |
| } |
| |
| ret = request->getResultShot(&dst_ext); |
| if (ret < 0) { |
| CLOGE2("getResultShot failed "); |
| return INVALID_OPERATION; |
| } |
| |
| if (dst_ext.shot.dm.request.frameCount > src_ext->shot.dm.request.frameCount) { |
| CLOGI("INFO(%s[%d]):Skip to update result. frameCount %d requestKey %d shot.request.frameCount %d", |
| __FUNCTION__, __LINE__, |
| frameCount, request->getKey(), dst_ext.shot.dm.request.frameCount); |
| return ret; |
| } |
| |
| currentPipelineDepth = dst_ext.shot.dm.request.pipelineDepth; |
| memcpy(&dst_ext.shot.dm, &src_ext->shot.dm, sizeof(struct camera2_dm)); |
| memcpy(&dst_ext.shot.udm, &src_ext->shot.udm, sizeof(struct camera2_udm)); |
| dst_ext.shot.dm.request.pipelineDepth = currentPipelineDepth; |
| |
| ret = request->setResultShot(&dst_ext); |
| if (ret < 0) { |
| CLOGE2("setResultShot failed "); |
| return INVALID_OPERATION; |
| } |
| |
| ret = m_metadataConverter->updateDynamicMeta(request); |
| |
| CLOGV2("result is set (%d)", request->getFrameCount()); |
| return ret; |
| } |
| |
| status_t ExynosCamera3::m_pushJpegResult(ExynosCameraFrame *frame, int size, ExynosCameraBuffer *buffer) |
| { |
| status_t ret = NO_ERROR; |
| ExynosCameraStream *stream = NULL; |
| camera3_stream_buffer_t streamBuffer; |
| camera3_stream_buffer_t *output_buffers; |
| ResultRequest resultRequest = NULL; |
| ExynosCameraRequest *request = NULL; |
| camera3_capture_result_t requestResult; |
| |
| ExynosCameraBufferManager *bufferMgr = NULL; |
| |
| ret = m_streamManager->getStream(HAL_STREAM_ID_JPEG, &stream); |
| if (ret != NO_ERROR) { |
| CLOGE2("Failed to getStream from StreamMgr. streamId HAL_STREAM_ID_JPEG"); |
| return ret; |
| } |
| |
| if (stream == NULL) { |
| CLOGE2("stream is NULL"); |
| return INVALID_OPERATION; |
| } |
| |
| ret = stream->getStream(&streamBuffer.stream); |
| if (ret != NO_ERROR) { |
| CLOGE2("Failed to getStream from ExynosCameraStream. streamId HAL_STREAM_ID_JPEG"); |
| return ret; |
| } |
| |
| ret = stream->getBufferManager(&bufferMgr); |
| if (ret != NO_ERROR) { |
| CLOGE2("Failed to getBufferManager. streamId HAL_STREAM_ID_JPEG"); |
| return ret; |
| } |
| |
| ret = bufferMgr->getHandleByIndex(&streamBuffer.buffer, buffer->index); |
| if (ret != NO_ERROR) { |
| CLOGE2("Failed to getHandleByIndex. bufferIndex %d", buffer->index); |
| return ret; |
| } |
| |
| streamBuffer.status = CAMERA3_BUFFER_STATUS_OK; |
| streamBuffer.acquire_fence = -1; |
| streamBuffer.release_fence = -1; |
| |
| camera3_jpeg_blob_t jpeg_blob; |
| jpeg_blob.jpeg_blob_id = CAMERA3_JPEG_BLOB_ID; |
| jpeg_blob.jpeg_size = size; |
| memcpy(buffer->addr[0]+buffer->size[0]-sizeof(camera3_jpeg_blob_t), &jpeg_blob, sizeof(camera3_jpeg_blob_t)); |
| |
| request = m_requestMgr->getServiceRequest(frame->getFrameCount()); |
| |
| #if !defined(ENABLE_FULL_FRAME) |
| /* try to notify if notify callback was not called in same framecount */ |
| if (request->getCallbackDone(EXYNOS_REQUEST_RESULT::CALLBACK_NOTIFY_ONLY) == false) { |
| /* can't send notify cause of one request including render, video */ |
| if (m_needNotify(request) == true) { |
| CLOGV2("notify(%d)", frame->getFrameCount()); |
| m_sendNotify(frame->getFrameCount(), CAMERA3_MSG_SHUTTER); |
| } |
| } |
| #endif |
| |
| CameraMetadata setting = request->getResultMeta(); |
| int32_t jpegsize = size; |
| ret = setting.update(ANDROID_JPEG_SIZE, &jpegsize, 1); |
| if (ret < 0) { |
| CLOGE2("ANDROID_JPEG_SIZE update failed(%d)", ret); |
| } |
| |
| /* update jpeg size */ |
| request->setResultMeta(setting); |
| |
| CLOGD2("Set JPEG result Done. frameCount %d request->Key %d", |
| frame->getFrameCount(), request->getKey()); |
| |
| resultRequest = m_requestMgr->createResultRequest(frame->getFrameCount(), EXYNOS_REQUEST_RESULT::CALLBACK_BUFFER_ONLY, NULL, NULL); |
| resultRequest->pushStreamBuffer(&streamBuffer); |
| |
| m_requestMgr->callbackSequencerLock(); |
| request->increaseCompleteBufferCount(); |
| m_requestMgr->callbackRequest(resultRequest); |
| m_requestMgr->callbackSequencerUnlock(); |
| |
| CLOGD2("result is set"); |
| |
| return ret; |
| } |
| |
| ExynosCameraRequest* ExynosCamera3::m_popResult(CameraMetadata &result, uint32_t frameCount) |
| { |
| ExynosCameraRequest *request = NULL; |
| struct camera2_shot_ext dst_ext; |
| |
| request = m_requestMgr->getServiceRequest(frameCount); |
| if (request == NULL) { |
| CLOGE2("getRequest failed "); |
| result.clear(); |
| return NULL; |
| } |
| |
| result = request->getResultMeta(); |
| |
| CLOGV2("m_popResult(%d)", request->getFrameCount()); |
| |
| return request; |
| } |
| |
| status_t ExynosCamera3::m_deleteRequest(uint32_t frameCount) |
| { |
| status_t ret = OK; |
| |
| ret = m_requestMgr->deleteServiceRequest(frameCount); |
| |
| return ret; |
| } |
| |
| status_t ExynosCamera3::m_setReprocessingBuffer(void) |
| { |
| int ret = 0; |
| int pictureMaxW = 0, pictureMaxH = 0; |
| int hwPictureW = 0, hwPictureH = 0; |
| int maxThumbnailW = 0, maxThumbnailH = 0; |
| unsigned int planeSize[EXYNOS_CAMERA_BUFFER_MAX_PLANES] = {0}; |
| unsigned int bytesPerLine[EXYNOS_CAMERA_BUFFER_MAX_PLANES] = {0}; |
| int pictureFormat = 0; |
| int planeCount = 0; |
| int bufferCount = 0; |
| int minBufferCount = NUM_REPROCESSING_BUFFERS; |
| int maxBufferCount = NUM_PICTURE_BUFFERS; |
| bool needMmap = false; |
| 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(&pictureMaxW, &pictureMaxH); |
| CLOGI2("HW Picture MAX width x height = %dx%d", pictureMaxW, pictureMaxH); |
| m_parameters->getMaxThumbnailSize(&maxThumbnailW, &maxThumbnailH); |
| CLOGI2("Thumbnail Max width x height = %dx%d", maxThumbnailW, maxThumbnailH); |
| pictureFormat = m_parameters->getHwPictureFormat(); |
| |
| /* for reprocessing */ |
| if (m_parameters->getUsePureBayerReprocessing() == true) { |
| #ifdef CAMERA_PACKED_BAYER_ENABLE |
| #ifdef DEBUG_RAWDUMP |
| if (m_parameters->checkBayerDumpEnable()) { |
| bytesPerLine[0] = pictureMaxW * 2; |
| planeSize[0] = pictureMaxW * pictureMaxH * 2; |
| } else |
| #endif /* DEBUG_RAWDUMP */ |
| { |
| bytesPerLine[0] = ROUND_UP((pictureMaxW * 3 / 2), 16); |
| planeSize[0] = bytesPerLine[0] * pictureMaxH; |
| } |
| #else |
| planeSize[0] = pictureMaxW * pictureMaxH * 2; |
| #endif |
| planeCount = 2; |
| bufferCount = NUM_REPROCESSING_BUFFERS; |
| |
| type = EXYNOS_CAMERA_BUFFER_ION_CACHED_TYPE; |
| allocMode = BUFFER_MANAGER_ALLOCATION_ONDEMAND; |
| |
| if (m_parameters->getHighResolutionCallbackMode() == true) { |
| /* ISP Reprocessing Buffer realloc for high resolution callback */ |
| minBufferCount = 2; |
| } |
| |
| ret = m_allocBuffers(m_ispReprocessingBufferMgr, planeCount, planeSize, bytesPerLine, minBufferCount, maxBufferCount, type, allocMode, true, false); |
| if (ret < 0) { |
| CLOGE2("m_ispReprocessingBufferMgr m_allocBuffers(minBufferCount=%d/maxBufferCount=%d) fail", minBufferCount, maxBufferCount); |
| return ret; |
| } |
| } |
| |
| if( m_parameters->getHighSpeedRecording() ) { |
| m_parameters->getHwSensorSize(&hwPictureW, &hwPictureH); |
| CLOGI2("HW Picture(HighSpeed) width x height = %dx%d", hwPictureW, hwPictureH); |
| } else { |
| m_parameters->getMaxSensorSize(&hwPictureW, &hwPictureH); |
| CLOGI2("HW Picture width x height = %dx%d", hwPictureW, hwPictureH); |
| } |
| |
| if (m_parameters->isUseYuvReprocessingForThumbnail() == true) |
| needMmap = true; |
| else |
| needMmap = false; |
| |
| bytesPerLine[0] = 0; |
| planeSize[0] = ALIGN_UP(hwPictureW, GSCALER_IMG_ALIGN) * ALIGN_UP(hwPictureH, GSCALER_IMG_ALIGN) * 2; |
| planeCount = 2; |
| minBufferCount = 1; |
| maxBufferCount = NUM_PICTURE_BUFFERS; |
| |
| type = EXYNOS_CAMERA_BUFFER_ION_CACHED_TYPE; |
| if (m_parameters->isHWFCEnabled() == true) |
| allocMode = BUFFER_MANAGER_ALLOCATION_ATONCE; |
| else |
| allocMode = BUFFER_MANAGER_ALLOCATION_ONDEMAND; |
| |
| if (m_parameters->getHighResolutionCallbackMode() == true) { |
| /* SCC Reprocessing Buffer realloc for high resolution callback */ |
| minBufferCount = 2; |
| } |
| |
| ret = m_allocBuffers(m_yuvCaptureReprocessingBufferMgr, |
| planeCount, planeSize, bytesPerLine, |
| minBufferCount, maxBufferCount, |
| type, allocMode, true, needMmap); |
| if (ret < 0) { |
| CLOGE2("m_yuvCaptureReprocessingBufferMgr m_allocBuffers(minBufferCount=%d, maxBufferCount=%d) fail", minBufferCount, maxBufferCount); |
| return ret; |
| } |
| |
| /* Reprocessing Thumbanil buffer */ |
| switch (pictureFormat) { |
| case V4L2_PIX_FMT_NV21M: |
| planeCount = 3; |
| planeSize[0] = maxThumbnailW * maxThumbnailH; |
| planeSize[1] = maxThumbnailW * maxThumbnailH / 2; |
| case V4L2_PIX_FMT_NV21: |
| default: |
| planeCount = 2; |
| planeSize[0] = FRAME_SIZE(V4L2_PIX_2_HAL_PIXEL_FORMAT(pictureFormat), maxThumbnailW, maxThumbnailH); |
| } |
| |
| minBufferCount = 1; |
| maxBufferCount = m_exynosconfig->current->bufInfo.num_picture_buffers; |
| |
| type = EXYNOS_CAMERA_BUFFER_ION_CACHED_TYPE; |
| |
| ret = m_allocBuffers(m_thumbnailBufferMgr, |
| planeCount, planeSize, bytesPerLine, |
| minBufferCount, maxBufferCount, |
| type, allocMode, true, needMmap); |
| if (ret != NO_ERROR) { |
| CLOGE2("m_thumbnailBufferMgr m_allocBuffers(minBufferCount=%d, maxBufferCount=%d) fail", |
| minBufferCount, maxBufferCount); |
| return ret; |
| } |
| |
| return NO_ERROR; |
| } |
| |
| bool ExynosCamera3::m_reprocessingFrameFactoryStartThreadFunc(void) |
| { |
| status_t ret = 0; |
| ExynosCamera3FrameFactory *factory = NULL; |
| |
| factory = m_frameFactory[FRAME_FACTORY_TYPE_REPROCESSING]; |
| if (factory == NULL) { |
| CLOGE2("Can't start FrameFactory!!!! FrameFactory is NULL!!"); |
| |
| return false; |
| } else if (factory->isCreated() == false) { |
| CLOGE2("Reprocessing FrameFactory is NOT created!"); |
| return false; |
| } |
| |
| /* Set buffer manager */ |
| ret = m_setupReprocessingPipeline(); |
| if (ret != NO_ERROR) { |
| CLOGE2("Failed to setupReprocessingPipeline. ret %d", ret); |
| return false; |
| } |
| |
| ret = factory->initPipes(); |
| if (ret < 0) { |
| CLOGE2("Failed to initPipes. ret %d", ret); |
| return false; |
| } |
| |
| ret = m_startReprocessingFrameFactory(factory); |
| if (ret < 0) { |
| CLOGE2("Failed to startReprocessingFrameFactory"); |
| /* TODO: Need release buffers and error exit */ |
| return false; |
| } |
| |
| return false; |
| } |
| |
| status_t ExynosCamera3::m_startReprocessingFrameFactory(ExynosCamera3FrameFactory *factory) |
| { |
| ExynosCameraAutoTimer autoTimer(__FUNCTION__); |
| |
| status_t ret = 0; |
| |
| CLOGD2("- IN -"); |
| |
| ret = factory->preparePipes(); |
| if (ret < 0) { |
| CLOGE2("m_reprocessingFrameFactory preparePipe fail"); |
| return ret; |
| } |
| |
| /* stream on pipes */ |
| ret = factory->startPipes(); |
| if (ret < 0) { |
| CLOGE2("m_reprocessingFrameFactory startPipe fail"); |
| return ret; |
| } |
| |
| m_flagStartReprocessingFrameFactory = true; |
| |
| return NO_ERROR; |
| } |
| |
| status_t ExynosCamera3::m_stopReprocessingFrameFactory(ExynosCamera3FrameFactory *factory) |
| { |
| CLOGI2("- IN -"); |
| status_t ret = 0; |
| |
| if (factory != NULL) { |
| ret = factory->stopPipes(); |
| if (ret < 0) { |
| CLOGE2("m_reprocessingFrameFactory0>stopPipe() fail"); |
| } |
| } |
| |
| CLOGD2("clear m_captureProcessList(Picture) Frame list"); |
| ret = m_clearList(&m_captureProcessList, &m_captureProcessLock); |
| if (ret < 0) { |
| CLOGE2("m_clearList fail"); |
| return ret; |
| } |
| |
| m_flagStartReprocessingFrameFactory = false; |
| |
| return NO_ERROR; |
| } |
| |
| status_t ExynosCamera3::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) |
| CLOGW2("retry(%d) setupEntity for pipeId(%d)", retry, pipeId); |
| } while(ret < 0 && retry < (TOTAL_WAITING_TIME/WAITING_TIME)); |
| |
| return ret; |
| } |
| |
| bool ExynosCamera3::m_startPictureBufferThreadFunc(void) |
| { |
| int ret = 0; |
| |
| ret = m_setPictureBuffer(); |
| if (ret < 0) { |
| CLOGE2("m_setPictureBuffer failed"); |
| |
| /* TODO: Need release buffers and error exit */ |
| |
| return false; |
| } |
| |
| if (m_parameters->isReprocessing() == true) { |
| ret = m_setReprocessingBuffer(); |
| if (ret < 0) { |
| CLOGE2("m_setReprocessing Buffer fail"); |
| return ret; |
| } |
| } |
| |
| return false; |
| } |
| |
| status_t ExynosCamera3::m_setPictureBuffer(void) |
| { |
| int ret = 0; |
| unsigned int planeSize[3] = {0}; |
| unsigned int bytesPerLine[3] = {0}; |
| int pictureW = 0, pictureH = 0, pictureFormat = 0; |
| int planeCount = 0; |
| int minBufferCount = 1; |
| int maxBufferCount = 1; |
| exynos_camera_buffer_type_t type = EXYNOS_CAMERA_BUFFER_ION_NONCACHED_TYPE; |
| buffer_manager_allocation_mode_t allocMode = BUFFER_MANAGER_ALLOCATION_ONDEMAND; |
| |
| m_parameters->getMaxPictureSize(&pictureW, &pictureH); |
| pictureFormat = m_parameters->getPictureFormat(); |
| if ((m_parameters->needGSCForCapture(getCameraId()) == true)) { |
| planeSize[0] = pictureW * pictureH * 2; |
| planeCount = 1; |
| minBufferCount = 1; |
| maxBufferCount = m_exynosconfig->current->bufInfo.num_picture_buffers; |
| |
| // Pre-allocate certain amount of buffers enough to fed into 3 JPEG save threads. |
| if (m_parameters->getSeriesShotCount() > 0) |
| minBufferCount = NUM_BURST_GSC_JPEG_INIT_BUFFER; |
| |
| ret = m_allocBuffers(m_gscBufferMgr, planeCount, planeSize, bytesPerLine, minBufferCount, maxBufferCount, type, allocMode, false, false); |
| if (ret < 0) { |
| CLOGE2("m_gscBufferMgr m_allocBuffers(minBufferCount=%d, maxBufferCount=%d) fail", minBufferCount, maxBufferCount); |
| return ret; |
| } |
| } |
| |
| return ret; |
| } |
| |
| #ifdef SAMSUNG_COMPANION |
| int ExynosCamera3::m_getSensorId(int m_cameraId) |
| { |
| unsigned int scenario = 0; |
| unsigned int scenarioBit = 0; |
| unsigned int nodeNumBit = 0; |
| unsigned int sensorIdBit = 0; |
| unsigned int sensorId = getSensorId(m_cameraId); |
| |
| scenarioBit = (scenario << SCENARIO_SHIFT); |
| |
| nodeNumBit = ((FIMC_IS_VIDEO_SS0_NUM - FIMC_IS_VIDEO_SS0_NUM) << SSX_VINDEX_SHIFT); |
| |
| sensorIdBit = (sensorId << 0); |
| |
| return (scenarioBit) | (nodeNumBit) | (sensorIdBit); |
| } |
| |
| bool ExynosCamera3::m_companionThreadFunc(void) |
| { |
| CLOGI("INFO(%s[%d]):", __FUNCTION__, __LINE__); |
| ExynosCameraDurationTimer m_timer; |
| long long durationTime = 0; |
| int loop = false; |
| int ret = 0; |
| |
| m_timer.start(); |
| |
| m_companionNode = new ExynosCameraNode(); |
| |
| ret = m_companionNode->create("companion", m_cameraId); |
| if (ret < 0) { |
| CLOGE2("Companion Node create fail, ret(%d)", ret); |
| } |
| |
| ret = m_companionNode->open(MAIN_CAMERA_COMPANION_NUM); |
| if (ret < 0) { |
| CLOGE2("Companion Node open fail, ret(%d)", ret); |
| } |
| CLOGD2("Companion Node(%d) opened running)", MAIN_CAMERA_COMPANION_NUM); |
| |
| ret = m_companionNode->setInput(m_getSensorId(m_cameraId)); |
| if (ret < 0) { |
| CLOGE2("Companion Node s_input fail, ret(%d)", ret); |
| } |
| CLOGD2("Companion Node(%d) s_input", MAIN_CAMERA_COMPANION_NUM); |
| |
| m_timer.stop(); |
| durationTime = m_timer.durationMsecs(); |
| CLOGD2("duration time(%5d msec)", (int)durationTime); |
| |
| /* one shot */ |
| return loop; |
| } |
| #endif |
| |
| #if defined(SAMSUNG_EEPROM) |
| bool ExynosCamera3::m_eepromThreadFunc(void) |
| { |
| CLOGI("INFO(%s[%d]):", __FUNCTION__, __LINE__); |
| ExynosCameraDurationTimer m_timer; |
| long long durationTime = 0; |
| char sensorFW[50] = {0,}; |
| int ret = 0; |
| FILE *fp = NULL; |
| |
| m_timer.start(); |
| |
| if(m_cameraId == CAMERA_ID_BACK) { |
| fp = fopen(SENSOR_FW_PATH_BACK, "r"); |
| } else { |
| fp = fopen(SENSOR_FW_PATH_FRONT, "r"); |
| } |
| if (fp == NULL) { |
| CLOGE2("failed to open sysfs. camera id = %d", m_cameraId); |
| goto err; |
| } |
| |
| if (fgets(sensorFW, sizeof(sensorFW), fp) == NULL) { |
| CLOGE2("failed to read sysfs entry"); |
| goto err; |
| } |
| |
| /* int numread = strlen(sensorFW); */ |
| CLOGI2("eeprom read complete. Sensor FW ver: %s", sensorFW); |
| |
| err: |
| if (fp != NULL) |
| fclose(fp); |
| |
| m_timer.stop(); |
| durationTime = m_timer.durationMsecs(); |
| CLOGD2("duration time(%5d msec)", (int)durationTime); |
| |
| /* one shot */ |
| return false; |
| } |
| #endif |
| |
| status_t ExynosCamera3::m_startCompanion(void) |
| { |
| #ifdef SAMSUNG_COMPANION |
| if(m_parameters->isCompanion(getCameraId()) == true) { |
| if (m_companionNode == NULL) { |
| m_companionThread = new mainCameraThread(this, &ExynosCamera3::m_companionThreadFunc, |
| "companionshotThread", PRIORITY_URGENT_DISPLAY); |
| if (m_companionThread != NULL) { |
| m_companionThread->run(); |
| CLOGD2("companionThread starts"); |
| } else { |
| CLOGE2("failed the m_companionThread."); |
| } |
| } else { |
| CLOGW2("m_companionNode != NULL. so, it already running"); |
| } |
| } |
| #endif |
| |
| #if defined(SAMSUNG_EEPROM) |
| if ((m_use_companion == false) && (isEEprom(getCameraId()) == true)) { |
| m_eepromThread = new mainCameraThread(this, &ExynosCamera3::m_eepromThreadFunc, |
| "cameraeepromThread", PRIORITY_URGENT_DISPLAY); |
| if (m_eepromThread != NULL) { |
| m_eepromThread->run(); |
| CLOGD2("eepromThread starts"); |
| } else { |
| CLOGE2("failed the m_eepromThread"); |
| } |
| } |
| #endif |
| |
| return NO_ERROR; |
| } |
| |
| status_t ExynosCamera3::m_stopCompanion(void) |
| { |
| #ifdef SAMSUNG_COMPANION |
| if(m_parameters->isCompanion(getCameraId()) == true) { |
| if (m_companionThread != NULL) { |
| CLOGI2("wait m_companionThread"); |
| m_companionThread->requestExitAndWait(); |
| CLOGI2("wait m_companionThread end"); |
| } else { |
| CLOGI2("m_companionThread is NULL"); |
| } |
| |
| if (m_companionNode != NULL) { |
| ExynosCameraDurationTimer timer; |
| |
| timer.start(); |
| |
| if (m_companionNode->close() != NO_ERROR) { |
| CLOGE2("close fail"); |
| } |
| delete m_companionNode; |
| m_companionNode = NULL; |
| |
| CLOGD2("Companion Node(%d) closed", MAIN_CAMERA_COMPANION_NUM); |
| |
| timer.stop(); |
| CLOGD2("duration time(%5d msec)", (int)timer.durationMsecs()); |
| |
| } |
| } |
| #endif |
| |
| #if defined(SAMSUNG_EEPROM) |
| if ((m_parameters->isCompanion(getCameraId()) == false) && (isEEprom(getCameraId()) == true)) { |
| if (m_eepromThread != NULL) { |
| CLOGI2("wait m_eepromThread"); |
| m_eepromThread->requestExitAndWait(); |
| } else { |
| CLOGI2("m_eepromThread is NULL"); |
| } |
| } |
| #endif |
| |
| return NO_ERROR; |
| } |
| |
| status_t ExynosCamera3::m_waitCompanionThreadEnd(void) |
| { |
| ExynosCameraDurationTimer timer; |
| |
| timer.start(); |
| |
| #ifdef SAMSUNG_COMPANION |
| if (m_use_companion == true) { |
| if (m_companionThread != NULL) { |
| m_companionThread->join(); |
| } else { |
| CLOGI2("m_companionThread is NULL"); |
| } |
| } |
| #endif |
| |
| timer.stop(); |
| CLOGI2("companion waiting time : duration time(%5d msec)", (int)timer.durationMsecs()); |
| |
| CLOGI2("companionThread join"); |
| |
| return NO_ERROR; |
| } |
| |
| status_t ExynosCamera3::m_generateInternalFrame(uint32_t frameCount, ExynosCamera3FrameFactory *factory, List<ExynosCameraFrame *> *list, Mutex *listLock, ExynosCameraFrame **newFrame) |
| { |
| status_t ret = OK; |
| *newFrame = NULL; |
| |
| CLOGV2("frameCount(%d)", frameCount); |
| ret = m_searchFrameFromList(list, listLock, frameCount, newFrame); |
| if (ret < 0) { |
| CLOGE2("searchFrameFromList fail"); |
| return INVALID_OPERATION; |
| } |
| |
| if (*newFrame == NULL) { |
| *newFrame = factory->createNewFrame(frameCount); |
| if (*newFrame == NULL) { |
| CLOGE2("newFrame is NULL"); |
| return UNKNOWN_ERROR; |
| } |
| listLock->lock(); |
| list->push_back(*newFrame); |
| listLock->unlock(); |
| } |
| |
| /* Set frame type into FRAME_TYPE_INTERNAL */ |
| ret = (*newFrame)->setFrameInfo(m_parameters, frameCount, FRAME_TYPE_INTERNAL); |
| if (ret != NO_ERROR) { |
| ALOGE("ERR(%s[%d]):Failed to setFrameInfo with INTERNAL. frameCount %d", |
| __FUNCTION__, __LINE__, frameCount); |
| return ret; |
| } |
| |
| return ret; |
| } |
| |
| bool ExynosCamera3::m_internalFrameThreadFunc(void) |
| { |
| status_t ret = 0; |
| int index = 0; |
| ExynosCameraFrame *newFrame = NULL; |
| |
| CLOGV2("Enter m_internalFrameThreadFunc"); |
| |
| /* 1. Get new internal frame */ |
| ret = m_internalFrameDoneQ->waitAndPopProcessQ(&newFrame); |
| if (ret < 0) { |
| /* TODO: We need to make timeout duration depends on FPS */ |
| if (ret == TIMED_OUT) { |
| CLOGV2("wait timeout"); |
| } else { |
| CLOGE2("wait and pop fail, ret(%d)", ret); |
| /* TODO: doing exception handling */ |
| } |
| return false; |
| } |
| |
| CLOGV2("handle internal frame : previewStream frameCnt(%d) (%d)", newFrame->getFrameCount(), newFrame->getFrameType()); |
| |
| /* 2. Redirection for the normal frame */ |
| if (newFrame->getFrameType() != FRAME_TYPE_INTERNAL) { |
| CLOGE2("push to m_pipeFrameDoneQ handler : previewStream frameCnt(%d)", newFrame->getFrameCount()); |
| m_pipeFrameDoneQ[PIPE_3AA]->pushProcessQ(&newFrame); |
| return true; |
| } |
| |
| /* 3. Handle the internal frame for each pipe */ |
| ret = m_handleInternalFrame(newFrame); |
| |
| if (ret < 0) { |
| CLOGE2("handle preview frame fail"); |
| return ret; |
| } |
| |
| if (newFrame->isComplete() == true/* && newFrame->getFrameCapture() == false */) { |
| ret = m_removeFrameFromList(&m_processList, &m_processLock, newFrame); |
| |
| if (ret < 0) { |
| CLOGE2("remove frame from processList fail, ret(%d)", ret); |
| } |
| |
| CLOGV2("internal frame complete, count(%d)", newFrame->getFrameCount()); |
| newFrame->decRef(); |
| m_frameMgr->deleteFrame(newFrame); |
| newFrame = NULL; |
| m_captureResultDoneCondition.signal(); |
| } |
| |
| return true; |
| } |
| |
| bool ExynosCamera3::m_doInternalFrame(ExynosCameraRequest *request) |
| { |
| status_t ret = NO_ERROR; |
| bool internalFlag = false; |
| |
| struct camera2_shot_ext cur_shot_ext; |
| struct camera2_shot_ext prev_shot_ext; |
| |
| memset(&cur_shot_ext, 0x00, sizeof(struct camera2_shot_ext)); |
| memset(&prev_shot_ext, 0x00, sizeof(struct camera2_shot_ext)); |
| |
| ret = request->getServiceShot(&cur_shot_ext); |
| if (ret != NO_ERROR) { |
| CLOGE2("Get service shot fail, Request Key(%d), ret(%d)", request->getKey(), ret); |
| return false; |
| } |
| |
| ret = request->getPrevShot(&prev_shot_ext); |
| if (ret != NO_ERROR) { |
| CLOGE2("Get service previous shot fail, Request Key(%d), ret(%d)", request->getKey(), ret); |
| return false; |
| } |
| |
| if (cur_shot_ext.shot.ctl.aa.aeMode == AA_AEMODE_OFF || cur_shot_ext.shot.ctl.aa.mode == AA_CONTROL_OFF) { |
| if ((cur_shot_ext.shot.ctl.sensor.exposureTime != prev_shot_ext.shot.ctl.sensor.exposureTime) |
| || (cur_shot_ext.shot.ctl.sensor.frameDuration!= prev_shot_ext.shot.ctl.sensor.frameDuration) |
| || (cur_shot_ext.shot.ctl.aa.vendor_isoValue != prev_shot_ext.shot.ctl.aa.vendor_isoValue)) { |
| CLOGI2("Create internal frame for manual AE setting"); |
| internalFlag = true; |
| } |
| } |
| |
| if ((cur_shot_ext.shot.ctl.lens.opticalStabilizationMode == OPTICAL_STABILIZATION_MODE_STILL) |
| && (prev_shot_ext.shot.ctl.lens.opticalStabilizationMode == OPTICAL_STABILIZATION_MODE_CENTERING)) { |
| CLOGI2("Create internal frame for ois mode (OFF -> ON)"); |
| internalFlag = true; |
| } |
| |
| #if 0 //for test |
| if (cur_shot_ext.shot.ctl.aa.aeLock != prev_shot_ext.shot.ctl.aa.aeLock ) { |
| CLOGI2("Create internal frame for ae lock (%d -> %d)", |
| prev_shot_ext.shot.ctl.aa.aeLock,cur_shot_ext.shot.ctl.aa.aeLock); |
| internalFlag = true; |
| } |
| #endif |
| |
| return internalFlag; |
| } |
| |
| status_t ExynosCamera3::m_handleInternalFrame(ExynosCameraFrame *frame) |
| { |
| ExynosCameraFrameEntity *entity = NULL; |
| ExynosCameraFrame *newFrame = NULL; |
| ExynosCameraBuffer buffer; |
| ExynosCameraBuffer t3acBuffer; |
| ExynosCamera3FrameFactory *factory = m_frameFactory[FRAME_FACTORY_TYPE_CAPTURE_PREVIEW]; |
| ExynosCameraStream *stream = NULL; |
| camera3_capture_result_t captureResult; |
| camera3_notify_msg_t notityMsg; |
| ExynosCameraRequest* request = NULL; |
| ResultRequest resultRequest = NULL; |
| |
| struct camera2_shot_ext meta_shot_ext; |
| struct camera2_dm *dm = NULL; |
| uint32_t framecount = 0; |
| int32_t reprocessingBayerMode = m_parameters->getReprocessingBayerMode(); |
| |
| entity_state_t entityState = ENTITY_STATE_COMPLETE; |
| status_t ret = OK; |
| |
| entity = frame->getFrameDoneFirstEntity(); |
| if (entity == NULL) { |
| CLOGE2("current entity is NULL"); |
| /* TODO: doing exception handling */ |
| return true; |
| } |
| CLOGV2("handle internal frame : previewStream frameCnt(%d) entityID(%d)", frame->getFrameCount(), entity->getPipeId()); |
| |
| switch(entity->getPipeId()) { |
| case PIPE_3AA: |
| /* Notify ShotDone to mainThread */ |
| framecount = frame->getFrameCount(); |
| m_shotDoneQ->pushProcessQ(&framecount); |
| |
| ret = frame->getSrcBuffer(entity->getPipeId(), &buffer); |
| if (ret < 0) { |
| CLOGE2("getSrcBuffer fail, pipeId(%d), ret(%d)", entity->getPipeId(), ret); |
| return ret; |
| } |
| |
| if (buffer.index >= 0) { |
| ret = m_updateTimestamp(frame, &buffer, false); |
| if (ret != NO_ERROR) { |
| CLOGE2("[F%d B%d]Failed to updateTimestamp", |
| frame->getFrameCount(), buffer.index); |
| return ret; |
| } |
| |
| if (m_parameters->isFlite3aaOtf() == false) |
| ret = m_putBuffers(m_fliteBufferMgr, buffer.index); |
| else |
| ret = m_putBuffers(m_3aaBufferMgr, buffer.index); |
| |
| if (ret < 0) { |
| CLOGE2("put Buffer fail"); |
| } |
| } |
| |
| frame->setMetaDataEnable(true); |
| |
| t3acBuffer.index = -1; |
| |
| if (frame->getRequest(PIPE_3AC) == true) { |
| ret = frame->getDstBuffer(entity->getPipeId(), &t3acBuffer, factory->getNodeType(PIPE_3AC)); |
| if (ret != NO_ERROR) { |
| CLOGE2("getDstBuffer fail, pipeId(%d), ret(%d)", entity->getPipeId(), ret); |
| } |
| } |
| |
| if (m_parameters->isReprocessing() == true) { |
| if (m_captureSelector == NULL) { |
| CLOGE2("m_captureSelector is NULL"); |
| return INVALID_OPERATION; |
| } |
| } else { |
| if (m_sccCaptureSelector == NULL) { |
| CLOGE2("m_sccCaptureSelector is NULL"); |
| return INVALID_OPERATION; |
| } |
| } |
| |
| if (0 <= t3acBuffer.index) { |
| if (m_parameters->isUseYuvReprocessing() == true |
| || frame->getFrameCapture() == true) { |
| if (m_parameters->getHighSpeedRecording() == true) { |
| if (m_parameters->isUsing3acForIspc() == true) |
| ret = m_putBuffers(m_yuvCaptureBufferMgr, t3acBuffer.index); |
| else |
| ret = m_putBuffers(m_fliteBufferMgr, t3acBuffer.index); |
| |
| if (ret < 0) { |
| CLOGE2("m_putBuffers(m_fliteBufferMgr, %d) fail", t3acBuffer.index); |
| break; |
| } |
| } else { |
| entity_buffer_state_t bufferstate = ENTITY_BUFFER_STATE_NOREQ; |
| ret = frame->getDstBufferState(entity->getPipeId(), &bufferstate, factory->getNodeType(PIPE_3AC)); |
| if (ret == NO_ERROR && bufferstate != ENTITY_BUFFER_STATE_ERROR) { |
| if (m_parameters->isUseYuvReprocessing() == false |
| && m_parameters->isUsing3acForIspc() == true) |
| ret = m_sccCaptureSelector->manageFrameHoldListForDynamicBayer(frame); |
| else |
| ret = m_captureSelector->manageFrameHoldList(frame, entity->getPipeId(), false, factory->getNodeType(PIPE_3AC)); |
| |
| if (ret < 0) { |
| CLOGE2("manageFrameHoldList fail"); |
| return ret; |
| } |
| } else { |
| if (m_parameters->isUsing3acForIspc() == true) |
| ret = m_putBuffers(m_yuvCaptureBufferMgr, t3acBuffer.index); |
| else |
| ret = m_putBuffers(m_fliteBufferMgr, t3acBuffer.index); |
| |
| if (ret < 0) { |
| CLOGE2("m_putBuffers(m_fliteBufferMgr, %d) fail", t3acBuffer.index); |
| break; |
| } |
| } |
| } |
| } else { |
| if (reprocessingBayerMode == REPROCESSING_BAYER_MODE_DIRTY_ALWAYS_ON) { |
| CLOGW2("frame->getRequest(PIPE_3AC) == false. so, just m_putBuffers(t3acBuffer.index(%d)..., pipeId(%d), ret(%d)", |
| t3acBuffer.index, entity->getPipeId(), ret); |
| } |
| |
| if (m_parameters->isUsing3acForIspc() == true) |
| ret = m_putBuffers(m_yuvCaptureBufferMgr, t3acBuffer.index); |
| else |
| ret = m_putBuffers(m_fliteBufferMgr, t3acBuffer.index); |
| |
| if (ret < 0) { |
| CLOGE2("m_putBuffers(m_fliteBufferMgr, %d) fail", t3acBuffer.index); |
| break; |
| } |
| } |
| } |
| |
| break; |
| case PIPE_VRA: |
| ret = frame->getDstBuffer(entity->getPipeId(), &buffer); |
| if (ret != NO_ERROR) { |
| CLOGE("ERR(%s[%d]):getDstBuffer fail, pipeId(%d), ret(%d)", |
| __FUNCTION__, __LINE__, entity->getPipeId(), ret); |
| return ret; |
| } |
| |
| if (buffer.index >= 0) { |
| ret = m_vraBufferMgr->putBuffer(buffer.index, EXYNOS_CAMERA_BUFFER_POSITION_IN_HAL); |
| if (ret != NO_ERROR) |
| CLOGW("WARN(%s[%d]):Put VRA buffer fail, ret(%d)", __FUNCTION__, __LINE__, ret); |
| } |
| |
| break; |
| case PIPE_FLITE: |
| /* TODO: HACK: Will be removed, this is driver's job */ |
| if (m_parameters->isFlite3aaOtf() == true) { |
| ret = m_handleBayerBuffer(frame); |
| if (ret < NO_ERROR) { |
| CLOGE("ERR(%s[%d]):Handle bayer buffer failed, framecount(%d), pipeId(%d), ret(%d)", |
| __FUNCTION__, __LINE__, frame->getFrameCount(), entity->getPipeId(), ret); |
| return ret; |
| } |
| } else { |
| ret = frame->getDstBuffer(entity->getPipeId(), &buffer); |
| |
| if (ret < 0) { |
| CLOGE("ERR(%s[%d]):getDstBuffer fail, pipeId(%d), ret(%d)", |
| __FUNCTION__, __LINE__, entity->getPipeId(), ret); |
| return ret; |
| } |
| |
| CLOGV("DEBUG(%s[%d]):Deliver Flite Buffer to 3AA. driver->framecount %d hal->framecount %d", |
| __FUNCTION__, __LINE__, |
| getMetaDmRequestFrameCount((struct camera2_shot_ext *)buffer.addr[buffer.planeCount-1]), |
| frame->getFrameCount()); |
| |
| ret = m_setupEntity(PIPE_3AA, frame, &buffer, NULL); |
| if (ret != NO_ERROR) { |
| CLOGE("ERR(%s[%d]):setSrcBuffer failed, pipeId(%d), ret(%d)", |
| __FUNCTION__, __LINE__, PIPE_3AA, ret); |
| return ret; |
| } |
| |
| factory->pushFrameToPipe(&frame, PIPE_3AA); |
| } |
| |
| break; |
| default: |
| CLOGE2("Invalid pipe ID"); |
| break; |
| } |
| |
| ret = frame->setEntityState(entity->getPipeId(), entityState); |
| if (ret < 0) { |
| CLOGE2("setEntityState fail, pipeId(%d), state(%d), ret(%d)", entity->getPipeId(), ENTITY_STATE_COMPLETE, ret); |
| return ret; |
| } |
| |
| return ret; |
| } |
| |
| #ifdef MONITOR_LOG_SYNC |
| uint32_t ExynosCamera3::m_getSyncLogId(void) |
| { |
| return ++cameraSyncLogId; |
| } |
| #endif |
| |
| bool ExynosCamera3::m_monitorThreadFunc(void) |
| { |
| CLOGV("INFO(%s[%d]):", __FUNCTION__, __LINE__); |
| |
| int *threadState; |
| struct timeval dqTime; |
| uint64_t *timeInterval; |
| int *countRenew; |
| int camId = getCameraId(); |
| int ret = NO_ERROR; |
| int loopCount = 0; |
| |
| int dtpStatus = 0; |
| int pipeIdFlite = 0; |
| int pipeIdScp = 0; |
| ExynosCamera3FrameFactory *factory = NULL; |
| |
| for (loopCount = 0; loopCount < MONITOR_THREAD_INTERVAL; loopCount += (MONITOR_THREAD_INTERVAL/20)) { |
| if (m_flushFlag == true) { |
| CLOGI2("m_flushFlag(%d)", m_flushFlag); |
| return false; |
| } |
| usleep(MONITOR_THREAD_INTERVAL/20); |
| } |
| |
| if (m_parameters->isFlite3aaOtf() == true || getCameraId() == CAMERA_ID_BACK) { |
| pipeIdFlite = PIPE_FLITE; |
| pipeIdScp = PIPE_3AA; |
| } else { |
| pipeIdFlite = PIPE_FLITE_FRONT; |
| pipeIdScp = PIPE_3AA_FRONT; |
| } |
| |
| factory = m_frameFactory[FRAME_FACTORY_TYPE_CAPTURE_PREVIEW]; |
| if (factory == NULL) { |
| CLOGE2("frameFactory is NULL"); |
| return false; |
| } |
| |
| if (factory->checkPipeThreadRunning(pipeIdScp) == false) { |
| CLOGE2("Scp pipe is not running.. Skip monitoring."); |
| return false; |
| } |
| #ifdef MONITOR_LOG_SYNC |
| uint32_t pipeIdIsp = 0; |
| |
| if (m_parameters->isFlite3aaOtf() == true || getCameraId() == CAMERA_ID_BACK) |
| pipeIdIsp = PIPE_3AA; |
| else |
| pipeIdIsp = PIPE_3AA_FRONT; |
| |
| /* If it is not front camera in dual and sensor pipe is running, do sync log */ |
| if (factory->checkPipeThreadRunning(pipeIdIsp) && |
| !(getCameraId() == CAMERA_ID_FRONT && m_parameters->getDualMode())) { |
| if (!(m_syncLogDuration % MONITOR_LOG_SYNC_INTERVAL)) { |
| uint32_t syncLogId = m_getSyncLogId(); |
| CLOGI2("@FIMC_IS_SYNC %d", syncLogId); |
| factory->syncLog(pipeIdIsp, syncLogId); |
| } |
| m_syncLogDuration++; |
| } |
| #endif |
| factory->getControl(V4L2_CID_IS_G_DTPSTATUS, &dtpStatus, pipeIdFlite); |
| |
| if (dtpStatus == 1) { |
| CLOGE2("(%d)", dtpStatus); |
| dump(); |
| |
| #if 0//def CAMERA_GED_FEATURE |
| /* in GED */ |
| android_printAssert(NULL, LOG_TAG, "killed by itself"); |
| #else |
| /* specifically defined */ |
| /* m_notifyCb(CAMERA_MSG_ERROR, 1002, 0, m_callbackCookie); */ |
| /* or */ |
| /* android_printAssert(NULL, LOG_TAG, "killed by itself"); */ |
| #endif |
| return false; |
| } |
| |
| #ifdef SENSOR_OVERFLOW_CHECK |
| factory->getControl(V4L2_CID_IS_G_DTPSTATUS, &dtpStatus, pipeIdFlite); |
| if (dtpStatus == 1) { |
| CLOGE2("(%d)", dtpStatus); |
| dump(); |
| #if 0//def CAMERA_GED_FEATURE |
| /* in GED */ |
| android_printAssert(NULL, LOG_TAG, "killed by itself"); |
| #else |
| /* specifically defined */ |
| /* m_notifyCb(CAMERA_MSG_ERROR, 1002, 0, m_callbackCookie); */ |
| /* or */ |
| /* android_printAssert(NULL, LOG_TAG, "killed by itself"); */ |
| #endif |
| return false; |
| } |
| #endif |
| factory->getThreadState(&threadState, pipeIdScp); |
| factory->getThreadRenew(&countRenew, pipeIdScp); |
| |
| if ((*threadState == ERROR_POLLING_DETECTED) || (*countRenew > ERROR_DQ_BLOCKED_COUNT)) { |
| CLOGE2("(%d)", *threadState); |
| if((*countRenew > ERROR_DQ_BLOCKED_COUNT)) |
| CLOGE2("ERROR_DQ_BLOCKED) ; ERROR_DQ_BLOCKED_COUNT =20"); |
| |
| dump(); |
| #ifdef SAMSUNG_TN_FEATURE |
| #if 0 |
| /* this tn feature was commented for 3.2 */ |
| if (m_recordingEnabled == true |
| && m_parameters->msgTypeEnabled(CAMERA_MSG_VIDEO_FRAME) |
| && m_recordingCallbackHeap != NULL |
| && m_callbackCookie != NULL) { |
| m_dataCbTimestamp( |
| 0, |
| CAMERA_MSG_ERROR | CAMERA_MSG_VIDEO_FRAME, |
| m_recordingCallbackHeap, |
| 0, |
| m_callbackCookie); |
| CLOGD2("Timestamp callback with CAMERA_MSG_ERROR"); |
| } |
| #endif |
| #endif |
| #if 0//def CAMERA_GED_FEATURE |
| /* in GED */ |
| android_printAssert(NULL, LOG_TAG, "killed by itself"); |
| #else |
| /* specifically defined */ |
| /* m_notifyCb(CAMERA_MSG_ERROR, 1002, 0, m_callbackCookie); */ |
| /* or */ |
| /* android_printAssert(NULL, LOG_TAG, "killed by itself"); */ |
| #endif |
| return false; |
| } else { |
| CLOGV2(" (%d)", *threadState); |
| } |
| |
| gettimeofday(&dqTime, NULL); |
| factory->getThreadInterval(&timeInterval, pipeIdScp); |
| |
| CLOGV2("Thread IntervalTime [%lld]", *timeInterval); |
| CLOGV2("Thread Renew Count [%d]", *countRenew); |
| |
| factory->incThreadRenew(pipeIdScp); |
| |
| return true; |
| } |
| |
| }; /* namespace android */ |