| /* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions are |
| * met: |
| * * Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * * Redistributions in binary form must reproduce the above |
| * copyright notice, this list of conditions and the following |
| * disclaimer in the documentation and/or other materials provided |
| * with the distribution. |
| * * Neither the name of The Linux Foundation nor the names of its |
| * contributors may be used to endorse or promote products derived |
| * from this software without specific prior written permission. |
| * |
| * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED |
| * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |
| * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT |
| * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS |
| * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
| * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
| * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR |
| * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, |
| * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE |
| * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN |
| * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| * |
| */ |
| |
| #define LOG_TAG "QCamera2HWI" |
| |
| // To remove |
| #include <cutils/properties.h> |
| |
| // System definitions |
| #include <utils/Errors.h> |
| #include <dlfcn.h> |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include "gralloc_priv.h" |
| #include "native_handle.h" |
| |
| // Camera definitions |
| #include "android/QCamera2External.h" |
| #include "QCamera2HWI.h" |
| #include "QCameraBufferMaps.h" |
| #include "QCameraFlash.h" |
| #include "QCameraTrace.h" |
| |
| extern "C" { |
| #include "mm_camera_dbg.h" |
| } |
| |
| #define MAP_TO_DRIVER_COORDINATE(val, base, scale, offset) \ |
| ((int32_t)val * (int32_t)scale / (int32_t)base + (int32_t)offset) |
| #define CAMERA_MIN_STREAMING_BUFFERS 3 |
| #define EXTRA_ZSL_PREVIEW_STREAM_BUF 2 |
| #define CAMERA_MIN_JPEG_ENCODING_BUFFERS 2 |
| #define CAMERA_MIN_VIDEO_BUFFERS 9 |
| #define CAMERA_MIN_CALLBACK_BUFFERS 5 |
| #define CAMERA_LONGSHOT_STAGES 4 |
| #define CAMERA_MIN_CAMERA_BATCH_BUFFERS 6 |
| #define CAMERA_ISP_PING_PONG_BUFFERS 2 |
| #define MIN_UNDEQUEUED_BUFFERS 1 // This is required if preview window is not set |
| #define CAMERA_MIN_DISPLAY_BUFFERS 2 |
| #define CAMERA_DEFAULT_FPS 30000 |
| |
| #define HDR_CONFIDENCE_THRESHOLD 0.4 |
| |
| #define CAMERA_OPEN_PERF_TIME_OUT 500 // 500 milliseconds |
| |
| // Very long wait, just to be sure we don't deadlock |
| #define CAMERA_DEFERRED_THREAD_TIMEOUT 5000000000 // 5 seconds |
| #define CAMERA_DEFERRED_MAP_BUF_TIMEOUT 2000000000 // 2 seconds |
| #define CAMERA_MIN_METADATA_BUFFERS 10 // Need at least 10 for ZSL snapshot |
| #define CAMERA_INITIAL_MAPPABLE_PREVIEW_BUFFERS 5 |
| #define CAMERA_MAX_PARAM_APPLY_DELAY 3 |
| |
| namespace qcamera { |
| |
| extern cam_capability_t *gCamCapability[MM_CAMERA_MAX_NUM_SENSORS]; |
| extern pthread_mutex_t gCamLock; |
| volatile uint32_t gCamHalLogLevel = 1; |
| extern uint8_t gNumCameraSessions; |
| uint32_t QCamera2HardwareInterface::sNextJobId = 1; |
| |
| camera_device_ops_t QCamera2HardwareInterface::mCameraOps = { |
| .set_preview_window = QCamera2HardwareInterface::set_preview_window, |
| .set_callbacks = QCamera2HardwareInterface::set_CallBacks, |
| .enable_msg_type = QCamera2HardwareInterface::enable_msg_type, |
| .disable_msg_type = QCamera2HardwareInterface::disable_msg_type, |
| .msg_type_enabled = QCamera2HardwareInterface::msg_type_enabled, |
| |
| .start_preview = QCamera2HardwareInterface::start_preview, |
| .stop_preview = QCamera2HardwareInterface::stop_preview, |
| .preview_enabled = QCamera2HardwareInterface::preview_enabled, |
| .store_meta_data_in_buffers= QCamera2HardwareInterface::store_meta_data_in_buffers, |
| |
| .start_recording = QCamera2HardwareInterface::start_recording, |
| .stop_recording = QCamera2HardwareInterface::stop_recording, |
| .recording_enabled = QCamera2HardwareInterface::recording_enabled, |
| .release_recording_frame = QCamera2HardwareInterface::release_recording_frame, |
| |
| .auto_focus = QCamera2HardwareInterface::auto_focus, |
| .cancel_auto_focus = QCamera2HardwareInterface::cancel_auto_focus, |
| |
| .take_picture = QCamera2HardwareInterface::take_picture, |
| .cancel_picture = QCamera2HardwareInterface::cancel_picture, |
| |
| .set_parameters = QCamera2HardwareInterface::set_parameters, |
| .get_parameters = QCamera2HardwareInterface::get_parameters, |
| .put_parameters = QCamera2HardwareInterface::put_parameters, |
| .send_command = QCamera2HardwareInterface::send_command, |
| |
| .release = QCamera2HardwareInterface::release, |
| .dump = QCamera2HardwareInterface::dump, |
| }; |
| |
| /*=========================================================================== |
| * FUNCTION : set_preview_window |
| * |
| * DESCRIPTION: set preview window. |
| * |
| * PARAMETERS : |
| * @device : ptr to camera device struct |
| * @window : window ops table |
| * |
| * RETURN : int32_t type of status |
| * NO_ERROR -- success |
| * none-zero failure code |
| *==========================================================================*/ |
| int QCamera2HardwareInterface::set_preview_window(struct camera_device *device, |
| struct preview_stream_ops *window) |
| { |
| ATRACE_CALL(); |
| int rc = NO_ERROR; |
| QCamera2HardwareInterface *hw = |
| reinterpret_cast<QCamera2HardwareInterface *>(device->priv); |
| if (!hw) { |
| LOGE("NULL camera device"); |
| return BAD_VALUE; |
| } |
| LOGD("E camera id %d window = %p", hw->getCameraId(), window); |
| |
| hw->lockAPI(); |
| qcamera_api_result_t apiResult; |
| rc = hw->processAPI(QCAMERA_SM_EVT_SET_PREVIEW_WINDOW, (void *)window); |
| if (rc == NO_ERROR) { |
| hw->waitAPIResult(QCAMERA_SM_EVT_SET_PREVIEW_WINDOW, &apiResult); |
| rc = apiResult.status; |
| } |
| hw->unlockAPI(); |
| LOGD("X camera id %d", hw->getCameraId()); |
| |
| return rc; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : set_CallBacks |
| * |
| * DESCRIPTION: set callbacks for notify and data |
| * |
| * PARAMETERS : |
| * @device : ptr to camera device struct |
| * @notify_cb : notify cb |
| * @data_cb : data cb |
| * @data_cb_timestamp : video data cd with timestamp |
| * @get_memory : ops table for request gralloc memory |
| * @user : user data ptr |
| * |
| * RETURN : none |
| *==========================================================================*/ |
| void QCamera2HardwareInterface::set_CallBacks(struct camera_device *device, |
| camera_notify_callback notify_cb, |
| camera_data_callback data_cb, |
| camera_data_timestamp_callback data_cb_timestamp, |
| camera_request_memory get_memory, |
| void *user) |
| { |
| ATRACE_CALL(); |
| QCamera2HardwareInterface *hw = |
| reinterpret_cast<QCamera2HardwareInterface *>(device->priv); |
| if (!hw) { |
| LOGE("NULL camera device"); |
| return; |
| } |
| LOGD("E camera id %d", hw->getCameraId()); |
| |
| qcamera_sm_evt_setcb_payload_t payload; |
| payload.notify_cb = notify_cb; |
| payload.data_cb = data_cb; |
| payload.data_cb_timestamp = data_cb_timestamp; |
| payload.get_memory = get_memory; |
| payload.user = user; |
| |
| hw->lockAPI(); |
| qcamera_api_result_t apiResult; |
| int32_t rc = hw->processAPI(QCAMERA_SM_EVT_SET_CALLBACKS, (void *)&payload); |
| if (rc == NO_ERROR) { |
| hw->waitAPIResult(QCAMERA_SM_EVT_SET_CALLBACKS, &apiResult); |
| } |
| hw->unlockAPI(); |
| LOGD("X camera id %d", hw->getCameraId()); |
| |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : enable_msg_type |
| * |
| * DESCRIPTION: enable certain msg type |
| * |
| * PARAMETERS : |
| * @device : ptr to camera device struct |
| * @msg_type : msg type mask |
| * |
| * RETURN : none |
| *==========================================================================*/ |
| void QCamera2HardwareInterface::enable_msg_type(struct camera_device *device, int32_t msg_type) |
| { |
| ATRACE_CALL(); |
| QCamera2HardwareInterface *hw = |
| reinterpret_cast<QCamera2HardwareInterface *>(device->priv); |
| if (!hw) { |
| LOGE("NULL camera device"); |
| return; |
| } |
| LOGD("E camera id %d", hw->getCameraId()); |
| |
| hw->lockAPI(); |
| qcamera_api_result_t apiResult; |
| int32_t rc = hw->processAPI(QCAMERA_SM_EVT_ENABLE_MSG_TYPE, (void *)&msg_type); |
| if (rc == NO_ERROR) { |
| hw->waitAPIResult(QCAMERA_SM_EVT_ENABLE_MSG_TYPE, &apiResult); |
| } |
| hw->unlockAPI(); |
| LOGD("X camera id %d", hw->getCameraId()); |
| |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : disable_msg_type |
| * |
| * DESCRIPTION: disable certain msg type |
| * |
| * PARAMETERS : |
| * @device : ptr to camera device struct |
| * @msg_type : msg type mask |
| * |
| * RETURN : none |
| *==========================================================================*/ |
| void QCamera2HardwareInterface::disable_msg_type(struct camera_device *device, int32_t msg_type) |
| { |
| ATRACE_CALL(); |
| QCamera2HardwareInterface *hw = |
| reinterpret_cast<QCamera2HardwareInterface *>(device->priv); |
| if (!hw) { |
| LOGE("NULL camera device"); |
| return; |
| } |
| LOGD("E camera id %d", hw->getCameraId()); |
| |
| hw->lockAPI(); |
| qcamera_api_result_t apiResult; |
| int32_t rc = hw->processAPI(QCAMERA_SM_EVT_DISABLE_MSG_TYPE, (void *)&msg_type); |
| if (rc == NO_ERROR) { |
| hw->waitAPIResult(QCAMERA_SM_EVT_DISABLE_MSG_TYPE, &apiResult); |
| } |
| hw->unlockAPI(); |
| LOGD("X camera id %d", hw->getCameraId()); |
| |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : msg_type_enabled |
| * |
| * DESCRIPTION: if certain msg type is enabled |
| * |
| * PARAMETERS : |
| * @device : ptr to camera device struct |
| * @msg_type : msg type mask |
| * |
| * RETURN : 1 -- enabled |
| * 0 -- not enabled |
| *==========================================================================*/ |
| int QCamera2HardwareInterface::msg_type_enabled(struct camera_device *device, int32_t msg_type) |
| { |
| ATRACE_CALL(); |
| int ret = NO_ERROR; |
| QCamera2HardwareInterface *hw = |
| reinterpret_cast<QCamera2HardwareInterface *>(device->priv); |
| if (!hw) { |
| LOGE("NULL camera device"); |
| return BAD_VALUE; |
| } |
| LOGD("E camera id %d", hw->getCameraId()); |
| |
| hw->lockAPI(); |
| qcamera_api_result_t apiResult; |
| ret = hw->processAPI(QCAMERA_SM_EVT_MSG_TYPE_ENABLED, (void *)&msg_type); |
| if (ret == NO_ERROR) { |
| hw->waitAPIResult(QCAMERA_SM_EVT_MSG_TYPE_ENABLED, &apiResult); |
| ret = apiResult.enabled; |
| } |
| hw->unlockAPI(); |
| LOGD("X camera id %d", hw->getCameraId()); |
| |
| return ret; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : prepare_preview |
| * |
| * DESCRIPTION: prepare preview |
| * |
| * PARAMETERS : |
| * @device : ptr to camera device struct |
| * |
| * RETURN : int32_t type of status |
| * NO_ERROR -- success |
| * none-zero failure code |
| *==========================================================================*/ |
| int QCamera2HardwareInterface::prepare_preview(struct camera_device *device) |
| { |
| ATRACE_CALL(); |
| int ret = NO_ERROR; |
| QCamera2HardwareInterface *hw = |
| reinterpret_cast<QCamera2HardwareInterface *>(device->priv); |
| if (!hw) { |
| LOGE("NULL camera device"); |
| return BAD_VALUE; |
| } |
| LOGH("[KPI Perf]: E PROFILE_PREPARE_PREVIEW camera id %d", |
| hw->getCameraId()); |
| hw->lockAPI(); |
| qcamera_api_result_t apiResult; |
| qcamera_sm_evt_enum_t evt = QCAMERA_SM_EVT_PREPARE_PREVIEW; |
| ret = hw->processAPI(evt, NULL); |
| if (ret == NO_ERROR) { |
| hw->waitAPIResult(evt, &apiResult); |
| ret = apiResult.status; |
| } |
| hw->unlockAPI(); |
| LOGH("[KPI Perf]: X"); |
| return ret; |
| } |
| |
| |
| /*=========================================================================== |
| * FUNCTION : start_preview |
| * |
| * DESCRIPTION: start preview |
| * |
| * PARAMETERS : |
| * @device : ptr to camera device struct |
| * |
| * RETURN : int32_t type of status |
| * NO_ERROR -- success |
| * none-zero failure code |
| *==========================================================================*/ |
| int QCamera2HardwareInterface::start_preview(struct camera_device *device) |
| { |
| KPI_ATRACE_CALL(); |
| int ret = NO_ERROR; |
| QCamera2HardwareInterface *hw = |
| reinterpret_cast<QCamera2HardwareInterface *>(device->priv); |
| if (!hw) { |
| LOGE("NULL camera device"); |
| return BAD_VALUE; |
| } |
| LOGI("[KPI Perf]: E PROFILE_START_PREVIEW camera id %d", |
| hw->getCameraId()); |
| |
| // Release the timed perf lock acquired in openCamera |
| hw->m_perfLock.lock_rel_timed(); |
| |
| hw->m_perfLock.lock_acq(); |
| hw->lockAPI(); |
| qcamera_api_result_t apiResult; |
| qcamera_sm_evt_enum_t evt = QCAMERA_SM_EVT_START_PREVIEW; |
| if (hw->isNoDisplayMode()) { |
| evt = QCAMERA_SM_EVT_START_NODISPLAY_PREVIEW; |
| } |
| ret = hw->processAPI(evt, NULL); |
| if (ret == NO_ERROR) { |
| hw->waitAPIResult(evt, &apiResult); |
| ret = apiResult.status; |
| } |
| hw->unlockAPI(); |
| hw->m_bPreviewStarted = true; |
| LOGI("[KPI Perf]: X ret = %d", ret); |
| return ret; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : stop_preview |
| * |
| * DESCRIPTION: stop preview |
| * |
| * PARAMETERS : |
| * @device : ptr to camera device struct |
| * |
| * RETURN : none |
| *==========================================================================*/ |
| void QCamera2HardwareInterface::stop_preview(struct camera_device *device) |
| { |
| KPI_ATRACE_CALL(); |
| QCamera2HardwareInterface *hw = |
| reinterpret_cast<QCamera2HardwareInterface *>(device->priv); |
| if (!hw) { |
| LOGE("NULL camera device"); |
| return; |
| } |
| LOGI("[KPI Perf]: E PROFILE_STOP_PREVIEW camera id %d", |
| hw->getCameraId()); |
| |
| // Disable power Hint for preview |
| hw->m_perfLock.powerHint(POWER_HINT_VIDEO_ENCODE, false); |
| |
| hw->m_perfLock.lock_acq(); |
| hw->lockAPI(); |
| qcamera_api_result_t apiResult; |
| int32_t ret = hw->processAPI(QCAMERA_SM_EVT_STOP_PREVIEW, NULL); |
| if (ret == NO_ERROR) { |
| hw->waitAPIResult(QCAMERA_SM_EVT_STOP_PREVIEW, &apiResult); |
| } |
| hw->unlockAPI(); |
| LOGI("[KPI Perf]: X ret = %d", ret); |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : preview_enabled |
| * |
| * DESCRIPTION: if preview is running |
| * |
| * PARAMETERS : |
| * @device : ptr to camera device struct |
| * |
| * RETURN : 1 -- running |
| * 0 -- not running |
| *==========================================================================*/ |
| int QCamera2HardwareInterface::preview_enabled(struct camera_device *device) |
| { |
| ATRACE_CALL(); |
| int ret = NO_ERROR; |
| QCamera2HardwareInterface *hw = |
| reinterpret_cast<QCamera2HardwareInterface *>(device->priv); |
| if (!hw) { |
| LOGE("NULL camera device"); |
| return BAD_VALUE; |
| } |
| LOGD("E camera id %d", hw->getCameraId()); |
| |
| hw->lockAPI(); |
| qcamera_api_result_t apiResult; |
| ret = hw->processAPI(QCAMERA_SM_EVT_PREVIEW_ENABLED, NULL); |
| if (ret == NO_ERROR) { |
| hw->waitAPIResult(QCAMERA_SM_EVT_PREVIEW_ENABLED, &apiResult); |
| ret = apiResult.enabled; |
| } |
| |
| //if preview enabled, can enable preview callback send |
| if(apiResult.enabled) { |
| hw->m_stateMachine.setPreviewCallbackNeeded(true); |
| } |
| hw->unlockAPI(); |
| LOGD("X camera id %d", hw->getCameraId()); |
| |
| return ret; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : store_meta_data_in_buffers |
| * |
| * DESCRIPTION: if need to store meta data in buffers for video frame |
| * |
| * PARAMETERS : |
| * @device : ptr to camera device struct |
| * @enable : flag if enable |
| * |
| * RETURN : int32_t type of status |
| * NO_ERROR -- success |
| * none-zero failure code |
| *==========================================================================*/ |
| int QCamera2HardwareInterface::store_meta_data_in_buffers( |
| struct camera_device *device, int enable) |
| { |
| int ret = NO_ERROR; |
| QCamera2HardwareInterface *hw = |
| reinterpret_cast<QCamera2HardwareInterface *>(device->priv); |
| if (!hw) { |
| LOGE("NULL camera device"); |
| return BAD_VALUE; |
| } |
| LOGD("E camera id %d", hw->getCameraId()); |
| |
| hw->lockAPI(); |
| qcamera_api_result_t apiResult; |
| ret = hw->processAPI(QCAMERA_SM_EVT_STORE_METADATA_IN_BUFS, (void *)&enable); |
| if (ret == NO_ERROR) { |
| hw->waitAPIResult(QCAMERA_SM_EVT_STORE_METADATA_IN_BUFS, &apiResult); |
| ret = apiResult.status; |
| } |
| hw->unlockAPI(); |
| LOGD("X camera id %d", hw->getCameraId()); |
| |
| return ret; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : restart_start_preview |
| * |
| * DESCRIPTION: start preview as part of the restart preview |
| * |
| * PARAMETERS : |
| * @device : ptr to camera device struct |
| * |
| * RETURN : int32_t type of status |
| * NO_ERROR -- success |
| * none-zero failure code |
| *==========================================================================*/ |
| int QCamera2HardwareInterface::restart_start_preview(struct camera_device *device) |
| { |
| ATRACE_CALL(); |
| int ret = NO_ERROR; |
| QCamera2HardwareInterface *hw = |
| reinterpret_cast<QCamera2HardwareInterface *>(device->priv); |
| if (!hw) { |
| LOGE("NULL camera device"); |
| return BAD_VALUE; |
| } |
| LOGI("E camera id %d", hw->getCameraId()); |
| hw->lockAPI(); |
| qcamera_api_result_t apiResult; |
| |
| if (hw->getRelatedCamSyncInfo()->sync_control == CAM_SYNC_RELATED_SENSORS_ON) { |
| ret = hw->processAPI(QCAMERA_SM_EVT_RESTART_START_PREVIEW, NULL); |
| if (ret == NO_ERROR) { |
| hw->waitAPIResult(QCAMERA_SM_EVT_RESTART_START_PREVIEW, &apiResult); |
| ret = apiResult.status; |
| } |
| } else { |
| LOGE("This function is not supposed to be called in single-camera mode"); |
| ret = INVALID_OPERATION; |
| } |
| // Preview restart done, update the mPreviewRestartNeeded flag to false. |
| hw->mPreviewRestartNeeded = false; |
| hw->unlockAPI(); |
| LOGI("X camera id %d", hw->getCameraId()); |
| |
| return ret; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : restart_stop_preview |
| * |
| * DESCRIPTION: stop preview as part of the restart preview |
| * |
| * PARAMETERS : |
| * @device : ptr to camera device struct |
| * |
| * RETURN : int32_t type of status |
| * NO_ERROR -- success |
| * none-zero failure code |
| *==========================================================================*/ |
| int QCamera2HardwareInterface::restart_stop_preview(struct camera_device *device) |
| { |
| ATRACE_CALL(); |
| int ret = NO_ERROR; |
| QCamera2HardwareInterface *hw = |
| reinterpret_cast<QCamera2HardwareInterface *>(device->priv); |
| if (!hw) { |
| LOGE("NULL camera device"); |
| return BAD_VALUE; |
| } |
| LOGI("E camera id %d", hw->getCameraId()); |
| hw->lockAPI(); |
| qcamera_api_result_t apiResult; |
| |
| if (hw->getRelatedCamSyncInfo()->sync_control == CAM_SYNC_RELATED_SENSORS_ON) { |
| ret = hw->processAPI(QCAMERA_SM_EVT_RESTART_STOP_PREVIEW, NULL); |
| if (ret == NO_ERROR) { |
| hw->waitAPIResult(QCAMERA_SM_EVT_RESTART_STOP_PREVIEW, &apiResult); |
| ret = apiResult.status; |
| } |
| } else { |
| LOGE("This function is not supposed to be called in single-camera mode"); |
| ret = INVALID_OPERATION; |
| } |
| |
| hw->unlockAPI(); |
| LOGI("X camera id %d", hw->getCameraId()); |
| |
| return ret; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : pre_start_recording |
| * |
| * DESCRIPTION: prepare for the start recording |
| * |
| * PARAMETERS : |
| * @device : ptr to camera device struct |
| * |
| * RETURN : int32_t type of status |
| * NO_ERROR -- success |
| * none-zero failure code |
| *==========================================================================*/ |
| int QCamera2HardwareInterface::pre_start_recording(struct camera_device *device) |
| { |
| ATRACE_CALL(); |
| int ret = NO_ERROR; |
| QCamera2HardwareInterface *hw = |
| reinterpret_cast<QCamera2HardwareInterface *>(device->priv); |
| if (!hw) { |
| LOGE("NULL camera device"); |
| return BAD_VALUE; |
| } |
| LOGH("[KPI Perf]: E PROFILE_PRE_START_RECORDING camera id %d", |
| hw->getCameraId()); |
| hw->lockAPI(); |
| qcamera_api_result_t apiResult; |
| ret = hw->processAPI(QCAMERA_SM_EVT_PRE_START_RECORDING, NULL); |
| if (ret == NO_ERROR) { |
| hw->waitAPIResult(QCAMERA_SM_EVT_PRE_START_RECORDING, &apiResult); |
| ret = apiResult.status; |
| } |
| hw->unlockAPI(); |
| LOGH("[KPI Perf]: X"); |
| return ret; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : start_recording |
| * |
| * DESCRIPTION: start recording |
| * |
| * PARAMETERS : |
| * @device : ptr to camera device struct |
| * |
| * RETURN : int32_t type of status |
| * NO_ERROR -- success |
| * none-zero failure code |
| *==========================================================================*/ |
| int QCamera2HardwareInterface::start_recording(struct camera_device *device) |
| { |
| ATRACE_CALL(); |
| int ret = NO_ERROR; |
| QCamera2HardwareInterface *hw = |
| reinterpret_cast<QCamera2HardwareInterface *>(device->priv); |
| if (!hw) { |
| LOGE("NULL camera device"); |
| return BAD_VALUE; |
| } |
| LOGI("[KPI Perf]: E PROFILE_START_RECORDING camera id %d", |
| hw->getCameraId()); |
| // Give HWI control to call pre_start_recording in single camera mode. |
| // In dual-cam mode, this control belongs to muxer. |
| if (hw->getRelatedCamSyncInfo()->sync_control != CAM_SYNC_RELATED_SENSORS_ON) { |
| ret = pre_start_recording(device); |
| if (ret != NO_ERROR) { |
| LOGE("pre_start_recording failed with ret = %d", ret); |
| return ret; |
| } |
| } |
| |
| hw->lockAPI(); |
| qcamera_api_result_t apiResult; |
| ret = hw->processAPI(QCAMERA_SM_EVT_START_RECORDING, NULL); |
| if (ret == NO_ERROR) { |
| hw->waitAPIResult(QCAMERA_SM_EVT_START_RECORDING, &apiResult); |
| ret = apiResult.status; |
| } |
| hw->unlockAPI(); |
| hw->m_bRecordStarted = true; |
| LOGI("[KPI Perf]: X ret = %d", ret); |
| |
| return ret; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : stop_recording |
| * |
| * DESCRIPTION: stop recording |
| * |
| * PARAMETERS : |
| * @device : ptr to camera device struct |
| * |
| * RETURN : none |
| *==========================================================================*/ |
| void QCamera2HardwareInterface::stop_recording(struct camera_device *device) |
| { |
| ATRACE_CALL(); |
| QCamera2HardwareInterface *hw = |
| reinterpret_cast<QCamera2HardwareInterface *>(device->priv); |
| if (!hw) { |
| LOGE("NULL camera device"); |
| return; |
| } |
| LOGI("[KPI Perf]: E PROFILE_STOP_RECORDING camera id %d", |
| hw->getCameraId()); |
| |
| hw->lockAPI(); |
| qcamera_api_result_t apiResult; |
| int32_t ret = hw->processAPI(QCAMERA_SM_EVT_STOP_RECORDING, NULL); |
| if (ret == NO_ERROR) { |
| hw->waitAPIResult(QCAMERA_SM_EVT_STOP_RECORDING, &apiResult); |
| } |
| hw->unlockAPI(); |
| LOGI("[KPI Perf]: X ret = %d", ret); |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : recording_enabled |
| * |
| * DESCRIPTION: if recording is running |
| * |
| * PARAMETERS : |
| * @device : ptr to camera device struct |
| * |
| * RETURN : 1 -- running |
| * 0 -- not running |
| *==========================================================================*/ |
| int QCamera2HardwareInterface::recording_enabled(struct camera_device *device) |
| { |
| ATRACE_CALL(); |
| int ret = NO_ERROR; |
| QCamera2HardwareInterface *hw = |
| reinterpret_cast<QCamera2HardwareInterface *>(device->priv); |
| if (!hw) { |
| LOGE("NULL camera device"); |
| return BAD_VALUE; |
| } |
| LOGD("E camera id %d", hw->getCameraId()); |
| hw->lockAPI(); |
| qcamera_api_result_t apiResult; |
| ret = hw->processAPI(QCAMERA_SM_EVT_RECORDING_ENABLED, NULL); |
| if (ret == NO_ERROR) { |
| hw->waitAPIResult(QCAMERA_SM_EVT_RECORDING_ENABLED, &apiResult); |
| ret = apiResult.enabled; |
| } |
| hw->unlockAPI(); |
| LOGD("X camera id %d", hw->getCameraId()); |
| |
| return ret; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : release_recording_frame |
| * |
| * DESCRIPTION: return recording frame back |
| * |
| * PARAMETERS : |
| * @device : ptr to camera device struct |
| * @opaque : ptr to frame to be returned |
| * |
| * RETURN : none |
| *==========================================================================*/ |
| void QCamera2HardwareInterface::release_recording_frame( |
| struct camera_device *device, const void *opaque) |
| { |
| ATRACE_CALL(); |
| int32_t ret = NO_ERROR; |
| QCamera2HardwareInterface *hw = |
| reinterpret_cast<QCamera2HardwareInterface *>(device->priv); |
| if (!hw) { |
| LOGE("NULL camera device"); |
| return; |
| } |
| if (!opaque) { |
| LOGE("Error!! Frame info is NULL"); |
| return; |
| } |
| LOGD("E camera id %d", hw->getCameraId()); |
| |
| hw->lockAPI(); |
| qcamera_api_result_t apiResult; |
| ret = hw->processAPI(QCAMERA_SM_EVT_RELEASE_RECORIDNG_FRAME, (void *)opaque); |
| if (ret == NO_ERROR) { |
| hw->waitAPIResult(QCAMERA_SM_EVT_RELEASE_RECORIDNG_FRAME, &apiResult); |
| } |
| hw->unlockAPI(); |
| LOGD("X camera id %d", hw->getCameraId()); |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : auto_focus |
| * |
| * DESCRIPTION: start auto focus |
| * |
| * PARAMETERS : |
| * @device : ptr to camera device struct |
| * |
| * RETURN : int32_t type of status |
| * NO_ERROR -- success |
| * none-zero failure code |
| *==========================================================================*/ |
| int QCamera2HardwareInterface::auto_focus(struct camera_device *device) |
| { |
| KPI_ATRACE_INT("Camera:AutoFocus", 1); |
| int ret = NO_ERROR; |
| QCamera2HardwareInterface *hw = |
| reinterpret_cast<QCamera2HardwareInterface *>(device->priv); |
| if (!hw) { |
| LOGE("NULL camera device"); |
| return BAD_VALUE; |
| } |
| LOGH("[KPI Perf] : E PROFILE_AUTO_FOCUS camera id %d", |
| hw->getCameraId()); |
| hw->lockAPI(); |
| qcamera_api_result_t apiResult; |
| ret = hw->processAPI(QCAMERA_SM_EVT_START_AUTO_FOCUS, NULL); |
| if (ret == NO_ERROR) { |
| hw->waitAPIResult(QCAMERA_SM_EVT_START_AUTO_FOCUS, &apiResult); |
| ret = apiResult.status; |
| } |
| hw->unlockAPI(); |
| LOGH("[KPI Perf] : X ret = %d", ret); |
| |
| return ret; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : cancel_auto_focus |
| * |
| * DESCRIPTION: cancel auto focus |
| * |
| * PARAMETERS : |
| * @device : ptr to camera device struct |
| * |
| * RETURN : int32_t type of status |
| * NO_ERROR -- success |
| * none-zero failure code |
| *==========================================================================*/ |
| int QCamera2HardwareInterface::cancel_auto_focus(struct camera_device *device) |
| { |
| ATRACE_CALL(); |
| int ret = NO_ERROR; |
| QCamera2HardwareInterface *hw = |
| reinterpret_cast<QCamera2HardwareInterface *>(device->priv); |
| if (!hw) { |
| LOGE("NULL camera device"); |
| return BAD_VALUE; |
| } |
| LOGH("[KPI Perf] : E PROFILE_CANCEL_AUTO_FOCUS camera id %d", |
| hw->getCameraId()); |
| hw->lockAPI(); |
| qcamera_api_result_t apiResult; |
| ret = hw->processAPI(QCAMERA_SM_EVT_STOP_AUTO_FOCUS, NULL); |
| if (ret == NO_ERROR) { |
| hw->waitAPIResult(QCAMERA_SM_EVT_STOP_AUTO_FOCUS, &apiResult); |
| ret = apiResult.status; |
| } |
| hw->unlockAPI(); |
| LOGH("[KPI Perf] : X ret = %d", ret); |
| return ret; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : pre_take_picture |
| * |
| * DESCRIPTION: pre take picture, restart preview if necessary. |
| * |
| * PARAMETERS : |
| * @device : ptr to camera device struct |
| * |
| * RETURN : int32_t type of status |
| * NO_ERROR -- success |
| * none-zero failure code |
| *==========================================================================*/ |
| int QCamera2HardwareInterface::pre_take_picture(struct camera_device *device) |
| { |
| ATRACE_CALL(); |
| int ret = NO_ERROR; |
| QCamera2HardwareInterface *hw = |
| reinterpret_cast<QCamera2HardwareInterface *>(device->priv); |
| if (!hw) { |
| LOGE("NULL camera device"); |
| return BAD_VALUE; |
| } |
| LOGH("[KPI Perf]: E PROFILE_PRE_TAKE_PICTURE camera id %d", |
| hw->getCameraId()); |
| hw->lockAPI(); |
| qcamera_api_result_t apiResult; |
| ret = hw->processAPI(QCAMERA_SM_EVT_PRE_TAKE_PICTURE, NULL); |
| if (ret == NO_ERROR) { |
| hw->waitAPIResult(QCAMERA_SM_EVT_PRE_TAKE_PICTURE, &apiResult); |
| ret = apiResult.status; |
| } |
| hw->unlockAPI(); |
| LOGH("[KPI Perf]: X"); |
| return ret; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : take_picture |
| * |
| * DESCRIPTION: take picture |
| * |
| * PARAMETERS : |
| * @device : ptr to camera device struct |
| * |
| * RETURN : int32_t type of status |
| * NO_ERROR -- success |
| * none-zero failure code |
| *==========================================================================*/ |
| int QCamera2HardwareInterface::take_picture(struct camera_device *device) |
| { |
| KPI_ATRACE_CALL(); |
| int ret = NO_ERROR; |
| QCamera2HardwareInterface *hw = |
| reinterpret_cast<QCamera2HardwareInterface *>(device->priv); |
| if (!hw) { |
| LOGE("NULL camera device"); |
| return BAD_VALUE; |
| } |
| LOGI("[KPI Perf]: E PROFILE_TAKE_PICTURE camera id %d", |
| hw->getCameraId()); |
| if (!hw->mLongshotEnabled) { |
| hw->m_perfLock.lock_acq(); |
| } |
| qcamera_api_result_t apiResult; |
| |
| /** Added support for Retro-active Frames: |
| * takePicture() is called before preparing Snapshot to indicate the |
| * mm-camera-channel to pick up legacy frames even |
| * before LED estimation is triggered. |
| */ |
| |
| LOGH("isLiveSnap %d, isZSL %d, isHDR %d longshot = %d", |
| hw->isLiveSnapshot(), hw->isZSLMode(), hw->isHDRMode(), |
| hw->isLongshotEnabled()); |
| |
| // Check for Retro-active Frames |
| if ((hw->mParameters.getNumOfRetroSnapshots() > 0) && |
| !hw->isLiveSnapshot() && hw->isZSLMode() && |
| !hw->isHDRMode() && !hw->isLongshotEnabled()) { |
| // Set Retro Picture Mode |
| hw->setRetroPicture(1); |
| hw->m_bLedAfAecLock = 0; |
| LOGL("Retro Enabled"); |
| |
| // Give HWI control to call pre_take_picture in single camera mode. |
| // In dual-cam mode, this control belongs to muxer. |
| if (hw->getRelatedCamSyncInfo()->sync_control != CAM_SYNC_RELATED_SENSORS_ON) { |
| ret = pre_take_picture(device); |
| if (ret != NO_ERROR) { |
| LOGE("pre_take_picture failed with ret = %d",ret); |
| return ret; |
| } |
| } |
| |
| /* Call take Picture for total number of snapshots required. |
| This includes the number of retro frames and normal frames */ |
| hw->lockAPI(); |
| ret = hw->processAPI(QCAMERA_SM_EVT_TAKE_PICTURE, NULL); |
| if (ret == NO_ERROR) { |
| // Wait for retro frames, before calling prepare snapshot |
| LOGD("Wait for Retro frames to be done"); |
| hw->waitAPIResult(QCAMERA_SM_EVT_TAKE_PICTURE, &apiResult); |
| ret = apiResult.status; |
| } |
| /* Unlock API since it is acquired in prepare snapshot seperately */ |
| hw->unlockAPI(); |
| |
| /* Prepare snapshot in case LED needs to be flashed */ |
| LOGD("Start Prepare Snapshot"); |
| ret = hw->prepare_snapshot(device); |
| } |
| else { |
| hw->setRetroPicture(0); |
| // Check if prepare snapshot is done |
| if (!hw->mPrepSnapRun) { |
| // Ignore the status from prepare_snapshot |
| hw->prepare_snapshot(device); |
| } |
| |
| // Give HWI control to call pre_take_picture in single camera mode. |
| // In dual-cam mode, this control belongs to muxer. |
| if (hw->getRelatedCamSyncInfo()->sync_control != CAM_SYNC_RELATED_SENSORS_ON) { |
| ret = pre_take_picture(device); |
| if (ret != NO_ERROR) { |
| LOGE("pre_take_picture failed with ret = %d",ret); |
| return ret; |
| } |
| } |
| |
| // Regardless what the result value for prepare_snapshot, |
| // go ahead with capture anyway. Just like the way autofocus |
| // is handled in capture case |
| /* capture */ |
| LOGL("Capturing normal frames"); |
| hw->lockAPI(); |
| ret = hw->processAPI(QCAMERA_SM_EVT_TAKE_PICTURE, NULL); |
| if (ret == NO_ERROR) { |
| hw->waitAPIResult(QCAMERA_SM_EVT_TAKE_PICTURE, &apiResult); |
| ret = apiResult.status; |
| } |
| hw->unlockAPI(); |
| if (!hw->isLongshotEnabled()){ |
| // For longshot mode, we prepare snapshot only once |
| hw->mPrepSnapRun = false; |
| } |
| } |
| LOGI("[KPI Perf]: X ret = %d", ret); |
| return ret; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : cancel_picture |
| * |
| * DESCRIPTION: cancel current take picture request |
| * |
| * PARAMETERS : |
| * @device : ptr to camera device struct |
| * |
| * RETURN : int32_t type of status |
| * NO_ERROR -- success |
| * none-zero failure code |
| *==========================================================================*/ |
| int QCamera2HardwareInterface::cancel_picture(struct camera_device *device) |
| { |
| ATRACE_CALL(); |
| int ret = NO_ERROR; |
| QCamera2HardwareInterface *hw = |
| reinterpret_cast<QCamera2HardwareInterface *>(device->priv); |
| if (!hw) { |
| LOGE("NULL camera device"); |
| return BAD_VALUE; |
| } |
| LOGI("[KPI Perf]: E PROFILE_CANCEL_PICTURE camera id %d", |
| hw->getCameraId()); |
| hw->lockAPI(); |
| qcamera_api_result_t apiResult; |
| ret = hw->processAPI(QCAMERA_SM_EVT_CANCEL_PICTURE, NULL); |
| if (ret == NO_ERROR) { |
| hw->waitAPIResult(QCAMERA_SM_EVT_CANCEL_PICTURE, &apiResult); |
| ret = apiResult.status; |
| } |
| hw->unlockAPI(); |
| LOGI("[KPI Perf]: X camera id %d ret = %d", hw->getCameraId(), ret); |
| |
| return ret; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : set_parameters |
| * |
| * DESCRIPTION: set camera parameters |
| * |
| * PARAMETERS : |
| * @device : ptr to camera device struct |
| * @parms : string of packed parameters |
| * |
| * RETURN : int32_t type of status |
| * NO_ERROR -- success |
| * none-zero failure code |
| *==========================================================================*/ |
| int QCamera2HardwareInterface::set_parameters(struct camera_device *device, |
| const char *parms) |
| { |
| ATRACE_CALL(); |
| int ret = NO_ERROR; |
| QCamera2HardwareInterface *hw = |
| reinterpret_cast<QCamera2HardwareInterface *>(device->priv); |
| if (!hw) { |
| LOGE("NULL camera device"); |
| return BAD_VALUE; |
| } |
| LOGD("E camera id %d", hw->getCameraId()); |
| hw->lockAPI(); |
| qcamera_api_result_t apiResult; |
| ret = hw->processAPI(QCAMERA_SM_EVT_SET_PARAMS, (void *)parms); |
| if (ret == NO_ERROR) { |
| hw->waitAPIResult(QCAMERA_SM_EVT_SET_PARAMS, &apiResult); |
| ret = apiResult.status; |
| } |
| |
| // Give HWI control to restart (if necessary) after set params |
| // in single camera mode. In dual-cam mode, this control belongs to muxer. |
| if (hw->getRelatedCamSyncInfo()->sync_control != CAM_SYNC_RELATED_SENSORS_ON) { |
| if ((ret == NO_ERROR) && hw->getNeedRestart()) { |
| LOGD("stopping after param change"); |
| ret = hw->processAPI(QCAMERA_SM_EVT_SET_PARAMS_STOP, NULL); |
| if (ret == NO_ERROR) { |
| hw->waitAPIResult(QCAMERA_SM_EVT_SET_PARAMS_STOP, &apiResult); |
| ret = apiResult.status; |
| } |
| } |
| |
| if (ret == NO_ERROR) { |
| LOGD("committing param change"); |
| ret = hw->processAPI(QCAMERA_SM_EVT_SET_PARAMS_COMMIT, NULL); |
| if (ret == NO_ERROR) { |
| hw->waitAPIResult(QCAMERA_SM_EVT_SET_PARAMS_COMMIT, &apiResult); |
| ret = apiResult.status; |
| } |
| } |
| |
| if ((ret == NO_ERROR) && hw->getNeedRestart()) { |
| LOGD("restarting after param change"); |
| ret = hw->processAPI(QCAMERA_SM_EVT_SET_PARAMS_RESTART, NULL); |
| if (ret == NO_ERROR) { |
| hw->waitAPIResult(QCAMERA_SM_EVT_SET_PARAMS_RESTART, &apiResult); |
| ret = apiResult.status; |
| } |
| } |
| } |
| |
| hw->unlockAPI(); |
| LOGD("X camera id %d ret %d", hw->getCameraId(), ret); |
| |
| return ret; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : stop_after_set_params |
| * |
| * DESCRIPTION: stop after a set param call, if necessary |
| * |
| * PARAMETERS : |
| * @device : ptr to camera device struct |
| * |
| * RETURN : int32_t type of status |
| * NO_ERROR -- success |
| * none-zero failure code |
| *==========================================================================*/ |
| int QCamera2HardwareInterface::stop_after_set_params(struct camera_device *device) |
| { |
| ATRACE_CALL(); |
| int ret = NO_ERROR; |
| QCamera2HardwareInterface *hw = |
| reinterpret_cast<QCamera2HardwareInterface *>(device->priv); |
| if (!hw) { |
| LOGE("NULL camera device"); |
| return BAD_VALUE; |
| } |
| LOGD("E camera id %d", hw->getCameraId()); |
| hw->lockAPI(); |
| qcamera_api_result_t apiResult; |
| |
| if (hw->getRelatedCamSyncInfo()->sync_control == CAM_SYNC_RELATED_SENSORS_ON) { |
| ret = hw->processAPI(QCAMERA_SM_EVT_SET_PARAMS_STOP, NULL); |
| if (ret == NO_ERROR) { |
| hw->waitAPIResult(QCAMERA_SM_EVT_SET_PARAMS_STOP, &apiResult); |
| ret = apiResult.status; |
| } |
| } else { |
| LOGE("is not supposed to be called in single-camera mode"); |
| ret = INVALID_OPERATION; |
| } |
| |
| hw->unlockAPI(); |
| LOGD("X camera id %d", hw->getCameraId()); |
| |
| return ret; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : commit_params |
| * |
| * DESCRIPTION: commit after a set param call |
| * |
| * PARAMETERS : |
| * @device : ptr to camera device struct |
| * |
| * RETURN : int32_t type of status |
| * NO_ERROR -- success |
| * none-zero failure code |
| *==========================================================================*/ |
| int QCamera2HardwareInterface::commit_params(struct camera_device *device) |
| { |
| ATRACE_CALL(); |
| int ret = NO_ERROR; |
| QCamera2HardwareInterface *hw = |
| reinterpret_cast<QCamera2HardwareInterface *>(device->priv); |
| if (!hw) { |
| LOGE("NULL camera device"); |
| return BAD_VALUE; |
| } |
| LOGD("E camera id %d", hw->getCameraId()); |
| hw->lockAPI(); |
| qcamera_api_result_t apiResult; |
| |
| if (hw->getRelatedCamSyncInfo()->sync_control == CAM_SYNC_RELATED_SENSORS_ON) { |
| ret = hw->processAPI(QCAMERA_SM_EVT_SET_PARAMS_COMMIT, NULL); |
| if (ret == NO_ERROR) { |
| hw->waitAPIResult(QCAMERA_SM_EVT_SET_PARAMS_COMMIT, &apiResult); |
| ret = apiResult.status; |
| } |
| } else { |
| LOGE("is not supposed to be called in single-camera mode"); |
| ret = INVALID_OPERATION; |
| } |
| |
| hw->unlockAPI(); |
| LOGD("X camera id %d", hw->getCameraId()); |
| |
| return ret; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : restart_after_set_params |
| * |
| * DESCRIPTION: restart after a set param call, if necessary |
| * |
| * PARAMETERS : |
| * @device : ptr to camera device struct |
| * |
| * RETURN : int32_t type of status |
| * NO_ERROR -- success |
| * none-zero failure code |
| *==========================================================================*/ |
| int QCamera2HardwareInterface::restart_after_set_params(struct camera_device *device) |
| { |
| ATRACE_CALL(); |
| int ret = NO_ERROR; |
| QCamera2HardwareInterface *hw = |
| reinterpret_cast<QCamera2HardwareInterface *>(device->priv); |
| if (!hw) { |
| LOGE("NULL camera device"); |
| return BAD_VALUE; |
| } |
| LOGD("E camera id %d", hw->getCameraId()); |
| hw->lockAPI(); |
| qcamera_api_result_t apiResult; |
| |
| if (hw->getRelatedCamSyncInfo()->sync_control == CAM_SYNC_RELATED_SENSORS_ON) { |
| ret = hw->processAPI(QCAMERA_SM_EVT_SET_PARAMS_RESTART, NULL); |
| if (ret == NO_ERROR) { |
| hw->waitAPIResult(QCAMERA_SM_EVT_SET_PARAMS_RESTART, &apiResult); |
| ret = apiResult.status; |
| } |
| } else { |
| LOGE("is not supposed to be called in single-camera mode"); |
| ret = INVALID_OPERATION; |
| } |
| |
| hw->unlockAPI(); |
| LOGD("X camera id %d", hw->getCameraId()); |
| return ret; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : get_parameters |
| * |
| * DESCRIPTION: query camera parameters |
| * |
| * PARAMETERS : |
| * @device : ptr to camera device struct |
| * |
| * RETURN : packed parameters in a string |
| *==========================================================================*/ |
| char* QCamera2HardwareInterface::get_parameters(struct camera_device *device) |
| { |
| ATRACE_CALL(); |
| char *ret = NULL; |
| QCamera2HardwareInterface *hw = |
| reinterpret_cast<QCamera2HardwareInterface *>(device->priv); |
| if (!hw) { |
| LOGE("NULL camera device"); |
| return NULL; |
| } |
| LOGD("E camera id %d", hw->getCameraId()); |
| hw->lockAPI(); |
| qcamera_api_result_t apiResult; |
| int32_t rc = hw->processAPI(QCAMERA_SM_EVT_GET_PARAMS, NULL); |
| if (rc == NO_ERROR) { |
| hw->waitAPIResult(QCAMERA_SM_EVT_GET_PARAMS, &apiResult); |
| ret = apiResult.params; |
| } |
| hw->unlockAPI(); |
| LOGD("E camera id %d", hw->getCameraId()); |
| |
| return ret; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : put_parameters |
| * |
| * DESCRIPTION: return camera parameters string back to HAL |
| * |
| * PARAMETERS : |
| * @device : ptr to camera device struct |
| * @parm : ptr to parameter string to be returned |
| * |
| * RETURN : none |
| *==========================================================================*/ |
| void QCamera2HardwareInterface::put_parameters(struct camera_device *device, |
| char *parm) |
| { |
| ATRACE_CALL(); |
| QCamera2HardwareInterface *hw = |
| reinterpret_cast<QCamera2HardwareInterface *>(device->priv); |
| if (!hw) { |
| LOGE("NULL camera device"); |
| return; |
| } |
| LOGD("E camera id %d", hw->getCameraId()); |
| hw->lockAPI(); |
| qcamera_api_result_t apiResult; |
| int32_t ret = hw->processAPI(QCAMERA_SM_EVT_PUT_PARAMS, (void *)parm); |
| if (ret == NO_ERROR) { |
| hw->waitAPIResult(QCAMERA_SM_EVT_PUT_PARAMS, &apiResult); |
| } |
| hw->unlockAPI(); |
| LOGD("E camera id %d", hw->getCameraId()); |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : send_command |
| * |
| * DESCRIPTION: command to be executed |
| * |
| * PARAMETERS : |
| * @device : ptr to camera device struct |
| * @cmd : cmd to be executed |
| * @arg1 : ptr to optional argument1 |
| * @arg2 : ptr to optional argument2 |
| * |
| * RETURN : int32_t type of status |
| * NO_ERROR -- success |
| * none-zero failure code |
| *==========================================================================*/ |
| int QCamera2HardwareInterface::send_command(struct camera_device *device, |
| int32_t cmd, |
| int32_t arg1, |
| int32_t arg2) |
| { |
| ATRACE_CALL(); |
| int ret = NO_ERROR; |
| QCamera2HardwareInterface *hw = |
| reinterpret_cast<QCamera2HardwareInterface *>(device->priv); |
| if (!hw) { |
| LOGE("NULL camera device"); |
| return BAD_VALUE; |
| } |
| LOGD("E camera id %d", hw->getCameraId()); |
| |
| qcamera_sm_evt_command_payload_t payload; |
| memset(&payload, 0, sizeof(qcamera_sm_evt_command_payload_t)); |
| payload.cmd = cmd; |
| payload.arg1 = arg1; |
| payload.arg2 = arg2; |
| hw->lockAPI(); |
| qcamera_api_result_t apiResult; |
| ret = hw->processAPI(QCAMERA_SM_EVT_SEND_COMMAND, (void *)&payload); |
| if (ret == NO_ERROR) { |
| hw->waitAPIResult(QCAMERA_SM_EVT_SEND_COMMAND, &apiResult); |
| ret = apiResult.status; |
| } |
| hw->unlockAPI(); |
| LOGD("E camera id %d", hw->getCameraId()); |
| |
| return ret; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : send_command_restart |
| * |
| * DESCRIPTION: restart if necessary after a send_command |
| * |
| * PARAMETERS : |
| * @device : ptr to camera device struct |
| * @cmd : cmd to be executed |
| * @arg1 : ptr to optional argument1 |
| * @arg2 : ptr to optional argument2 |
| * |
| * RETURN : int32_t type of status |
| * NO_ERROR -- success |
| * none-zero failure code |
| *==========================================================================*/ |
| int QCamera2HardwareInterface::send_command_restart(struct camera_device *device, |
| int32_t cmd, |
| int32_t arg1, |
| int32_t arg2) |
| { |
| ATRACE_CALL(); |
| int ret = NO_ERROR; |
| QCamera2HardwareInterface *hw = |
| reinterpret_cast<QCamera2HardwareInterface *>(device->priv); |
| if (!hw) { |
| LOGE("NULL camera device"); |
| return BAD_VALUE; |
| } |
| |
| qcamera_sm_evt_command_payload_t payload; |
| memset(&payload, 0, sizeof(qcamera_sm_evt_command_payload_t)); |
| payload.cmd = cmd; |
| payload.arg1 = arg1; |
| payload.arg2 = arg2; |
| hw->lockAPI(); |
| qcamera_api_result_t apiResult; |
| ret = hw->processAPI(QCAMERA_SM_EVT_SEND_COMMAND_RESTART, (void *)&payload); |
| if (ret == NO_ERROR) { |
| hw->waitAPIResult(QCAMERA_SM_EVT_SEND_COMMAND_RESTART, &apiResult); |
| ret = apiResult.status; |
| } |
| hw->unlockAPI(); |
| LOGD("E camera id %d", hw->getCameraId()); |
| |
| return ret; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : release |
| * |
| * DESCRIPTION: release camera resource |
| * |
| * PARAMETERS : |
| * @device : ptr to camera device struct |
| * |
| * RETURN : none |
| *==========================================================================*/ |
| void QCamera2HardwareInterface::release(struct camera_device *device) |
| { |
| ATRACE_CALL(); |
| QCamera2HardwareInterface *hw = |
| reinterpret_cast<QCamera2HardwareInterface *>(device->priv); |
| if (!hw) { |
| LOGE("NULL camera device"); |
| return; |
| } |
| LOGD("E camera id %d", hw->getCameraId()); |
| hw->lockAPI(); |
| qcamera_api_result_t apiResult; |
| int32_t ret = hw->processAPI(QCAMERA_SM_EVT_RELEASE, NULL); |
| if (ret == NO_ERROR) { |
| hw->waitAPIResult(QCAMERA_SM_EVT_RELEASE, &apiResult); |
| } |
| hw->unlockAPI(); |
| LOGD("E camera id %d", hw->getCameraId()); |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : dump |
| * |
| * DESCRIPTION: dump camera status |
| * |
| * PARAMETERS : |
| * @device : ptr to camera device struct |
| * @fd : fd for status to be dumped to |
| * |
| * RETURN : int32_t type of status |
| * NO_ERROR -- success |
| * none-zero failure code |
| *==========================================================================*/ |
| int QCamera2HardwareInterface::dump(struct camera_device *device, int fd) |
| { |
| int ret = NO_ERROR; |
| |
| //Log level property is read when "adb shell dumpsys media.camera" is |
| //called so that the log level can be controlled without restarting |
| //media server |
| getLogLevel(); |
| QCamera2HardwareInterface *hw = |
| reinterpret_cast<QCamera2HardwareInterface *>(device->priv); |
| if (!hw) { |
| LOGE("NULL camera device"); |
| return BAD_VALUE; |
| } |
| LOGD("E camera id %d", hw->getCameraId()); |
| hw->lockAPI(); |
| qcamera_api_result_t apiResult; |
| ret = hw->processAPI(QCAMERA_SM_EVT_DUMP, (void *)&fd); |
| if (ret == NO_ERROR) { |
| hw->waitAPIResult(QCAMERA_SM_EVT_DUMP, &apiResult); |
| ret = apiResult.status; |
| } |
| hw->unlockAPI(); |
| LOGD("E camera id %d", hw->getCameraId()); |
| |
| return ret; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : close_camera_device |
| * |
| * DESCRIPTION: close camera device |
| * |
| * PARAMETERS : |
| * @device : ptr to camera device struct |
| * |
| * RETURN : int32_t type of status |
| * NO_ERROR -- success |
| * none-zero failure code |
| *==========================================================================*/ |
| int QCamera2HardwareInterface::close_camera_device(hw_device_t *hw_dev) |
| { |
| KPI_ATRACE_CALL(); |
| int ret = NO_ERROR; |
| |
| QCamera2HardwareInterface *hw = |
| reinterpret_cast<QCamera2HardwareInterface *>( |
| reinterpret_cast<camera_device_t *>(hw_dev)->priv); |
| if (!hw) { |
| LOGE("NULL camera device"); |
| return BAD_VALUE; |
| } |
| LOGI("[KPI Perf]: E camera id %d", hw->getCameraId()); |
| delete hw; |
| LOGI("[KPI Perf]: X"); |
| return ret; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : register_face_image |
| * |
| * DESCRIPTION: register a face image into imaging lib for face authenticatio/ |
| * face recognition |
| * |
| * PARAMETERS : |
| * @device : ptr to camera device struct |
| * @img_ptr : ptr to image buffer |
| * @config : ptr to config about input image, i.e., format, dimension, and etc. |
| * |
| * RETURN : >=0 unique ID of face registerd. |
| * <0 failure. |
| *==========================================================================*/ |
| int QCamera2HardwareInterface::register_face_image(struct camera_device *device, |
| void *img_ptr, |
| cam_pp_offline_src_config_t *config) |
| { |
| ATRACE_CALL(); |
| int ret = NO_ERROR; |
| QCamera2HardwareInterface *hw = |
| reinterpret_cast<QCamera2HardwareInterface *>(device->priv); |
| if (!hw) { |
| LOGE("NULL camera device"); |
| return BAD_VALUE; |
| } |
| LOGD("E camera id %d", hw->getCameraId()); |
| qcamera_sm_evt_reg_face_payload_t payload; |
| memset(&payload, 0, sizeof(qcamera_sm_evt_reg_face_payload_t)); |
| payload.img_ptr = img_ptr; |
| payload.config = config; |
| hw->lockAPI(); |
| qcamera_api_result_t apiResult; |
| ret = hw->processAPI(QCAMERA_SM_EVT_REG_FACE_IMAGE, (void *)&payload); |
| if (ret == NO_ERROR) { |
| hw->waitAPIResult(QCAMERA_SM_EVT_REG_FACE_IMAGE, &apiResult); |
| ret = apiResult.handle; |
| } |
| hw->unlockAPI(); |
| LOGD("E camera id %d", hw->getCameraId()); |
| |
| return ret; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : prepare_snapshot |
| * |
| * DESCRIPTION: prepares hardware for snapshot |
| * |
| * PARAMETERS : |
| * @device : ptr to camera device struct |
| * |
| * RETURN : int32_t type of status |
| * NO_ERROR -- success |
| * none-zero failure code |
| *==========================================================================*/ |
| int QCamera2HardwareInterface::prepare_snapshot(struct camera_device *device) |
| { |
| ATRACE_CALL(); |
| int ret = NO_ERROR; |
| QCamera2HardwareInterface *hw = |
| reinterpret_cast<QCamera2HardwareInterface *>(device->priv); |
| if (!hw) { |
| LOGE("NULL camera device"); |
| return BAD_VALUE; |
| } |
| if (hw->isLongshotEnabled() && hw->mPrepSnapRun == true) { |
| // For longshot mode, we prepare snapshot only once |
| LOGH("prepare snapshot only once "); |
| return NO_ERROR; |
| } |
| LOGH("[KPI Perf]: E PROFILE_PREPARE_SNAPSHOT camera id %d", |
| hw->getCameraId()); |
| hw->lockAPI(); |
| qcamera_api_result_t apiResult; |
| |
| /* Prepare snapshot in case LED needs to be flashed */ |
| if (hw->mFlashNeeded || hw->mParameters.isChromaFlashEnabled()) { |
| /* Prepare snapshot in case LED needs to be flashed */ |
| ret = hw->processAPI(QCAMERA_SM_EVT_PREPARE_SNAPSHOT, NULL); |
| if (ret == NO_ERROR) { |
| hw->waitAPIResult(QCAMERA_SM_EVT_PREPARE_SNAPSHOT, &apiResult); |
| ret = apiResult.status; |
| } |
| hw->mPrepSnapRun = true; |
| } |
| hw->unlockAPI(); |
| LOGH("[KPI Perf]: X, ret: %d", ret); |
| return ret; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : QCamera2HardwareInterface |
| * |
| * DESCRIPTION: constructor of QCamera2HardwareInterface |
| * |
| * PARAMETERS : |
| * @cameraId : camera ID |
| * |
| * RETURN : none |
| *==========================================================================*/ |
| QCamera2HardwareInterface::QCamera2HardwareInterface(uint32_t cameraId) |
| : mCameraId(cameraId), |
| mCameraHandle(NULL), |
| mCameraOpened(false), |
| mDualCamera(false), |
| m_bRelCamCalibValid(false), |
| mPreviewWindow(NULL), |
| mMsgEnabled(0), |
| mStoreMetaDataInFrame(0), |
| mJpegCb(NULL), |
| mCallbackCookie(NULL), |
| mJpegCallbackCookie(NULL), |
| m_bMpoEnabled(TRUE), |
| m_stateMachine(this), |
| m_smThreadActive(true), |
| m_postprocessor(this), |
| m_thermalAdapter(QCameraThermalAdapter::getInstance()), |
| m_cbNotifier(this), |
| m_bPreviewStarted(false), |
| m_bRecordStarted(false), |
| m_currentFocusState(CAM_AF_STATE_INACTIVE), |
| mDumpFrmCnt(0U), |
| mDumpSkipCnt(0U), |
| mThermalLevel(QCAMERA_THERMAL_NO_ADJUSTMENT), |
| mActiveAF(false), |
| m_HDRSceneEnabled(false), |
| mLongshotEnabled(false), |
| mLiveSnapshotThread(0), |
| mIntPicThread(0), |
| mFlashNeeded(false), |
| mFlashConfigured(false), |
| mDeviceRotation(0U), |
| mCaptureRotation(0U), |
| mJpegExifRotation(0U), |
| mUseJpegExifRotation(false), |
| mIs3ALocked(false), |
| mPrepSnapRun(false), |
| mZoomLevel(0), |
| mPreviewRestartNeeded(false), |
| mVFrameCount(0), |
| mVLastFrameCount(0), |
| mVLastFpsTime(0), |
| mVFps(0), |
| mPFrameCount(0), |
| mPLastFrameCount(0), |
| mPLastFpsTime(0), |
| mPFps(0), |
| mLowLightConfigured(false), |
| mInstantAecFrameCount(0), |
| m_bIntJpegEvtPending(false), |
| m_bIntRawEvtPending(false), |
| mReprocJob(0), |
| mJpegJob(0), |
| mMetadataAllocJob(0), |
| mInitPProcJob(0), |
| mParamAllocJob(0), |
| mParamInitJob(0), |
| mOutputCount(0), |
| mInputCount(0), |
| mAdvancedCaptureConfigured(false), |
| mHDRBracketingEnabled(false), |
| mNumPreviewFaces(-1), |
| mJpegClientHandle(0), |
| mJpegHandleOwner(false), |
| mMetadataMem(NULL), |
| mCACDoneReceived(false), |
| m_bNeedRestart(false), |
| mBootToMonoTimestampOffset(0), |
| bDepthAFCallbacks(true) |
| { |
| #ifdef TARGET_TS_MAKEUP |
| memset(&mFaceRect, -1, sizeof(mFaceRect)); |
| #endif |
| getLogLevel(); |
| ATRACE_CALL(); |
| mCameraDevice.common.tag = HARDWARE_DEVICE_TAG; |
| mCameraDevice.common.version = HARDWARE_DEVICE_API_VERSION(1, 0); |
| mCameraDevice.common.close = close_camera_device; |
| mCameraDevice.ops = &mCameraOps; |
| mCameraDevice.priv = this; |
| |
| mDualCamera = is_dual_camera_by_idx(cameraId); |
| |
| pthread_mutex_init(&m_lock, NULL); |
| pthread_cond_init(&m_cond, NULL); |
| |
| m_apiResultList = NULL; |
| |
| pthread_mutex_init(&m_evtLock, NULL); |
| pthread_cond_init(&m_evtCond, NULL); |
| memset(&m_evtResult, 0, sizeof(qcamera_api_result_t)); |
| |
| |
| pthread_mutex_init(&m_int_lock, NULL); |
| pthread_cond_init(&m_int_cond, NULL); |
| |
| memset(m_channels, 0, sizeof(m_channels)); |
| |
| memset(&mExifParams, 0, sizeof(mm_jpeg_exif_params_t)); |
| |
| memset(m_BackendFileName, 0, QCAMERA_MAX_FILEPATH_LENGTH); |
| |
| memset(mDefOngoingJobs, 0, sizeof(mDefOngoingJobs)); |
| memset(&mJpegMetadata, 0, sizeof(mJpegMetadata)); |
| memset(&mJpegHandle, 0, sizeof(mJpegHandle)); |
| memset(&mJpegMpoHandle, 0, sizeof(mJpegMpoHandle)); |
| |
| mDeferredWorkThread.launch(deferredWorkRoutine, this); |
| mDeferredWorkThread.sendCmd(CAMERA_CMD_TYPE_START_DATA_PROC, FALSE, FALSE); |
| m_perfLock.lock_init(); |
| |
| pthread_mutex_init(&mGrallocLock, NULL); |
| mEnqueuedBuffers = 0; |
| mFrameSkipStart = 0; |
| mFrameSkipEnd = 0; |
| mLastPreviewFrameID = 0; |
| |
| //Load and read GPU library. |
| lib_surface_utils = NULL; |
| LINK_get_surface_pixel_alignment = NULL; |
| mSurfaceStridePadding = CAM_PAD_TO_32; |
| lib_surface_utils = dlopen("libadreno_utils.so", RTLD_NOW); |
| if (lib_surface_utils) { |
| *(void **)&LINK_get_surface_pixel_alignment = |
| dlsym(lib_surface_utils, "get_gpu_pixel_alignment"); |
| if (LINK_get_surface_pixel_alignment) { |
| mSurfaceStridePadding = LINK_get_surface_pixel_alignment(); |
| } |
| dlclose(lib_surface_utils); |
| } |
| prev_zoomLevel = 0; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : ~QCamera2HardwareInterface |
| * |
| * DESCRIPTION: destructor of QCamera2HardwareInterface |
| * |
| * PARAMETERS : none |
| * |
| * RETURN : none |
| *==========================================================================*/ |
| QCamera2HardwareInterface::~QCamera2HardwareInterface() |
| { |
| LOGH("E"); |
| |
| mDeferredWorkThread.sendCmd(CAMERA_CMD_TYPE_STOP_DATA_PROC, TRUE, TRUE); |
| mDeferredWorkThread.exit(); |
| |
| if (mMetadataMem != NULL) { |
| delete mMetadataMem; |
| mMetadataMem = NULL; |
| } |
| |
| m_perfLock.lock_acq(); |
| lockAPI(); |
| m_smThreadActive = false; |
| unlockAPI(); |
| m_stateMachine.releaseThread(); |
| closeCamera(); |
| m_perfLock.lock_rel(); |
| m_perfLock.lock_deinit(); |
| pthread_mutex_destroy(&m_lock); |
| pthread_cond_destroy(&m_cond); |
| pthread_mutex_destroy(&m_evtLock); |
| pthread_cond_destroy(&m_evtCond); |
| pthread_mutex_destroy(&m_int_lock); |
| pthread_cond_destroy(&m_int_cond); |
| pthread_mutex_destroy(&mGrallocLock); |
| LOGH("X"); |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : deferPPInit |
| * |
| * DESCRIPTION: Queue postproc init task to deferred thread |
| * |
| * PARAMETERS : none |
| * |
| * RETURN : uint32_t job id of pproc init job |
| * 0 -- failure |
| *==========================================================================*/ |
| uint32_t QCamera2HardwareInterface::deferPPInit() |
| { |
| // init pproc |
| DeferWorkArgs args; |
| DeferPProcInitArgs pprocInitArgs; |
| |
| memset(&args, 0, sizeof(DeferWorkArgs)); |
| memset(&pprocInitArgs, 0, sizeof(DeferPProcInitArgs)); |
| |
| pprocInitArgs.jpeg_cb = jpegEvtHandle; |
| pprocInitArgs.user_data = this; |
| args.pprocInitArgs = pprocInitArgs; |
| |
| return queueDeferredWork(CMD_DEF_PPROC_INIT, |
| args); |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : openCamera |
| * |
| * DESCRIPTION: open camera |
| * |
| * PARAMETERS : |
| * @hw_device : double ptr for camera device struct |
| * |
| * RETURN : int32_t type of status |
| * NO_ERROR -- success |
| * none-zero failure code |
| *==========================================================================*/ |
| int QCamera2HardwareInterface::openCamera(struct hw_device_t **hw_device) |
| { |
| KPI_ATRACE_CALL(); |
| int rc = NO_ERROR; |
| if (mCameraOpened) { |
| *hw_device = NULL; |
| LOGE("Permission Denied"); |
| return PERMISSION_DENIED; |
| } |
| LOGI("[KPI Perf]: E PROFILE_OPEN_CAMERA camera id %d", |
| mCameraId); |
| m_perfLock.lock_acq_timed(CAMERA_OPEN_PERF_TIME_OUT); |
| rc = openCamera(); |
| if (rc == NO_ERROR){ |
| *hw_device = &mCameraDevice.common; |
| if (m_thermalAdapter.init(this) != 0) { |
| LOGW("Init thermal adapter failed"); |
| } |
| } |
| else |
| *hw_device = NULL; |
| |
| LOGI("[KPI Perf]: X PROFILE_OPEN_CAMERA camera id %d, rc: %d", |
| mCameraId, rc); |
| |
| return rc; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : openCamera |
| * |
| * DESCRIPTION: open camera |
| * |
| * PARAMETERS : none |
| * |
| * RETURN : int32_t type of status |
| * NO_ERROR -- success |
| * none-zero failure code |
| *==========================================================================*/ |
| int QCamera2HardwareInterface::openCamera() |
| { |
| int32_t rc = NO_ERROR; |
| char value[PROPERTY_VALUE_MAX]; |
| |
| if (mCameraHandle) { |
| LOGE("Failure: Camera already opened"); |
| return ALREADY_EXISTS; |
| } |
| |
| rc = QCameraFlash::getInstance().reserveFlashForCamera(mCameraId); |
| if (rc < 0) { |
| LOGE("Failed to reserve flash for camera id: %d", |
| mCameraId); |
| return UNKNOWN_ERROR; |
| } |
| |
| // alloc param buffer |
| DeferWorkArgs args; |
| memset(&args, 0, sizeof(args)); |
| mParamAllocJob = queueDeferredWork(CMD_DEF_PARAM_ALLOC, args); |
| if (mParamAllocJob == 0) { |
| LOGE("Failed queueing PARAM_ALLOC job"); |
| return -ENOMEM; |
| } |
| |
| if (gCamCapability[mCameraId] != NULL) { |
| // allocate metadata buffers |
| DeferWorkArgs args; |
| DeferMetadataAllocArgs metadataAllocArgs; |
| |
| memset(&args, 0, sizeof(args)); |
| memset(&metadataAllocArgs, 0, sizeof(metadataAllocArgs)); |
| |
| uint32_t padding = |
| gCamCapability[mCameraId]->padding_info.plane_padding; |
| metadataAllocArgs.size = PAD_TO_SIZE(sizeof(metadata_buffer_t), |
| padding); |
| metadataAllocArgs.bufferCnt = CAMERA_MIN_METADATA_BUFFERS; |
| args.metadataAllocArgs = metadataAllocArgs; |
| |
| mMetadataAllocJob = queueDeferredWork(CMD_DEF_METADATA_ALLOC, args); |
| if (mMetadataAllocJob == 0) { |
| LOGE("Failed to allocate metadata buffer"); |
| rc = -ENOMEM; |
| goto error_exit1; |
| } |
| |
| rc = camera_open((uint8_t)mCameraId, &mCameraHandle); |
| if (rc) { |
| LOGE("camera_open failed. rc = %d, mCameraHandle = %p", |
| rc, mCameraHandle); |
| goto error_exit2; |
| } |
| |
| mCameraHandle->ops->register_event_notify(mCameraHandle->camera_handle, |
| camEvtHandle, |
| (void *) this); |
| } else { |
| LOGH("Capabilities not inited, initializing now."); |
| |
| rc = camera_open((uint8_t)mCameraId, &mCameraHandle); |
| if (rc) { |
| LOGE("camera_open failed. rc = %d, mCameraHandle = %p", |
| rc, mCameraHandle); |
| goto error_exit2; |
| } |
| |
| if(NO_ERROR != initCapabilities(mCameraId,mCameraHandle)) { |
| LOGE("initCapabilities failed."); |
| rc = UNKNOWN_ERROR; |
| goto error_exit3; |
| } |
| |
| mCameraHandle->ops->register_event_notify(mCameraHandle->camera_handle, |
| camEvtHandle, |
| (void *) this); |
| } |
| |
| mActiveCamera = MM_CAMERA_TYPE_MAIN; |
| if (isDualCamera()) { |
| mActiveCamera |= MM_CAMERA_TYPE_AUX; |
| } |
| |
| // Init params in the background |
| // 1. It's safe to queue init job, even if alloc job is not yet complete. |
| // It will be queued to the same thread, so the alloc is guaranteed to |
| // finish first. |
| // 2. However, it is not safe to begin param init until after camera is |
| // open. That is why we wait until after camera open completes to schedule |
| // this task. |
| memset(&args, 0, sizeof(args)); |
| mParamInitJob = queueDeferredWork(CMD_DEF_PARAM_INIT, args); |
| if (mParamInitJob == 0) { |
| LOGE("Failed queuing PARAM_INIT job"); |
| rc = -ENOMEM; |
| goto error_exit3; |
| } |
| |
| mCameraOpened = true; |
| |
| //Notify display HAL that a camera session is active. |
| //But avoid calling the same during bootup because camera service might open/close |
| //cameras at boot time during its initialization and display service will also internally |
| //wait for camera service to initialize first while calling this display API, resulting in a |
| //deadlock situation. Since boot time camera open/close calls are made only to fetch |
| //capabilities, no need of this display bw optimization. |
| //Use "service.bootanim.exit" property to know boot status. |
| property_get("service.bootanim.exit", value, "0"); |
| if (atoi(value) == 1) { |
| pthread_mutex_lock(&gCamLock); |
| if (gNumCameraSessions++ == 0) { |
| setCameraLaunchStatus(true); |
| } |
| pthread_mutex_unlock(&gCamLock); |
| } |
| |
| // Setprop to decide the time source (whether boottime or monotonic). |
| // By default, use monotonic time. |
| property_get("persist.camera.time.monotonic", value, "1"); |
| mBootToMonoTimestampOffset = 0; |
| if (atoi(value) == 1) { |
| // if monotonic is set, then need to use time in monotonic. |
| // So, Measure the clock offset between BOOTTIME and MONOTONIC |
| // The clock domain source for ISP is BOOTTIME and |
| // for Video/display is MONOTONIC |
| // The below offset is used to convert from clock domain of other subsystem |
| // (video/hardware composer) to that of camera. Assumption is that this |
| // offset won't change during the life cycle of the camera device. In other |
| // words, camera device shouldn't be open during CPU suspend. |
| mBootToMonoTimestampOffset = getBootToMonoTimeOffset(); |
| } |
| LOGH("mBootToMonoTimestampOffset = %lld", mBootToMonoTimestampOffset); |
| |
| memset(value, 0, sizeof(value)); |
| property_get("persist.camera.depth.focus.cb", value, "1"); |
| bDepthAFCallbacks = atoi(value); |
| |
| return NO_ERROR; |
| |
| error_exit3: |
| if(mJpegClientHandle) { |
| deinitJpegHandle(); |
| } |
| mCameraHandle->ops->close_camera(mCameraHandle->camera_handle); |
| mCameraHandle = NULL; |
| error_exit2: |
| waitDeferredWork(mMetadataAllocJob); |
| error_exit1: |
| waitDeferredWork(mParamAllocJob); |
| return rc; |
| |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : bundleRelatedCameras |
| * |
| * DESCRIPTION: bundle cameras to enable syncing of cameras |
| * |
| * PARAMETERS : |
| * @sync :indicates whether syncing is On or Off |
| * @sessionid :session id for other camera session |
| * |
| * RETURN : int32_t type of status |
| * NO_ERROR -- success |
| * none-zero failure code |
| *==========================================================================*/ |
| int QCamera2HardwareInterface::bundleRelatedCameras(bool syncOn, |
| uint32_t sessionid) |
| { |
| LOGD("bundleRelatedCameras sync %d with sessionid %d", |
| syncOn, sessionid); |
| |
| int32_t rc = mParameters.bundleRelatedCameras(syncOn, sessionid); |
| if (rc != NO_ERROR) { |
| LOGE("bundleRelatedCameras failed %d", rc); |
| return rc; |
| } |
| return rc; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : getCameraSessionId |
| * |
| * DESCRIPTION: gets the backend session Id of this HWI instance |
| * |
| * PARAMETERS : |
| * @sessionid : pointer to the output session id |
| * |
| * RETURN : int32_t type of status |
| * NO_ERROR -- success |
| * none-zero failure code |
| *==========================================================================*/ |
| int QCamera2HardwareInterface::getCameraSessionId(uint32_t* session_id) |
| { |
| int32_t rc = NO_ERROR; |
| |
| if(session_id != NULL) { |
| rc = mCameraHandle->ops->get_session_id(mCameraHandle->camera_handle, |
| session_id); |
| LOGD("Getting Camera Session Id %d", *session_id); |
| } else { |
| LOGE("Session Id is Null"); |
| return UNKNOWN_ERROR; |
| } |
| return rc; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : isFrameSyncEnabled |
| * |
| * DESCRIPTION: returns whether frame sync is enabled |
| * |
| * PARAMETERS : none |
| * |
| * RETURN : bool indicating whether frame sync is enabled |
| *==========================================================================*/ |
| bool QCamera2HardwareInterface::isFrameSyncEnabled(void) |
| { |
| return mParameters.isFrameSyncEnabled(); |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : setFrameSyncEnabled |
| * |
| * DESCRIPTION: sets whether frame sync is enabled |
| * |
| * PARAMETERS : |
| * @enable : flag whether to enable or disable frame sync |
| * |
| * RETURN : int32_t type of status |
| * NO_ERROR -- success |
| * none-zero failure code |
| *==========================================================================*/ |
| int32_t QCamera2HardwareInterface::setFrameSyncEnabled(bool enable) |
| { |
| return mParameters.setFrameSyncEnabled(enable); |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : getRelatedCamSyncInfo |
| * |
| * DESCRIPTION:returns the related cam sync info for this HWI instance |
| * |
| * PARAMETERS :none |
| * |
| * RETURN : const pointer to cam_sync_related_sensors_event_info_t |
| *==========================================================================*/ |
| const cam_sync_related_sensors_event_info_t* |
| QCamera2HardwareInterface::getRelatedCamSyncInfo(void) |
| { |
| return mParameters.getRelatedCamSyncInfo(); |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : setRelatedCamSyncInfo |
| * |
| * DESCRIPTION:sets the related cam sync info for this HWI instance |
| * |
| * PARAMETERS : |
| * @info : ptr to related cam info parameters |
| * |
| * RETURN : int32_t type of status |
| * NO_ERROR -- success |
| * none-zero failure code |
| *==========================================================================*/ |
| int32_t QCamera2HardwareInterface::setRelatedCamSyncInfo( |
| cam_sync_related_sensors_event_info_t* info) |
| { |
| if(info) { |
| return mParameters.setRelatedCamSyncInfo(info); |
| } else { |
| return BAD_TYPE; |
| } |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : getMpoComposition |
| * |
| * DESCRIPTION:function to retrieve whether Mpo composition should be enabled |
| * or not |
| * |
| * PARAMETERS :none |
| * |
| * RETURN : bool indicates whether mpo composition is enabled or not |
| *==========================================================================*/ |
| bool QCamera2HardwareInterface::getMpoComposition(void) |
| { |
| LOGH("MpoComposition:%d ", m_bMpoEnabled); |
| return m_bMpoEnabled; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : setMpoComposition |
| * |
| * DESCRIPTION:set if Mpo composition should be enabled for this HWI instance |
| * |
| * PARAMETERS : |
| * @enable : indicates whether Mpo composition enabled or not |
| * |
| * RETURN : int32_t type of status |
| * NO_ERROR -- success |
| * none-zero failure code |
| *==========================================================================*/ |
| int32_t QCamera2HardwareInterface::setMpoComposition(bool enable) |
| { |
| // By default set Mpo composition to disable |
| m_bMpoEnabled = false; |
| |
| // Enable Mpo composition only if |
| // 1) frame sync is ON between two cameras and |
| // 2) any advanced features are not enabled (AOST features) and |
| // 3) not in recording mode (for liveshot case) |
| // 4) flash is not needed |
| if ((getRelatedCamSyncInfo()->sync_control == CAM_SYNC_RELATED_SENSORS_ON) && |
| !mParameters.isAdvCamFeaturesEnabled() && |
| !mParameters.getRecordingHintValue() && |
| !mFlashNeeded && |
| !isLongshotEnabled()) { |
| m_bMpoEnabled = enable; |
| LOGH("MpoComposition:%d ", m_bMpoEnabled); |
| return NO_ERROR; |
| } else { |
| return BAD_TYPE; |
| } |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : getRecordingHintValue |
| * |
| * DESCRIPTION:function to retrieve recording hint value |
| * |
| * PARAMETERS :none |
| * |
| * RETURN : bool indicates whether recording hint is enabled or not |
| *==========================================================================*/ |
| bool QCamera2HardwareInterface::getRecordingHintValue(void) |
| { |
| return mParameters.getRecordingHintValue(); |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : setRecordingHintValue |
| * |
| * DESCRIPTION:set recording hint value |
| * |
| * PARAMETERS : |
| * @enable : video hint value |
| * |
| * RETURN : int32_t type of status |
| * NO_ERROR -- success |
| * none-zero failure code |
| *==========================================================================*/ |
| int32_t QCamera2HardwareInterface::setRecordingHintValue(int32_t value) |
| { |
| return mParameters.updateRecordingHintValue(value); |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : closeCamera |
| * |
| * DESCRIPTION: close camera |
| * |
| * PARAMETERS : none |
| * |
| * RETURN : int32_t type of status |
| * NO_ERROR -- success |
| * none-zero failure code |
| *==========================================================================*/ |
| int QCamera2HardwareInterface::closeCamera() |
| { |
| int rc = NO_ERROR; |
| int i; |
| char value[PROPERTY_VALUE_MAX]; |
| LOGI("E"); |
| if (!mCameraOpened) { |
| return NO_ERROR; |
| } |
| LOGI("[KPI Perf]: E PROFILE_CLOSE_CAMERA camera id %d", |
| mCameraId); |
| |
| // set open flag to false |
| mCameraOpened = false; |
| |
| // Reset Stream config info |
| mParameters.setStreamConfigure(false, false, true); |
| |
| // deinit Parameters |
| mParameters.deinit(); |
| |
| // exit notifier |
| m_cbNotifier.exit(); |
| |
| // stop and deinit postprocessor |
| waitDeferredWork(mReprocJob); |
| // Close the JPEG session |
| waitDeferredWork(mJpegJob); |
| m_postprocessor.stop(); |
| deinitJpegHandle(); |
| m_postprocessor.deinit(); |
| mInitPProcJob = 0; // reset job id, so pproc can be reinited later |
| |
| m_thermalAdapter.deinit(); |
| |
| // delete all channels if not already deleted |
| for (i = 0; i < QCAMERA_CH_TYPE_MAX; i++) { |
| if (m_channels[i] != NULL) { |
| m_channels[i]->stop(); |
| delete m_channels[i]; |
| m_channels[i] = NULL; |
| } |
| } |
| |
| //free all pending api results here |
| if(m_apiResultList != NULL) { |
| api_result_list *apiResultList = m_apiResultList; |
| api_result_list *apiResultListNext; |
| while (apiResultList != NULL) { |
| apiResultListNext = apiResultList->next; |
| free(apiResultList); |
| apiResultList = apiResultListNext; |
| } |
| } |
| |
| rc = mCameraHandle->ops->close_camera(mCameraHandle->camera_handle); |
| mCameraHandle = NULL; |
| |
| //Notify display HAL that there is no active camera session |
| //but avoid calling the same during bootup. Refer to openCamera |
| //for more details. |
| property_get("service.bootanim.exit", value, "0"); |
| if (atoi(value) == 1) { |
| pthread_mutex_lock(&gCamLock); |
| if (--gNumCameraSessions == 0) { |
| setCameraLaunchStatus(false); |
| } |
| pthread_mutex_unlock(&gCamLock); |
| } |
| |
| if (mExifParams.debug_params) { |
| free(mExifParams.debug_params); |
| mExifParams.debug_params = NULL; |
| } |
| |
| if (QCameraFlash::getInstance().releaseFlashFromCamera(mCameraId) != 0) { |
| LOGD("Failed to release flash for camera id: %d", |
| mCameraId); |
| } |
| |
| LOGI("[KPI Perf]: X PROFILE_CLOSE_CAMERA camera id %d, rc: %d", |
| mCameraId, rc); |
| |
| return rc; |
| } |
| |
| #define DATA_PTR(MEM_OBJ,INDEX) MEM_OBJ->getPtr( INDEX ) |
| |
| |
| /*=========================================================================== |
| * FUNCTION : getCapabilities |
| * |
| * DESCRIPTION: query camera capability from back-end |
| * |
| * PARAMETERS : |
| * @ops : mm-interface ops structure |
| * @cam_handle : camera handle for which we need capability |
| * |
| * RETURN : ptr type of capability structure |
| * capability for success |
| * NULL for failure |
| *==========================================================================*/ |
| cam_capability_t *QCamera2HardwareInterface::getCapabilities(mm_camera_ops_t *ops, |
| uint32_t cam_handle) |
| { |
| int rc = NO_ERROR; |
| QCameraHeapMemory *capabilityHeap = NULL; |
| cam_capability_t *cap_ptr = NULL; |
| |
| if (ops == NULL) { |
| LOGE("Invalid arguments"); |
| return NULL; |
| } |
| |
| capabilityHeap = new QCameraHeapMemory(1); |
| if (capabilityHeap == NULL) { |
| LOGE("creation of capabilityHeap failed"); |
| return NULL; |
| } |
| |
| /* Allocate memory for capability buffer */ |
| rc = capabilityHeap->allocate(1, sizeof(cam_capability_t), NON_SECURE); |
| if(rc != OK) { |
| LOGE("No memory for cappability"); |
| goto allocate_failed; |
| } |
| |
| /* Map memory for capability buffer */ |
| memset(DATA_PTR(capabilityHeap,0), 0, sizeof(cam_capability_t)); |
| |
| cam_buf_map_type_list bufMapList; |
| rc = QCameraBufferMaps::makeSingletonBufMapList( |
| CAM_MAPPING_BUF_TYPE_CAPABILITY, |
| 0 /*stream id*/, 0 /*buffer index*/, -1 /*plane index*/, |
| 0 /*cookie*/, capabilityHeap->getFd(0), sizeof(cam_capability_t), |
| bufMapList, capabilityHeap->getPtr(0)); |
| |
| if (rc == NO_ERROR) { |
| rc = ops->map_bufs(cam_handle, |
| &bufMapList); |
| } |
| if(rc < 0) { |
| LOGE("failed to map capability buffer"); |
| goto map_failed; |
| } |
| |
| /* Query Capability */ |
| rc = ops->query_capability(cam_handle); |
| if(rc < 0) { |
| LOGE("failed to query capability"); |
| rc = FAILED_TRANSACTION; |
| goto query_failed; |
| } |
| |
| cap_ptr = (cam_capability_t *)malloc(sizeof(cam_capability_t)); |
| if (cap_ptr == NULL) { |
| LOGE("out of memory"); |
| rc = NO_MEMORY; |
| goto query_failed; |
| } |
| |
| memset(cap_ptr, 0, sizeof(cam_capability_t)); |
| memcpy(cap_ptr, DATA_PTR(capabilityHeap, 0), sizeof(cam_capability_t)); |
| |
| int index; |
| for (index = 0; index < CAM_ANALYSIS_INFO_MAX; index++) { |
| cam_analysis_info_t *p_analysis_info = &cap_ptr->analysis_info[index]; |
| p_analysis_info->analysis_padding_info.offset_info.offset_x = 0; |
| p_analysis_info->analysis_padding_info.offset_info.offset_y = 0; |
| } |
| |
| query_failed: |
| ops->unmap_buf(cam_handle, CAM_MAPPING_BUF_TYPE_CAPABILITY); |
| map_failed: |
| capabilityHeap->deallocate(); |
| allocate_failed: |
| delete capabilityHeap; |
| |
| if (rc != NO_ERROR) { |
| return NULL; |
| } else { |
| return cap_ptr; |
| } |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : initCapabilities |
| * |
| * DESCRIPTION: initialize camera capabilities in static data struct |
| * |
| * PARAMETERS : |
| * @cameraId : camera Id |
| * |
| * RETURN : int32_t type of status |
| * NO_ERROR -- success |
| * none-zero failure code |
| *==========================================================================*/ |
| int QCamera2HardwareInterface::initCapabilities(uint32_t cameraId, |
| mm_camera_vtbl_t *cameraHandle) |
| { |
| ATRACE_CALL(); |
| int rc = 0; |
| uint32_t handle = 0; |
| |
| rc = camera_open((uint8_t)cameraId, &cameraHandle); |
| if (rc) { |
| LOGE("camera_open failed. rc = %d", rc); |
| goto open_failed; |
| } |
| if (!cameraHandle) { |
| LOGE("camera_open failed. cameraHandle = %p", cameraHandle); |
| goto open_failed; |
| } |
| |
| handle = get_main_camera_handle(cameraHandle->camera_handle); |
| gCamCapability[cameraId] = getCapabilities(cameraHandle->ops, handle); |
| if (gCamCapability[cameraId] == NULL) { |
| rc = FAILED_TRANSACTION; |
| goto failed_op; |
| } |
| |
| if (is_dual_camera_by_idx(cameraId)) { |
| handle = get_aux_camera_handle(cameraHandle->camera_handle); |
| gCamCapability[cameraId]->aux_cam_cap = |
| getCapabilities(cameraHandle->ops, handle); |
| if (gCamCapability[cameraId]->aux_cam_cap == NULL) { |
| rc = FAILED_TRANSACTION; |
| free(gCamCapability[cameraId]); |
| goto failed_op; |
| } |
| } |
| failed_op: |
| cameraHandle->ops->close_camera(cameraHandle->camera_handle); |
| cameraHandle = NULL; |
| open_failed: |
| return rc; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : getCapabilities |
| * |
| * DESCRIPTION: query camera capabilities |
| * |
| * PARAMETERS : |
| * @cameraId : camera Id |
| * @info : camera info struct to be filled in with camera capabilities |
| * |
| * RETURN : int type of status |
| * NO_ERROR -- success |
| * none-zero failure code |
| *==========================================================================*/ |
| int QCamera2HardwareInterface::getCapabilities(uint32_t cameraId, |
| struct camera_info *info, cam_sync_type_t *p_cam_type) |
| { |
| ATRACE_CALL(); |
| int rc = NO_ERROR; |
| struct camera_info *p_info = NULL; |
| pthread_mutex_lock(&gCamLock); |
| p_info = get_cam_info(cameraId, p_cam_type); |
| p_info->device_version = CAMERA_DEVICE_API_VERSION_1_0; |
| p_info->static_camera_characteristics = NULL; |
| memcpy(info, p_info, sizeof (struct camera_info)); |
| pthread_mutex_unlock(&gCamLock); |
| return rc; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : getCamHalCapabilities |
| * |
| * DESCRIPTION: get the HAL capabilities structure |
| * |
| * PARAMETERS : |
| * @cameraId : camera Id |
| * |
| * RETURN : capability structure of respective camera |
| * |
| *==========================================================================*/ |
| cam_capability_t* QCamera2HardwareInterface::getCamHalCapabilities() |
| { |
| return gCamCapability[mCameraId]; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : getBufNumForAux |
| * |
| * DESCRIPTION: return number of stream buffers needed for aux camera given stream type |
| * |
| * PARAMETERS : |
| * @stream_type : type of stream |
| * |
| * RETURN : number of buffers needed |
| * NOTE : Based on the use cases and auxillary camera type, |
| we can decide buffer count |
| *==========================================================================*/ |
| uint8_t QCamera2HardwareInterface::getBufNumForAux(cam_stream_type_t stream_type) |
| { |
| if (!isDualCamera()) { |
| return 0; |
| } |
| |
| uint8_t bufferCnt = 1; |
| switch (stream_type) { |
| case CAM_STREAM_TYPE_PREVIEW: |
| case CAM_STREAM_TYPE_VIDEO: |
| case CAM_STREAM_TYPE_SNAPSHOT: |
| case CAM_STREAM_TYPE_METADATA: |
| case CAM_STREAM_TYPE_CALLBACK: |
| case CAM_STREAM_TYPE_ANALYSIS: |
| case CAM_STREAM_TYPE_POSTVIEW: |
| case CAM_STREAM_TYPE_RAW: |
| case CAM_STREAM_TYPE_OFFLINE_PROC: |
| case CAM_STREAM_TYPE_DEFAULT: |
| case CAM_STREAM_TYPE_MAX: |
| //For wide & tele, we use same buffer count premary and aux streams. |
| bufferCnt = getBufNumRequired(stream_type); |
| break; |
| default: |
| break; |
| } |
| LOGH("Buffer Cnt for Aux Camera : %d", bufferCnt); |
| return bufferCnt; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : getBufNumRequired |
| * |
| * DESCRIPTION: return number of stream buffers needed for given stream type |
| * |
| * PARAMETERS : |
| * @stream_type : type of stream |
| * |
| * RETURN : number of buffers needed |
| *==========================================================================*/ |
| uint8_t QCamera2HardwareInterface::getBufNumRequired(cam_stream_type_t stream_type) |
| { |
| int bufferCnt = 0; |
| int minCaptureBuffers = mParameters.getNumOfSnapshots(); |
| char value[PROPERTY_VALUE_MAX]; |
| bool raw_yuv = false; |
| int persist_cnt = 0; |
| int minPrevFps, maxPrevFps; |
| |
| int zslQBuffers = mParameters.getZSLQueueDepth(); |
| |
| int minCircularBufNum = mParameters.getMaxUnmatchedFramesInQueue() + |
| CAMERA_MIN_JPEG_ENCODING_BUFFERS; |
| |
| int maxStreamBuf = minCaptureBuffers + mParameters.getMaxUnmatchedFramesInQueue() + |
| mParameters.getNumOfExtraHDRInBufsIfNeeded() - |
| mParameters.getNumOfExtraHDROutBufsIfNeeded() + |
| mParameters.getNumOfExtraBuffersForImageProc() + |
| EXTRA_ZSL_PREVIEW_STREAM_BUF; |
| |
| int minUndequeCount = 0; |
| if (!isNoDisplayMode()) { |
| if(mPreviewWindow != NULL) { |
| if (mPreviewWindow->get_min_undequeued_buffer_count(mPreviewWindow,&minUndequeCount) |
| != 0) { |
| LOGW("get_min_undequeued_buffer_count failed"); |
| //TODO: hardcoded because MIN_UNDEQUEUED_BUFFERS not defined |
| //minUndequeCount = BufferQueue::MIN_UNDEQUEUED_BUFFERS; |
| minUndequeCount = MIN_UNDEQUEUED_BUFFERS; |
| } |
| } else { |
| //preview window might not be set at this point. So, query directly |
| //from BufferQueue implementation of gralloc buffers. |
| //minUndequeCount = BufferQueue::MIN_UNDEQUEUED_BUFFERS; |
| //hardcoded because MIN_UNDEQUEUED_BUFFERS not defined. REVISIT |
| minUndequeCount = MIN_UNDEQUEUED_BUFFERS; |
| } |
| if (minUndequeCount != MIN_UNDEQUEUED_BUFFERS) { |
| // minUndequeCount from valid preview window != hardcoded MIN_UNDEQUEUED_BUFFERS |
| // and so change the MACRO as per minUndequeCount |
| LOGW("WARNING : minUndequeCount(%d) != hardcoded value(%d)", |
| minUndequeCount, MIN_UNDEQUEUED_BUFFERS); |
| } |
| } |
| |
| LOGD("minCaptureBuffers = %d zslQBuffers = %d minCircularBufNum = %d" |
| "maxStreamBuf = %d minUndequeCount = %d", |
| minCaptureBuffers, zslQBuffers, minCircularBufNum, |
| maxStreamBuf, minUndequeCount); |
| // Get buffer count for the particular stream type |
| switch (stream_type) { |
| case CAM_STREAM_TYPE_PREVIEW: |
| { |
| if (mParameters.isZSLMode()) { |
| // We need to add two extra streming buffers to add |
| // flexibility in forming matched super buf in ZSL queue. |
| // with number being 'zslQBuffers + minCircularBufNum' |
| // we see preview buffers sometimes get dropped at CPP |
| // and super buf is not forming in ZSL Q for long time. |
| |
| bufferCnt = zslQBuffers + minCircularBufNum + |
| mParameters.getNumOfExtraBuffersForImageProc() + |
| mParameters.getNumOfExtraBuffersForPreview() + |
| mParameters.getNumOfExtraHDRInBufsIfNeeded(); |
| } else { |
| bufferCnt = CAMERA_MIN_STREAMING_BUFFERS + |
| mParameters.getMaxUnmatchedFramesInQueue() + |
| mParameters.getNumOfExtraBuffersForPreview(); |
| } |
| // ISP allocates native preview buffers and so reducing same from HAL allocation |
| if (bufferCnt > CAMERA_ISP_PING_PONG_BUFFERS ) |
| bufferCnt -= CAMERA_ISP_PING_PONG_BUFFERS; |
| |
| // Extra ZSL preview frames are not needed for HFR case. |
| // Thumbnail will not be derived from preview for HFR live snapshot case. |
| if ((mParameters.getRecordingHintValue() == true) |
| && (!mParameters.isHfrMode())) { |
| bufferCnt += EXTRA_ZSL_PREVIEW_STREAM_BUF; |
| } |
| //Adding Extra preview buffers for 60FPS usecase. |
| mParameters.getPreviewFpsRange(&minPrevFps, &maxPrevFps); |
| if (maxPrevFps > CAMERA_DEFAULT_FPS) { |
| bufferCnt += CAMERA_MIN_DISPLAY_BUFFERS; |
| } |
| |
| // Add the display minUndequeCount count on top of camera requirement |
| bufferCnt += minUndequeCount; |
| |
| property_get("persist.camera.preview_yuv", value, "0"); |
| persist_cnt = atoi(value); |
| if ((persist_cnt < CAM_MAX_NUM_BUFS_PER_STREAM) |
| && (bufferCnt < persist_cnt)) { |
| bufferCnt = persist_cnt; |
| } |
| } |
| break; |
| case CAM_STREAM_TYPE_POSTVIEW: |
| { |
| bufferCnt = minCaptureBuffers + |
| mParameters.getMaxUnmatchedFramesInQueue() + |
| mParameters.getNumOfExtraHDRInBufsIfNeeded() - |
| mParameters.getNumOfExtraHDROutBufsIfNeeded() + |
| mParameters.getNumOfExtraBuffersForImageProc(); |
| |
| if (bufferCnt > maxStreamBuf) { |
| bufferCnt = maxStreamBuf; |
| } |
| bufferCnt += minUndequeCount; |
| } |
| break; |
| case CAM_STREAM_TYPE_SNAPSHOT: |
| { |
| if (mParameters.isZSLMode() || mLongshotEnabled) { |
| if ((minCaptureBuffers == 1 || mParameters.isUbiRefocus()) && |
| !mLongshotEnabled) { |
| // Single ZSL snapshot case |
| bufferCnt = zslQBuffers + CAMERA_MIN_STREAMING_BUFFERS + |
| mParameters.getNumOfExtraBuffersForImageProc(); |
| } |
| else { |
| // ZSL Burst or Longshot case |
| bufferCnt = zslQBuffers + minCircularBufNum + |
| mParameters.getNumOfExtraBuffersForImageProc(); |
| } |
| if (getSensorType() == CAM_SENSOR_YUV && bufferCnt > CAMERA_ISP_PING_PONG_BUFFERS) { |
| //ISP allocates native buffers in YUV case |
| bufferCnt -= CAMERA_ISP_PING_PONG_BUFFERS; |
| } |
| } else { |
| bufferCnt = minCaptureBuffers + |
| mParameters.getNumOfExtraHDRInBufsIfNeeded() - |
| mParameters.getNumOfExtraHDROutBufsIfNeeded() + |
| mParameters.getNumOfExtraBuffersForImageProc(); |
| |
| if (bufferCnt > maxStreamBuf) { |
| bufferCnt = maxStreamBuf; |
| } |
| } |
| } |
| break; |
| case CAM_STREAM_TYPE_RAW: |
| property_get("persist.camera.raw_yuv", value, "0"); |
| raw_yuv = atoi(value) > 0 ? true : false; |
| |
| if (isRdiMode() || raw_yuv) { |
| bufferCnt = zslQBuffers + minCircularBufNum; |
| } else if (mParameters.isZSLMode()) { |
| bufferCnt = zslQBuffers + minCircularBufNum; |
| if (getSensorType() == CAM_SENSOR_YUV && bufferCnt > CAMERA_ISP_PING_PONG_BUFFERS) { |
| //ISP allocates native buffers in YUV case |
| bufferCnt -= CAMERA_ISP_PING_PONG_BUFFERS; |
| } |
| |
| } else { |
| bufferCnt = minCaptureBuffers + |
| mParameters.getNumOfExtraHDRInBufsIfNeeded() - |
| mParameters.getNumOfExtraHDROutBufsIfNeeded() + |
| mParameters.getNumOfExtraBuffersForImageProc(); |
| |
| if (bufferCnt > maxStreamBuf) { |
| bufferCnt = maxStreamBuf; |
| } |
| } |
| |
| property_get("persist.camera.preview_raw", value, "0"); |
| persist_cnt = atoi(value); |
| if ((persist_cnt < CAM_MAX_NUM_BUFS_PER_STREAM) |
| && (bufferCnt < persist_cnt)) { |
| bufferCnt = persist_cnt; |
| } |
| property_get("persist.camera.video_raw", value, "0"); |
| persist_cnt = atoi(value); |
| if ((persist_cnt < CAM_MAX_NUM_BUFS_PER_STREAM) |
| && (bufferCnt < persist_cnt)) { |
| bufferCnt = persist_cnt; |
| } |
| |
| break; |
| case CAM_STREAM_TYPE_VIDEO: |
| { |
| if (mParameters.getBufBatchCount()) { |
| //Video Buffer in case of HFR or camera batching.. |
| bufferCnt = CAMERA_MIN_CAMERA_BATCH_BUFFERS; |
| } else if (mParameters.getVideoBatchSize()) { |
| //Video Buffer count only for HAL to HAL batching. |
| bufferCnt = (CAMERA_MIN_VIDEO_BATCH_BUFFERS |
| * mParameters.getVideoBatchSize()); |
| if (bufferCnt < CAMERA_MIN_VIDEO_BUFFERS) { |
| bufferCnt = CAMERA_MIN_VIDEO_BUFFERS; |
| } |
| } else { |
| // No batching enabled. |
| bufferCnt = CAMERA_MIN_VIDEO_BUFFERS; |
| } |
| |
| bufferCnt += mParameters.getNumOfExtraBuffersForVideo(); |
| //if its 4K encoding usecase, then add extra buffer |
| cam_dimension_t dim; |
| mParameters.getStreamDimension(CAM_STREAM_TYPE_VIDEO, dim); |
| if (is4k2kResolution(&dim)) { |
| //get additional buffer count |
| property_get("vidc.enc.dcvs.extra-buff-count", value, "0"); |
| bufferCnt += atoi(value); |
| } |
| } |
| break; |
| case CAM_STREAM_TYPE_METADATA: |
| { |
| if (mParameters.isZSLMode()) { |
| // MetaData buffers should be >= (Preview buffers-minUndequeCount) |
| bufferCnt = zslQBuffers + minCircularBufNum + |
| mParameters.getNumOfExtraHDRInBufsIfNeeded() - |
| mParameters.getNumOfExtraHDROutBufsIfNeeded() + |
| mParameters.getNumOfExtraBuffersForImageProc() + |
| EXTRA_ZSL_PREVIEW_STREAM_BUF; |
| } else { |
| bufferCnt = minCaptureBuffers + |
| mParameters.getNumOfExtraHDRInBufsIfNeeded() - |
| mParameters.getNumOfExtraHDROutBufsIfNeeded() + |
| mParameters.getMaxUnmatchedFramesInQueue() + |
| CAMERA_MIN_STREAMING_BUFFERS + |
| mParameters.getNumOfExtraBuffersForImageProc(); |
| |
| if (bufferCnt > zslQBuffers + minCircularBufNum) { |
| bufferCnt = zslQBuffers + minCircularBufNum; |
| } |
| } |
| if (CAMERA_MIN_METADATA_BUFFERS > bufferCnt) { |
| bufferCnt = CAMERA_MIN_METADATA_BUFFERS; |
| } |
| } |
| break; |
| case CAM_STREAM_TYPE_OFFLINE_PROC: |
| { |
| bufferCnt = minCaptureBuffers; |
| // One of the ubifocus buffers is miscellaneous buffer |
| if (mParameters.isUbiRefocus()) { |
| bufferCnt -= 1; |
| } |
| if (mLongshotEnabled) { |
| bufferCnt = mParameters.getLongshotStages(); |
| } |
| } |
| break; |
| case CAM_STREAM_TYPE_CALLBACK: |
| bufferCnt = CAMERA_MIN_CALLBACK_BUFFERS; |
| break; |
| case CAM_STREAM_TYPE_ANALYSIS: |
| case CAM_STREAM_TYPE_DEFAULT: |
| case CAM_STREAM_TYPE_MAX: |
| default: |
| bufferCnt = 0; |
| break; |
| } |
| |
| LOGH("Buffer count = %d for stream type = %d", bufferCnt, stream_type); |
| if (CAM_MAX_NUM_BUFS_PER_STREAM < bufferCnt) { |
| LOGW("Buffer count %d for stream type %d exceeds limit %d", |
| bufferCnt, stream_type, CAM_MAX_NUM_BUFS_PER_STREAM); |
| return CAM_MAX_NUM_BUFS_PER_STREAM; |
| } |
| |
| return (uint8_t)bufferCnt; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : getStreamRefCount |
| * |
| * DESCRIPTION: return number of instance of stream of stream type |
| * |
| * PARAMETERS : |
| * @stream_type : type of stream |
| * |
| * RETURN : number of stream instances |
| * NOTE : Based on the use cases and auxillary camera type, |
| we can decide stream reference count. |
| For example in wide and tele use case, we duplicate all stream |
| streams from premary to auxillary. |
| *==========================================================================*/ |
| uint8_t QCamera2HardwareInterface::getStreamRefCount(cam_stream_type_t stream_type) |
| { |
| uint8_t ref_cnt = 1; |
| switch (stream_type) { |
| case CAM_STREAM_TYPE_PREVIEW: |
| case CAM_STREAM_TYPE_SNAPSHOT: |
| case CAM_STREAM_TYPE_VIDEO: |
| case CAM_STREAM_TYPE_METADATA: |
| case CAM_STREAM_TYPE_ANALYSIS: |
| case CAM_STREAM_TYPE_CALLBACK: |
| if (isDualCamera()) { |
| ref_cnt++; |
| } |
| break; |
| case CAM_STREAM_TYPE_POSTVIEW: |
| case CAM_STREAM_TYPE_RAW: |
| case CAM_STREAM_TYPE_OFFLINE_PROC: |
| case CAM_STREAM_TYPE_DEFAULT: |
| case CAM_STREAM_TYPE_MAX: |
| default: |
| break; |
| } |
| return ref_cnt; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : getCamHandleForChannel |
| * |
| * DESCRIPTION: return actual camera handle based on use case |
| * |
| * PARAMETERS : |
| * @ch_type : type of channel |
| * |
| * RETURN : uint32_t type camera handle |
| * NOTE : Based on the use cases and auxillary camera type, we can decide cam handle for channel. |
| Incase, we want to avoid any channel for auxillary camera, we can decide here |
| *==========================================================================*/ |
| uint32_t QCamera2HardwareInterface::getCamHandleForChannel(qcamera_ch_type_enum_t ch_type) |
| { |
| uint32_t handle = 0; |
| if (!isDualCamera()) { |
| return mCameraHandle->camera_handle; |
| } |
| |
| /*Based on the use case, decide camera handle for channel*/ |
| switch (ch_type) { |
| case QCAMERA_CH_TYPE_ZSL: |
| case QCAMERA_CH_TYPE_CAPTURE: |
| case QCAMERA_CH_TYPE_PREVIEW: |
| case QCAMERA_CH_TYPE_VIDEO: |
| case QCAMERA_CH_TYPE_SNAPSHOT: |
| case QCAMERA_CH_TYPE_RAW: |
| case QCAMERA_CH_TYPE_METADATA: |
| case QCAMERA_CH_TYPE_ANALYSIS: |
| case QCAMERA_CH_TYPE_CALLBACK: |
| case QCAMERA_CH_TYPE_MAX: |
| default: |
| handle = mCameraHandle->camera_handle; |
| break; |
| case QCAMERA_CH_TYPE_REPROCESSING: |
| handle = get_main_camera_handle(mCameraHandle->camera_handle); |
| break; |
| } |
| return handle; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : allocateStreamBuf |
| * |
| * DESCRIPTION: alocate stream buffers |
| * |
| * PARAMETERS : |
| * @stream_type : type of stream |
| * @size : size of buffer |
| * @stride : stride of buffer |
| * @scanline : scanline of buffer |
| * @bufferCnt : [IN/OUT] minimum num of buffers to be allocated. |
| * could be modified during allocation if more buffers needed |
| * |
| * RETURN : ptr to a memory obj that holds stream buffers. |
| * NULL if failed |
| *==========================================================================*/ |
| QCameraMemory *QCamera2HardwareInterface::allocateStreamBuf( |
| cam_stream_type_t stream_type, size_t size, int stride, int scanline, |
| uint8_t &bufferCnt) |
| { |
| int rc = NO_ERROR; |
| QCameraMemory *mem = NULL; |
| bool bCachedMem = QCAMERA_ION_USE_CACHE; |
| bool bPoolMem = false; |
| char value[PROPERTY_VALUE_MAX]; |
| property_get("persist.camera.mem.usepool", value, "1"); |
| if (atoi(value) == 1) { |
| bPoolMem = true; |
| } |
| |
| // Allocate stream buffer memory object |
| switch (stream_type) { |
| case CAM_STREAM_TYPE_PREVIEW: |
| { |
| if (isNoDisplayMode()) { |
| mem = new QCameraStreamMemory(mGetMemory, |
| bCachedMem, |
| (bPoolMem) ? &m_memoryPool : NULL, |
| stream_type); |
| } else { |
| cam_dimension_t dim; |
| int minFPS, maxFPS; |
| QCameraGrallocMemory *grallocMemory = |
| new QCameraGrallocMemory(mGetMemory); |
| |
| mParameters.getStreamDimension(stream_type, dim); |
| /* we are interested only in maxfps here */ |
| mParameters.getPreviewFpsRange(&minFPS, &maxFPS); |
| int usage = 0; |
| if(mParameters.isUBWCEnabled()) { |
| cam_format_t fmt; |
| mParameters.getStreamFormat(CAM_STREAM_TYPE_PREVIEW,fmt); |
| if (fmt == CAM_FORMAT_YUV_420_NV12_UBWC) { |
| usage = GRALLOC_USAGE_PRIVATE_ALLOC_UBWC ; |
| } |
| } |
| if (grallocMemory) { |
| grallocMemory->setMappable( |
| CAMERA_INITIAL_MAPPABLE_PREVIEW_BUFFERS); |
| grallocMemory->setWindowInfo(mPreviewWindow, |
| dim.width,dim.height, stride, scanline, |
| mParameters.getPreviewHalPixelFormat(), |
| maxFPS, usage); |
| pthread_mutex_lock(&mGrallocLock); |
| if (bufferCnt > CAMERA_INITIAL_MAPPABLE_PREVIEW_BUFFERS) { |
| mEnqueuedBuffers = (bufferCnt - |
| CAMERA_INITIAL_MAPPABLE_PREVIEW_BUFFERS); |
| } else { |
| mEnqueuedBuffers = 0; |
| } |
| pthread_mutex_unlock(&mGrallocLock); |
| } |
| mem = grallocMemory; |
| } |
| } |
| break; |
| case CAM_STREAM_TYPE_POSTVIEW: |
| { |
| if (isNoDisplayMode() || isPreviewRestartEnabled()) { |
| mem = new QCameraStreamMemory(mGetMemory, bCachedMem); |
| } else { |
| cam_dimension_t dim; |
| int minFPS, maxFPS; |
| QCameraGrallocMemory *grallocMemory = |
| new QCameraGrallocMemory(mGetMemory); |
| |
| mParameters.getStreamDimension(stream_type, dim); |
| /* we are interested only in maxfps here */ |
| mParameters.getPreviewFpsRange(&minFPS, &maxFPS); |
| if (grallocMemory) { |
| grallocMemory->setWindowInfo(mPreviewWindow, dim.width, |
| dim.height, stride, scanline, |
| mParameters.getPreviewHalPixelFormat(), maxFPS); |
| } |
| mem = grallocMemory; |
| } |
| } |
| break; |
| case CAM_STREAM_TYPE_ANALYSIS: |
| case CAM_STREAM_TYPE_SNAPSHOT: |
| case CAM_STREAM_TYPE_RAW: |
| case CAM_STREAM_TYPE_OFFLINE_PROC: |
| mem = new QCameraStreamMemory(mGetMemory, |
| bCachedMem, |
| (bPoolMem) ? &m_memoryPool : NULL, |
| stream_type); |
| break; |
| case CAM_STREAM_TYPE_METADATA: |
| { |
| if (mMetadataMem == NULL) { |
| mem = new QCameraMetadataStreamMemory(QCAMERA_ION_USE_CACHE); |
| } else { |
| mem = mMetadataMem; |
| mMetadataMem = NULL; |
| |
| int32_t numAdditionalBuffers = bufferCnt - mem->getCnt(); |
| if (numAdditionalBuffers > 0) { |
| rc = mem->allocateMore(numAdditionalBuffers, size); |
| if (rc != NO_ERROR) { |
| LOGE("Failed to allocate additional buffers, " |
| "but attempting to proceed."); |
| } |
| } |
| bufferCnt = mem->getCnt(); |
| // The memory is already allocated and initialized, so |
| // simply return here. |
| return mem; |
| } |
| } |
| break; |
| case CAM_STREAM_TYPE_VIDEO: |
| { |
| //Use uncached allocation by default |
| if (mParameters.isVideoBuffersCached() || mParameters.isSeeMoreEnabled() || |
| mParameters.isHighQualityNoiseReductionMode()) { |
| bCachedMem = QCAMERA_ION_USE_CACHE; |
| } |
| else { |
| bCachedMem = QCAMERA_ION_USE_NOCACHE; |
| } |
| |
| QCameraVideoMemory *videoMemory = NULL; |
| if (mParameters.getVideoBatchSize()) { |
| videoMemory = new QCameraVideoMemory( |
| mGetMemory, FALSE, QCAMERA_MEM_TYPE_BATCH); |
| if (videoMemory == NULL) { |
| LOGE("Out of memory for video batching obj"); |
| return NULL; |
| } |
| /* |
| * numFDs = BATCH size |
| * numInts = 5 // OFFSET, SIZE, USAGE, TIMESTAMP, FORMAT |
| */ |
| rc = videoMemory->allocateMeta( |
| CAMERA_MIN_VIDEO_BATCH_BUFFERS, |
| mParameters.getVideoBatchSize(), |
| VIDEO_METADATA_NUM_INTS); |
| if (rc < 0) { |
| delete videoMemory; |
| return NULL; |
| } |
| } else { |
| videoMemory = |
| new QCameraVideoMemory(mGetMemory, bCachedMem); |
| if (videoMemory == NULL) { |
| LOGE("Out of memory for video obj"); |
| return NULL; |
| } |
| } |
| |
| int usage = 0; |
| cam_format_t fmt; |
| mParameters.getStreamFormat(CAM_STREAM_TYPE_VIDEO,fmt); |
| if (mParameters.isUBWCEnabled() && (fmt == CAM_FORMAT_YUV_420_NV12_UBWC)) { |
| usage = private_handle_t::PRIV_FLAGS_UBWC_ALIGNED; |
| } |
| videoMemory->setVideoInfo(usage, fmt); |
| mem = videoMemory; |
| } |
| break; |
| case CAM_STREAM_TYPE_CALLBACK: |
| mem = new QCameraStreamMemory(mGetMemory, |
| bCachedMem, |
| (bPoolMem) ? &m_memoryPool : NULL, |
| stream_type); |
| break; |
| case CAM_STREAM_TYPE_DEFAULT: |
| case CAM_STREAM_TYPE_MAX: |
| default: |
| break; |
| } |
| if (!mem) { |
| return NULL; |
| } |
| |
| if (bufferCnt > 0) { |
| if (mParameters.isSecureMode() && |
| (stream_type == CAM_STREAM_TYPE_RAW) && |
| (mParameters.isRdiMode())) { |
| LOGD("Allocating %d secure buffers of size %d ", bufferCnt, size); |
| rc = mem->allocate(bufferCnt, size, SECURE); |
| } else { |
| rc = mem->allocate(bufferCnt, size, NON_SECURE); |
| } |
| if (rc < 0) { |
| delete mem; |
| return NULL; |
| } |
| bufferCnt = mem->getCnt(); |
| } |
| LOGH("rc = %d type = %d count = %d size = %d cache = %d, pool = %d", |
| rc, stream_type, bufferCnt, size, bCachedMem, bPoolMem); |
| return mem; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : allocateMoreStreamBuf |
| * |
| * DESCRIPTION: alocate more stream buffers from the memory object |
| * |
| * PARAMETERS : |
| * @mem_obj : memory object ptr |
| * @size : size of buffer |
| * @bufferCnt : [IN/OUT] additional number of buffers to be allocated. |
| * output will be the number of total buffers |
| * |
| * RETURN : int32_t type of status |
| * NO_ERROR -- success |
| * none-zero failure code |
| *==========================================================================*/ |
| int32_t QCamera2HardwareInterface::allocateMoreStreamBuf( |
| QCameraMemory *mem_obj, size_t size, uint8_t &bufferCnt) |
| { |
| int rc = NO_ERROR; |
| |
| if (bufferCnt > 0) { |
| rc = mem_obj->allocateMore(bufferCnt, size); |
| bufferCnt = mem_obj->getCnt(); |
| } |
| return rc; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : allocateMiscBuf |
| * |
| * DESCRIPTION: alocate miscellaneous buffer |
| * |
| * PARAMETERS : |
| * @streamInfo : stream info |
| * |
| * RETURN : ptr to a memory obj that holds stream info buffer. |
| * NULL if failed |
| *==========================================================================*/ |
| QCameraHeapMemory *QCamera2HardwareInterface::allocateMiscBuf( |
| cam_stream_info_t *streamInfo) |
| { |
| int rc = NO_ERROR; |
| uint8_t bufNum = 0; |
| size_t bufSize = 0; |
| QCameraHeapMemory *miscBuf = NULL; |
| cam_feature_mask_t feature_mask = |
| streamInfo->reprocess_config.pp_feature_config.feature_mask; |
| |
| switch (streamInfo->stream_type) { |
| case CAM_STREAM_TYPE_OFFLINE_PROC: |
| if (CAM_QCOM_FEATURE_TRUEPORTRAIT & feature_mask) { |
| bufNum = 1; |
| bufSize = mParameters.getTPMaxMetaSize(); |
| } else if (CAM_QCOM_FEATURE_REFOCUS & feature_mask) { |
| bufNum = 1; |
| bufSize = mParameters.getRefocusMaxMetaSize(); |
| } |
| break; |
| default: |
| break; |
| } |
| |
| if (bufNum && bufSize) { |
| miscBuf = new QCameraHeapMemory(QCAMERA_ION_USE_CACHE); |
| |
| if (!miscBuf) { |
| LOGE("Unable to allocate miscBuf object"); |
| return NULL; |
| } |
| |
| rc = miscBuf->allocate(bufNum, bufSize, NON_SECURE); |
| if (rc < 0) { |
| LOGE("Failed to allocate misc buffer memory"); |
| delete miscBuf; |
| return NULL; |
| } |
| } |
| |
| return miscBuf; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : initStreamInfoBuf |
| * |
| * DESCRIPTION: initialize stream info buffer based on stream type |
| * |
| * PARAMETERS : |
| * @stream_type : type of stream |
| * |
| * RETURN : ptr to a memory obj that holds stream info buffer. |
| * NULL if failed |
| *==========================================================================*/ |
| int QCamera2HardwareInterface::initStreamInfoBuf(cam_stream_type_t stream_type, |
| cam_stream_info_t *streamInfo) |
| { |
| int rc = NO_ERROR; |
| int32_t dt = 0; |
| int32_t vc = 0; |
| |
| memset(streamInfo, 0, sizeof(cam_stream_info_t)); |
| streamInfo->stream_type = stream_type; |
| rc = mParameters.getStreamFormat(stream_type, streamInfo->fmt); |
| rc = mParameters.getStreamDimension(stream_type, streamInfo->dim); |
| rc = mParameters.getStreamRotation(stream_type, streamInfo->pp_config, streamInfo->dim); |
| streamInfo->num_bufs = getBufNumRequired(stream_type); |
| streamInfo->buf_cnt = streamInfo->num_bufs; |
| streamInfo->streaming_mode = CAM_STREAMING_MODE_CONTINUOUS; |
| streamInfo->is_secure = NON_SECURE; |
| |
| switch (stream_type) { |
| case CAM_STREAM_TYPE_SNAPSHOT: |
| if ((mParameters.isZSLMode() && mParameters.getRecordingHintValue() != true) || |
| mLongshotEnabled) { |
| streamInfo->streaming_mode = CAM_STREAMING_MODE_CONTINUOUS; |
| } else { |
| streamInfo->streaming_mode = CAM_STREAMING_MODE_BURST; |
| streamInfo->num_of_burst = (uint8_t) |
| (mParameters.getNumOfSnapshots() |
| + mParameters.getNumOfExtraHDRInBufsIfNeeded() |
| - mParameters.getNumOfExtraHDROutBufsIfNeeded() |
| + mParameters.getNumOfExtraBuffersForImageProc()); |
| } |
| break; |
| case CAM_STREAM_TYPE_RAW: { |
| char value[PROPERTY_VALUE_MAX]; |
| bool raw_yuv = false; |
| property_get("persist.camera.raw_yuv", value, "0"); |
| raw_yuv = atoi(value) > 0 ? true : false; |
| if ((mParameters.isZSLMode()) || (isRdiMode()) || (raw_yuv)) { |
| streamInfo->streaming_mode = CAM_STREAMING_MODE_CONTINUOUS; |
| } else { |
| streamInfo->streaming_mode = CAM_STREAMING_MODE_BURST; |
| streamInfo->num_of_burst = mParameters.getNumOfSnapshots(); |
| } |
| if (mParameters.isSecureMode() && mParameters.isRdiMode()) { |
| streamInfo->is_secure = SECURE; |
| } else { |
| streamInfo->is_secure = NON_SECURE; |
| } |
| } |
| if (CAM_FORMAT_META_RAW_10BIT == streamInfo->fmt) { |
| mParameters.updateDtVc(&dt, &vc); |
| if (dt) |
| streamInfo->dt = dt; |
| streamInfo->vc = vc; |
| } |
| |
| break; |
| case CAM_STREAM_TYPE_POSTVIEW: |
| if (mLongshotEnabled) { |
| streamInfo->streaming_mode = CAM_STREAMING_MODE_CONTINUOUS; |
| } else { |
| streamInfo->streaming_mode = CAM_STREAMING_MODE_BURST; |
| streamInfo->num_of_burst = (uint8_t)(mParameters.getNumOfSnapshots() |
| + mParameters.getNumOfExtraHDRInBufsIfNeeded() |
| - mParameters.getNumOfExtraHDROutBufsIfNeeded() |
| + mParameters.getNumOfExtraBuffersForImageProc()); |
| } |
| break; |
| case CAM_STREAM_TYPE_VIDEO: |
| streamInfo->dis_enable = mParameters.isDISEnabled(); |
| if (mParameters.getBufBatchCount()) { |
| //Update stream info structure with batch mode info |
| streamInfo->streaming_mode = CAM_STREAMING_MODE_BATCH; |
| streamInfo->user_buf_info.frame_buf_cnt = mParameters.getBufBatchCount(); |
| streamInfo->user_buf_info.size = |
| (uint32_t)(sizeof(struct msm_camera_user_buf_cont_t)); |
| cam_fps_range_t pFpsRange; |
| mParameters.getHfrFps(pFpsRange); |
| streamInfo->user_buf_info.frameInterval = |
| (long)((1000/pFpsRange.video_max_fps) * 1000); |
| LOGH("Video Batch Count = %d, interval = %d", |
| streamInfo->user_buf_info.frame_buf_cnt, |
| streamInfo->user_buf_info.frameInterval); |
| } |
| if (mParameters.getRecordingHintValue()) { |
| if(mParameters.isDISEnabled()) { |
| streamInfo->is_type = mParameters.getVideoISType(); |
| } else { |
| streamInfo->is_type = IS_TYPE_NONE; |
| } |
| } |
| if (mParameters.isSecureMode()) { |
| streamInfo->is_secure = SECURE; |
| } |
| break; |
| case CAM_STREAM_TYPE_PREVIEW: |
| if (mParameters.getRecordingHintValue()) { |
| if(mParameters.isDISEnabled()) { |
| streamInfo->is_type = mParameters.getPreviewISType(); |
| } else { |
| streamInfo->is_type = IS_TYPE_NONE; |
| } |
| } |
| if (mParameters.isSecureMode()) { |
| streamInfo->is_secure = SECURE; |
| } |
| break; |
| case CAM_STREAM_TYPE_ANALYSIS: |
| streamInfo->noFrameExpected = 1; |
| break; |
| default: |
| break; |
| } |
| |
| // Update feature mask |
| mParameters.updatePpFeatureMask(stream_type); |
| |
| // Get feature mask |
| mParameters.getStreamPpMask(stream_type, streamInfo->pp_config.feature_mask); |
| |
| // Update pp config |
| if (streamInfo->pp_config.feature_mask & CAM_QCOM_FEATURE_FLIP) { |
| int flipMode = mParameters.getFlipMode(stream_type); |
| if (flipMode > 0) { |
| streamInfo->pp_config.flip = (uint32_t)flipMode; |
| } |
| } |
| if (streamInfo->pp_config.feature_mask & CAM_QCOM_FEATURE_SHARPNESS) { |
| streamInfo->pp_config.sharpness = mParameters.getSharpness(); |
| } |
| if (streamInfo->pp_config.feature_mask & CAM_QCOM_FEATURE_EFFECT) { |
| streamInfo->pp_config.effect = mParameters.getEffectValue(); |
| } |
| |
| if (streamInfo->pp_config.feature_mask & CAM_QCOM_FEATURE_DENOISE2D) { |
| streamInfo->pp_config.denoise2d.denoise_enable = 1; |
| streamInfo->pp_config.denoise2d.process_plates = |
| mParameters.getDenoiseProcessPlate(CAM_INTF_PARM_WAVELET_DENOISE); |
| } |
| |
| if (!((needReprocess()) && (CAM_STREAM_TYPE_SNAPSHOT == stream_type || |
| CAM_STREAM_TYPE_RAW == stream_type))) { |
| if (gCamCapability[mCameraId]->qcom_supported_feature_mask & |
| CAM_QCOM_FEATURE_CROP) |
| streamInfo->pp_config.feature_mask |= CAM_QCOM_FEATURE_CROP; |
| if (gCamCapability[mCameraId]->qcom_supported_feature_mask & |
| CAM_QCOM_FEATURE_SCALE) |
| streamInfo->pp_config.feature_mask |= CAM_QCOM_FEATURE_SCALE; |
| } |
| streamInfo->aux_str_info = NULL; |
| |
| LOGH("type %d, fmt %d, dim %dx%d, num_bufs %d mask = 0x%x is_type %d\n", |
| stream_type, streamInfo->fmt, streamInfo->dim.width, |
| streamInfo->dim.height, streamInfo->num_bufs, |
| streamInfo->pp_config.feature_mask, |
| streamInfo->is_type); |
| |
| return rc; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : allocateStreamInfoBuf |
| * |
| * DESCRIPTION: alocate stream info buffer |
| * |
| * PARAMETERS : |
| * @stream_type : type of stream |
| * @bufCount : stream info buffer count |
| * |
| * RETURN : ptr to a memory obj that holds stream info buffer. |
| * NULL if failed |
| *==========================================================================*/ |
| QCameraHeapMemory *QCamera2HardwareInterface::allocateStreamInfoBuf( |
| cam_stream_type_t stream_type, uint8_t bufCount) |
| { |
| int rc = NO_ERROR; |
| |
| QCameraHeapMemory *streamInfoBuf = new QCameraHeapMemory(QCAMERA_ION_USE_CACHE); |
| if (!streamInfoBuf) { |
| LOGE("allocateStreamInfoBuf: Unable to allocate streamInfo object"); |
| return NULL; |
| } |
| |
| if (bufCount > MM_CAMERA_MAX_CAM_CNT) { |
| LOGE("buffer count should be lesser than max camera : %d", bufCount); |
| return NULL; |
| } |
| rc = streamInfoBuf->allocate(bufCount, sizeof(cam_stream_info_t), NON_SECURE); |
| if (rc < 0) { |
| LOGE("allocateStreamInfoBuf: Failed to allocate stream info memory"); |
| delete streamInfoBuf; |
| return NULL; |
| } |
| |
| for (uint8_t i = 0; i < bufCount; i++) { |
| cam_stream_info_t *streamInfo = (cam_stream_info_t *)streamInfoBuf->getPtr(i); |
| memset(streamInfo, 0, sizeof(cam_stream_info_t)); |
| rc = initStreamInfoBuf(stream_type, streamInfo); |
| if (rc < 0) { |
| LOGE("initStreamInfoBuf failed"); |
| delete streamInfoBuf; |
| return NULL; |
| } |
| } |
| |
| cam_stream_info_t *streamInfo = (cam_stream_info_t *)streamInfoBuf->getPtr(0); |
| if (bufCount == MM_CAMERA_MAX_CAM_CNT) { |
| cam_stream_info_t *s_streamInfo = (cam_stream_info_t *)streamInfoBuf->getPtr(1); |
| streamInfo->aux_str_info = s_streamInfo; |
| } |
| |
| if (streamInfo->aux_str_info != NULL) { |
| /*Update StreamInfo for Aux camera*/ |
| streamInfo->aux_str_info->buf_cnt = getBufNumForAux(stream_type); |
| streamInfo->num_bufs += streamInfo->aux_str_info->buf_cnt; |
| streamInfo->aux_str_info->num_bufs += streamInfo->aux_str_info->buf_cnt; |
| } |
| return streamInfoBuf; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : allocateStreamUserBuf |
| * |
| * DESCRIPTION: allocate user ptr for stream buffers |
| * |
| * PARAMETERS : |
| * @streamInfo : stream info structure |
| * |
| * RETURN : ptr to a memory obj that holds stream info buffer. |
| * NULL if failed |
| |
| *==========================================================================*/ |
| QCameraMemory *QCamera2HardwareInterface::allocateStreamUserBuf( |
| cam_stream_info_t *streamInfo) |
| { |
| int rc = NO_ERROR; |
| QCameraMemory *mem = NULL; |
| int size = 0; |
| |
| if (streamInfo->streaming_mode != CAM_STREAMING_MODE_BATCH) { |
| LOGE("Stream is not in BATCH mode. Invalid Stream"); |
| return NULL; |
| } |
| |
| // Allocate stream user buffer memory object |
| switch (streamInfo->stream_type) { |
| case CAM_STREAM_TYPE_VIDEO: { |
| QCameraVideoMemory *video_mem = new QCameraVideoMemory( |
| mGetMemory, FALSE, QCAMERA_MEM_TYPE_BATCH); |
| if (video_mem == NULL) { |
| LOGE("Out of memory for video obj"); |
| return NULL; |
| } |
| /* |
| * numFDs = BATCH size |
| * numInts = 5 // OFFSET, SIZE, USAGE, TIMESTAMP, FORMAT |
| */ |
| rc = video_mem->allocateMeta(streamInfo->num_bufs, |
| mParameters.getBufBatchCount(), VIDEO_METADATA_NUM_INTS); |
| if (rc < 0) { |
| LOGE("allocateMeta failed"); |
| delete video_mem; |
| return NULL; |
| } |
| int usage = 0; |
| cam_format_t fmt; |
| mParameters.getStreamFormat(CAM_STREAM_TYPE_VIDEO, fmt); |
| if(mParameters.isUBWCEnabled() && (fmt == CAM_FORMAT_YUV_420_NV12_UBWC)) { |
| usage = private_handle_t::PRIV_FLAGS_UBWC_ALIGNED; |
| } |
| video_mem->setVideoInfo(usage, fmt); |
| mem = static_cast<QCameraMemory *>(video_mem); |
| } |
| break; |
| |
| case CAM_STREAM_TYPE_PREVIEW: |
| case CAM_STREAM_TYPE_POSTVIEW: |
| case CAM_STREAM_TYPE_ANALYSIS: |
| case CAM_STREAM_TYPE_SNAPSHOT: |
| case CAM_STREAM_TYPE_RAW: |
| case CAM_STREAM_TYPE_METADATA: |
| case CAM_STREAM_TYPE_OFFLINE_PROC: |
| case CAM_STREAM_TYPE_CALLBACK: |
| LOGE("Stream type Not supported.for BATCH processing"); |
| break; |
| |
| case CAM_STREAM_TYPE_DEFAULT: |
| case CAM_STREAM_TYPE_MAX: |
| default: |
| break; |
| } |
| if (!mem) { |
| LOGE("Failed to allocate mem"); |
| return NULL; |
| } |
| |
| /*Size of this buffer will be number of batch buffer */ |
| size = PAD_TO_SIZE((streamInfo->num_bufs * streamInfo->user_buf_info.size), |
| CAM_PAD_TO_4K); |
| |
| LOGH("Allocating BATCH Buffer count = %d", streamInfo->num_bufs); |
| |
| if (size > 0) { |
| // Allocating one buffer for all batch buffers |
| rc = mem->allocate(1, size, NON_SECURE); |
| if (rc < 0) { |
| delete mem; |
| return NULL; |
| } |
| } |
| return mem; |
| } |
| |
| |
| /*=========================================================================== |
| * FUNCTION : waitForDeferredAlloc |
| * |
| * DESCRIPTION: Wait for deferred allocation, if applicable |
| * (applicable only for metadata buffers so far) |
| * |
| * PARAMETERS : |
| * @stream_type : type of stream to (possibly) wait for |
| * |
| * RETURN : None |
| *==========================================================================*/ |
| void QCamera2HardwareInterface::waitForDeferredAlloc(cam_stream_type_t stream_type) |
| { |
| if (stream_type == CAM_STREAM_TYPE_METADATA) { |
| waitDeferredWork(mMetadataAllocJob); |
| } |
| } |
| |
| |
| /*=========================================================================== |
| * FUNCTION : setPreviewWindow |
| * |
| * DESCRIPTION: set preview window impl |
| * |
| * PARAMETERS : |
| * @window : ptr to window ops table struct |
| * |
| * RETURN : int32_t type of status |
| * NO_ERROR -- success |
| * none-zero failure code |
| *==========================================================================*/ |
| int QCamera2HardwareInterface::setPreviewWindow( |
| struct preview_stream_ops *window) |
| { |
| mPreviewWindow = window; |
| return NO_ERROR; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : setCallBacks |
| * |
| * DESCRIPTION: set callbacks impl |
| * |
| * PARAMETERS : |
| * @notify_cb : notify cb |
| * @data_cb : data cb |
| * @data_cb_timestamp : data cb with time stamp |
| * @get_memory : request memory ops table |
| * @user : user data ptr |
| * |
| * RETURN : int32_t type of status |
| * NO_ERROR -- success |
| * none-zero failure code |
| *==========================================================================*/ |
| int QCamera2HardwareInterface::setCallBacks(camera_notify_callback notify_cb, |
| camera_data_callback data_cb, |
| camera_data_timestamp_callback data_cb_timestamp, |
| camera_request_memory get_memory, |
| void *user) |
| { |
| mNotifyCb = notify_cb; |
| mDataCb = data_cb; |
| mDataCbTimestamp = data_cb_timestamp; |
| mGetMemory = get_memory; |
| mCallbackCookie = user; |
| m_cbNotifier.setCallbacks(notify_cb, data_cb, data_cb_timestamp, user); |
| return NO_ERROR; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : setJpegCallBacks |
| * |
| * DESCRIPTION: set JPEG callbacks impl |
| * |
| * PARAMETERS : |
| * @jpegCb : Jpeg callback method |
| * @callbackCookie : callback cookie |
| * |
| * RETURN : int32_t type of status |
| * NO_ERROR -- success |
| * none-zero failure code |
| *==========================================================================*/ |
| void QCamera2HardwareInterface::setJpegCallBacks(jpeg_data_callback jpegCb, |
| void *callbackCookie) |
| { |
| LOGH("camera id %d", getCameraId()); |
| mJpegCb = jpegCb; |
| mJpegCallbackCookie = callbackCookie; |
| m_cbNotifier.setJpegCallBacks(mJpegCb, mJpegCallbackCookie); |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : enableMsgType |
| * |
| * DESCRIPTION: enable msg type impl |
| * |
| * PARAMETERS : |
| * @msg_type : msg type mask to be enabled |
| * |
| * RETURN : int32_t type of status |
| * NO_ERROR -- success |
| * none-zero failure code |
| *==========================================================================*/ |
| int QCamera2HardwareInterface::enableMsgType(int32_t msg_type) |
| { |
| int32_t rc = NO_ERROR; |
| |
| if (mParameters.isUBWCEnabled()) { |
| /*Need Special CALLBACK stream incase application requesting for |
| Preview callback in UBWC case*/ |
| if (!(msgTypeEnabled(CAMERA_MSG_PREVIEW_FRAME)) && |
| (msg_type & CAMERA_MSG_PREVIEW_FRAME)) { |
| // Start callback channel only when preview/zsl channel is active |
| QCameraChannel* previewCh = NULL; |
| if (isZSLMode() && (getRecordingHintValue() != true)) { |
| previewCh = m_channels[QCAMERA_CH_TYPE_ZSL]; |
| } else { |
| previewCh = m_channels[QCAMERA_CH_TYPE_PREVIEW]; |
| } |
| QCameraChannel* callbackCh = m_channels[QCAMERA_CH_TYPE_CALLBACK]; |
| if ((callbackCh != NULL) && |
| (previewCh != NULL) && previewCh->isActive()) { |
| rc = startChannel(QCAMERA_CH_TYPE_CALLBACK); |
| if (rc != NO_ERROR) { |
| LOGE("START Callback Channel failed"); |
| } |
| } |
| } |
| } |
| mMsgEnabled |= msg_type; |
| LOGH("(0x%x) : mMsgEnabled = 0x%x rc = %d", msg_type , mMsgEnabled, rc); |
| return rc; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : disableMsgType |
| * |
| * DESCRIPTION: disable msg type impl |
| * |
| * PARAMETERS : |
| * @msg_type : msg type mask to be disabled |
| * |
| * RETURN : int32_t type of status |
| * NO_ERROR -- success |
| * none-zero failure code |
| *==========================================================================*/ |
| int QCamera2HardwareInterface::disableMsgType(int32_t msg_type) |
| { |
| int32_t rc = NO_ERROR; |
| |
| if (mParameters.isUBWCEnabled()) { |
| /*STOP CALLBACK STREAM*/ |
| if ((msgTypeEnabled(CAMERA_MSG_PREVIEW_FRAME)) && |
| (msg_type & CAMERA_MSG_PREVIEW_FRAME)) { |
| // Stop callback channel only if it is active |
| if ((m_channels[QCAMERA_CH_TYPE_CALLBACK] != NULL) && |
| (m_channels[QCAMERA_CH_TYPE_CALLBACK]->isActive())) { |
| rc = stopChannel(QCAMERA_CH_TYPE_CALLBACK); |
| if (rc != NO_ERROR) { |
| LOGE("STOP Callback Channel failed"); |
| } |
| } |
| } |
| } |
| mMsgEnabled &= ~msg_type; |
| LOGH("(0x%x) : mMsgEnabled = 0x%x rc = %d", msg_type , mMsgEnabled, rc); |
| return rc; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : msgTypeEnabled |
| * |
| * DESCRIPTION: impl to determine if certain msg_type is enabled |
| * |
| * PARAMETERS : |
| * @msg_type : msg type mask |
| * |
| * RETURN : 0 -- not enabled |
| * none 0 -- enabled |
| *==========================================================================*/ |
| int QCamera2HardwareInterface::msgTypeEnabled(int32_t msg_type) |
| { |
| return (mMsgEnabled & msg_type); |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : msgTypeEnabledWithLock |
| * |
| * DESCRIPTION: impl to determine if certain msg_type is enabled with lock |
| * |
| * PARAMETERS : |
| * @msg_type : msg type mask |
| * |
| * RETURN : 0 -- not enabled |
| * none 0 -- enabled |
| *==========================================================================*/ |
| int QCamera2HardwareInterface::msgTypeEnabledWithLock(int32_t msg_type) |
| { |
| int enabled = 0; |
| lockAPI(); |
| enabled = mMsgEnabled & msg_type; |
| unlockAPI(); |
| return enabled; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : startPreview |
| * |
| * DESCRIPTION: start preview impl |
| * |
| * PARAMETERS : none |
| * |
| * RETURN : int32_t type of status |
| * NO_ERROR -- success |
| * none-zero failure code |
| *==========================================================================*/ |
| int QCamera2HardwareInterface::startPreview() |
| { |
| KPI_ATRACE_CALL(); |
| int32_t rc = NO_ERROR; |
| |
| LOGI("E ZSL = %d Recording Hint = %d", mParameters.isZSLMode(), |
| mParameters.getRecordingHintValue()); |
| |
| m_perfLock.lock_acq(); |
| |
| updateThermalLevel((void *)&mThermalLevel); |
| |
| setDisplayFrameSkip(); |
| |
| // start preview stream |
| if (mParameters.isZSLMode() && mParameters.getRecordingHintValue() != true) { |
| rc = startChannel(QCAMERA_CH_TYPE_ZSL); |
| } else { |
| rc = startChannel(QCAMERA_CH_TYPE_PREVIEW); |
| } |
| |
| if (rc != NO_ERROR) { |
| LOGE("failed to start channels"); |
| m_perfLock.lock_rel(); |
| return rc; |
| } |
| |
| if ((msgTypeEnabled(CAMERA_MSG_PREVIEW_FRAME)) |
| && (m_channels[QCAMERA_CH_TYPE_CALLBACK] != NULL)) { |
| rc = startChannel(QCAMERA_CH_TYPE_CALLBACK); |
| if (rc != NO_ERROR) { |
| LOGE("failed to start callback stream"); |
| stopChannel(QCAMERA_CH_TYPE_ZSL); |
| stopChannel(QCAMERA_CH_TYPE_PREVIEW); |
| m_perfLock.lock_rel(); |
| return rc; |
| } |
| } |
| |
| updatePostPreviewParameters(); |
| m_stateMachine.setPreviewCallbackNeeded(true); |
| |
| // if job id is non-zero, that means the postproc init job is already |
| // pending or complete |
| if (mInitPProcJob == 0) { |
| mInitPProcJob = deferPPInit(); |
| if (mInitPProcJob == 0) { |
| LOGE("Unable to initialize postprocessor, mCameraHandle = %p", |
| mCameraHandle); |
| rc = -ENOMEM; |
| m_perfLock.lock_rel(); |
| return rc; |
| } |
| } |
| m_perfLock.lock_rel(); |
| |
| if (rc == NO_ERROR) { |
| // Set power Hint for preview |
| m_perfLock.powerHint(POWER_HINT_VIDEO_ENCODE, true); |
| } |
| |
| LOGI("X rc = %d", rc); |
| return rc; |
| } |
| |
| int32_t QCamera2HardwareInterface::updatePostPreviewParameters() { |
| // Enable OIS only in Camera mode and 4k2k camcoder mode |
| int32_t rc = NO_ERROR; |
| rc = mParameters.updateOisValue(1); |
| return NO_ERROR; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : stopPreview |
| * |
| * DESCRIPTION: stop preview impl |
| * |
| * PARAMETERS : none |
| * |
| * RETURN : int32_t type of status |
| * NO_ERROR -- success |
| * none-zero failure code |
| *==========================================================================*/ |
| int QCamera2HardwareInterface::stopPreview() |
| { |
| KPI_ATRACE_CALL(); |
| LOGI("E"); |
| mNumPreviewFaces = -1; |
| mActiveAF = false; |
| |
| // Disable power Hint for preview |
| m_perfLock.powerHint(POWER_HINT_VIDEO_ENCODE, false); |
| |
| m_perfLock.lock_acq(); |
| |
| // stop preview stream |
| stopChannel(QCAMERA_CH_TYPE_CALLBACK); |
| stopChannel(QCAMERA_CH_TYPE_ZSL); |
| stopChannel(QCAMERA_CH_TYPE_PREVIEW); |
| stopChannel(QCAMERA_CH_TYPE_RAW); |
| |
| m_cbNotifier.flushPreviewNotifications(); |
| //add for ts makeup |
| #ifdef TARGET_TS_MAKEUP |
| ts_makeup_finish(); |
| #endif |
| // delete all channels from preparePreview |
| unpreparePreview(); |
| |
| m_perfLock.lock_rel(); |
| |
| LOGI("X"); |
| return NO_ERROR; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : storeMetaDataInBuffers |
| * |
| * DESCRIPTION: enable store meta data in buffers for video frames impl |
| * |
| * PARAMETERS : |
| * @enable : flag if need enable |
| * |
| * RETURN : int32_t type of status |
| * NO_ERROR -- success |
| * none-zero failure code |
| *==========================================================================*/ |
| int QCamera2HardwareInterface::storeMetaDataInBuffers(int enable) |
| { |
| mStoreMetaDataInFrame = enable; |
| return NO_ERROR; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : preStartRecording |
| * |
| * DESCRIPTION: Prepare start recording impl |
| * |
| * PARAMETERS : none |
| * |
| * RETURN : int32_t type of status |
| * NO_ERROR -- success |
| * none-zero failure code |
| *==========================================================================*/ |
| int QCamera2HardwareInterface::preStartRecording() |
| { |
| int32_t rc = NO_ERROR; |
| LOGH("E"); |
| if (mParameters.getRecordingHintValue() == false) { |
| |
| // Give HWI control to restart preview only in single camera mode. |
| // In dual-cam mode, this control belongs to muxer. |
| if (getRelatedCamSyncInfo()->sync_control != CAM_SYNC_RELATED_SENSORS_ON) { |
| LOGH("start recording when hint is false, stop preview first"); |
| stopPreview(); |
| |
| // Set recording hint to TRUE |
| mParameters.updateRecordingHintValue(TRUE); |
| rc = preparePreview(); |
| if (rc == NO_ERROR) { |
| rc = startPreview(); |
| } |
| } |
| else |
| { |
| // For dual cam mode, update the flag mPreviewRestartNeeded to true |
| // Restart control will be handled by muxer. |
| mPreviewRestartNeeded = true; |
| } |
| } |
| |
| LOGH("X rc = %d", rc); |
| return rc; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : startRecording |
| * |
| * DESCRIPTION: start recording impl |
| * |
| * PARAMETERS : none |
| * |
| * RETURN : int32_t type of status |
| * NO_ERROR -- success |
| * none-zero failure code |
| *==========================================================================*/ |
| int QCamera2HardwareInterface::startRecording() |
| { |
| int32_t rc = NO_ERROR; |
| |
| LOGI("E"); |
| //link meta stream with video channel if low power mode. |
| if (isLowPowerMode()) { |
| // Find and try to link a metadata stream from preview channel |
| QCameraChannel *pMetaChannel = NULL; |
| QCameraStream *pMetaStream = NULL; |
| QCameraChannel *pVideoChannel = m_channels[QCAMERA_CH_TYPE_VIDEO]; |
| |
| if (m_channels[QCAMERA_CH_TYPE_PREVIEW] != NULL) { |
| pMetaChannel = m_channels[QCAMERA_CH_TYPE_PREVIEW]; |
| uint32_t streamNum = pMetaChannel->getNumOfStreams(); |
| QCameraStream *pStream = NULL; |
| for (uint32_t i = 0 ; i < streamNum ; i++ ) { |
| pStream = pMetaChannel->getStreamByIndex(i); |
| if ((NULL != pStream) && |
| (CAM_STREAM_TYPE_METADATA == pStream->getMyType())) { |
| pMetaStream = pStream; |
| break; |
| } |
| } |
| } |
| |
| if ((NULL != pMetaChannel) && (NULL != pMetaStream)) { |
| rc = pVideoChannel->linkStream(pMetaChannel, pMetaStream); |
| if (NO_ERROR != rc) { |
| LOGW("Metadata stream link failed %d", rc); |
| } |
| } |
| } |
| |
| if (rc == NO_ERROR) { |
| rc = startChannel(QCAMERA_CH_TYPE_VIDEO); |
| } |
| |
| if (mParameters.isTNRSnapshotEnabled() && !isLowPowerMode()) { |
| QCameraChannel *pChannel = m_channels[QCAMERA_CH_TYPE_SNAPSHOT]; |
| if (!mParameters.is4k2kVideoResolution()) { |
| // Find and try to link a metadata stream from preview channel |
| QCameraChannel *pMetaChannel = NULL; |
| QCameraStream *pMetaStream = NULL; |
| |
| if (m_channels[QCAMERA_CH_TYPE_PREVIEW] != NULL) { |
| pMetaChannel = m_channels[QCAMERA_CH_TYPE_PREVIEW]; |
| uint32_t streamNum = pMetaChannel->getNumOfStreams(); |
| QCameraStream *pStream = NULL; |
| for (uint32_t i = 0 ; i < streamNum ; i++ ) { |
| pStream = pMetaChannel->getStreamByIndex(i); |
| if ((NULL != pStream) && |
| (CAM_STREAM_TYPE_METADATA == |
| pStream->getMyType())) { |
| pMetaStream = pStream; |
| break; |
| } |
| } |
| } |
| |
| if ((NULL != pMetaChannel) && (NULL != pMetaStream)) { |
| rc = pChannel->linkStream(pMetaChannel, pMetaStream); |
| if (NO_ERROR != rc) { |
| LOGW("Metadata stream link failed %d", rc); |
| } |
| } |
| } |
| LOGH("START snapshot Channel for TNR processing"); |
| rc = pChannel->start(); |
| } |
| |
| if (rc == NO_ERROR) { |
| // Set power Hint for video encoding |
| m_perfLock.powerHint(POWER_HINT_VIDEO_ENCODE, true); |
| } |
| |
| LOGI("X rc = %d", rc); |
| return rc; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : stopRecording |
| * |
| * DESCRIPTION: stop recording impl |
| * |
| * PARAMETERS : none |
| * |
| * RETURN : int32_t type of status |
| * NO_ERROR -- success |
| * none-zero failure code |
| *==========================================================================*/ |
| int QCamera2HardwareInterface::stopRecording() |
| { |
| LOGI("E"); |
| // stop snapshot channel |
| if (mParameters.isTNRSnapshotEnabled()) { |
| LOGH("STOP snapshot Channel for TNR processing"); |
| stopChannel(QCAMERA_CH_TYPE_SNAPSHOT); |
| } |
| int rc = stopChannel(QCAMERA_CH_TYPE_VIDEO); |
| |
| m_cbNotifier.flushVideoNotifications(); |
| // Disable power hint for video encoding |
| m_perfLock.powerHint(POWER_HINT_VIDEO_ENCODE, false); |
| LOGI("X rc = %d", rc); |
| return rc; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : releaseRecordingFrame |
| * |
| * DESCRIPTION: return video frame impl |
| * |
| * PARAMETERS : |
| * @opaque : ptr to video frame to be returned |
| * |
| * RETURN : int32_t type of status |
| * NO_ERROR -- success |
| * none-zero failure code |
| *==========================================================================*/ |
| int QCamera2HardwareInterface::releaseRecordingFrame(const void * opaque) |
| { |
| int32_t rc = UNKNOWN_ERROR; |
| QCameraVideoChannel *pChannel = |
| (QCameraVideoChannel *)m_channels[QCAMERA_CH_TYPE_VIDEO]; |
| LOGD("opaque data = %p",opaque); |
| |
| if(pChannel != NULL) { |
| rc = pChannel->releaseFrame(opaque, mStoreMetaDataInFrame > 0); |
| } |
| return rc; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : autoFocus |
| * |
| * DESCRIPTION: start auto focus impl |
| * |
| * PARAMETERS : none |
| * |
| * RETURN : int32_t type of status |
| * NO_ERROR -- success |
| * none-zero failure code |
| *==========================================================================*/ |
| int QCamera2HardwareInterface::autoFocus() |
| { |
| int rc = NO_ERROR; |
| cam_focus_mode_type focusMode = mParameters.getFocusMode(); |
| LOGH("E"); |
| |
| switch (focusMode) { |
| case CAM_FOCUS_MODE_AUTO: |
| case CAM_FOCUS_MODE_MACRO: |
| case CAM_FOCUS_MODE_CONTINOUS_VIDEO: |
| case CAM_FOCUS_MODE_CONTINOUS_PICTURE: |
| mActiveAF = true; |
| LOGI("Send AUTO FOCUS event. focusMode=%d, m_currentFocusState=%d", |
| focusMode, m_currentFocusState); |
| rc = mCameraHandle->ops->do_auto_focus(mCameraHandle->camera_handle); |
| break; |
| case CAM_FOCUS_MODE_INFINITY: |
| case CAM_FOCUS_MODE_FIXED: |
| case CAM_FOCUS_MODE_EDOF: |
| default: |
| LOGI("No ops in focusMode (%d)", focusMode); |
| rc = sendEvtNotify(CAMERA_MSG_FOCUS, true, 0); |
| break; |
| } |
| |
| if (NO_ERROR != rc) { |
| mActiveAF = false; |
| } |
| LOGH("X rc = %d", rc); |
| return rc; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : cancelAutoFocus |
| * |
| * DESCRIPTION: cancel auto focus impl |
| * |
| * PARAMETERS : none |
| * |
| * RETURN : int32_t type of status |
| * NO_ERROR -- success |
| * none-zero failure code |
| *==========================================================================*/ |
| int QCamera2HardwareInterface::cancelAutoFocus() |
| { |
| int rc = NO_ERROR; |
| cam_focus_mode_type focusMode = mParameters.getFocusMode(); |
| |
| switch (focusMode) { |
| case CAM_FOCUS_MODE_AUTO: |
| case CAM_FOCUS_MODE_MACRO: |
| case CAM_FOCUS_MODE_CONTINOUS_VIDEO: |
| case CAM_FOCUS_MODE_CONTINOUS_PICTURE: |
| mActiveAF = false; |
| rc = mCameraHandle->ops->cancel_auto_focus(mCameraHandle->camera_handle); |
| break; |
| case CAM_FOCUS_MODE_INFINITY: |
| case CAM_FOCUS_MODE_FIXED: |
| case CAM_FOCUS_MODE_EDOF: |
| default: |
| LOGD("No ops in focusMode (%d)", focusMode); |
| break; |
| } |
| return rc; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : processUFDumps |
| * |
| * DESCRIPTION: process UF jpeg dumps for refocus support |
| * |
| * PARAMETERS : |
| * @evt : payload of jpeg event, including information about jpeg encoding |
| * status, jpeg size and so on. |
| * |
| * RETURN : int32_t type of status |
| * NO_ERROR -- success |
| * none-zero failure code |
| * |
| * NOTE : none |
| *==========================================================================*/ |
| bool QCamera2HardwareInterface::processUFDumps(qcamera_jpeg_evt_payload_t *evt) |
| { |
| bool ret = true; |
| if (mParameters.isUbiRefocus()) { |
| int index = (int)getOutputImageCount(); |
| bool allFocusImage = (index == ((int)mParameters.getRefocusOutputCount() - 1)); |
| char name[FILENAME_MAX]; |
| |
| camera_memory_t *jpeg_mem = NULL; |
| omx_jpeg_ouput_buf_t *jpeg_out = NULL; |
| size_t dataLen; |
| uint8_t *dataPtr; |
| if (NO_ERROR != waitDeferredWork(mInitPProcJob)) { |
| LOGE("Init PProc Deferred work failed"); |
| return false; |
| } |
| if (!m_postprocessor.getJpegMemOpt()) { |
| dataLen = evt->out_data.buf_filled_len; |
| dataPtr = evt->out_data.buf_vaddr; |
| } else { |
| jpeg_out = (omx_jpeg_ouput_buf_t*) evt->out_data.buf_vaddr; |
| if (!jpeg_out) { |
| LOGE("Null pointer detected"); |
| return false; |
| } |
| jpeg_mem = (camera_memory_t *)jpeg_out->mem_hdl; |
| if (!jpeg_mem) { |
| LOGE("Null pointer detected"); |
| return false; |
| } |
| dataPtr = (uint8_t *)jpeg_mem->data; |
| dataLen = jpeg_mem->size; |
| } |
| |
| if (allFocusImage) { |
| snprintf(name, sizeof(name), "AllFocusImage"); |
| index = -1; |
| } else { |
| snprintf(name, sizeof(name), "%d", 0); |
| } |
| CAM_DUMP_TO_FILE(QCAMERA_DUMP_FRM_LOCATION"ubifocus", name, index, "jpg", |
| dataPtr, dataLen); |
| LOGD("Dump the image %d %d allFocusImage %d", |
| getOutputImageCount(), index, allFocusImage); |
| setOutputImageCount(getOutputImageCount() + 1); |
| if (!allFocusImage) { |
| ret = false; |
| } |
| } |
| return ret; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : unconfigureAdvancedCapture |
| * |
| * DESCRIPTION: unconfigure Advanced Capture. |
| * |
| * PARAMETERS : none |
| * |
| * RETURN : int32_t type of status |
| * NO_ERROR -- success |
| * none-zero failure code |
| *==========================================================================*/ |
| int32_t QCamera2HardwareInterface::unconfigureAdvancedCapture() |
| { |
| int32_t rc = NO_ERROR; |
| |
| /*Disable Quadra CFA mode*/ |
| LOGH("Disabling Quadra CFA mode"); |
| mParameters.setQuadraCfaMode(false, true); |
| |
| if (mAdvancedCaptureConfigured) { |
| |
| mAdvancedCaptureConfigured = false; |
| |
| if(mIs3ALocked) { |
| mParameters.set3ALock(false); |
| mIs3ALocked = false; |
| } |
| if (mParameters.isHDREnabled() || mParameters.isAEBracketEnabled()) { |
| rc = mParameters.setToneMapMode(true, true); |
| if (rc != NO_ERROR) { |
| LOGW("Failed to enable tone map during HDR/AEBracketing"); |
| } |
| mHDRBracketingEnabled = false; |
| rc = mParameters.stopAEBracket(); |
| } else if ((mParameters.isChromaFlashEnabled()) |
| || (mFlashConfigured && !mLongshotEnabled) |
| || (mLowLightConfigured == true) |
| || (mParameters.getManualCaptureMode() >= CAM_MANUAL_CAPTURE_TYPE_2)) { |
| rc = mParameters.resetFrameCapture(TRUE, mLowLightConfigured); |
| } else if (mParameters.isUbiFocusEnabled() || mParameters.isUbiRefocus()) { |
| rc = configureAFBracketing(false); |
| } else if (mParameters.isOptiZoomEnabled()) { |
| rc = mParameters.setAndCommitZoom(mZoomLevel); |
| setDisplaySkip(FALSE, CAMERA_MAX_PARAM_APPLY_DELAY); |
| } else if (mParameters.isStillMoreEnabled()) { |
| cam_still_more_t stillmore_config = mParameters.getStillMoreSettings(); |
| stillmore_config.burst_count = 0; |
| mParameters.setStillMoreSettings(stillmore_config); |
| |
| /* If SeeMore is running, it will handle re-enabling tone map */ |
| if (!mParameters.isSeeMoreEnabled() && !mParameters.isLTMForSeeMoreEnabled()) { |
| rc = mParameters.setToneMapMode(true, true); |
| if (rc != NO_ERROR) { |
| LOGW("Failed to enable tone map during StillMore"); |
| } |
| } |
| |
| /* Re-enable Tintless */ |
| mParameters.setTintless(true); |
| } else { |
| LOGW("No Advanced Capture feature enabled!!"); |
| rc = BAD_VALUE; |
| } |
| } |
| |
| return rc; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : configureAdvancedCapture |
| * |
| * DESCRIPTION: configure Advanced Capture. |
| * |
| * PARAMETERS : none |
| * |
| * RETURN : int32_t type of status |
| * NO_ERROR -- success |
| * none-zero failure code |
| *==========================================================================*/ |
| int32_t QCamera2HardwareInterface::configureAdvancedCapture() |
| { |
| LOGH("E"); |
| int32_t rc = NO_ERROR; |
| |
| rc = mParameters.checkFeatureConcurrency(); |
| if (rc != NO_ERROR) { |
| LOGE("Cannot support Advanced capture modes"); |
| return rc; |
| } |
| /*Enable Quadra CFA mode*/ |
| LOGH("Enabling Quadra CFA mode"); |
| mParameters.setQuadraCfaMode(true, true); |
| |
| setOutputImageCount(0); |
| mInputCount = 0; |
| mAdvancedCaptureConfigured = true; |
| /* Display should be disabled for advanced modes */ |
| bool bSkipDisplay = true; |
| |
| if (getRelatedCamSyncInfo()->mode == CAM_MODE_SECONDARY) { |
| // no Advance capture settings for Aux camera |
| LOGH("X Secondary Camera, no need to process!! "); |
| return rc; |
| } |
| |
| /* Do not stop display if in stillmore livesnapshot */ |
| if (mParameters.isStillMoreEnabled() && |
| mParameters.isSeeMoreEnabled()) { |
| bSkipDisplay = false; |
| } |
| if (mParameters.isUbiFocusEnabled() || mParameters.isUbiRefocus()) { |
| rc = configureAFBracketing(); |
| } else if (mParameters.isOptiZoomEnabled()) { |
| rc = configureOptiZoom(); |
| } else if(mParameters.isHDREnabled()) { |
| rc = configureHDRBracketing(); |
| if (mHDRBracketingEnabled) { |
| rc = mParameters.setToneMapMode(false, true); |
| if (rc != NO_ERROR) { |
| LOGW("Failed to disable tone map during HDR"); |
| } |
| } |
| } else if (mParameters.isAEBracketEnabled()) { |
| rc = mParameters.setToneMapMode(false, true); |
| if (rc != NO_ERROR) { |
| LOGW("Failed to disable tone map during AEBracketing"); |
| } |
| rc = configureAEBracketing(); |
| } else if (mParameters.isStillMoreEnabled()) { |
| bSkipDisplay = false; |
| rc = configureStillMore(); |
| } else if ((mParameters.isChromaFlashEnabled()) |
| || (mParameters.getLowLightLevel() != CAM_LOW_LIGHT_OFF) |
| || (mParameters.getManualCaptureMode() >= CAM_MANUAL_CAPTURE_TYPE_2)) { |
| rc = mParameters.configFrameCapture(TRUE); |
| if (mParameters.getLowLightLevel() != CAM_LOW_LIGHT_OFF) { |
| mLowLightConfigured = true; |
| } |
| } else if (mFlashNeeded && !mLongshotEnabled) { |
| rc = mParameters.configFrameCapture(TRUE); |
| mFlashConfigured = true; |
| bSkipDisplay = false; |
| } else { |
| LOGH("Advanced Capture feature not enabled!! "); |
| mAdvancedCaptureConfigured = false; |
| bSkipDisplay = false; |
| } |
| |
| LOGH("Stop preview temporarily for advanced captures"); |
| setDisplaySkip(bSkipDisplay); |
| |
| LOGH("X rc = %d", rc); |
| return rc; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : configureAFBracketing |
| * |
| * DESCRIPTION: configure AF Bracketing. |
| * |
| * PARAMETERS : none |
| * |
| * RETURN : int32_t type of status |
| * NO_ERROR -- success |
| * none-zero failure code |
| *==========================================================================*/ |
| int32_t QCamera2HardwareInterface::configureAFBracketing(bool enable) |
| { |
| LOGH("E"); |
| int32_t rc = NO_ERROR; |
| cam_af_bracketing_t *af_bracketing_need; |
| |
| if (mParameters.isUbiRefocus()) { |
| af_bracketing_need = |
| &gCamCapability[mCameraId]->refocus_af_bracketing_need; |
| } else { |
| af_bracketing_need = |
| &gCamCapability[mCameraId]->ubifocus_af_bracketing_need; |
| } |
| |
| //Enable AF Bracketing. |
| cam_af_bracketing_t afBracket; |
| memset(&afBracket, 0, sizeof(cam_af_bracketing_t)); |
| afBracket.enable = enable; |
| afBracket.burst_count = af_bracketing_need->burst_count; |
| |
| for(int8_t i = 0; i < MAX_AF_BRACKETING_VALUES; i++) { |
| afBracket.focus_steps[i] = af_bracketing_need->focus_steps[i]; |
| LOGH("focus_step[%d] = %d", i, afBracket.focus_steps[i]); |
| } |
| //Send cmd to backend to set AF Bracketing for Ubi Focus. |
| rc = mParameters.commitAFBracket(afBracket); |
| if ( NO_ERROR != rc ) { |
| LOGE("cannot configure AF bracketing"); |
| return rc; |
| } |
| if (enable) { |
| mParameters.set3ALock(true); |
| mIs3ALocked = true; |
| } |
| LOGH("X rc = %d", rc); |
| return rc; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : configureHDRBracketing |
| * |
| * DESCRIPTION: configure HDR Bracketing. |
| * |
| * PARAMETERS : none |
| * |
| * RETURN : int32_t type of status |
| * NO_ERROR -- success |
| * none-zero failure code |
| *==========================================================================*/ |
| int32_t QCamera2HardwareInterface::configureHDRBracketing() |
| { |
| LOGH("E"); |
| int32_t rc = NO_ERROR; |
| |
| cam_hdr_bracketing_info_t& hdrBracketingSetting = |
| gCamCapability[mCameraId]->hdr_bracketing_setting; |
| |
| // 'values' should be in "idx1,idx2,idx3,..." format |
| uint32_t hdrFrameCount = |
| hdrBracketingSetting.num_frames; |
| LOGH("HDR values %d, %d frame count: %u", |
| (int8_t) hdrBracketingSetting.exp_val.values[0], |
| (int8_t) hdrBracketingSetting.exp_val.values[1], |
| hdrFrameCount); |
| |
| // Enable AE Bracketing for HDR |
| cam_exp_bracketing_t aeBracket; |
| memset(&aeBracket, 0, sizeof(cam_exp_bracketing_t)); |
| aeBracket.mode = |
| hdrBracketingSetting.exp_val.mode; |
| |
| if (aeBracket.mode == CAM_EXP_BRACKETING_ON) { |
| mHDRBracketingEnabled = true; |
| } |
| |
| String8 tmp; |
| for (uint32_t i = 0; i < hdrFrameCount; i++) { |
| tmp.appendFormat("%d", |
| (int8_t) hdrBracketingSetting.exp_val.values[i]); |
| tmp.append(","); |
| } |
| if (mParameters.isHDR1xFrameEnabled() |
| && mParameters.isHDR1xExtraBufferNeeded()) { |
| tmp.appendFormat("%d", 0); |
| tmp.append(","); |
| } |
| |
| if( !tmp.isEmpty() && |
| ( MAX_EXP_BRACKETING_LENGTH > tmp.length() ) ) { |
| //Trim last comma |
| memset(aeBracket.values, '\0', MAX_EXP_BRACKETING_LENGTH); |
| memcpy(aeBracket.values, tmp.string(), tmp.length() - 1); |
| } |
| |
| LOGH("HDR config values %s", |
| aeBracket.values); |
| rc = mParameters.setHDRAEBracket(aeBracket); |
| if ( NO_ERROR != rc ) { |
| LOGE("cannot configure HDR bracketing"); |
| return rc; |
| } |
| LOGH("X rc = %d", rc); |
| return rc; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : configureAEBracketing |
| * |
| * DESCRIPTION: configure AE Bracketing. |
| * |
| * PARAMETERS : none |
| * |
| * RETURN : int32_t type of status |
| * NO_ERROR -- success |
| * none-zero failure code |
| *==========================================================================*/ |
| int32_t QCamera2HardwareInterface::configureAEBracketing() |
| { |
| LOGH("E"); |
| int32_t rc = NO_ERROR; |
| |
| rc = mParameters.setAEBracketing(); |
| if ( NO_ERROR != rc ) { |
| LOGE("cannot configure AE bracketing"); |
| return rc; |
| } |
| LOGH("X rc = %d", rc); |
| return rc; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : configureOptiZoom |
| * |
| * DESCRIPTION: configure Opti Zoom. |
| * |
| * PARAMETERS : none |
| * |
| * RETURN : int32_t type of status |
| * NO_ERROR -- success |
| * none-zero failure code |
| *==========================================================================*/ |
| int32_t QCamera2HardwareInterface::configureOptiZoom() |
| { |
| int32_t rc = NO_ERROR; |
| |
| //store current zoom level. |
| mZoomLevel = mParameters.getParmZoomLevel(); |
| |
| //set zoom level to 1x; |
| mParameters.setAndCommitZoom(0); |
| |
| mParameters.set3ALock(true); |
| mIs3ALocked = true; |
| |
| return rc; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : configureStillMore |
| * |
| * DESCRIPTION: configure StillMore. |
| * |
| * PARAMETERS : none |
| * |
| * RETURN : int32_t type of status |
| * NO_ERROR -- success |
| * none-zero failure code |
| *==========================================================================*/ |
| int32_t QCamera2HardwareInterface::configureStillMore() |
| { |
| int32_t rc = NO_ERROR; |
| uint8_t burst_cnt = 0; |
| cam_still_more_t stillmore_config; |
| cam_still_more_t stillmore_cap; |
| |
| /* Disable Tone Map. If seemore is enabled, it will handle disabling it. */ |
| if (!mParameters.isSeeMoreEnabled() && !mParameters.isLTMForSeeMoreEnabled()) { |
| rc = mParameters.setToneMapMode(false, true); |
| if (rc != NO_ERROR) { |
| LOGW("Failed to disable tone map during StillMore"); |
| } |
| } |
| |
| /* Lock 3A */ |
| mParameters.set3ALock(true); |
| mIs3ALocked = true; |
| |
| /* Disable Tintless */ |
| mParameters.setTintless(false); |
| |
| /* Initialize burst count from capability */ |
| stillmore_cap = mParameters.getStillMoreCapability(); |
| burst_cnt = stillmore_cap.max_burst_count; |
| |
| /* Reconfigure burst count from dynamic scene data */ |
| cam_dyn_img_data_t dynamic_img_data = mParameters.getDynamicImgData(); |
| if (dynamic_img_data.input_count >= stillmore_cap.min_burst_count && |
| dynamic_img_data.input_count <= stillmore_cap.max_burst_count) { |
| burst_cnt = dynamic_img_data.input_count; |
| } |
| |
| /* Reconfigure burst count in the case of liveshot */ |
| if (mParameters.isSeeMoreEnabled()) { |
| burst_cnt = 1; |
| } |
| |
| /* Reconfigure burst count from user input */ |
| char prop[PROPERTY_VALUE_MAX]; |
| property_get("persist.camera.imglib.stillmore", prop, "0"); |
| uint8_t burst_setprop = (uint32_t)atoi(prop); |
| if (burst_setprop != 0) { |
| if ((burst_setprop < stillmore_cap.min_burst_count) || |
| (burst_setprop > stillmore_cap.max_burst_count)) { |
| burst_cnt = stillmore_cap.max_burst_count; |
| } else { |
| burst_cnt = burst_setprop; |
| } |
| } |
| |
| memset(&stillmore_config, 0, sizeof(cam_still_more_t)); |
| stillmore_config.burst_count = burst_cnt; |
| mParameters.setStillMoreSettings(stillmore_config); |
| |
| LOGH("Stillmore burst %d", burst_cnt); |
| |
| return rc; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : stopAdvancedCapture |
| * |
| * DESCRIPTION: stops advanced capture based on capture type |
| * |
| * PARAMETERS : |
| * @pChannel : channel. |
| * |
| * RETURN : int32_t type of status |
| * NO_ERROR -- success |
| * none-zero failure code |
| *==========================================================================*/ |
| int32_t QCamera2HardwareInterface::stopAdvancedCapture( |
| QCameraPicChannel *pChannel) |
| { |
| LOGH("stop bracketig"); |
| int32_t rc = NO_ERROR; |
| |
| if(mParameters.isUbiFocusEnabled() || mParameters.isUbiRefocus()) { |
| rc = pChannel->stopAdvancedCapture(MM_CAMERA_AF_BRACKETING); |
| } else if (mParameters.isChromaFlashEnabled() |
| || (mFlashConfigured && !mLongshotEnabled) |
| || (mLowLightConfigured == true) |
| || (mParameters.getManualCaptureMode() >= CAM_MANUAL_CAPTURE_TYPE_2)) { |
| rc = pChannel->stopAdvancedCapture(MM_CAMERA_FRAME_CAPTURE); |
| mFlashConfigured = false; |
| mLowLightConfigured = false; |
| } else if(mParameters.isHDREnabled() |
| || mParameters.isAEBracketEnabled()) { |
| rc = pChannel->stopAdvancedCapture(MM_CAMERA_AE_BRACKETING); |
| } else if (mParameters.isOptiZoomEnabled()) { |
| rc = pChannel->stopAdvancedCapture(MM_CAMERA_ZOOM_1X); |
| } else if (mParameters.isStillMoreEnabled()) { |
| LOGH("stopAdvancedCapture not needed for StillMore"); |
| } else { |
| LOGH("No Advanced Capture feature enabled!"); |
| rc = BAD_VALUE; |
| } |
| return rc; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : startAdvancedCapture |
| * |
| * DESCRIPTION: starts advanced capture based on capture type |
| * |
| * PARAMETERS : |
| * @pChannel : channel. |
| * |
| * RETURN : int32_t type of status |
| * NO_ERROR -- success |
| * none-zero failure code |
| *==========================================================================*/ |
| int32_t QCamera2HardwareInterface::startAdvancedCapture( |
| QCameraPicChannel *pChannel) |
| { |
| LOGH("Start bracketing"); |
| int32_t rc = NO_ERROR; |
| |
| if(mParameters.isUbiFocusEnabled() || mParameters.isUbiRefocus()) { |
| rc = pChannel->startAdvancedCapture(MM_CAMERA_AF_BRACKETING); |
| } else if (mParameters.isOptiZoomEnabled()) { |
| rc = pChannel->startAdvancedCapture(MM_CAMERA_ZOOM_1X); |
| } else if (mParameters.isStillMoreEnabled()) { |
| LOGH("startAdvancedCapture not needed for StillMore"); |
| } else if (mParameters.isHDREnabled() |
| || mParameters.isAEBracketEnabled()) { |
| rc = pChannel->startAdvancedCapture(MM_CAMERA_AE_BRACKETING); |
| } else if (mParameters.isChromaFlashEnabled() |
| || (mFlashNeeded && !mLongshotEnabled) |
| || (mLowLightConfigured == true) |
| || (mParameters.getManualCaptureMode() >= CAM_MANUAL_CAPTURE_TYPE_2)) { |
| cam_capture_frame_config_t config = mParameters.getCaptureFrameConfig(); |
| rc = pChannel->startAdvancedCapture(MM_CAMERA_FRAME_CAPTURE, &config); |
| } else { |
| LOGE("No Advanced Capture feature enabled!"); |
| rc = BAD_VALUE; |
| } |
| return rc; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : preTakePicture |
| * |
| * DESCRIPTION: Prepare take picture impl, Restarts preview if necessary |
| * |
| * PARAMETERS : none |
| * |
| * RETURN : int32_t type of status |
| * NO_ERROR -- success |
| * none-zero failure code |
| *==========================================================================*/ |
| int QCamera2HardwareInterface::preTakePicture() |
| { |
| int32_t rc = NO_ERROR; |
| LOGH("E"); |
| if (mParameters.getRecordingHintValue() == true) { |
| |
| // Give HWI control to restart preview only in single camera mode. |
| // In dual-cam mode, this control belongs to muxer. |
| if (getRelatedCamSyncInfo()->sync_control != CAM_SYNC_RELATED_SENSORS_ON) { |
| LOGH("restart preview if rec hint is true and preview is running"); |
| stopPreview(); |
| mParameters.updateRecordingHintValue(FALSE); |
| // start preview again |
| rc = preparePreview(); |
| if (rc == NO_ERROR) { |
| rc = startPreview(); |
| if (rc != NO_ERROR) { |
| unpreparePreview(); |
| } |
| } |
| } |
| else |
| { |
| // For dual cam mode, update the flag mPreviewRestartNeeded to true |
| // Restart control will be handled by muxer. |
| mPreviewRestartNeeded = true; |
| } |
| } |
| |
| LOGH("X rc = %d", rc); |
| return rc; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : takePicture |
| * |
| * DESCRIPTION: take picture impl |
| * |
| * PARAMETERS : none |
| * |
| * RETURN : int32_t type of status |
| * NO_ERROR -- success |
| * none-zero failure code |
| *==========================================================================*/ |
| int QCamera2HardwareInterface::takePicture() |
| { |
| int rc = NO_ERROR; |
| |
| // Get total number for snapshots (retro + regular) |
| uint8_t numSnapshots = mParameters.getNumOfSnapshots(); |
| // Get number of retro-active snapshots |
| uint8_t numRetroSnapshots = mParameters.getNumOfRetroSnapshots(); |
| LOGH("E"); |
| |
| //Set rotation value from user settings as Jpeg rotation |
| //to configure back-end modules. |
| mParameters.setJpegRotation(mParameters.getRotation()); |
| |
| // Check if retro-active snapshots are not enabled |
| if (!isRetroPicture() || !mParameters.isZSLMode()) { |
| numRetroSnapshots = 0; |
| LOGH("Reset retro snaphot count to zero"); |
| } |
| |
| //Do special configure for advanced capture modes. |
| rc = configureAdvancedCapture(); |
| if (rc != NO_ERROR) { |
| LOGE("Unsupported capture call"); |
| return rc; |
| } |
| |
| #ifdef DUAL_CAM_TEST //Temporary macro. Added to simulate B+B snapshot. Will be removed |
| if(mActiveCamera == (MM_CAMERA_TYPE_MAIN | MM_CAMERA_TYPE_AUX)) { |
| numSnapshots = 1; |
| } |
| #endif |
| |
| if (mAdvancedCaptureConfigured) { |
| numSnapshots = mParameters.getBurstCountForAdvancedCapture(); |
| } |
| LOGI("snap count = %d zsl = %d advanced = %d", |
| numSnapshots, mParameters.isZSLMode(), mAdvancedCaptureConfigured); |
| |
| if (mParameters.isZSLMode()) { |
| QCameraChannel *pChannel = m_channels[QCAMERA_CH_TYPE_ZSL]; |
| QCameraPicChannel *pPicChannel = (QCameraPicChannel *)pChannel; |
| if (NULL != pPicChannel) { |
| |
| if (mParameters.getofflineRAW()) { |
| startRAWChannel(pPicChannel); |
| pPicChannel = (QCameraPicChannel *)m_channels[QCAMERA_CH_TYPE_RAW]; |
| if (pPicChannel == NULL) { |
| LOGE("RAW Channel is NULL in Manual capture mode"); |
| stopRAWChannel(); |
| return UNKNOWN_ERROR; |
| } |
| } |
| |
| rc = configureOnlineRotation(*pPicChannel); |
| if (rc != NO_ERROR) { |
| LOGE("online rotation failed"); |
| return rc; |
| } |
| |
| // start postprocessor |
| DeferWorkArgs args; |
| memset(&args, 0, sizeof(DeferWorkArgs)); |
| |
| args.pprocArgs = pPicChannel; |
| |
| // No need to wait for mInitPProcJob here, because it was |
| // queued in startPreview, and will definitely be processed before |
| // mReprocJob can begin. |
| mReprocJob = queueDeferredWork(CMD_DEF_PPROC_START, |
| args); |
| if (mReprocJob == 0) { |
| LOGE("Failure: Unable to start pproc"); |
| return -ENOMEM; |
| } |
| |
| // Check if all preview buffers are mapped before creating |
| // a jpeg session as preview stream buffers are queried during the same |
| uint8_t numStreams = pChannel->getNumOfStreams(); |
| QCameraStream *pStream = NULL; |
| QCameraStream *pPreviewStream = NULL; |
| for (uint8_t i = 0 ; i < numStreams ; i++ ) { |
| pStream = pChannel->getStreamByIndex(i); |
| if (!pStream) |
| continue; |
| if (CAM_STREAM_TYPE_PREVIEW == pStream->getMyType()) { |
| pPreviewStream = pStream; |
| break; |
| } |
| } |
| if (pPreviewStream != NULL) { |
| Mutex::Autolock l(mMapLock); |
| QCameraMemory *pMemory = pStream->getStreamBufs(); |
| if (!pMemory) { |
| LOGE("Error!! pMemory is NULL"); |
| return -ENOMEM; |
| } |
| |
| uint8_t waitCnt = 2; |
| while (!pMemory->checkIfAllBuffersMapped() && (waitCnt > 0)) { |
| LOGL(" Waiting for preview buffers to be mapped"); |
| mMapCond.waitRelative( |
| mMapLock, CAMERA_DEFERRED_MAP_BUF_TIMEOUT); |
| LOGL("Wait completed!!"); |
| waitCnt--; |
| } |
| // If all buffers are not mapped after retries, assert |
| assert(pMemory->checkIfAllBuffersMapped()); |
| } else { |
| assert(pPreviewStream); |
| } |
| |
| // Create JPEG session |
| mJpegJob = queueDeferredWork(CMD_DEF_CREATE_JPEG_SESSION, |
| args); |
| if (mJpegJob == 0) { |
| LOGE("Failed to queue CREATE_JPEG_SESSION"); |
| if (NO_ERROR != waitDeferredWork(mReprocJob)) { |
| LOGE("Reprocess Deferred work was failed"); |
| } |
| m_postprocessor.stop(); |
| return -ENOMEM; |
| } |
| |
| if (mAdvancedCaptureConfigured) { |
| rc = startAdvancedCapture(pPicChannel); |
| if (rc != NO_ERROR) { |
| LOGE("cannot start zsl advanced capture"); |
| return rc; |
| } |
| } |
| if (mLongshotEnabled && mPrepSnapRun) { |
| mCameraHandle->ops->start_zsl_snapshot( |
| mCameraHandle->camera_handle, |
| pPicChannel->getMyHandle()); |
| } |
| // If frame sync is ON and it is a SECONDARY camera, |
| // we do not need to send the take picture command to interface |
| // It will be handled along with PRIMARY camera takePicture request |
| mm_camera_req_buf_t buf; |
| memset(&buf, 0x0, sizeof(buf)); |
| if ((!mParameters.isAdvCamFeaturesEnabled() && |
| !mFlashNeeded && |
| !isLongshotEnabled() && |
| isFrameSyncEnabled()) && |
| (getRelatedCamSyncInfo()->sync_control == |
| CAM_SYNC_RELATED_SENSORS_ON)) { |
| if (getRelatedCamSyncInfo()->mode == CAM_MODE_PRIMARY) { |
| buf.type = MM_CAMERA_REQ_FRAME_SYNC_BUF; |
| buf.num_buf_requested = numSnapshots; |
| rc = pPicChannel->takePicture(&buf); |
| if (rc != NO_ERROR) { |
| LOGE("FS_DBG cannot take ZSL picture, stop pproc"); |
| if (NO_ERROR != waitDeferredWork(mReprocJob)) { |
| LOGE("Reprocess Deferred work failed"); |
| return UNKNOWN_ERROR; |
| } |
| if (NO_ERROR != waitDeferredWork(mJpegJob)) { |
| LOGE("Jpeg Deferred work failed"); |
| return UNKNOWN_ERROR; |
| } |
| m_postprocessor.stop(); |
| return rc; |
| } |
| LOGI("PRIMARY camera: send frame sync takePicture!!"); |
| } |
| } else { |
| buf.type = MM_CAMERA_REQ_SUPER_BUF; |
| buf.num_buf_requested = numSnapshots; |
| buf.num_retro_buf_requested = numRetroSnapshots; |
| rc = pPicChannel->takePicture(&buf); |
| if (rc != NO_ERROR) { |
| LOGE("cannot take ZSL picture, stop pproc"); |
| if (NO_ERROR != waitDeferredWork(mReprocJob)) { |
| LOGE("Reprocess Deferred work failed"); |
| return UNKNOWN_ERROR; |
| } |
| if (NO_ERROR != waitDeferredWork(mJpegJob)) { |
| LOGE("Jpeg Deferred work failed"); |
| return UNKNOWN_ERROR; |
| } |
| m_postprocessor.stop(); |
| return rc; |
| } |
| } |
| } else { |
| LOGE("ZSL channel is NULL"); |
| return UNKNOWN_ERROR; |
| } |
| } else { |
| |
| // start snapshot |
| if (mParameters.isJpegPictureFormat() || |
| mParameters.isNV16PictureFormat() || |
| mParameters.isNV21PictureFormat()) { |
| |
| //STOP Preview for Non ZSL use case |
| stopPreview(); |
| |
| //Config CAPTURE channels |
| rc = declareSnapshotStreams(); |
| if (NO_ERROR != rc) { |
| return rc; |
| } |
| |
| rc = addCaptureChannel(); |
| if ((rc == NO_ERROR) && |
| (NULL != m_channels[QCAMERA_CH_TYPE_CAPTURE])) { |
| |
| if (!mParameters.getofflineRAW()) { |
| rc = configureOnlineRotation( |
| *m_channels[QCAMERA_CH_TYPE_CAPTURE]); |
| if (rc != NO_ERROR) { |
| LOGE("online rotation failed"); |
| delChannel(QCAMERA_CH_TYPE_CAPTURE); |
| return rc; |
| } |
| } |
| |
| DeferWorkArgs args; |
| memset(&args, 0, sizeof(DeferWorkArgs)); |
| |
| args.pprocArgs = m_channels[QCAMERA_CH_TYPE_CAPTURE]; |
| |
| // No need to wait for mInitPProcJob here, because it was |
| // queued in startPreview, and will definitely be processed before |
| // mReprocJob can begin. |
| mReprocJob = queueDeferredWork(CMD_DEF_PPROC_START, |
| args); |
| if (mReprocJob == 0) { |
| LOGE("Failure: Unable to start pproc"); |
| return -ENOMEM; |
| } |
| |
| // Create JPEG session |
| mJpegJob = queueDeferredWork(CMD_DEF_CREATE_JPEG_SESSION, |
| args); |
| if (mJpegJob == 0) { |
| LOGE("Failed to queue CREATE_JPEG_SESSION"); |
| if (NO_ERROR != waitDeferredWork(mReprocJob)) { |
| LOGE("Reprocess Deferred work was failed"); |
| } |
| m_postprocessor.stop(); |
| return -ENOMEM; |
| } |
| |
| // start catpure channel |
| rc = m_channels[QCAMERA_CH_TYPE_CAPTURE]->start(); |
| if (rc != NO_ERROR) { |
| LOGE("cannot start capture channel"); |
| if (NO_ERROR != waitDeferredWork(mReprocJob)) { |
| LOGE("Reprocess Deferred work failed"); |
| return UNKNOWN_ERROR; |
| } |
| if (NO_ERROR != waitDeferredWork(mJpegJob)) { |
| LOGE("Jpeg Deferred work failed"); |
| return UNKNOWN_ERROR; |
| } |
| delChannel(QCAMERA_CH_TYPE_CAPTURE); |
| return rc; |
| } |
| |
| QCameraPicChannel *pCapChannel = |
| (QCameraPicChannel *)m_channels[QCAMERA_CH_TYPE_CAPTURE]; |
| if (NULL != pCapChannel) { |
| if (mParameters.isUbiFocusEnabled() || |
| mParameters.isUbiRefocus() || |
| mParameters.isChromaFlashEnabled()) { |
| rc = startAdvancedCapture(pCapChannel); |
| if (rc != NO_ERROR) { |
| LOGE("cannot start advanced capture"); |
| return rc; |
| } |
| } |
| } |
| if ( mLongshotEnabled ) { |
| rc = longShot(); |
| if (NO_ERROR != rc) { |
| if (NO_ERROR != waitDeferredWork(mReprocJob)) { |
| LOGE("Reprocess Deferred work failed"); |
| return UNKNOWN_ERROR; |
| } |
| if (NO_ERROR != waitDeferredWork(mJpegJob)) { |
| LOGE("Jpeg Deferred work failed"); |
| return UNKNOWN_ERROR; |
| } |
| delChannel(QCAMERA_CH_TYPE_CAPTURE); |
| return rc; |
| } |
| } |
| } else { |
| LOGE("cannot add capture channel"); |
| delChannel(QCAMERA_CH_TYPE_CAPTURE); |
| return rc; |
| } |
| } else { |
| // Stop Preview before taking NZSL snapshot |
| stopPreview(); |
| |
| rc = mParameters.updateRAW(gCamCapability[mCameraId]->raw_dim[0]); |
| if (NO_ERROR != rc) { |
| LOGE("Raw dimension update failed %d", rc); |
| return rc; |
| } |
| |
| rc = declareSnapshotStreams(); |
| if (NO_ERROR != rc) { |
| LOGE("RAW stream info configuration failed %d", rc); |
| return rc; |
| } |
| |
| rc = addChannel(QCAMERA_CH_TYPE_RAW); |
| if (rc == NO_ERROR) { |
| // start postprocessor |
| if (NO_ERROR != waitDeferredWork(mInitPProcJob)) { |
| LOGE("Reprocess Deferred work failed"); |
| return UNKNOWN_ERROR; |
| } |
| |
| rc = m_postprocessor.start(m_channels[QCAMERA_CH_TYPE_RAW]); |
| if (rc != NO_ERROR) { |
| LOGE("cannot start postprocessor"); |
| delChannel(QCAMERA_CH_TYPE_RAW); |
| return rc; |
| } |
| |
| rc = startChannel(QCAMERA_CH_TYPE_RAW); |
| if (rc != NO_ERROR) { |
| LOGE("cannot start raw channel"); |
| m_postprocessor.stop(); |
| delChannel(QCAMERA_CH_TYPE_RAW); |
| return rc; |
| } |
| } else { |
| LOGE("cannot add raw channel"); |
| return rc; |
| } |
| } |
| } |
| |
| //When take picture, stop sending preview callbacks to APP |
| m_stateMachine.setPreviewCallbackNeeded(false); |
| LOGI("X rc = %d", rc); |
| return rc; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : configureOnlineRotation |
| * |
| * DESCRIPTION: Configure backend with expected rotation for snapshot stream |
| * |
| * PARAMETERS : |
| * @ch : Channel containing a snapshot stream |
| * |
| * RETURN : int32_t type of status |
| * NO_ERROR -- success |
| * none-zero failure code |
| *==========================================================================*/ |
| int32_t QCamera2HardwareInterface::configureOnlineRotation(QCameraChannel &ch) |
| { |
| int rc = NO_ERROR; |
| uint32_t streamId = 0; |
| QCameraStream *pStream = NULL; |
| |
| for (uint8_t i = 0; i < ch.getNumOfStreams(); i++) { |
| QCameraStream *stream = ch.getStreamByIndex(i); |
| if ((NULL != stream) && |
| ((CAM_STREAM_TYPE_SNAPSHOT == stream->getMyType()) |
| || (CAM_STREAM_TYPE_RAW == stream->getMyType()))) { |
| pStream = stream; |
| break; |
| } |
| } |
| |
| if (NULL == pStream) { |
| LOGE("No snapshot stream found!"); |
| return BAD_VALUE; |
| } |
| |
| streamId = pStream->getMyServerID(); |
| // Update online rotation configuration |
| rc = mParameters.addOnlineRotation(mParameters.getJpegRotation(), streamId, |
| mParameters.getDeviceRotation()); |
| if (rc != NO_ERROR) { |
| LOGE("addOnlineRotation failed %d", rc); |
| return rc; |
| } |
| |
| return rc; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : declareSnapshotStreams |
| * |
| * DESCRIPTION: Configure backend with expected snapshot streams |
| * |
| * PARAMETERS : none |
| * |
| * RETURN : int32_t type of status |
| * NO_ERROR -- success |
| * none-zero failure code |
| *==========================================================================*/ |
| int32_t QCamera2HardwareInterface::declareSnapshotStreams() |
| { |
| int rc = NO_ERROR; |
| |
| // Update stream info configuration |
| rc = mParameters.setStreamConfigure(true, mLongshotEnabled, false); |
| if (rc != NO_ERROR) { |
| LOGE("setStreamConfigure failed %d", rc); |
| return rc; |
| } |
| |
| return rc; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : longShot |
| * |
| * DESCRIPTION: Queue one more ZSL frame |
| * in the longshot pipe. |
| * |
| * PARAMETERS : none |
| * |
| * RETURN : int32_t type of status |
| * NO_ERROR -- success |
| * none-zero failure code |
| *==========================================================================*/ |
| int32_t QCamera2HardwareInterface::longShot() |
| { |
| int32_t rc = NO_ERROR; |
| uint8_t numSnapshots = mParameters.getNumOfSnapshots(); |
| QCameraPicChannel *pChannel = NULL; |
| |
| if (mParameters.isZSLMode()) { |
| pChannel = (QCameraPicChannel *)m_channels[QCAMERA_CH_TYPE_ZSL]; |
| } else { |
| pChannel = (QCameraPicChannel *)m_channels[QCAMERA_CH_TYPE_CAPTURE]; |
| } |
| |
| if (NULL != pChannel) { |
| mm_camera_req_buf_t buf; |
| memset(&buf, 0x0, sizeof(buf)); |
| buf.type = MM_CAMERA_REQ_SUPER_BUF; |
| buf.num_buf_requested = numSnapshots; |
| rc = pChannel->takePicture(&buf); |
| } else { |
| LOGE("Capture channel not initialized!"); |
| rc = NO_INIT; |
| goto end; |
| } |
| |
| end: |
| return rc; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : stopCaptureChannel |
| * |
| * DESCRIPTION: Stops capture channel |
| * |
| * PARAMETERS : |
| * @destroy : Set to true to stop and delete camera channel. |
| * Set to false to only stop capture channel. |
| * |
| * RETURN : int32_t type of status |
| * NO_ERROR -- success |
| * none-zero failure code |
| *==========================================================================*/ |
| int QCamera2HardwareInterface::stopCaptureChannel(bool destroy) |
| { |
| int rc = NO_ERROR; |
| if (mParameters.isJpegPictureFormat() || |
| mParameters.isNV16PictureFormat() || |
| mParameters.isNV21PictureFormat()) { |
| mParameters.setQuadraCfaMode(false, true); |
| rc = stopChannel(QCAMERA_CH_TYPE_CAPTURE); |
| if (destroy && (NO_ERROR == rc)) { |
| // Destroy camera channel but dont release context |
| waitDeferredWork(mJpegJob); |
| rc = delChannel(QCAMERA_CH_TYPE_CAPTURE, false); |
| } |
| } |
| |
| return rc; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : cancelPicture |
| * |
| * DESCRIPTION: cancel picture impl |
| * |
| * PARAMETERS : none |
| * |
| * RETURN : int32_t type of status |
| * NO_ERROR -- success |
| * none-zero failure code |
| *==========================================================================*/ |
| int QCamera2HardwareInterface::cancelPicture() |
| { |
| waitDeferredWork(mReprocJob); |
| waitDeferredWork(mJpegJob); |
| |
| //stop post processor |
| m_postprocessor.stop(); |
| |
| unconfigureAdvancedCapture(); |
| LOGH("Enable display frames again"); |
| setDisplaySkip(FALSE); |
| |
| if (!mLongshotEnabled) { |
| m_perfLock.lock_rel(); |
| } |
| |
| if (mParameters.isZSLMode()) { |
| QCameraPicChannel *pPicChannel = NULL; |
| if (mParameters.getofflineRAW()) { |
| pPicChannel = (QCameraPicChannel *)m_channels[QCAMERA_CH_TYPE_RAW]; |
| } else { |
| pPicChannel = (QCameraPicChannel *)m_channels[QCAMERA_CH_TYPE_ZSL]; |
| } |
| if (NULL != pPicChannel) { |
| pPicChannel->cancelPicture(); |
| stopRAWChannel(); |
| stopAdvancedCapture(pPicChannel); |
| } |
| } else { |
| |
| // normal capture case |
| if (mParameters.isJpegPictureFormat() || |
| mParameters.isNV16PictureFormat() || |
| mParameters.isNV21PictureFormat()) { |
| stopChannel(QCAMERA_CH_TYPE_CAPTURE); |
| delChannel(QCAMERA_CH_TYPE_CAPTURE); |
| } else { |
| stopChannel(QCAMERA_CH_TYPE_RAW); |
| delChannel(QCAMERA_CH_TYPE_RAW); |
| } |
| } |
| |
| return NO_ERROR; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : captureDone |
| * |
| * DESCRIPTION: Function called when the capture is completed before encoding |
| * |
| * PARAMETERS : none |
| * |
| * RETURN : none |
| *==========================================================================*/ |
| void QCamera2HardwareInterface::captureDone() |
| { |
| qcamera_sm_internal_evt_payload_t *payload = |
| (qcamera_sm_internal_evt_payload_t *) |
| malloc(sizeof(qcamera_sm_internal_evt_payload_t)); |
| if (NULL != payload) { |
| memset(payload, 0, sizeof(qcamera_sm_internal_evt_payload_t)); |
| payload->evt_type = QCAMERA_INTERNAL_EVT_ZSL_CAPTURE_DONE; |
| int32_t rc = processEvt(QCAMERA_SM_EVT_EVT_INTERNAL, payload); |
| if (rc != NO_ERROR) { |
| LOGE("processEvt ZSL capture done failed"); |
| free(payload); |
| payload = NULL; |
| } |
| } else { |
| LOGE("No memory for ZSL capture done event"); |
| } |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : Live_Snapshot_thread |
| * |
| * DESCRIPTION: Seperate thread for taking live snapshot during recording |
| * |
| * PARAMETERS : @data - pointer to QCamera2HardwareInterface class object |
| * |
| * RETURN : none |
| *==========================================================================*/ |
| void* Live_Snapshot_thread (void* data) |
| { |
| |
| QCamera2HardwareInterface *hw = reinterpret_cast<QCamera2HardwareInterface *>(data); |
| if (!hw) { |
| LOGE("take_picture_thread: NULL camera device"); |
| return (void *)BAD_VALUE; |
| } |
| if (hw->bLiveSnapshot) { |
| hw->takeLiveSnapshot_internal(); |
| } else { |
| hw->cancelLiveSnapshot_internal(); |
| } |
| return (void* )NULL; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : Int_Pic_thread |
| * |
| * DESCRIPTION: Seperate thread for taking snapshot triggered by camera backend |
| * |
| * PARAMETERS : @data - pointer to QCamera2HardwareInterface class object |
| * |
| * RETURN : none |
| *==========================================================================*/ |
| void* Int_Pic_thread (void* data) |
| { |
| int rc = NO_ERROR; |
| |
| QCamera2HardwareInterface *hw = reinterpret_cast<QCamera2HardwareInterface *>(data); |
| |
| if (!hw) { |
| LOGE("take_picture_thread: NULL camera device"); |
| return (void *)BAD_VALUE; |
| } |
| |
| bool JpegMemOpt = false; |
| char raw_format[PROPERTY_VALUE_MAX]; |
| |
| memset(raw_format, 0, sizeof(raw_format)); |
| |
| rc = hw->takeBackendPic_internal(&JpegMemOpt, &raw_format[0]); |
| if (rc == NO_ERROR) { |
| hw->checkIntPicPending(JpegMemOpt, &raw_format[0]); |
| } else { |
| //Snapshot attempt not successful, we need to do cleanup here |
| hw->clearIntPendingEvents(); |
| } |
| |
| return (void* )NULL; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : takeLiveSnapshot |
| * |
| * DESCRIPTION: take live snapshot during recording |
| * |
| * PARAMETERS : none |
| * |
| * RETURN : int32_t type of status |
| * NO_ERROR -- success |
| * none-zero failure code |
| *==========================================================================*/ |
| int QCamera2HardwareInterface::takeLiveSnapshot() |
| { |
| int rc = NO_ERROR; |
| if (mLiveSnapshotThread != 0) { |
| pthread_join(mLiveSnapshotThread,NULL); |
| mLiveSnapshotThread = 0; |
| } |
| bLiveSnapshot = true; |
| rc= pthread_create(&mLiveSnapshotThread, NULL, Live_Snapshot_thread, (void *) this); |
| if (!rc) { |
| pthread_setname_np(mLiveSnapshotThread, "CAM_liveSnap"); |
| } |
| return rc; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : takePictureInternal |
| * |
| * DESCRIPTION: take snapshot triggered by backend |
| * |
| * PARAMETERS : none |
| * |
| * RETURN : int32_t type of status |
| * NO_ERROR -- success |
| * none-zero failure code |
| *==========================================================================*/ |
| int QCamera2HardwareInterface::takePictureInternal() |
| { |
| int rc = NO_ERROR; |
| rc= pthread_create(&mIntPicThread, NULL, Int_Pic_thread, (void *) this); |
| if (!rc) { |
| pthread_setname_np(mIntPicThread, "CAM_IntPic"); |
| } |
| return rc; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : checkIntPicPending |
| * |
| * DESCRIPTION: timed wait for jpeg completion event, and send |
| * back completion event to backend |
| * |
| * PARAMETERS : none |
| * |
| * RETURN : none |
| *==========================================================================*/ |
| void QCamera2HardwareInterface::checkIntPicPending(bool JpegMemOpt, char *raw_format) |
| { |
| bool bSendToBackend = true; |
| cam_int_evt_params_t params; |
| int rc = NO_ERROR; |
| |
| struct timespec ts; |
| struct timeval tp; |
| gettimeofday(&tp, NULL); |
| ts.tv_sec = tp.tv_sec + 5; |
| ts.tv_nsec = tp.tv_usec * 1000; |
| |
| if (true == m_bIntJpegEvtPending || |
| (true == m_bIntRawEvtPending)) { |
| //Waiting in HAL for snapshot taken notification |
| pthread_mutex_lock(&m_int_lock); |
| rc = pthread_cond_timedwait(&m_int_cond, &m_int_lock, &ts); |
| if (ETIMEDOUT == rc || 0x0 == m_BackendFileName[0]) { |
| //Hit a timeout, or some spurious activity |
| bSendToBackend = false; |
| } |
| |
| if (true == m_bIntJpegEvtPending) { |
| params.event_type = 0; |
| mParameters.getStreamFormat(CAM_STREAM_TYPE_SNAPSHOT, params.picture_format); |
| } else if (true == m_bIntRawEvtPending) { |
| params.event_type = 1; |
| mParameters.getStreamFormat(CAM_STREAM_TYPE_RAW, params.picture_format); |
| } |
| pthread_mutex_unlock(&m_int_lock); |
| |
| if (true == m_bIntJpegEvtPending) { |
| //Attempting to restart preview after taking JPEG snapshot |
| lockAPI(); |
| rc = processAPI(QCAMERA_SM_EVT_SNAPSHOT_DONE, NULL); |
| unlockAPI(); |
| m_postprocessor.setJpegMemOpt(JpegMemOpt); |
| } else if (true == m_bIntRawEvtPending) { |
| //Attempting to restart preview after taking RAW snapshot |
| stopChannel(QCAMERA_CH_TYPE_RAW); |
| delChannel(QCAMERA_CH_TYPE_RAW); |
| //restoring the old raw format |
| property_set("persist.camera.raw.format", raw_format); |
| } |
| |
| if (true == bSendToBackend) { |
| //send event back to server with the file path |
| params.dim = m_postprocessor.m_dst_dim; |
| memcpy(¶ms.path[0], &m_BackendFileName[0], QCAMERA_MAX_FILEPATH_LENGTH); |
| memset(&m_BackendFileName[0], 0x0, QCAMERA_MAX_FILEPATH_LENGTH); |
| params.size = mBackendFileSize; |
| rc = mParameters.setIntEvent(params); |
| } |
| |
| clearIntPendingEvents(); |
| } |
| |
| return; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : takeBackendPic_internal |
| * |
| * DESCRIPTION: take snapshot triggered by backend |
| * |
| * PARAMETERS : none |
| * |
| * RETURN : int32_t type of status |
| * NO_ERROR -- success |
| * none-zero failure code |
| *==========================================================================*/ |
| int QCamera2HardwareInterface::takeBackendPic_internal(bool *JpegMemOpt, char *raw_format) |
| { |
| int rc = NO_ERROR; |
| qcamera_api_result_t apiResult; |
| |
| lockAPI(); |
| //Set rotation value from user settings as Jpeg rotation |
| //to configure back-end modules. |
| mParameters.setJpegRotation(mParameters.getRotation()); |
| |
| setRetroPicture(0); |
| /* Prepare snapshot in case LED needs to be flashed */ |
| if (mFlashNeeded == 1 || mParameters.isChromaFlashEnabled()) { |
| // Start Preparing for normal Frames |
| LOGH("Start Prepare Snapshot"); |
| /* Prepare snapshot in case LED needs to be flashed */ |
| rc = processAPI(QCAMERA_SM_EVT_PREPARE_SNAPSHOT, NULL); |
| if (rc == NO_ERROR) { |
| waitAPIResult(QCAMERA_SM_EVT_PREPARE_SNAPSHOT, &apiResult); |
| rc = apiResult.status; |
| } |
| LOGH("Prep Snapshot done rc = %d", rc); |
| mPrepSnapRun = true; |
| } |
| unlockAPI(); |
| |
| if (true == m_bIntJpegEvtPending) { |
| //Attempting to take JPEG snapshot |
| if (NO_ERROR != waitDeferredWork(mInitPProcJob)) { |
| LOGE("Init PProc Deferred work failed"); |
| return UNKNOWN_ERROR; |
| } |
| *JpegMemOpt = m_postprocessor.getJpegMemOpt(); |
| m_postprocessor.setJpegMemOpt(false); |
| |
| /* capture */ |
| lockAPI(); |
| LOGH("Capturing internal snapshot"); |
| rc = processAPI(QCAMERA_SM_EVT_TAKE_PICTURE, NULL); |
| if (rc == NO_ERROR) { |
| waitAPIResult(QCAMERA_SM_EVT_TAKE_PICTURE, &apiResult); |
| rc = apiResult.status; |
| } |
| unlockAPI(); |
| } else if (true == m_bIntRawEvtPending) { |
| //Attempting to take RAW snapshot |
| (void)JpegMemOpt; |
| stopPreview(); |
| |
| //getting the existing raw format type |
| property_get("persist.camera.raw.format", raw_format, "17"); |
| //setting it to a default know value for this task |
| property_set("persist.camera.raw.format", "18"); |
| |
| rc = addChannel(QCAMERA_CH_TYPE_RAW); |
| if (rc == NO_ERROR) { |
| // start postprocessor |
| if (NO_ERROR != waitDeferredWork(mInitPProcJob)) { |
| LOGE("Init PProc Deferred work failed"); |
| return UNKNOWN_ERROR; |
| } |
| rc = m_postprocessor.start(m_channels[QCAMERA_CH_TYPE_RAW]); |
| if (rc != NO_ERROR) { |
| LOGE("cannot start postprocessor"); |
| delChannel(QCAMERA_CH_TYPE_RAW); |
| return rc; |
| } |
| |
| rc = startChannel(QCAMERA_CH_TYPE_RAW); |
| if (rc != NO_ERROR) { |
| LOGE("cannot start raw channel"); |
| m_postprocessor.stop(); |
| delChannel(QCAMERA_CH_TYPE_RAW); |
| return rc; |
| } |
| } else { |
| LOGE("cannot add raw channel"); |
| return rc; |
| } |
| } |
| |
| return rc; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : clearIntPendingEvents |
| * |
| * DESCRIPTION: clear internal pending events pertaining to backend |
| * snapshot requests |
| * |
| * PARAMETERS : none |
| * |
| * RETURN : int32_t type of status |
| * NO_ERROR -- success |
| * none-zero failure code |
| *==========================================================================*/ |
| void QCamera2HardwareInterface::clearIntPendingEvents() |
| { |
| int rc = NO_ERROR; |
| |
| if (true == m_bIntRawEvtPending) { |
| preparePreview(); |
| startPreview(); |
| } |
| if (true == m_bIntJpegEvtPending) { |
| if (false == mParameters.isZSLMode()) { |
| lockAPI(); |
| rc = processAPI(QCAMERA_SM_EVT_START_PREVIEW, NULL); |
| unlockAPI(); |
| } |
| } |
| |
| pthread_mutex_lock(&m_int_lock); |
| if (true == m_bIntJpegEvtPending) { |
| m_bIntJpegEvtPending = false; |
| } else if (true == m_bIntRawEvtPending) { |
| m_bIntRawEvtPending = false; |
| } |
| pthread_mutex_unlock(&m_int_lock); |
| return; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : takeLiveSnapshot_internal |
| * |
| * DESCRIPTION: take live snapshot during recording |
| * |
| * PARAMETERS : none |
| * |
| * RETURN : int32_t type of status |
| * NO_ERROR -- success |
| * none-zero failure code |
| *==========================================================================*/ |
| int QCamera2HardwareInterface::takeLiveSnapshot_internal() |
| { |
| int rc = NO_ERROR; |
| |
| QCameraChannel *pChannel = NULL; |
| QCameraChannel *pPreviewChannel = NULL; |
| QCameraStream *pPreviewStream = NULL; |
| QCameraStream *pStream = NULL; |
| |
| //Set rotation value from user settings as Jpeg rotation |
| //to configure back-end modules. |
| mParameters.setJpegRotation(mParameters.getRotation()); |
| |
| // Configure advanced capture |
| rc = configureAdvancedCapture(); |
| if (rc != NO_ERROR) { |
| LOGE("Unsupported capture call"); |
| goto end; |
| } |
| |
| if (isLowPowerMode()) { |
| pChannel = m_channels[QCAMERA_CH_TYPE_VIDEO]; |
| } else { |
| pChannel = m_channels[QCAMERA_CH_TYPE_SNAPSHOT]; |
| } |
| |
| if (NULL == pChannel) { |
| LOGE("Snapshot/Video channel not initialized"); |
| rc = NO_INIT; |
| goto end; |
| } |
| |
| // Check if all preview buffers are mapped before creating |
| // a jpeg session as preview stream buffers are queried during the same |
| pPreviewChannel = m_channels[QCAMERA_CH_TYPE_PREVIEW]; |
| if (pPreviewChannel != NULL) { |
| uint32_t numStreams = pPreviewChannel->getNumOfStreams(); |
| |
| for (uint8_t i = 0 ; i < numStreams ; i++ ) { |
| pStream = pPreviewChannel->getStreamByIndex(i); |
| if (!pStream) |
| continue; |
| if (CAM_STREAM_TYPE_PREVIEW == pStream->getMyType()) { |
| pPreviewStream = pStream; |
| break; |
| } |
| } |
| |
| if (pPreviewStream != NULL) { |
| Mutex::Autolock l(mMapLock); |
| QCameraMemory *pMemory = pStream->getStreamBufs(); |
| if (!pMemory) { |
| LOGE("Error!! pMemory is NULL"); |
| return -ENOMEM; |
| } |
| |
| uint8_t waitCnt = 2; |
| while (!pMemory->checkIfAllBuffersMapped() && (waitCnt > 0)) { |
| LOGL(" Waiting for preview buffers to be mapped"); |
| mMapCond.waitRelative( |
| mMapLock, CAMERA_DEFERRED_MAP_BUF_TIMEOUT); |
| LOGL("Wait completed!!"); |
| waitCnt--; |
| } |
| // If all buffers are not mapped after retries, assert |
| assert(pMemory->checkIfAllBuffersMapped()); |
| } else { |
| assert(pPreviewStream); |
| } |
| } |
| |
| DeferWorkArgs args; |
| memset(&args, 0, sizeof(DeferWorkArgs)); |
| |
| args.pprocArgs = pChannel; |
| |
| // No need to wait for mInitPProcJob here, because it was |
| // queued in startPreview, and will definitely be processed before |
| // mReprocJob can begin. |
| mReprocJob = queueDeferredWork(CMD_DEF_PPROC_START, |
| args); |
| if (mReprocJob == 0) { |
| LOGE("Failed to queue CMD_DEF_PPROC_START"); |
| rc = -ENOMEM; |
| goto end; |
| } |
| |
| // Create JPEG session |
| mJpegJob = queueDeferredWork(CMD_DEF_CREATE_JPEG_SESSION, |
| args); |
| if (mJpegJob == 0) { |
| LOGE("Failed to queue CREATE_JPEG_SESSION"); |
| if (NO_ERROR != waitDeferredWork(mReprocJob)) { |
| LOGE("Reprocess Deferred work was failed"); |
| } |
| m_postprocessor.stop(); |
| rc = -ENOMEM; |
| goto end; |
| } |
| |
| if (isLowPowerMode()) { |
| mm_camera_req_buf_t buf; |
| memset(&buf, 0x0, sizeof(buf)); |
| buf.type = MM_CAMERA_REQ_SUPER_BUF; |
| buf.num_buf_requested = 1; |
| rc = ((QCameraVideoChannel*)pChannel)->takePicture(&buf); |
| goto end; |
| } |
| |
| //Disable reprocess for 4K liveshot case |
| if (!mParameters.is4k2kVideoResolution()) { |
| rc = configureOnlineRotation(*m_channels[QCAMERA_CH_TYPE_SNAPSHOT]); |
| if (rc != NO_ERROR) { |
| LOGE("online rotation failed"); |
| if (NO_ERROR != waitDeferredWork(mReprocJob)) { |
| LOGE("Reprocess Deferred work was failed"); |
| } |
| if (NO_ERROR != waitDeferredWork(mJpegJob)) { |
| LOGE("Jpeg Deferred work was failed"); |
| } |
| m_postprocessor.stop(); |
| return rc; |
| } |
| } |
| |
| if ((NULL != pChannel) && (mParameters.isTNRSnapshotEnabled())) { |
| QCameraStream *pStream = NULL; |
| for (uint32_t i = 0 ; i < pChannel->getNumOfStreams(); i++ ) { |
| pStream = pChannel->getStreamByIndex(i); |
| if ((NULL != pStream) && |
| (CAM_STREAM_TYPE_SNAPSHOT == pStream->getMyType())) { |
| break; |
| } |
| } |
| if (pStream != NULL) { |
| LOGD("REQUEST_FRAMES event for TNR snapshot"); |
| cam_stream_parm_buffer_t param; |
| memset(¶m, 0, sizeof(cam_stream_parm_buffer_t)); |
| param.type = CAM_STREAM_PARAM_TYPE_REQUEST_FRAMES; |
| param.frameRequest.enableStream = 1; |
| rc = pStream->setParameter(param); |
| if (rc != NO_ERROR) { |
| LOGE("Stream Event REQUEST_FRAMES failed"); |
| } |
| goto end; |
| } |
| } |
| |
| // start snapshot channel |
| if ((rc == NO_ERROR) && (NULL != pChannel)) { |
| // Do not link metadata stream for 4K2k resolution |
| // as CPP processing would be done on snapshot stream and not |
| // reprocess stream |
| if (!mParameters.is4k2kVideoResolution()) { |
| // Find and try to link a metadata stream from preview channel |
| QCameraChannel *pMetaChannel = NULL; |
| QCameraStream *pMetaStream = NULL; |
| QCameraStream *pPreviewStream = NULL; |
| |
| if (m_channels[QCAMERA_CH_TYPE_PREVIEW] != NULL) { |
| pMetaChannel = m_channels[QCAMERA_CH_TYPE_PREVIEW]; |
| uint32_t streamNum = pMetaChannel->getNumOfStreams(); |
| QCameraStream *pStream = NULL; |
| for (uint32_t i = 0 ; i < streamNum ; i++ ) { |
| pStream = pMetaChannel->getStreamByIndex(i); |
| if (NULL != pStream) { |
| if (CAM_STREAM_TYPE_METADATA == pStream->getMyType()) { |
| pMetaStream = pStream; |
| } else if ((CAM_STREAM_TYPE_PREVIEW == pStream->getMyType()) |
| && (!mParameters.isHfrMode())) { |
| // Do not link preview stream for HFR live snapshot. |
| // Thumbnail will not be derived from preview for HFR live snapshot. |
| pPreviewStream = pStream; |
| } |
| } |
| } |
| } |
| |
| if ((NULL != pMetaChannel) && (NULL != pMetaStream)) { |
| rc = pChannel->linkStream(pMetaChannel, pMetaStream); |
| if (NO_ERROR != rc) { |
| LOGE("Metadata stream link failed %d", rc); |
| } |
| } |
| if ((NULL != pMetaChannel) && (NULL != pPreviewStream)) { |
| rc = pChannel->linkStream(pMetaChannel, pPreviewStream); |
| if (NO_ERROR != rc) { |
| LOGE("Preview stream link failed %d", rc); |
| } |
| } |
| } |
| rc = pChannel->start(); |
| } |
| |
| end: |
| if (rc != NO_ERROR) { |
| rc = processAPI(QCAMERA_SM_EVT_CANCEL_PICTURE, NULL); |
| rc = sendEvtNotify(CAMERA_MSG_ERROR, UNKNOWN_ERROR, 0); |
| } |
| return rc; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : cancelLiveSnapshot |
| * |
| * DESCRIPTION: cancel current live snapshot request |
| * |
| * PARAMETERS : none |
| * |
| * RETURN : int32_t type of status |
| * NO_ERROR -- success |
| * none-zero failure code |
| *==========================================================================*/ |
| int QCamera2HardwareInterface::cancelLiveSnapshot() |
| { |
| int rc = NO_ERROR; |
| if (mLiveSnapshotThread != 0) { |
| pthread_join(mLiveSnapshotThread,NULL); |
| mLiveSnapshotThread = 0; |
| } |
| bLiveSnapshot = false; |
| rc= pthread_create(&mLiveSnapshotThread, NULL, Live_Snapshot_thread, (void *) this); |
| if (!rc) { |
| pthread_setname_np(mLiveSnapshotThread, "CAM_cancel_liveSnap"); |
| } |
| return rc; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : cancelLiveSnapshot_internal |
| * |
| * DESCRIPTION: cancel live snapshot during recording |
| * |
| * PARAMETERS : none |
| * |
| * RETURN : int32_t type of status |
| * NO_ERROR -- success |
| * none-zero failure code |
| *==========================================================================*/ |
| int QCamera2HardwareInterface::cancelLiveSnapshot_internal() { |
| int rc = NO_ERROR; |
| |
| unconfigureAdvancedCapture(); |
| LOGH("Enable display frames again"); |
| setDisplaySkip(FALSE); |
| |
| if (!mLongshotEnabled) { |
| m_perfLock.lock_rel(); |
| } |
| |
| //stop post processor |
| m_postprocessor.stop(); |
| |
| // stop snapshot channel |
| if (!mParameters.isTNRSnapshotEnabled()) { |
| rc = stopChannel(QCAMERA_CH_TYPE_SNAPSHOT); |
| } else { |
| QCameraChannel *pChannel = m_channels[QCAMERA_CH_TYPE_SNAPSHOT]; |
| if (NULL != pChannel) { |
| QCameraStream *pStream = NULL; |
| for (uint32_t i = 0 ; i < pChannel->getNumOfStreams(); i++ ) { |
| pStream = pChannel->getStreamByIndex(i); |
| if ((NULL != pStream) && |
| (CAM_STREAM_TYPE_SNAPSHOT == |
| pStream->getMyType())) { |
| break; |
| } |
| } |
| if (pStream != NULL) { |
| LOGD("REQUEST_FRAMES event for TNR snapshot"); |
| cam_stream_parm_buffer_t param; |
| memset(¶m, 0, sizeof(cam_stream_parm_buffer_t)); |
| param.type = CAM_STREAM_PARAM_TYPE_REQUEST_FRAMES; |
| param.frameRequest.enableStream = 0; |
| rc = pStream->setParameter(param); |
| if (rc != NO_ERROR) { |
| LOGE("Stream Event REQUEST_FRAMES failed"); |
| } |
| } |
| } |
| } |
| |
| return rc; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : putParameters |
| * |
| * DESCRIPTION: put parameters string impl |
| * |
| * PARAMETERS : |
| * @parms : parameters string to be released |
| * |
| * RETURN : int32_t type of status |
| * NO_ERROR -- success |
| * none-zero failure code |
| *==========================================================================*/ |
| int QCamera2HardwareInterface::putParameters(char *parms) |
| { |
| free(parms); |
| return NO_ERROR; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : sendCommand |
| * |
| * DESCRIPTION: send command impl |
| * |
| * PARAMETERS : |
| * @command : command to be executed |
| * @arg1 : optional argument 1 |
| * @arg2 : optional argument 2 |
| * |
| * RETURN : int32_t type of status |
| * NO_ERROR -- success |
| * none-zero failure code |
| *==========================================================================*/ |
| int QCamera2HardwareInterface::sendCommand(int32_t command, |
| __unused int32_t &arg1, __unused int32_t &arg2) |
| { |
| int rc = NO_ERROR; |
| |
| switch (command) { |
| #ifndef VANILLA_HAL |
| case CAMERA_CMD_LONGSHOT_ON: |
| m_perfLock.lock_acq(); |
| arg1 = arg2 = 0; |
| // Longshot can only be enabled when image capture |
| // is not active. |
| if ( !m_stateMachine.isCaptureRunning() ) { |
| LOGI("Longshot Enabled"); |
| mLongshotEnabled = true; |
| rc = mParameters.setLongshotEnable(mLongshotEnabled); |
| |
| // Due to recent buffer count optimizations |
| // ZSL might run with considerably less buffers |
| // when not in longshot mode. Preview needs to |
| // restart in this case. |
| if (isZSLMode() && m_stateMachine.isPreviewRunning()) { |
| QCameraChannel *pChannel = NULL; |
| QCameraStream *pSnapStream = NULL; |
| pChannel = m_channels[QCAMERA_CH_TYPE_ZSL]; |
| if (NULL != pChannel) { |
| QCameraStream *pStream = NULL; |
| for (uint32_t i = 0; i < pChannel->getNumOfStreams(); i++) { |
| pStream = pChannel->getStreamByIndex(i); |
| if (pStream != NULL) { |
| if (pStream->isTypeOf(CAM_STREAM_TYPE_SNAPSHOT)) { |
| pSnapStream = pStream; |
| break; |
| } |
| } |
| } |
| if (NULL != pSnapStream) { |
| uint8_t required = 0; |
| required = getBufNumRequired(CAM_STREAM_TYPE_SNAPSHOT); |
| if (pSnapStream->getBufferCount() < required) { |
| // We restart here, to reset the FPS and no |
| // of buffers as per the requirement of longshot usecase. |
| arg1 = QCAMERA_SM_EVT_RESTART_PERVIEW; |
| if (getRelatedCamSyncInfo()->sync_control == |
| CAM_SYNC_RELATED_SENSORS_ON) { |
| arg2 = QCAMERA_SM_EVT_DELAYED_RESTART; |
| } |
| } |
| } |
| } |
| } |
| // |
| mPrepSnapRun = false; |
| mCACDoneReceived = FALSE; |
| } else { |
| rc = NO_INIT; |
| } |
| break; |
| case CAMERA_CMD_LONGSHOT_OFF: |
| m_perfLock.lock_rel(); |
| if ( mLongshotEnabled && m_stateMachine.isCaptureRunning() ) { |
| cancelPicture(); |
| processEvt(QCAMERA_SM_EVT_SNAPSHOT_DONE, NULL); |
| QCameraChannel *pZSLChannel = m_channels[QCAMERA_CH_TYPE_ZSL]; |
| if (isZSLMode() && (NULL != pZSLChannel) && mPrepSnapRun) { |
| mCameraHandle->ops->stop_zsl_snapshot( |
| mCameraHandle->camera_handle, |
| pZSLChannel->getMyHandle()); |
| } |
| } |
| mPrepSnapRun = false; |
| LOGI("Longshot Disabled"); |
| mLongshotEnabled = false; |
| rc = mParameters.setLongshotEnable(mLongshotEnabled); |
| mCACDoneReceived = FALSE; |
| break; |
| case CAMERA_CMD_HISTOGRAM_ON: |
| case CAMERA_CMD_HISTOGRAM_OFF: |
| rc = setHistogram(command == CAMERA_CMD_HISTOGRAM_ON? true : false); |
| LOGH("Histogram -> %s", |
| mParameters.isHistogramEnabled() ? "Enabled" : "Disabled"); |
| break; |
| #endif |
| case CAMERA_CMD_START_FACE_DETECTION: |
| case CAMERA_CMD_STOP_FACE_DETECTION: |
| mParameters.setFaceDetectionOption(command == CAMERA_CMD_START_FACE_DETECTION? true : false); |
| rc = setFaceDetection(command == CAMERA_CMD_START_FACE_DETECTION? true : false); |
| LOGH("FaceDetection -> %s", |
| mParameters.isFaceDetectionEnabled() ? "Enabled" : "Disabled"); |
| break; |
| #ifndef VANILLA_HAL |
| case CAMERA_CMD_HISTOGRAM_SEND_DATA: |
| #endif |
| default: |
| rc = NO_ERROR; |
| break; |
| } |
| return rc; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : registerFaceImage |
| * |
| * DESCRIPTION: register face image impl |
| * |
| * PARAMETERS : |
| * @img_ptr : ptr to image buffer |
| * @config : ptr to config struct about input image info |
| * @faceID : [OUT] face ID to uniquely identifiy the registered face image |
| * |
| * RETURN : int32_t type of status |
| * NO_ERROR -- success |
| * none-zero failure code |
| *==========================================================================*/ |
| int QCamera2HardwareInterface::registerFaceImage(void *img_ptr, |
| cam_pp_offline_src_config_t *config, |
| int32_t &faceID) |
| { |
| int rc = NO_ERROR; |
| faceID = -1; |
| |
| if (img_ptr == NULL || config == NULL) { |
| LOGE("img_ptr or config is NULL"); |
| return BAD_VALUE; |
| } |
| |
| // allocate ion memory for source image |
| QCameraHeapMemory *imgBuf = new QCameraHeapMemory(QCAMERA_ION_USE_CACHE); |
| if (imgBuf == NULL) { |
| LOGE("Unable to new heap memory obj for image buf"); |
| return NO_MEMORY; |
| } |
| |
| rc = imgBuf->allocate(1, config->input_buf_planes.plane_info.frame_len, NON_SECURE); |
| if (rc < 0) { |
| LOGE("Unable to allocate heap memory for image buf"); |
| delete imgBuf; |
| return NO_MEMORY; |
| } |
| |
| void *pBufPtr = imgBuf->getPtr(0); |
| if (pBufPtr == NULL) { |
| LOGE("image buf is NULL"); |
| imgBuf->deallocate(); |
| delete imgBuf; |
| return NO_MEMORY; |
| } |
| memcpy(pBufPtr, img_ptr, config->input_buf_planes.plane_info.frame_len); |
| |
| cam_pp_feature_config_t pp_feature; |
| memset(&pp_feature, 0, sizeof(cam_pp_feature_config_t)); |
| pp_feature.feature_mask = CAM_QCOM_FEATURE_REGISTER_FACE; |
| QCameraReprocessChannel *pChannel = |
| addOfflineReprocChannel(*config, pp_feature, NULL, NULL); |
| |
| if (pChannel == NULL) { |
| LOGE("fail to add offline reprocess channel"); |
| imgBuf->deallocate(); |
| delete imgBuf; |
| return UNKNOWN_ERROR; |
| } |
| |
| rc = pChannel->start(); |
| if (rc != NO_ERROR) { |
| LOGE("Cannot start reprocess channel"); |
| imgBuf->deallocate(); |
| delete imgBuf; |
| delete pChannel; |
| return rc; |
| } |
| |
| ssize_t bufSize = imgBuf->getSize(0); |
| if (BAD_INDEX != bufSize) { |
| rc = pChannel->doReprocess(imgBuf->getFd(0), imgBuf->getPtr(0), |
| (size_t)bufSize, faceID); |
| } else { |
| LOGE("Failed to retrieve buffer size (bad index)"); |
| return UNKNOWN_ERROR; |
| } |
| |
| // done with register face image, free imgbuf and delete reprocess channel |
| imgBuf->deallocate(); |
| delete imgBuf; |
| imgBuf = NULL; |
| pChannel->stop(); |
| delete pChannel; |
| pChannel = NULL; |
| |
| return rc; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : release |
| * |
| * DESCRIPTION: release camera resource impl |
| * |
| * PARAMETERS : none |
| * |
| * RETURN : int32_t type of status |
| * NO_ERROR -- success |
| * none-zero failure code |
| *==========================================================================*/ |
| int QCamera2HardwareInterface::release() |
| { |
| // stop and delete all channels |
| for (int i = 0; i <QCAMERA_CH_TYPE_MAX ; i++) { |
| if (m_channels[i] != NULL) { |
| stopChannel((qcamera_ch_type_enum_t)i); |
| delChannel((qcamera_ch_type_enum_t)i); |
| } |
| } |
| |
| return NO_ERROR; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : dump |
| * |
| * DESCRIPTION: camera status dump impl |
| * |
| * PARAMETERS : |
| * @fd : fd for the buffer to be dumped with camera status |
| * |
| * RETURN : int32_t type of status |
| * NO_ERROR -- success |
| * none-zero failure code |
| *==========================================================================*/ |
| int QCamera2HardwareInterface::dump(int fd) |
| { |
| dprintf(fd, "\n Camera HAL information Begin \n"); |
| dprintf(fd, "Camera ID: %d \n", mCameraId); |
| dprintf(fd, "StoreMetaDataInFrame: %d \n", mStoreMetaDataInFrame); |
| dprintf(fd, "\n Configuration: %s", mParameters.dump().string()); |
| dprintf(fd, "\n State Information: %s", m_stateMachine.dump().string()); |
| dprintf(fd, "\n Camera HAL information End \n"); |
| |
| /* send UPDATE_DEBUG_LEVEL to the backend so that they can read the |
| debug level property */ |
| mParameters.updateDebugLevel(); |
| return NO_ERROR; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : processAPI |
| * |
| * DESCRIPTION: process API calls from upper layer |
| * |
| * PARAMETERS : |
| * @api : API to be processed |
| * @api_payload : ptr to API payload if any |
| * |
| * RETURN : int32_t type of status |
| * NO_ERROR -- success |
| * none-zero failure code |
| *==========================================================================*/ |
| int QCamera2HardwareInterface::processAPI(qcamera_sm_evt_enum_t api, void *api_payload) |
| { |
| int ret = DEAD_OBJECT; |
| |
| if (m_smThreadActive) { |
| ret = m_stateMachine.procAPI(api, api_payload); |
| } |
| |
| return ret; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : processEvt |
| * |
| * DESCRIPTION: process Evt from backend via mm-camera-interface |
| * |
| * PARAMETERS : |
| * @evt : event type to be processed |
| * @evt_payload : ptr to event payload if any |
| * |
| * RETURN : int32_t type of status |
| * NO_ERROR -- success |
| * none-zero failure code |
| *==========================================================================*/ |
| int QCamera2HardwareInterface::processEvt(qcamera_sm_evt_enum_t evt, void *evt_payload) |
| { |
| return m_stateMachine.procEvt(evt, evt_payload); |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : processSyncEvt |
| * |
| * DESCRIPTION: process synchronous Evt from backend |
| * |
| * PARAMETERS : |
| * @evt : event type to be processed |
| * @evt_payload : ptr to event payload if any |
| * |
| * RETURN : int32_t type of status |
| * NO_ERROR -- success |
| * none-zero failure code |
| *==========================================================================*/ |
| int QCamera2HardwareInterface::processSyncEvt(qcamera_sm_evt_enum_t evt, void *evt_payload) |
| { |
| int rc = NO_ERROR; |
| |
| pthread_mutex_lock(&m_evtLock); |
| rc = processEvt(evt, evt_payload); |
| if (rc == NO_ERROR) { |
| memset(&m_evtResult, 0, sizeof(qcamera_api_result_t)); |
| while (m_evtResult.request_api != evt) { |
| pthread_cond_wait(&m_evtCond, &m_evtLock); |
| } |
| rc = m_evtResult.status; |
| } |
| pthread_mutex_unlock(&m_evtLock); |
| |
| return rc; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : evtHandle |
| * |
| * DESCRIPTION: Function registerd to mm-camera-interface to handle backend events |
| * |
| * PARAMETERS : |
| * @camera_handle : event type to be processed |
| * @evt : ptr to event |
| * @user_data : user data ptr |
| * |
| * RETURN : none |
| *==========================================================================*/ |
| void QCamera2HardwareInterface::camEvtHandle(uint32_t /*camera_handle*/, |
| mm_camera_event_t *evt, |
| void *user_data) |
| { |
| QCamera2HardwareInterface *obj = (QCamera2HardwareInterface *)user_data; |
| if (obj && evt) { |
| mm_camera_event_t *payload = |
| (mm_camera_event_t *)malloc(sizeof(mm_camera_event_t)); |
| if (NULL != payload) { |
| *payload = *evt; |
| //peek into the event, if this is an eztune event from server, |
| //then we don't need to post it to the SM Qs, we shud directly |
| //spawn a thread and get the job done (jpeg or raw snapshot) |
| switch (payload->server_event_type) { |
| case CAM_EVENT_TYPE_INT_TAKE_JPEG: |
| //Received JPEG trigger from eztune |
| if (false == obj->m_bIntJpegEvtPending) { |
| pthread_mutex_lock(&obj->m_int_lock); |
| obj->m_bIntJpegEvtPending = true; |
| pthread_mutex_unlock(&obj->m_int_lock); |
| obj->takePictureInternal(); |
| } |
| free(payload); |
| break; |
| case CAM_EVENT_TYPE_INT_TAKE_RAW: |
| //Received RAW trigger from eztune |
| if (false == obj->m_bIntRawEvtPending) { |
| pthread_mutex_lock(&obj->m_int_lock); |
| obj->m_bIntRawEvtPending = true; |
| pthread_mutex_unlock(&obj->m_int_lock); |
| obj->takePictureInternal(); |
| } |
| free(payload); |
| break; |
| case CAM_EVENT_TYPE_DAEMON_DIED: |
| { |
| Mutex::Autolock l(obj->mDefLock); |
| obj->mDefCond.broadcast(); |
| LOGH("broadcast mDefCond signal\n"); |
| } |
| default: |
| obj->processEvt(QCAMERA_SM_EVT_EVT_NOTIFY, payload); |
| break; |
| } |
| } |
| } else { |
| LOGE("NULL user_data"); |
| } |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : jpegEvtHandle |
| * |
| * DESCRIPTION: Function registerd to mm-jpeg-interface to handle jpeg events |
| * |
| * PARAMETERS : |
| * @status : status of jpeg job |
| * @client_hdl: jpeg client handle |
| * @jobId : jpeg job Id |
| * @p_ouput : ptr to jpeg output result struct |
| * @userdata : user data ptr |
| * |
| * RETURN : none |
| *==========================================================================*/ |
| void QCamera2HardwareInterface::jpegEvtHandle(jpeg_job_status_t status, |
| uint32_t /*client_hdl*/, |
| uint32_t jobId, |
| mm_jpeg_output_t *p_output, |
| void *userdata) |
| { |
| QCamera2HardwareInterface *obj = (QCamera2HardwareInterface *)userdata; |
| if (obj) { |
| qcamera_jpeg_evt_payload_t *payload = |
| (qcamera_jpeg_evt_payload_t *)malloc(sizeof(qcamera_jpeg_evt_payload_t)); |
| if (NULL != payload) { |
| memset(payload, 0, sizeof(qcamera_jpeg_evt_payload_t)); |
| payload->status = status; |
| payload->jobId = jobId; |
| if (p_output != NULL) { |
| payload->out_data = *p_output; |
| } |
| obj->processEvt(QCAMERA_SM_EVT_JPEG_EVT_NOTIFY, payload); |
| } |
| } else { |
| LOGE("NULL user_data"); |
| } |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : thermalEvtHandle |
| * |
| * DESCRIPTION: routine to handle thermal event notification |
| * |
| * PARAMETERS : |
| * @level : thermal level |
| * @userdata : userdata passed in during registration |
| * @data : opaque data from thermal client |
| * |
| * RETURN : int32_t type of status |
| * NO_ERROR -- success |
| * none-zero failure code |
| *==========================================================================*/ |
| int QCamera2HardwareInterface::thermalEvtHandle( |
| qcamera_thermal_level_enum_t *level, void *userdata, void *data) |
| { |
| if (!mCameraOpened) { |
| LOGH("Camera is not opened, no need to handle thermal evt"); |
| return NO_ERROR; |
| } |
| |
| // Make sure thermal events are logged |
| LOGH("level = %d, userdata = %p, data = %p", |
| *level, userdata, data); |
| //We don't need to lockAPI, waitAPI here. QCAMERA_SM_EVT_THERMAL_NOTIFY |
| // becomes an aync call. This also means we can only pass payload |
| // by value, not by address. |
| return processAPI(QCAMERA_SM_EVT_THERMAL_NOTIFY, (void *)level); |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : sendEvtNotify |
| * |
| * DESCRIPTION: send event notify to notify thread |
| * |
| * PARAMETERS : |
| * @msg_type: msg type to be sent |
| * @ext1 : optional extension1 |
| * @ext2 : optional extension2 |
| * |
| * RETURN : int32_t type of status |
| * NO_ERROR -- success |
| * none-zero failure code |
| *==========================================================================*/ |
| int32_t QCamera2HardwareInterface::sendEvtNotify(int32_t msg_type, |
| int32_t ext1, |
| int32_t ext2) |
| { |
| qcamera_callback_argm_t cbArg; |
| memset(&cbArg, 0, sizeof(qcamera_callback_argm_t)); |
| cbArg.cb_type = QCAMERA_NOTIFY_CALLBACK; |
| cbArg.msg_type = msg_type; |
| cbArg.ext1 = ext1; |
| cbArg.ext2 = ext2; |
| return m_cbNotifier.notifyCallback(cbArg); |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : processAEInfo |
| * |
| * DESCRIPTION: process AE updates |
| * |
| * PARAMETERS : |
| * @ae_params: current AE parameters |
| * |
| * RETURN : None |
| *==========================================================================*/ |
| int32_t QCamera2HardwareInterface::processAEInfo(cam_3a_params_t &ae_params) |
| { |
| mParameters.updateAEInfo(ae_params); |
| if (mParameters.isInstantAECEnabled()) { |
| // Reset Instant AEC info only if instant aec enabled. |
| bool bResetInstantAec = false; |
| if (ae_params.settled) { |
| // If AEC settled, reset instant AEC |
| bResetInstantAec = true; |
| } else if ((mParameters.isInstantCaptureEnabled()) && |
| (mInstantAecFrameCount >= mParameters.getAecFrameBoundValue())) { |
| // if AEC not settled, and instant capture enabled, |
| // reset instant AEC only when frame count is |
| // more or equal to AEC frame bound value. |
| bResetInstantAec = true; |
| } else if ((mParameters.isInstantAECEnabled()) && |
| (mInstantAecFrameCount >= mParameters.getAecSkipDisplayFrameBound())) { |
| // if AEC not settled, and only instant AEC enabled, |
| // reset instant AEC only when frame count is |
| // more or equal to AEC skip display frame bound value. |
| bResetInstantAec = true; |
| } |
| |
| if (bResetInstantAec) { |
| LOGD("setting instant AEC to false"); |
| mParameters.setInstantAEC(false, true); |
| mInstantAecFrameCount = 0; |
| } |
| } |
| return NO_ERROR; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : processFocusPositionInfo |
| * |
| * DESCRIPTION: process AF updates |
| * |
| * PARAMETERS : |
| * @cur_pos_info: current lens position |
| * |
| * RETURN : None |
| *==========================================================================*/ |
| int32_t QCamera2HardwareInterface::processFocusPositionInfo(cam_focus_pos_info_t &cur_pos_info) |
| { |
| mParameters.updateCurrentFocusPosition(cur_pos_info); |
| return NO_ERROR; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : processAutoFocusEvent |
| * |
| * DESCRIPTION: process auto focus event |
| * |
| * PARAMETERS : |
| * @focus_data: struct containing auto focus result info |
| * |
| * RETURN : int32_t type of status |
| * NO_ERROR -- success |
| * none-zero failure code |
| *==========================================================================*/ |
| int32_t QCamera2HardwareInterface::processAutoFocusEvent(cam_auto_focus_data_t &focus_data) |
| { |
| int32_t ret = NO_ERROR; |
| LOGH("E"); |
| |
| if (getRelatedCamSyncInfo()->mode == CAM_MODE_SECONDARY) { |
| // Ignore focus updates |
| LOGH("X Secondary Camera, no need to process!! "); |
| return ret; |
| } |
| cam_focus_mode_type focusMode = mParameters.getFocusMode(); |
| LOGH("[AF_DBG] focusMode=%d, focusState=%d isDepth=%d", |
| focusMode, focus_data.focus_state, focus_data.isDepth); |
| |
| switch (focusMode) { |
| case CAM_FOCUS_MODE_AUTO: |
| case CAM_FOCUS_MODE_MACRO: |
| // ignore AF event if AF was already cancelled meanwhile |
| if (!mActiveAF) { |
| break; |
| } |
| // If the HAL focus mode is different from AF INFINITY focus mode, send event to app |
| if ((focus_data.focus_mode == CAM_FOCUS_MODE_INFINITY) && |
| (focus_data.focus_state == CAM_AF_STATE_INACTIVE)) { |
| ret = sendEvtNotify(CAMERA_MSG_FOCUS, true, 0); |
| mActiveAF = false; // reset the mActiveAF in this special case |
| break; |
| } |
| |
| //while transitioning from CAF->Auto/Macro, we might receive CAF related |
| //events (PASSIVE_*) due to timing. Ignore such events if any. |
| if ((focus_data.focus_state == CAM_AF_STATE_PASSIVE_SCAN) || |
| (focus_data.focus_state == CAM_AF_STATE_PASSIVE_FOCUSED) || |
| (focus_data.focus_state == CAM_AF_STATE_PASSIVE_UNFOCUSED)) { |
| break; |
| } |
| |
| //This is just an intermediate update to HAL indicating focus is in progress. No need |
| //to send this event to app. Same applies to INACTIVE state as well. |
| if ((focus_data.focus_state == CAM_AF_STATE_ACTIVE_SCAN) || |
| (focus_data.focus_state == CAM_AF_STATE_INACTIVE)) { |
| break; |
| } |
| // update focus distance |
| mParameters.updateFocusDistances(&focus_data.focus_dist); |
| |
| //flush any old snapshot frames in ZSL Q which are not focused. |
| if (mParameters.isZSLMode() && focus_data.flush_info.needFlush ) { |
| QCameraPicChannel *pZSLChannel = |
| (QCameraPicChannel *)m_channels[QCAMERA_CH_TYPE_ZSL]; |
| if (NULL != pZSLChannel) { |
| //flush the zsl-buffer |
| uint32_t flush_frame_idx = focus_data.flush_info.focused_frame_idx; |
| LOGD("flush the zsl-buffer before frame = %u.", flush_frame_idx); |
| pZSLChannel->flushSuperbuffer(flush_frame_idx); |
| } |
| } |
| |
| //send event to app finally |
| LOGI("Send AF DOne event to app"); |
| ret = sendEvtNotify(CAMERA_MSG_FOCUS, |
| (focus_data.focus_state == CAM_AF_STATE_FOCUSED_LOCKED), 0); |
| break; |
| case CAM_FOCUS_MODE_CONTINOUS_VIDEO: |
| case CAM_FOCUS_MODE_CONTINOUS_PICTURE: |
| |
| // If the HAL focus mode is different from AF INFINITY focus mode, send event to app |
| if ((focus_data.focus_mode == CAM_FOCUS_MODE_INFINITY) && |
| (focus_data.focus_state == CAM_AF_STATE_INACTIVE)) { |
| ret = sendEvtNotify(CAMERA_MSG_FOCUS, false, 0); |
| mActiveAF = false; // reset the mActiveAF in this special case |
| break; |
| } |
| |
| //If AutoFocus() is triggered while in CAF mode, ignore all CAF events (PASSIVE_*) and |
| //process/wait for only ACTIVE_* events. |
| if (((focus_data.focus_state == CAM_AF_STATE_PASSIVE_FOCUSED) || |
| (focus_data.focus_state == CAM_AF_STATE_PASSIVE_UNFOCUSED) || |
| (focus_data.focus_state == CAM_AF_STATE_PASSIVE_SCAN)) && mActiveAF) { |
| break; |
| } |
| |
| if (!bDepthAFCallbacks && focus_data.isDepth && |
| (focus_data.focus_state == CAM_AF_STATE_PASSIVE_SCAN)) { |
| LOGD("Skip sending scan state to app, if depth focus"); |
| break; |
| } |
| |
| //These are the AF states for which we need to send notification to app in CAF mode. |
| //This includes both regular CAF (PASSIVE) events as well as ACTIVE events ( in case |
| //AF is triggered while in CAF mode) |
| if ((focus_data.focus_state == CAM_AF_STATE_PASSIVE_FOCUSED) || |
| (focus_data.focus_state == CAM_AF_STATE_PASSIVE_UNFOCUSED) || |
| (focus_data.focus_state == CAM_AF_STATE_FOCUSED_LOCKED) || |
| (focus_data.focus_state == CAM_AF_STATE_NOT_FOCUSED_LOCKED)) { |
| |
| // update focus distance |
| mParameters.updateFocusDistances(&focus_data.focus_dist); |
| |
| if (mParameters.isZSLMode() && focus_data.flush_info.needFlush ) { |
| QCameraPicChannel *pZSLChannel = |
| (QCameraPicChannel *)m_channels[QCAMERA_CH_TYPE_ZSL]; |
| if (NULL != pZSLChannel) { |
| //flush the zsl-buffer |
| uint32_t flush_frame_idx = focus_data.flush_info.focused_frame_idx; |
| LOGD("flush the zsl-buffer before frame = %u.", flush_frame_idx); |
| pZSLChannel->flushSuperbuffer(flush_frame_idx); |
| } |
| } |
| |
| if (mActiveAF) { |
| LOGI("Send AF Done event to app"); |
| } |
| ret = sendEvtNotify(CAMERA_MSG_FOCUS, |
| ((focus_data.focus_state == CAM_AF_STATE_PASSIVE_FOCUSED) || |
| (focus_data.focus_state == CAM_AF_STATE_FOCUSED_LOCKED)), 0); |
| } |
| ret = sendEvtNotify(CAMERA_MSG_FOCUS_MOVE, |
| (focus_data.focus_state == CAM_AF_STATE_PASSIVE_SCAN), 0); |
| break; |
| case CAM_FOCUS_MODE_INFINITY: |
| case CAM_FOCUS_MODE_FIXED: |
| case CAM_FOCUS_MODE_EDOF: |
| default: |
| LOGH("no ops for autofocus event in focusmode %d", focusMode); |
| break; |
| } |
| |
| //Reset mActiveAF once we receive focus done event |
| if ((focus_data.focus_state == CAM_AF_STATE_FOCUSED_LOCKED) || |
| (focus_data.focus_state == CAM_AF_STATE_NOT_FOCUSED_LOCKED)) { |
| mActiveAF = false; |
| } |
| |
| LOGH("X"); |
| return ret; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : processZoomEvent |
| * |
| * DESCRIPTION: process zoom event |
| * |
| * PARAMETERS : |
| * @crop_info : crop info as a result of zoom operation |
| * |
| * RETURN : int32_t type of status |
| * NO_ERROR -- success |
| * none-zero failure code |
| *==========================================================================*/ |
| int32_t QCamera2HardwareInterface::processZoomEvent(cam_crop_data_t &crop_info) |
| { |
| int32_t ret = NO_ERROR; |
| |
| for (int i = 0; i < QCAMERA_CH_TYPE_MAX; i++) { |
| if (m_channels[i] != NULL) { |
| ret = m_channels[i]->processZoomDone(mPreviewWindow, crop_info); |
| } |
| } |
| return ret; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : processZSLCaptureDone |
| * |
| * DESCRIPTION: process ZSL capture done events |
| * |
| * PARAMETERS : None |
| * |
| * RETURN : int32_t type of status |
| * NO_ERROR -- success |
| * none-zero failure code |
| *==========================================================================*/ |
| int32_t QCamera2HardwareInterface::processZSLCaptureDone() |
| { |
| int rc = NO_ERROR; |
| |
| if (++mInputCount >= mParameters.getBurstCountForAdvancedCapture()) { |
| rc = unconfigureAdvancedCapture(); |
| } |
| |
| return rc; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : processRetroAECUnlock |
| * |
| * DESCRIPTION: process retro burst AEC unlock events |
| * |
| * PARAMETERS : None |
| * |
| * RETURN : int32_t type of status |
| * NO_ERROR -- success |
| * none-zero failure code |
| *==========================================================================*/ |
| int32_t QCamera2HardwareInterface::processRetroAECUnlock() |
| { |
| int rc = NO_ERROR; |
| |
| LOGH("LED assisted AF Release AEC Lock"); |
| rc = mParameters.setAecLock("false"); |
| if (NO_ERROR != rc) { |
| LOGE("Error setting AEC lock"); |
| return rc; |
| } |
| |
| rc = mParameters.commitParameters(); |
| if (NO_ERROR != rc) { |
| LOGE("Error during camera parameter commit"); |
| } else { |
| m_bLedAfAecLock = FALSE; |
| } |
| |
| return rc; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : processHDRData |
| * |
| * DESCRIPTION: process HDR scene events |
| * |
| * PARAMETERS : |
| * @hdr_scene : HDR scene event data |
| * |
| * RETURN : int32_t type of status |
| * NO_ERROR -- success |
| * none-zero failure code |
| *==========================================================================*/ |
| int32_t QCamera2HardwareInterface::processHDRData( |
| __unused cam_asd_hdr_scene_data_t hdr_scene) |
| { |
| int rc = NO_ERROR; |
| |
| #ifndef VANILLA_HAL |
| if (hdr_scene.is_hdr_scene && |
| (hdr_scene.hdr_confidence > HDR_CONFIDENCE_THRESHOLD) && |
| mParameters.isAutoHDREnabled()) { |
| m_HDRSceneEnabled = true; |
| } else { |
| m_HDRSceneEnabled = false; |
| } |
| mParameters.setHDRSceneEnable(m_HDRSceneEnabled); |
| |
| if ( msgTypeEnabled(CAMERA_MSG_META_DATA) ) { |
| |
| size_t data_len = sizeof(int); |
| size_t buffer_len = 1 *sizeof(int) //meta type |
| + 1 *sizeof(int) //data len |
| + 1 *sizeof(int); //data |
| camera_memory_t *hdrBuffer = mGetMemory(-1, |
| buffer_len, |
| 1, |
| mCallbackCookie); |
| if ( NULL == hdrBuffer ) { |
| LOGE("Not enough memory for auto HDR data"); |
| return NO_MEMORY; |
| } |
| |
| int *pHDRData = (int *)hdrBuffer->data; |
| if (pHDRData == NULL) { |
| LOGE("memory data ptr is NULL"); |
| return UNKNOWN_ERROR; |
| } |
| |
| pHDRData[0] = CAMERA_META_DATA_HDR; |
| pHDRData[1] = (int)data_len; |
| pHDRData[2] = m_HDRSceneEnabled; |
| |
| qcamera_callback_argm_t cbArg; |
| memset(&cbArg, 0, sizeof(qcamera_callback_argm_t)); |
| cbArg.cb_type = QCAMERA_DATA_CALLBACK; |
| cbArg.msg_type = CAMERA_MSG_META_DATA; |
| cbArg.data = hdrBuffer; |
| cbArg.user_data = hdrBuffer; |
| cbArg.cookie = this; |
| cbArg.release_cb = releaseCameraMemory; |
| rc = m_cbNotifier.notifyCallback(cbArg); |
| if (rc != NO_ERROR) { |
| LOGE("fail sending auto HDR notification"); |
| hdrBuffer->release(hdrBuffer); |
| } |
| } |
| |
| LOGH("hdr_scene_data: processHDRData: %d %f", |
| hdr_scene.is_hdr_scene, |
| hdr_scene.hdr_confidence); |
| |
| #endif |
| return rc; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : transAwbMetaToParams |
| * |
| * DESCRIPTION: translate awb params from metadata callback to QCameraParametersIntf |
| * |
| * PARAMETERS : |
| * @awb_params : awb params from metadata callback |
| * |
| * RETURN : int32_t type of status |
| * NO_ERROR -- success |
| * none-zero failure code |
| *==========================================================================*/ |
| int32_t QCamera2HardwareInterface::transAwbMetaToParams(cam_awb_params_t &awb_params) |
| { |
| mParameters.updateAWBParams(awb_params); |
| return NO_ERROR; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : processPrepSnapshotDone |
| * |
| * DESCRIPTION: process prep snapshot done event |
| * |
| * PARAMETERS : |
| * @prep_snapshot_state : state of prepare snapshot done. In other words, |
| * i.e. whether need future frames for capture. |
| * |
| * RETURN : int32_t type of status |
| * NO_ERROR -- success |
| * none-zero failure code |
| *==========================================================================*/ |
| int32_t QCamera2HardwareInterface::processPrepSnapshotDoneEvent( |
| cam_prep_snapshot_state_t prep_snapshot_state) |
| { |
| int32_t ret = NO_ERROR; |
| LOGI("[KPI Perf]: Received PREPARE SANSPHOT Done event state = %d", |
| prep_snapshot_state); |
| if (m_channels[QCAMERA_CH_TYPE_ZSL] && |
| prep_snapshot_state == NEED_FUTURE_FRAME) { |
| LOGH("already handled in mm-camera-intf, no ops here"); |
| if (isRetroPicture()) { |
| mParameters.setAecLock("true"); |
| mParameters.commitParameters(); |
| m_bLedAfAecLock = TRUE; |
| } |
| } |
| return ret; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : processASDUpdate |
| * |
| * DESCRIPTION: process ASD update event |
| * |
| * PARAMETERS : |
| * @scene: selected scene mode |
| * |
| * RETURN : int32_t type of status |
| * NO_ERROR -- success |
| * none-zero failure code |
| *==========================================================================*/ |
| int32_t QCamera2HardwareInterface::processASDUpdate( |
| __unused cam_asd_decision_t asd_decision) |
| { |
| #ifndef VANILLA_HAL |
| if ( msgTypeEnabled(CAMERA_MSG_META_DATA) ) { |
| size_t data_len = sizeof(cam_auto_scene_t); |
| size_t buffer_len = 1 *sizeof(int) //meta type |
| + 1 *sizeof(int) //data len |
| + data_len; //data |
| camera_memory_t *asdBuffer = mGetMemory(-1, |
| buffer_len, 1, mCallbackCookie); |
| if ( NULL == asdBuffer ) { |
| LOGE("Not enough memory for histogram data"); |
| return NO_MEMORY; |
| } |
| |
| int *pASDData = (int *)asdBuffer->data; |
| if (pASDData == NULL) { |
| LOGE("memory data ptr is NULL"); |
| return UNKNOWN_ERROR; |
| } |
| |
| pASDData[0] = CAMERA_META_DATA_ASD; |
| pASDData[1] = (int)data_len; |
| pASDData[2] = asd_decision.detected_scene; |
| |
| qcamera_callback_argm_t cbArg; |
| memset(&cbArg, 0, sizeof(qcamera_callback_argm_t)); |
| cbArg.cb_type = QCAMERA_DATA_CALLBACK; |
| cbArg.msg_type = CAMERA_MSG_META_DATA; |
| cbArg.data = asdBuffer; |
| cbArg.user_data = asdBuffer; |
| cbArg.cookie = this; |
| cbArg.release_cb = releaseCameraMemory; |
| int32_t rc = m_cbNotifier.notifyCallback(cbArg); |
| if (rc != NO_ERROR) { |
| LOGE("fail sending notification"); |
| asdBuffer->release(asdBuffer); |
| } |
| } |
| #endif |
| return NO_ERROR; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : processJpegNotify |
| * |
| * DESCRIPTION: process jpeg event |
| * |
| * PARAMETERS : |
| * @jpeg_evt: ptr to jpeg event payload |
| * |
| * RETURN : int32_t type of status |
| * NO_ERROR -- success |
| * none-zero failure code |
| *==========================================================================*/ |
| int32_t QCamera2HardwareInterface::processJpegNotify(qcamera_jpeg_evt_payload_t *jpeg_evt) |
| { |
| return m_postprocessor.processJpegEvt(jpeg_evt); |
| } |
| |
| |
| /*=========================================================================== |
| * FUNCTION : processDCFOVControl |
| * |
| * DESCRIPTION: Fill Dual camera FOV control |
| * |
| * PARAMETERS : none |
| * |
| * RETURN : int32_t type of status |
| * NO_ERROR -- success |
| * none-zero failure code |
| *==========================================================================*/ |
| int32_t QCamera2HardwareInterface::processDCFOVControl() |
| { |
| int32_t zoomLevel; |
| uint32_t camState = mActiveCamera; |
| |
| if (!isDualCamera()) { |
| return NO_ERROR; |
| } |
| |
| /*FOV control block needs to integrated here to decide dual camera |
| switch operation. |
| We can access application parameter, metadata buffer, |
| parameter buffer used for back-end here*/ |
| zoomLevel = mParameters.getParmZoomLevel(); |
| if (zoomLevel < 20) { |
| //WIDE Zone |
| LOGH("WIDE ZONE : %d and %d", zoomLevel, prev_zoomLevel); |
| if (camState & MM_CAMERA_TYPE_AUX) { |
| //Suspend Aux |
| camState &= (~MM_CAMERA_TYPE_AUX); |
| } |
| if (!(camState & MM_CAMERA_TYPE_MAIN)) { |
| //Activate Main |
| camState |= MM_CAMERA_TYPE_MAIN; |
| } |
| } else if (zoomLevel > 60) { |
| //TELE Zone |
| LOGH("TELE ZONE : %d and %d", zoomLevel, prev_zoomLevel); |
| if (!(camState & MM_CAMERA_TYPE_AUX)) { |
| //Activate Aux |
| camState |= MM_CAMERA_TYPE_AUX; |
| } |
| if (camState & MM_CAMERA_TYPE_MAIN) { |
| //Suspend Main |
| camState &= (~MM_CAMERA_TYPE_MAIN); |
| } |
| } else { |
| //Dual Zone |
| LOGH("DUAL ZONE : %d and %d", zoomLevel, prev_zoomLevel); |
| if (!(camState & MM_CAMERA_TYPE_AUX)) { |
| //Activate Aux |
| camState |= MM_CAMERA_TYPE_AUX; |
| } |
| if (!(camState & MM_CAMERA_TYPE_MAIN)) { |
| //Activate Main |
| camState |= MM_CAMERA_TYPE_MAIN; |
| } |
| } |
| |
| if (camState != 0 && camState != mActiveCamera) { |
| processCameraControl(camState); |
| } |
| |
| if (zoomLevel >= 40 && prev_zoomLevel < 40) { |
| //Switch camera |
| switchCameraCb(); |
| prev_zoomLevel = zoomLevel; |
| } else if (prev_zoomLevel >= 40 && zoomLevel < 40){ |
| switchCameraCb(); |
| prev_zoomLevel = zoomLevel; |
| } |
| return 0; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : processCameraControl |
| * |
| * DESCRIPTION: Suspend and resume camera |
| * |
| * PARAMETERS : |
| * |
| * RETURN : int32_t type of status |
| * NO_ERROR -- success |
| * none-zero failure code |
| *==========================================================================*/ |
| int32_t QCamera2HardwareInterface::processCameraControl(uint32_t camState) |
| { |
| int32_t ret = NO_ERROR; |
| |
| //Set camera controls to parameter and back-end |
| ret = mParameters.setCameraControls(camState, TRUE); |
| |
| //Update camera status to internal channel |
| for (int i = 0; i < QCAMERA_CH_TYPE_MAX; i++) { |
| if (m_channels[i] != NULL && m_channels[i]->isDualChannel()) { |
| ret = m_channels[i]->processCameraControl(camState); |
| if (ret != NO_ERROR) { |
| LOGE("Channel Switch Failed"); |
| break; |
| } |
| } |
| } |
| if (ret == NO_ERROR) { |
| if (camState == MM_CAMERA_TYPE_MAIN) { |
| m_ActiveHandle = get_main_camera_handle(mCameraHandle->camera_handle); |
| } else if (camState == MM_CAMERA_TYPE_AUX) { |
| m_ActiveHandle = get_aux_camera_handle(mCameraHandle->camera_handle); |
| } |
| } |
| LOGH("mActiveCamera = %d to %d", mActiveCamera, camState); |
| mActiveCamera = camState; |
| return ret; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : switchCameraCb |
| * |
| * DESCRIPTION: switch camera's in case of dual camera |
| * |
| * PARAMETERS : |
| * |
| * RETURN : int32_t type of status |
| * NO_ERROR -- success |
| * none-zero failure code |
| *==========================================================================*/ |
| int32_t QCamera2HardwareInterface::switchCameraCb() |
| { |
| int32_t ret = NO_ERROR; |
| |
| for (int i = 0; i < QCAMERA_CH_TYPE_MAX; i++) { |
| if (m_channels[i] != NULL && m_channels[i]->isDualChannel()) { |
| ret = m_channels[i]->switchChannelCb(); |
| if (ret != NO_ERROR) { |
| LOGE("Channel Switch Failed"); |
| break; |
| } |
| } |
| } |
| if (ret == NO_ERROR && mActiveCamera == MM_CAMERA_DUAL_CAM) { |
| if (get_aux_camera_handle(mCameraHandle->camera_handle) |
| == m_ActiveHandle) { |
| m_ActiveHandle = get_main_camera_handle(mCameraHandle->camera_handle); |
| } else if (get_main_camera_handle(mCameraHandle->camera_handle) |
| == m_ActiveHandle) { |
| m_ActiveHandle = get_aux_camera_handle(mCameraHandle->camera_handle); |
| } else { |
| m_ActiveHandle = mCameraHandle->camera_handle; |
| } |
| } |
| return ret; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : lockAPI |
| * |
| * DESCRIPTION: lock to process API |
| * |
| * PARAMETERS : none |
| * |
| * RETURN : none |
| *==========================================================================*/ |
| void QCamera2HardwareInterface::lockAPI() |
| { |
| pthread_mutex_lock(&m_lock); |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : waitAPIResult |
| * |
| * DESCRIPTION: wait for API result coming back. This is a blocking call, it will |
| * return only cerntain API event type arrives |
| * |
| * PARAMETERS : |
| * @api_evt : API event type |
| * |
| * RETURN : none |
| *==========================================================================*/ |
| void QCamera2HardwareInterface::waitAPIResult(qcamera_sm_evt_enum_t api_evt, |
| qcamera_api_result_t *apiResult) |
| { |
| LOGD("wait for API result of evt (%d)", api_evt); |
| int resultReceived = 0; |
| while (!resultReceived) { |
| pthread_cond_wait(&m_cond, &m_lock); |
| if (m_apiResultList != NULL) { |
| api_result_list *apiResultList = m_apiResultList; |
| api_result_list *apiResultListPrevious = m_apiResultList; |
| while (apiResultList != NULL) { |
| if (apiResultList->result.request_api == api_evt) { |
| resultReceived = 1; |
| *apiResult = apiResultList->result; |
| apiResultListPrevious->next = apiResultList->next; |
| if (apiResultList == m_apiResultList) { |
| m_apiResultList = apiResultList->next; |
| } |
| free(apiResultList); |
| break; |
| } |
| else { |
| apiResultListPrevious = apiResultList; |
| apiResultList = apiResultList->next; |
| } |
| } |
| } |
| } |
| LOGD("return (%d) from API result wait for evt (%d)", |
| apiResult->status, api_evt); |
| } |
| |
| |
| /*=========================================================================== |
| * FUNCTION : unlockAPI |
| * |
| * DESCRIPTION: API processing is done, unlock |
| * |
| * PARAMETERS : none |
| * |
| * RETURN : none |
| *==========================================================================*/ |
| void QCamera2HardwareInterface::unlockAPI() |
| { |
| pthread_mutex_unlock(&m_lock); |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : signalAPIResult |
| * |
| * DESCRIPTION: signal condition viarable that cerntain API event type arrives |
| * |
| * PARAMETERS : |
| * @result : API result |
| * |
| * RETURN : none |
| *==========================================================================*/ |
| void QCamera2HardwareInterface::signalAPIResult(qcamera_api_result_t *result) |
| { |
| |
| pthread_mutex_lock(&m_lock); |
| api_result_list *apiResult = (api_result_list *)malloc(sizeof(api_result_list)); |
| if (apiResult == NULL) { |
| LOGE("ERROR: malloc for api result failed, Result will not be sent"); |
| goto malloc_failed; |
| } |
| apiResult->result = *result; |
| apiResult->next = NULL; |
| if (m_apiResultList == NULL) m_apiResultList = apiResult; |
| else { |
| api_result_list *apiResultList = m_apiResultList; |
| while(apiResultList->next != NULL) apiResultList = apiResultList->next; |
| apiResultList->next = apiResult; |
| } |
| malloc_failed: |
| pthread_cond_broadcast(&m_cond); |
| pthread_mutex_unlock(&m_lock); |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : signalEvtResult |
| * |
| * DESCRIPTION: signal condition variable that certain event was processed |
| * |
| * PARAMETERS : |
| * @result : Event result |
| * |
| * RETURN : none |
| *==========================================================================*/ |
| void QCamera2HardwareInterface::signalEvtResult(qcamera_api_result_t *result) |
| { |
| pthread_mutex_lock(&m_evtLock); |
| m_evtResult = *result; |
| pthread_cond_signal(&m_evtCond); |
| pthread_mutex_unlock(&m_evtLock); |
| } |
| |
| int32_t QCamera2HardwareInterface::prepareRawStream(QCameraChannel *curChannel) |
| { |
| int32_t rc = NO_ERROR; |
| cam_dimension_t str_dim,max_dim; |
| QCameraChannel *pChannel; |
| |
| max_dim.width = 0; |
| max_dim.height = 0; |
| |
| for (int j = 0; j < QCAMERA_CH_TYPE_MAX; j++) { |
| if (m_channels[j] != NULL) { |
| pChannel = m_channels[j]; |
| for (uint8_t i = 0; i < pChannel->getNumOfStreams(); i++) { |
| QCameraStream *pStream = pChannel->getStreamByIndex(i); |
| if (pStream != NULL) { |
| if ((pStream->isTypeOf(CAM_STREAM_TYPE_METADATA)) |
| || (pStream->isTypeOf(CAM_STREAM_TYPE_POSTVIEW))) { |
| continue; |
| } |
| pStream->getFrameDimension(str_dim); |
| if (str_dim.width > max_dim.width) { |
| max_dim.width = str_dim.width; |
| } |
| if (str_dim.height > max_dim.height) { |
| max_dim.height = str_dim.height; |
| } |
| } |
| } |
| } |
| } |
| |
| for (uint8_t i = 0; i < curChannel->getNumOfStreams(); i++) { |
| QCameraStream *pStream = curChannel->getStreamByIndex(i); |
| if (pStream != NULL) { |
| if ((pStream->isTypeOf(CAM_STREAM_TYPE_METADATA)) |
| || (pStream->isTypeOf(CAM_STREAM_TYPE_POSTVIEW))) { |
| continue; |
| } |
| pStream->getFrameDimension(str_dim); |
| if (str_dim.width > max_dim.width) { |
| max_dim.width = str_dim.width; |
| } |
| if (str_dim.height > max_dim.height) { |
| max_dim.height = str_dim.height; |
| } |
| } |
| } |
| rc = mParameters.updateRAW(max_dim); |
| return rc; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : addStreamToChannel |
| * |
| * DESCRIPTION: add a stream into a channel |
| * |
| * PARAMETERS : |
| * @pChannel : ptr to channel obj |
| * @streamType : type of stream to be added |
| * @streamCB : callback of stream |
| * @userData : user data ptr to callback |
| * |
| * RETURN : int32_t type of status |
| * NO_ERROR -- success |
| * none-zero failure code |
| *==========================================================================*/ |
| int32_t QCamera2HardwareInterface::addStreamToChannel(QCameraChannel *pChannel, |
| cam_stream_type_t streamType, |
| stream_cb_routine streamCB, |
| void *userData) |
| { |
| int32_t rc = NO_ERROR; |
| QCameraHeapMemory *pStreamInfo = NULL; |
| |
| if (streamType == CAM_STREAM_TYPE_RAW) { |
| prepareRawStream(pChannel); |
| } |
| |
| pStreamInfo = allocateStreamInfoBuf(streamType, getStreamRefCount(streamType)); |
| if (pStreamInfo == NULL) { |
| LOGE("no mem for stream info buf"); |
| return NO_MEMORY; |
| } |
| |
| bool bDynAllocBuf = false; |
| if (isZSLMode() && streamType == CAM_STREAM_TYPE_SNAPSHOT) { |
| bDynAllocBuf = true; |
| } |
| |
| cam_padding_info_t padding_info; |
| |
| if (streamType == CAM_STREAM_TYPE_ANALYSIS) { |
| cam_analysis_info_t analysisInfo; |
| cam_feature_mask_t featureMask; |
| |
| featureMask = 0; |
| mParameters.getStreamPpMask(CAM_STREAM_TYPE_ANALYSIS, featureMask); |
| rc = mParameters.getAnalysisInfo( |
| ((mParameters.getRecordingHintValue() == true) && |
| mParameters.fdModeInVideo()), |
| FALSE, |
| featureMask, |
| &analysisInfo); |
| if (rc != NO_ERROR) { |
| LOGE("getAnalysisInfo failed, ret = %d", rc); |
| return rc; |
| } |
| |
| padding_info = analysisInfo.analysis_padding_info; |
| } else { |
| padding_info = |
| gCamCapability[mCameraId]->padding_info; |
| if (streamType == CAM_STREAM_TYPE_PREVIEW) { |
| padding_info.width_padding = mSurfaceStridePadding; |
| padding_info.height_padding = CAM_PAD_TO_2; |
| } |
| if((!needReprocess()) |
| || (streamType != CAM_STREAM_TYPE_SNAPSHOT) |
| || (!mParameters.isLLNoiseEnabled())) { |
| padding_info.offset_info.offset_x = 0; |
| padding_info.offset_info.offset_y = 0; |
| } |
| } |
| |
| bool deferAllocation = needDeferred(streamType); |
| LOGD("deferAllocation = %d bDynAllocBuf = %d, stream type = %d", |
| deferAllocation, bDynAllocBuf, streamType); |
| rc = pChannel->addStream(*this, |
| pStreamInfo, |
| NULL, |
| &padding_info, |
| streamCB, userData, |
| bDynAllocBuf, |
| deferAllocation); |
| |
| if (rc != NO_ERROR) { |
| LOGE("add stream type (%d) failed, ret = %d", |
| streamType, rc); |
| return rc; |
| } |
| |
| return rc; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : addPreviewChannel |
| * |
| * DESCRIPTION: add a preview channel that contains a preview stream |
| * |
| * PARAMETERS : none |
| * |
| * RETURN : int32_t type of status |
| * NO_ERROR -- success |
| * none-zero failure code |
| *==========================================================================*/ |
| int32_t QCamera2HardwareInterface::addPreviewChannel() |
| { |
| int32_t rc = NO_ERROR; |
| QCameraChannel *pChannel = NULL; |
| char value[PROPERTY_VALUE_MAX]; |
| bool raw_yuv = false; |
| |
| |
| if (m_channels[QCAMERA_CH_TYPE_PREVIEW] != NULL) { |
| // if we had preview channel before, delete it first |
| delete m_channels[QCAMERA_CH_TYPE_PREVIEW]; |
| m_channels[QCAMERA_CH_TYPE_PREVIEW] = NULL; |
| } |
| |
| uint32_t handle = getCamHandleForChannel(QCAMERA_CH_TYPE_PREVIEW); |
| pChannel = new QCameraChannel(handle, mCameraHandle->ops); |
| if (NULL == pChannel) { |
| LOGE("no mem for preview channel"); |
| return NO_MEMORY; |
| } |
| |
| // preview only channel, don't need bundle attr and cb |
| rc = pChannel->init(NULL, NULL, NULL); |
| if (rc != NO_ERROR) { |
| LOGE("init preview channel failed, ret = %d", rc); |
| return rc; |
| } |
| |
| // meta data stream always coexists with preview if applicable |
| rc = addStreamToChannel(pChannel, CAM_STREAM_TYPE_METADATA, |
| metadata_stream_cb_routine, this); |
| if (rc != NO_ERROR) { |
| LOGE("add metadata stream failed, ret = %d", rc); |
| return rc; |
| } |
| |
| if (isRdiMode()) { |
| rc = addStreamToChannel(pChannel, CAM_STREAM_TYPE_RAW, |
| rdi_mode_stream_cb_routine, this); |
| } else { |
| if (isNoDisplayMode()) { |
| rc = addStreamToChannel(pChannel, CAM_STREAM_TYPE_PREVIEW, |
| nodisplay_preview_stream_cb_routine, this); |
| } else { |
| rc = addStreamToChannel(pChannel, CAM_STREAM_TYPE_PREVIEW, |
| preview_stream_cb_routine, this); |
| #ifdef TARGET_TS_MAKEUP |
| int whiteLevel, cleanLevel; |
| if(mParameters.getTsMakeupInfo(whiteLevel, cleanLevel) == false) |
| #endif |
| if (!isDualCamera()) { |
| pChannel->setStreamSyncCB(CAM_STREAM_TYPE_PREVIEW, |
| synchronous_stream_cb_routine); |
| } |
| } |
| } |
| |
| if (((mParameters.fdModeInVideo()) |
| || (mParameters.getDcrf() == true) |
| || (mParameters.getRecordingHintValue() != true)) |
| && (!mParameters.isSecureMode())) { |
| rc = addStreamToChannel(pChannel, CAM_STREAM_TYPE_ANALYSIS, |
| NULL, this); |
| if (rc != NO_ERROR) { |
| LOGE("add Analysis stream failed, ret = %d", rc); |
| return rc; |
| } |
| } |
| |
| property_get("persist.camera.raw_yuv", value, "0"); |
| raw_yuv = atoi(value) > 0 ? true : false; |
| if ( raw_yuv ) { |
| rc = addStreamToChannel(pChannel,CAM_STREAM_TYPE_RAW, |
| preview_raw_stream_cb_routine,this); |
| if ( rc != NO_ERROR ) { |
| LOGE("add raw stream failed, ret = %d", __FUNCTION__, rc); |
| delete pChannel; |
| return rc; |
| } |
| } |
| |
| if (rc != NO_ERROR) { |
| LOGE("add preview stream failed, ret = %d", rc); |
| delete pChannel; |
| return rc; |
| } |
| |
| m_channels[QCAMERA_CH_TYPE_PREVIEW] = pChannel; |
| return rc; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : addVideoChannel |
| * |
| * DESCRIPTION: add a video channel that contains a video stream |
| * |
| * PARAMETERS : none |
| * |
| * RETURN : int32_t type of status |
| * NO_ERROR -- success |
| * none-zero failure code |
| *==========================================================================*/ |
| int32_t QCamera2HardwareInterface::addVideoChannel() |
| { |
| int32_t rc = NO_ERROR; |
| QCameraVideoChannel *pChannel = NULL; |
| |
| if (m_channels[QCAMERA_CH_TYPE_VIDEO] != NULL) { |
| // if we had video channel before, delete it first |
| delete m_channels[QCAMERA_CH_TYPE_VIDEO]; |
| m_channels[QCAMERA_CH_TYPE_VIDEO] = NULL; |
| } |
| |
| uint32_t handle = getCamHandleForChannel(QCAMERA_CH_TYPE_VIDEO); |
| pChannel = new QCameraVideoChannel(handle, mCameraHandle->ops); |
| if (NULL == pChannel) { |
| LOGE("no mem for video channel"); |
| return NO_MEMORY; |
| } |
| |
| if (isLowPowerMode()) { |
| mm_camera_channel_attr_t attr; |
| memset(&attr, 0, sizeof(mm_camera_channel_attr_t)); |
| attr.notify_mode = MM_CAMERA_SUPER_BUF_NOTIFY_BURST; |
| attr.look_back = 0; //wait for future frame for liveshot |
| attr.post_frame_skip = mParameters.getZSLBurstInterval(); |
| attr.water_mark = 1; //hold min buffers possible in Q |
| attr.max_unmatched_frames = mParameters.getMaxUnmatchedFramesInQueue(); |
| rc = pChannel->init(&attr, snapshot_channel_cb_routine, this); |
| } else { |
| // preview only channel, don't need bundle attr and cb |
| rc = pChannel->init(NULL, NULL, NULL); |
| } |
| |
| if (rc != 0) { |
| LOGE("init video channel failed, ret = %d", rc); |
| delete pChannel; |
| return rc; |
| } |
| |
| rc = addStreamToChannel(pChannel, CAM_STREAM_TYPE_VIDEO, |
| video_stream_cb_routine, this); |
| |
| if (rc != NO_ERROR) { |
| LOGE("add video stream failed, ret = %d", rc); |
| delete pChannel; |
| return rc; |
| } |
| |
| m_channels[QCAMERA_CH_TYPE_VIDEO] = pChannel; |
| return rc; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : addSnapshotChannel |
| * |
| * DESCRIPTION: add a snapshot channel that contains a snapshot stream |
| * |
| * PARAMETERS : none |
| * |
| * RETURN : int32_t type of status |
| * NO_ERROR -- success |
| * none-zero failure code |
| * NOTE : Add this channel for live snapshot usecase. Regular capture will |
| * use addCaptureChannel. |
| *==========================================================================*/ |
| int32_t QCamera2HardwareInterface::addSnapshotChannel() |
| { |
| int32_t rc = NO_ERROR; |
| QCameraChannel *pChannel = NULL; |
| |
| if (m_channels[QCAMERA_CH_TYPE_SNAPSHOT] != NULL) { |
| // if we had ZSL channel before, delete it first |
| delete m_channels[QCAMERA_CH_TYPE_SNAPSHOT]; |
| m_channels[QCAMERA_CH_TYPE_SNAPSHOT] = NULL; |
| } |
| |
| uint32_t handle = getCamHandleForChannel(QCAMERA_CH_TYPE_SNAPSHOT); |
| pChannel = new QCameraChannel(handle, mCameraHandle->ops); |
| if (NULL == pChannel) { |
| LOGE("no mem for snapshot channel"); |
| return NO_MEMORY; |
| } |
| |
| mm_camera_channel_attr_t attr; |
| memset(&attr, 0, sizeof(mm_camera_channel_attr_t)); |
| attr.notify_mode = MM_CAMERA_SUPER_BUF_NOTIFY_CONTINUOUS; |
| attr.look_back = 0; //wait for future frame for liveshot |
| attr.post_frame_skip = mParameters.getZSLBurstInterval(); |
| attr.water_mark = 1; //hold min buffers possible in Q |
| attr.max_unmatched_frames = mParameters.getMaxUnmatchedFramesInQueue(); |
| attr.priority = MM_CAMERA_SUPER_BUF_PRIORITY_LOW; |
| rc = pChannel->init(&attr, snapshot_channel_cb_routine, this); |
| if (rc != NO_ERROR) { |
| LOGE("init snapshot channel failed, ret = %d", rc); |
| delete pChannel; |
| return rc; |
| } |
| |
| rc = addStreamToChannel(pChannel, CAM_STREAM_TYPE_SNAPSHOT, |
| NULL, NULL); |
| if (rc != NO_ERROR) { |
| LOGE("add snapshot stream failed, ret = %d", rc); |
| delete pChannel; |
| return rc; |
| } |
| |
| m_channels[QCAMERA_CH_TYPE_SNAPSHOT] = pChannel; |
| return rc; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : addRawChannel |
| * |
| * DESCRIPTION: add a raw channel that contains a raw image stream |
| * |
| * PARAMETERS : none |
| * |
| * RETURN : int32_t type of status |
| * NO_ERROR -- success |
| * none-zero failure code |
| *==========================================================================*/ |
| int32_t QCamera2HardwareInterface::addRawChannel() |
| { |
| int32_t rc = NO_ERROR; |
| QCameraChannel *pChannel = NULL; |
| |
| if (m_channels[QCAMERA_CH_TYPE_RAW] != NULL) { |
| // if we had raw channel before, delete it first |
| delete m_channels[QCAMERA_CH_TYPE_RAW]; |
| m_channels[QCAMERA_CH_TYPE_RAW] = NULL; |
| } |
| |
| uint32_t handle = getCamHandleForChannel(QCAMERA_CH_TYPE_RAW); |
| pChannel = new QCameraChannel(handle, mCameraHandle->ops); |
| if (NULL == pChannel) { |
| LOGE("no mem for raw channel"); |
| return NO_MEMORY; |
| } |
| |
| if (mParameters.getofflineRAW()) { |
| mm_camera_channel_attr_t attr; |
| memset(&attr, 0, sizeof(mm_camera_channel_attr_t)); |
| attr.notify_mode = MM_CAMERA_SUPER_BUF_NOTIFY_BURST; |
| attr.look_back = mParameters.getZSLBackLookCount(); |
| attr.post_frame_skip = mParameters.getZSLBurstInterval(); |
| attr.water_mark = 1; |
| attr.max_unmatched_frames = mParameters.getMaxUnmatchedFramesInQueue(); |
| rc = pChannel->init(&attr, raw_channel_cb_routine, this); |
| if (rc != NO_ERROR) { |
| LOGE("init RAW channel failed, ret = %d", rc); |
| delete pChannel; |
| return rc; |
| } |
| } else { |
| rc = pChannel->init(NULL, NULL, NULL); |
| if (rc != NO_ERROR) { |
| LOGE("init raw channel failed, ret = %d", rc); |
| delete pChannel; |
| return rc; |
| } |
| } |
| |
| if (!mParameters.isZSLMode()) { |
| // meta data stream always coexists with snapshot in regular RAW capture case |
| rc = addStreamToChannel(pChannel, CAM_STREAM_TYPE_METADATA, |
| metadata_stream_cb_routine, this); |
| if (rc != NO_ERROR) { |
| LOGE("add metadata stream failed, ret = %d", rc); |
| delete pChannel; |
| return rc; |
| } |
| } |
| |
| if (mParameters.getofflineRAW()) { |
| rc = addStreamToChannel(pChannel, CAM_STREAM_TYPE_RAW, |
| NULL, this); |
| } else { |
| rc = addStreamToChannel(pChannel, CAM_STREAM_TYPE_RAW, |
| raw_stream_cb_routine, this); |
| } |
| if (rc != NO_ERROR) { |
| LOGE("add snapshot stream failed, ret = %d", rc); |
| delete pChannel; |
| return rc; |
| } |
| m_channels[QCAMERA_CH_TYPE_RAW] = pChannel; |
| return rc; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : addZSLChannel |
| * |
| * DESCRIPTION: add a ZSL channel that contains a preview stream and |
| * a snapshot stream |
| * |
| * PARAMETERS : none |
| * |
| * RETURN : int32_t type of status |
| * NO_ERROR -- success |
| * none-zero failure code |
| *==========================================================================*/ |
| int32_t QCamera2HardwareInterface::addZSLChannel() |
| { |
| int32_t rc = NO_ERROR; |
| QCameraPicChannel *pChannel = NULL; |
| char value[PROPERTY_VALUE_MAX]; |
| bool raw_yuv = false; |
| |
| if (m_channels[QCAMERA_CH_TYPE_ZSL] != NULL) { |
| // if we had ZSL channel before, delete it first |
| delete m_channels[QCAMERA_CH_TYPE_ZSL]; |
| m_channels[QCAMERA_CH_TYPE_ZSL] = NULL; |
| } |
| |
| uint32_t handle = getCamHandleForChannel(QCAMERA_CH_TYPE_ZSL); |
| pChannel = new QCameraPicChannel(handle, |
| mCameraHandle->ops); |
| if (NULL == pChannel) { |
| LOGE("no mem for ZSL channel"); |
| return NO_MEMORY; |
| } |
| |
| // ZSL channel, init with bundle attr and cb |
| mm_camera_channel_attr_t attr; |
| memset(&attr, 0, sizeof(mm_camera_channel_attr_t)); |
| if (mParameters.isSceneSelectionEnabled()) { |
| attr.notify_mode = MM_CAMERA_SUPER_BUF_NOTIFY_CONTINUOUS; |
| } else { |
| attr.notify_mode = MM_CAMERA_SUPER_BUF_NOTIFY_BURST; |
| } |
| attr.look_back = mParameters.getZSLBackLookCount(); |
| attr.post_frame_skip = mParameters.getZSLBurstInterval(); |
| if (mParameters.isOEMFeatEnabled()) { |
| attr.post_frame_skip++; |
| } |
| attr.water_mark = mParameters.getZSLQueueDepth(); |
| attr.max_unmatched_frames = mParameters.getMaxUnmatchedFramesInQueue(); |
| attr.user_expected_frame_id = |
| mParameters.isInstantCaptureEnabled() ? (uint8_t)mParameters.getAecFrameBoundValue() : 0; |
| |
| //Enabled matched queue |
| if (isFrameSyncEnabled()) { |
| LOGH("Enabling frame sync for dual camera, camera Id: %d", |
| mCameraId); |
| attr.enable_frame_sync = 1; |
| } |
| rc = pChannel->init(&attr, |
| zsl_channel_cb, |
| this); |
| if (rc != 0) { |
| LOGE("init ZSL channel failed, ret = %d", rc); |
| delete pChannel; |
| return rc; |
| } |
| |
| // meta data stream always coexists with preview if applicable |
| rc = addStreamToChannel(pChannel, CAM_STREAM_TYPE_METADATA, |
| metadata_stream_cb_routine, this); |
| if (rc != NO_ERROR) { |
| LOGE("add metadata stream failed, ret = %d", rc); |
| delete pChannel; |
| return rc; |
| } |
| |
| if (isNoDisplayMode()) { |
| rc = addStreamToChannel(pChannel, CAM_STREAM_TYPE_PREVIEW, |
| nodisplay_preview_stream_cb_routine, this); |
| } else { |
| rc = addStreamToChannel(pChannel, CAM_STREAM_TYPE_PREVIEW, |
| preview_stream_cb_routine, this); |
| #ifdef TARGET_TS_MAKEUP |
| int whiteLevel, cleanLevel; |
| if(mParameters.getTsMakeupInfo(whiteLevel, cleanLevel) == false) |
| #endif |
| if (!isDualCamera()) { |
| pChannel->setStreamSyncCB(CAM_STREAM_TYPE_PREVIEW, |
| synchronous_stream_cb_routine); |
| } |
| } |
| if (rc != NO_ERROR) { |
| LOGE("add preview stream failed, ret = %d", rc); |
| delete pChannel; |
| return rc; |
| } |
| |
| rc = addStreamToChannel(pChannel, CAM_STREAM_TYPE_SNAPSHOT, |
| NULL, this); |
| if (rc != NO_ERROR) { |
| LOGE("add snapshot stream failed, ret = %d", rc); |
| delete pChannel; |
| return rc; |
| } |
| |
| if (!mParameters.isSecureMode()) { |
| rc = addStreamToChannel(pChannel, CAM_STREAM_TYPE_ANALYSIS, |
| NULL, this); |
| if (rc != NO_ERROR) { |
| LOGE("add Analysis stream failed, ret = %d", rc); |
| delete pChannel; |
| return rc; |
| } |
| } |
| |
| property_get("persist.camera.raw_yuv", value, "0"); |
| raw_yuv = atoi(value) > 0 ? true : false; |
| if (raw_yuv) { |
| rc = addStreamToChannel(pChannel, |
| CAM_STREAM_TYPE_RAW, |
| preview_raw_stream_cb_routine, |
| this); |
| if (rc != NO_ERROR) { |
| LOGE("add raw stream failed, ret = %d", rc); |
| delete pChannel; |
| return rc; |
| } |
| } |
| |
| m_channels[QCAMERA_CH_TYPE_ZSL] = pChannel; |
| return rc; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : addCaptureChannel |
| * |
| * DESCRIPTION: add a capture channel that contains a snapshot stream |
| * and a postview stream |
| * |
| * PARAMETERS : none |
| * |
| * RETURN : int32_t type of status |
| * NO_ERROR -- success |
| * none-zero failure code |
| * NOTE : Add this channel for regular capture usecase. |
| * For Live snapshot usecase, use addSnapshotChannel. |
| *==========================================================================*/ |
| int32_t QCamera2HardwareInterface::addCaptureChannel() |
| { |
| int32_t rc = NO_ERROR; |
| QCameraPicChannel *pChannel = NULL; |
| char value[PROPERTY_VALUE_MAX]; |
| bool raw_yuv = false; |
| |
| if (m_channels[QCAMERA_CH_TYPE_CAPTURE] != NULL) { |
| delete m_channels[QCAMERA_CH_TYPE_CAPTURE]; |
| m_channels[QCAMERA_CH_TYPE_CAPTURE] = NULL; |
| } |
| |
| uint32_t handle = getCamHandleForChannel(QCAMERA_CH_TYPE_CAPTURE); |
| pChannel = new QCameraPicChannel(handle, mCameraHandle->ops); |
| if (NULL == pChannel) { |
| LOGE("no mem for capture channel"); |
| return NO_MEMORY; |
| } |
| |
| // Capture channel, only need snapshot and postview streams start together |
| mm_camera_channel_attr_t attr; |
| memset(&attr, 0, sizeof(mm_camera_channel_attr_t)); |
| if ( mLongshotEnabled ) { |
| attr.notify_mode = MM_CAMERA_SUPER_BUF_NOTIFY_BURST; |
| attr.look_back = mParameters.getZSLBackLookCount(); |
| attr.water_mark = mParameters.getZSLQueueDepth(); |
| } else { |
| attr.notify_mode = MM_CAMERA_SUPER_BUF_NOTIFY_CONTINUOUS; |
| } |
| attr.max_unmatched_frames = mParameters.getMaxUnmatchedFramesInQueue(); |
| |
| rc = pChannel->init(&attr, |
| capture_channel_cb_routine, |
| this); |
| if (rc != NO_ERROR) { |
| LOGE("init capture channel failed, ret = %d", rc); |
| return rc; |
| } |
| |
| // meta data stream always coexists with snapshot in regular capture case |
| rc = addStreamToChannel(pChannel, CAM_STREAM_TYPE_METADATA, |
| metadata_stream_cb_routine, this); |
| if (rc != NO_ERROR) { |
| LOGE("add metadata stream failed, ret = %d", rc); |
| return rc; |
| } |
| |
| if (mLongshotEnabled) { |
| rc = addStreamToChannel(pChannel, CAM_STREAM_TYPE_PREVIEW, |
| preview_stream_cb_routine, this); |
| if (rc != NO_ERROR) { |
| LOGE("add preview stream failed, ret = %d", rc); |
| return rc; |
| } |
| #ifdef TARGET_TS_MAKEUP |
| int whiteLevel, cleanLevel; |
| if(mParameters.getTsMakeupInfo(whiteLevel, cleanLevel) == false) |
| #endif |
| if (!isDualCamera()) { |
| pChannel->setStreamSyncCB(CAM_STREAM_TYPE_PREVIEW, |
| synchronous_stream_cb_routine); |
| } |
| //Not adding the postview stream to the capture channel if Quadra CFA is enabled. |
| } else if (!mParameters.getQuadraCfa()) { |
| rc = addStreamToChannel(pChannel, CAM_STREAM_TYPE_POSTVIEW, |
| NULL, this); |
| if (rc != NO_ERROR) { |
| LOGE("add postview stream failed, ret = %d", rc); |
| return rc; |
| } |
| } |
| |
| if (!mParameters.getofflineRAW()) { |
| rc = addStreamToChannel(pChannel, CAM_STREAM_TYPE_SNAPSHOT, |
| NULL, this); |
| if (rc != NO_ERROR) { |
| LOGE("add snapshot stream failed, ret = %d", rc); |
| return rc; |
| } |
| } |
| |
| stream_cb_routine stream_cb = NULL; |
| property_get("persist.camera.raw_yuv", value, "0"); |
| raw_yuv = atoi(value) > 0 ? true : false; |
| |
| if (raw_yuv) { |
| stream_cb = snapshot_raw_stream_cb_routine; |
| } |
| |
| if ((raw_yuv) || (mParameters.getofflineRAW())) { |
| rc = addStreamToChannel(pChannel, |
| CAM_STREAM_TYPE_RAW, stream_cb, this); |
| if (rc != NO_ERROR) { |
| LOGE("add raw stream failed, ret = %d", rc); |
| return rc; |
| } |
| } |
| |
| m_channels[QCAMERA_CH_TYPE_CAPTURE] = pChannel; |
| return rc; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : addMetaDataChannel |
| * |
| * DESCRIPTION: add a meta data channel that contains a metadata stream |
| * |
| * PARAMETERS : none |
| * |
| * RETURN : int32_t type of status |
| * NO_ERROR -- success |
| * none-zero failure code |
| *==========================================================================*/ |
| int32_t QCamera2HardwareInterface::addMetaDataChannel() |
| { |
| int32_t rc = NO_ERROR; |
| QCameraChannel *pChannel = NULL; |
| |
| if (m_channels[QCAMERA_CH_TYPE_METADATA] != NULL) { |
| delete m_channels[QCAMERA_CH_TYPE_METADATA]; |
| m_channels[QCAMERA_CH_TYPE_METADATA] = NULL; |
| } |
| |
| uint32_t handle = getCamHandleForChannel(QCAMERA_CH_TYPE_METADATA); |
| pChannel = new QCameraChannel(handle, mCameraHandle->ops); |
| if (NULL == pChannel) { |
| LOGE("no mem for metadata channel"); |
| return NO_MEMORY; |
| } |
| |
| rc = pChannel->init(NULL, |
| NULL, |
| NULL); |
| if (rc != NO_ERROR) { |
| LOGE("init metadata channel failed, ret = %d", rc); |
| delete pChannel; |
| return rc; |
| } |
| |
| rc = addStreamToChannel(pChannel, CAM_STREAM_TYPE_METADATA, |
| metadata_stream_cb_routine, this); |
| if (rc != NO_ERROR) { |
| LOGE("add metadata stream failed, ret = %d", rc); |
| delete pChannel; |
| return rc; |
| } |
| |
| m_channels[QCAMERA_CH_TYPE_METADATA] = pChannel; |
| return rc; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : addCallbackChannel |
| * |
| * DESCRIPTION: add a callback channel that contains a callback stream |
| * |
| * PARAMETERS : none |
| * |
| * RETURN : int32_t type of status |
| * NO_ERROR -- success |
| * none-zero failure code |
| *==========================================================================*/ |
| int32_t QCamera2HardwareInterface::addCallbackChannel() |
| { |
| int32_t rc = NO_ERROR; |
| QCameraChannel *pChannel = NULL; |
| |
| if (m_channels[QCAMERA_CH_TYPE_CALLBACK] != NULL) { |
| delete m_channels[QCAMERA_CH_TYPE_CALLBACK]; |
| m_channels[QCAMERA_CH_TYPE_CALLBACK] = NULL; |
| } |
| |
| uint32_t handle = getCamHandleForChannel(QCAMERA_CH_TYPE_CALLBACK); |
| pChannel = new QCameraChannel(handle, mCameraHandle->ops); |
| if (NULL == pChannel) { |
| LOGE("no mem for callback channel"); |
| return NO_MEMORY; |
| } |
| |
| rc = pChannel->init(NULL, NULL, this); |
| if (rc != NO_ERROR) { |
| LOGE("init callback channel failed, ret = %d", |
| rc); |
| delete pChannel; |
| return rc; |
| } |
| |
| rc = addStreamToChannel(pChannel, CAM_STREAM_TYPE_CALLBACK, |
| callback_stream_cb_routine, this); |
| if (rc != NO_ERROR) { |
| LOGE("add callback stream failed, ret = %d", rc); |
| delete pChannel; |
| return rc; |
| } |
| |
| m_channels[QCAMERA_CH_TYPE_CALLBACK] = pChannel; |
| return rc; |
| } |
| |
| |
| /*=========================================================================== |
| * FUNCTION : addAnalysisChannel |
| * |
| * DESCRIPTION: add a analysis channel that contains a analysis stream |
| * |
| * PARAMETERS : none |
| * |
| * RETURN : int32_t type of status |
| * NO_ERROR -- success |
| * none-zero failure code |
| *==========================================================================*/ |
| int32_t QCamera2HardwareInterface::addAnalysisChannel() |
| { |
| int32_t rc = NO_ERROR; |
| QCameraChannel *pChannel = NULL; |
| |
| if (m_channels[QCAMERA_CH_TYPE_ANALYSIS] != NULL) { |
| delete m_channels[QCAMERA_CH_TYPE_ANALYSIS]; |
| m_channels[QCAMERA_CH_TYPE_ANALYSIS] = NULL; |
| } |
| |
| uint32_t handle = getCamHandleForChannel(QCAMERA_CH_TYPE_ANALYSIS); |
| pChannel = new QCameraChannel(handle, mCameraHandle->ops); |
| if (NULL == pChannel) { |
| LOGE("no mem for metadata channel"); |
| return NO_MEMORY; |
| } |
| |
| rc = pChannel->init(NULL, NULL, this); |
| if (rc != NO_ERROR) { |
| LOGE("init Analysis channel failed, ret = %d", rc); |
| delete pChannel; |
| return rc; |
| } |
| |
| rc = addStreamToChannel(pChannel, CAM_STREAM_TYPE_ANALYSIS, |
| NULL, this); |
| if (rc != NO_ERROR) { |
| LOGE("add Analysis stream failed, ret = %d", rc); |
| delete pChannel; |
| return rc; |
| } |
| |
| m_channels[QCAMERA_CH_TYPE_ANALYSIS] = pChannel; |
| return rc; |
| } |
| |
| |
| /*=========================================================================== |
| * FUNCTION : getPPConfig |
| * |
| * DESCRIPTION: get Post processing configaration data |
| * |
| * PARAMETERS : |
| * @pp config: pp config structure pointer, |
| * @curIndex: current pp channel index |
| * @multipass: Flag if multipass prcessing enabled. |
| * |
| * RETURN : int32_t type of status |
| * NO_ERROR -- success |
| * none-zero failure code |
| *==========================================================================*/ |
| int32_t QCamera2HardwareInterface::getPPConfig(cam_pp_feature_config_t &pp_config, |
| int8_t curIndex, bool multipass) |
| { |
| int32_t rc = NO_ERROR; |
| int32_t feature_set = 0; |
| |
| if (multipass) { |
| LOGW("Multi pass enabled. Total Pass = %d, cur index = %d", |
| mParameters.getReprocCount(), curIndex); |
| } |
| |
| LOGH("Supported pproc feature mask = %llx", |
| gCamCapability[mCameraId]->qcom_supported_feature_mask); |
| cam_feature_mask_t feature_mask = gCamCapability[mCameraId]->qcom_supported_feature_mask; |
| int32_t zoomLevel = mParameters.getParmZoomLevel(); |
| uint32_t rotation = mParameters.getJpegRotation(); |
| int32_t effect = mParameters.getEffectValue(); |
| |
| pp_config.cur_reproc_count = curIndex + 1; |
| pp_config.total_reproc_count = mParameters.getReprocCount(); |
| |
| //Checking what feature mask to enable |
| if (curIndex == 0) { |
| if (mParameters.getQuadraCfa()) { |
| feature_set = 2; |
| } else { |
| feature_set = 0; |
| } |
| } else if (curIndex == 1) { |
| if (mParameters.getQuadraCfa()) { |
| feature_set = 0; |
| } else { |
| feature_set = 1; |
| } |
| } |
| |
| switch(feature_set) { |
| case 0: |
| //Configure feature mask for first pass of reprocessing |
| //check if any effects are enabled |
| if ((CAM_EFFECT_MODE_OFF != effect) && |
| (feature_mask & CAM_QCOM_FEATURE_EFFECT)) { |
| pp_config.feature_mask |= CAM_QCOM_FEATURE_EFFECT; |
| pp_config.effect = effect; |
| } |
| |
| //check for features that need to be enabled by default like sharpness |
| //(if supported by hw). |
| if ((feature_mask & CAM_QCOM_FEATURE_SHARPNESS) && |
| !mParameters.isOptiZoomEnabled()) { |
| pp_config.feature_mask |= CAM_QCOM_FEATURE_SHARPNESS; |
| pp_config.sharpness = mParameters.getSharpness(); |
| } |
| |
| //check if zoom is enabled |
| if ((zoomLevel > 0) && (feature_mask & CAM_QCOM_FEATURE_CROP)) { |
| pp_config.feature_mask |= CAM_QCOM_FEATURE_CROP; |
| } |
| |
| if (mParameters.isWNREnabled() && |
| (feature_mask & CAM_QCOM_FEATURE_DENOISE2D)) { |
| pp_config.feature_mask |= CAM_QCOM_FEATURE_DENOISE2D; |
| pp_config.denoise2d.denoise_enable = 1; |
| pp_config.denoise2d.process_plates = |
| mParameters.getDenoiseProcessPlate(CAM_INTF_PARM_WAVELET_DENOISE); |
| } |
| |
| if (isCACEnabled()) { |
| pp_config.feature_mask |= CAM_QCOM_FEATURE_CAC; |
| } |
| |
| //check if rotation is required |
| if ((feature_mask & CAM_QCOM_FEATURE_ROTATION) && (rotation > 0)) { |
| pp_config.feature_mask |= CAM_QCOM_FEATURE_ROTATION; |
| if (rotation == 0) { |
| pp_config.rotation = ROTATE_0; |
| } else if (rotation == 90) { |
| pp_config.rotation = ROTATE_90; |
| } else if (rotation == 180) { |
| pp_config.rotation = ROTATE_180; |
| } else if (rotation == 270) { |
| pp_config.rotation = ROTATE_270; |
| } |
| } |
| |
| if (mParameters.isHDREnabled()){ |
| pp_config.feature_mask |= CAM_QCOM_FEATURE_HDR; |
| pp_config.hdr_param.hdr_enable = 1; |
| pp_config.hdr_param.hdr_need_1x = mParameters.isHDR1xFrameEnabled(); |
| pp_config.hdr_param.hdr_mode = CAM_HDR_MODE_MULTIFRAME; |
| } else { |
| pp_config.feature_mask &= ~CAM_QCOM_FEATURE_HDR; |
| pp_config.hdr_param.hdr_enable = 0; |
| } |
| |
| //check if scaling is enabled |
| if ((feature_mask & CAM_QCOM_FEATURE_SCALE) && |
| mParameters.isReprocScaleEnabled() && |
| mParameters.isUnderReprocScaling()){ |
| pp_config.feature_mask |= CAM_QCOM_FEATURE_SCALE; |
| mParameters.getPicSizeFromAPK( |
| pp_config.scale_param.output_width, |
| pp_config.scale_param.output_height); |
| } |
| |
| if(mParameters.isUbiFocusEnabled()) { |
| pp_config.feature_mask |= CAM_QCOM_FEATURE_UBIFOCUS; |
| } else { |
| pp_config.feature_mask &= ~CAM_QCOM_FEATURE_UBIFOCUS; |
| } |
| |
| if(mParameters.isUbiRefocus()) { |
| pp_config.feature_mask |= CAM_QCOM_FEATURE_REFOCUS; |
| pp_config.misc_buf_param.misc_buffer_index = 0; |
| } else { |
| pp_config.feature_mask &= ~CAM_QCOM_FEATURE_REFOCUS; |
| } |
| |
| if(mParameters.isChromaFlashEnabled()) { |
| pp_config.feature_mask |= CAM_QCOM_FEATURE_CHROMA_FLASH; |
| pp_config.flash_value = CAM_FLASH_ON; |
| } else { |
| pp_config.feature_mask &= ~CAM_QCOM_FEATURE_CHROMA_FLASH; |
| } |
| |
| if(mParameters.isOptiZoomEnabled() && (0 <= zoomLevel)) { |
| pp_config.feature_mask |= CAM_QCOM_FEATURE_OPTIZOOM; |
| pp_config.zoom_level = (uint8_t) zoomLevel; |
| } else { |
| pp_config.feature_mask &= ~CAM_QCOM_FEATURE_OPTIZOOM; |
| } |
| |
| if (mParameters.getofflineRAW()) { |
| pp_config.feature_mask |= CAM_QCOM_FEATURE_RAW_PROCESSING; |
| } |
| |
| if (mParameters.isTruePortraitEnabled()) { |
| pp_config.feature_mask |= CAM_QCOM_FEATURE_TRUEPORTRAIT; |
| pp_config.misc_buf_param.misc_buffer_index = 0; |
| } else { |
| pp_config.feature_mask &= ~CAM_QCOM_FEATURE_TRUEPORTRAIT; |
| } |
| |
| if(mParameters.isStillMoreEnabled()) { |
| pp_config.feature_mask |= CAM_QCOM_FEATURE_STILLMORE; |
| } else { |
| pp_config.feature_mask &= ~CAM_QCOM_FEATURE_STILLMORE; |
| } |
| |
| if (mParameters.isOEMFeatEnabled()) { |
| pp_config.feature_mask |= CAM_OEM_FEATURE_1; |
| } |
| |
| if (mParameters.getCDSMode() != CAM_CDS_MODE_OFF) { |
| if (feature_mask & CAM_QCOM_FEATURE_DSDN) { |
| pp_config.feature_mask |= CAM_QCOM_FEATURE_DSDN; |
| } else { |
| pp_config.feature_mask |= CAM_QCOM_FEATURE_CDS; |
| } |
| } |
| |
| if ((multipass) && |
| (m_postprocessor.getPPChannelCount() > 1) |
| && (!mParameters.getQuadraCfa())) { |
| pp_config.feature_mask &= ~CAM_QCOM_FEATURE_PP_PASS_2; |
| pp_config.feature_mask &= ~CAM_QCOM_FEATURE_ROTATION; |
| pp_config.feature_mask &= ~CAM_QCOM_FEATURE_CDS; |
| pp_config.feature_mask &= ~CAM_QCOM_FEATURE_DSDN; |
| pp_config.feature_mask |= CAM_QCOM_FEATURE_CROP; |
| } else { |
| pp_config.feature_mask |= CAM_QCOM_FEATURE_SCALE; |
| } |
| |
| cam_dimension_t thumb_src_dim; |
| cam_dimension_t thumb_dst_dim; |
| mParameters.getThumbnailSize(&(thumb_dst_dim.width), &(thumb_dst_dim.height)); |
| mParameters.getStreamDimension(CAM_STREAM_TYPE_POSTVIEW,thumb_src_dim); |
| if ((thumb_dst_dim.width != thumb_src_dim.width) || |
| (thumb_dst_dim.height != thumb_src_dim.height)) { |
| if (thumb_dst_dim.width != 0 && thumb_dst_dim.height != 0) { |
| pp_config.feature_mask |= CAM_QCOM_FEATURE_CROP; |
| } |
| } |
| |
| break; |
| |
| case 1: |
| //Configure feature mask for second pass of reprocessing |
| pp_config.feature_mask |= CAM_QCOM_FEATURE_PP_PASS_2; |
| if ((feature_mask & CAM_QCOM_FEATURE_ROTATION) && (rotation > 0)) { |
| pp_config.feature_mask |= CAM_QCOM_FEATURE_ROTATION; |
| if (rotation == 0) { |
| pp_config.rotation = ROTATE_0; |
| } else if (rotation == 90) { |
| pp_config.rotation = ROTATE_90; |
| } else if (rotation == 180) { |
| pp_config.rotation = ROTATE_180; |
| } else if (rotation == 270) { |
| pp_config.rotation = ROTATE_270; |
| } |
| } |
| if (mParameters.getCDSMode() != CAM_CDS_MODE_OFF) { |
| if (feature_mask & CAM_QCOM_FEATURE_DSDN) { |
| pp_config.feature_mask |= CAM_QCOM_FEATURE_DSDN; |
| } else { |
| pp_config.feature_mask |= CAM_QCOM_FEATURE_CDS; |
| } |
| } |
| pp_config.feature_mask &= ~CAM_QCOM_FEATURE_RAW_PROCESSING; |
| pp_config.feature_mask &= ~CAM_QCOM_FEATURE_METADATA_PROCESSING; |
| break; |
| |
| case 2: |
| //Setting feature for Quadra CFA |
| pp_config.feature_mask |= CAM_QCOM_FEATURE_QUADRA_CFA; |
| break; |
| |
| } |
| |
| LOGH("pproc feature mask set = %llx pass count = %d", |
| pp_config.feature_mask, curIndex); |
| return rc; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : addReprocChannel |
| * |
| * DESCRIPTION: add a reprocess channel that will do reprocess on frames |
| * coming from input channel |
| * |
| * PARAMETERS : |
| * @pInputChannel : ptr to input channel whose frames will be post-processed |
| * @cur_channel_index : Current channel index in multipass |
| * |
| * RETURN : Ptr to the newly created channel obj. NULL if failed. |
| *==========================================================================*/ |
| QCameraReprocessChannel *QCamera2HardwareInterface::addReprocChannel( |
| QCameraChannel *pInputChannel, int8_t cur_channel_index) |
| { |
| int32_t rc = NO_ERROR; |
| QCameraReprocessChannel *pChannel = NULL; |
| uint32_t burst_cnt = mParameters.getNumOfSnapshots(); |
| uint32_t pHandle = getCamHandleForChannel(QCAMERA_CH_TYPE_REPROCESSING); |
| |
| if (pInputChannel == NULL) { |
| LOGE("input channel obj is NULL"); |
| return NULL; |
| } |
| |
| pChannel = new QCameraReprocessChannel(pHandle, mCameraHandle->ops); |
| if (NULL == pChannel) { |
| LOGE("no mem for reprocess channel"); |
| return NULL; |
| } |
| |
| // Capture channel, only need snapshot and postview streams start together |
| mm_camera_channel_attr_t attr; |
| memset(&attr, 0, sizeof(mm_camera_channel_attr_t)); |
| attr.notify_mode = MM_CAMERA_SUPER_BUF_NOTIFY_CONTINUOUS; |
| attr.max_unmatched_frames = mParameters.getMaxUnmatchedFramesInQueue(); |
| rc = pChannel->init(&attr, |
| postproc_channel_cb_routine, |
| this); |
| if (rc != NO_ERROR) { |
| LOGE("init reprocess channel failed, ret = %d", rc); |
| delete pChannel; |
| return NULL; |
| } |
| |
| // pp feature config |
| cam_pp_feature_config_t pp_config; |
| memset(&pp_config, 0, sizeof(cam_pp_feature_config_t)); |
| |
| rc = getPPConfig(pp_config, cur_channel_index, |
| ((mParameters.getReprocCount() > 1) ? TRUE : FALSE)); |
| if (rc != NO_ERROR){ |
| LOGE("Error while creating PP config"); |
| delete pChannel; |
| return NULL; |
| } |
| |
| uint8_t minStreamBufNum = getBufNumRequired(CAM_STREAM_TYPE_OFFLINE_PROC); |
| |
| //WNR and HDR happen inline. No extra buffers needed. |
| cam_feature_mask_t temp_feature_mask = pp_config.feature_mask; |
| temp_feature_mask &= ~CAM_QCOM_FEATURE_HDR; |
| if (temp_feature_mask && mParameters.isHDREnabled()) { |
| minStreamBufNum = (uint8_t)(1 + mParameters.getNumOfExtraHDRInBufsIfNeeded()); |
| } |
| |
| if (mParameters.isStillMoreEnabled()) { |
| cam_still_more_t stillmore_config = mParameters.getStillMoreSettings(); |
| pp_config.burst_cnt = stillmore_config.burst_count; |
| LOGH("Stillmore burst %d", pp_config.burst_cnt); |
| |
| // getNumOfExtraBuffersForImageProc returns 1 less buffer assuming |
| // number of capture is already added. In the case of liveshot, |
| // stillmore burst is 1. This is to account for the premature decrement |
| if (mParameters.getNumOfExtraBuffersForImageProc() == 0) { |
| minStreamBufNum += 1; |
| } |
| } |
| |
| if (mParameters.getManualCaptureMode() >= CAM_MANUAL_CAPTURE_TYPE_3) { |
| minStreamBufNum += mParameters.getReprocCount() - 1; |
| burst_cnt = mParameters.getReprocCount(); |
| if (cur_channel_index == 0) { |
| pChannel->setReprocCount(2); |
| } else { |
| pChannel->setReprocCount(1); |
| } |
| } else { |
| pChannel->setReprocCount(1); |
| } |
| |
| #ifdef DUAL_CAM_TEST //Temporary macro. Added to simulate B+B snapshot. Will be removed |
| if (isDualCamera()) { |
| minStreamBufNum += 1; |
| } |
| #endif |
| // Add non inplace image lib buffers only when ppproc is present, |
| // becuase pproc is non inplace and input buffers for img lib |
| // are output for pproc and this number of extra buffers is required |
| // If pproc is not there, input buffers for imglib are from snapshot stream |
| uint8_t imglib_extra_bufs = mParameters.getNumOfExtraBuffersForImageProc(); |
| if (temp_feature_mask && imglib_extra_bufs) { |
| // 1 is added because getNumOfExtraBuffersForImageProc returns extra |
| // buffers assuming number of capture is already added |
| minStreamBufNum = (uint8_t)(minStreamBufNum + imglib_extra_bufs + 1); |
| } |
| |
| //Mask out features that are already processed in snapshot stream. |
| cam_feature_mask_t snapshot_feature_mask = 0; |
| mParameters.getStreamPpMask(CAM_STREAM_TYPE_SNAPSHOT, snapshot_feature_mask); |
| |
| pp_config.feature_mask &= ~snapshot_feature_mask; |
| LOGH("Snapshot feature mask: 0x%llx, reproc feature mask: 0x%llx minStreamBufNum = %d", |
| snapshot_feature_mask, pp_config.feature_mask, minStreamBufNum); |
| |
| bool offlineReproc = needOfflineReprocessing(); |
| if (m_postprocessor.mOfflineDataBufs != NULL) { |
| offlineReproc = TRUE; |
| } |
| |
| cam_padding_info_t paddingInfo = gCamCapability[mCameraId]->padding_info; |
| paddingInfo.offset_info.offset_x = 0; |
| paddingInfo.offset_info.offset_y = 0; |
| rc = pChannel->addReprocStreamsFromSource(*this, |
| pp_config, |
| pInputChannel, |
| minStreamBufNum, |
| burst_cnt, |
| &paddingInfo, |
| mParameters, |
| mLongshotEnabled, |
| offlineReproc); |
| if (rc != NO_ERROR) { |
| delete pChannel; |
| return NULL; |
| } |
| |
| return pChannel; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : addOfflineReprocChannel |
| * |
| * DESCRIPTION: add a offline reprocess channel contains one reproc stream, |
| * that will do reprocess on frames coming from external images |
| * |
| * PARAMETERS : |
| * @img_config : offline reporcess image info |
| * @pp_feature : pp feature config |
| * |
| * RETURN : int32_t type of status |
| * NO_ERROR -- success |
| * none-zero failure code |
| *==========================================================================*/ |
| QCameraReprocessChannel *QCamera2HardwareInterface::addOfflineReprocChannel( |
| cam_pp_offline_src_config_t &img_config, |
| cam_pp_feature_config_t &pp_feature, |
| stream_cb_routine stream_cb, |
| void *userdata) |
| { |
| int32_t rc = NO_ERROR; |
| QCameraReprocessChannel *pChannel = NULL; |
| |
| pChannel = new QCameraReprocessChannel(mCameraHandle->camera_handle, |
| mCameraHandle->ops); |
| if (NULL == pChannel) { |
| LOGE("no mem for reprocess channel"); |
| return NULL; |
| } |
| |
| rc = pChannel->init(NULL, NULL, NULL); |
| if (rc != NO_ERROR) { |
| LOGE("init reprocess channel failed, ret = %d", rc); |
| delete pChannel; |
| return NULL; |
| } |
| |
| QCameraHeapMemory *pStreamInfo = allocateStreamInfoBuf(CAM_STREAM_TYPE_OFFLINE_PROC); |
| if (pStreamInfo == NULL) { |
| LOGE("no mem for stream info buf"); |
| delete pChannel; |
| return NULL; |
| } |
| |
| cam_stream_info_t *streamInfoBuf = (cam_stream_info_t *)pStreamInfo->getPtr(0); |
| memset(streamInfoBuf, 0, sizeof(cam_stream_info_t)); |
| streamInfoBuf->stream_type = CAM_STREAM_TYPE_OFFLINE_PROC; |
| streamInfoBuf->fmt = img_config.input_fmt; |
| streamInfoBuf->dim = img_config.input_dim; |
| streamInfoBuf->buf_planes = img_config.input_buf_planes; |
| streamInfoBuf->streaming_mode = CAM_STREAMING_MODE_BURST; |
| streamInfoBuf->num_of_burst = img_config.num_of_bufs; |
| |
| streamInfoBuf->reprocess_config.pp_type = CAM_OFFLINE_REPROCESS_TYPE; |
| streamInfoBuf->reprocess_config.offline = img_config; |
| streamInfoBuf->reprocess_config.pp_feature_config = pp_feature; |
| streamInfoBuf->num_bufs = img_config.num_of_bufs; |
| |
| rc = pChannel->addStream(*this, |
| pStreamInfo, NULL, |
| &gCamCapability[mCameraId]->padding_info, |
| stream_cb, userdata, false); |
| |
| if (rc != NO_ERROR) { |
| LOGE("add reprocess stream failed, ret = %d", rc); |
| delete pChannel; |
| return NULL; |
| } |
| |
| return pChannel; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : addChannel |
| * |
| * DESCRIPTION: add a channel by its type |
| * |
| * PARAMETERS : |
| * @ch_type : channel type |
| * |
| * RETURN : int32_t type of status |
| * NO_ERROR -- success |
| * none-zero failure code |
| *==========================================================================*/ |
| int32_t QCamera2HardwareInterface::addChannel(qcamera_ch_type_enum_t ch_type) |
| { |
| int32_t rc = UNKNOWN_ERROR; |
| switch (ch_type) { |
| case QCAMERA_CH_TYPE_ZSL: |
| rc = addZSLChannel(); |
| break; |
| case QCAMERA_CH_TYPE_CAPTURE: |
| rc = addCaptureChannel(); |
| break; |
| case QCAMERA_CH_TYPE_PREVIEW: |
| rc = addPreviewChannel(); |
| break; |
| case QCAMERA_CH_TYPE_VIDEO: |
| rc = addVideoChannel(); |
| break; |
| case QCAMERA_CH_TYPE_SNAPSHOT: |
| rc = addSnapshotChannel(); |
| break; |
| case QCAMERA_CH_TYPE_RAW: |
| rc = addRawChannel(); |
| break; |
| case QCAMERA_CH_TYPE_METADATA: |
| rc = addMetaDataChannel(); |
| break; |
| case QCAMERA_CH_TYPE_CALLBACK: |
| rc = addCallbackChannel(); |
| break; |
| case QCAMERA_CH_TYPE_ANALYSIS: |
| rc = addAnalysisChannel(); |
| break; |
| default: |
| break; |
| } |
| return rc; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : delChannel |
| * |
| * DESCRIPTION: delete a channel by its type |
| * |
| * PARAMETERS : |
| * @ch_type : channel type |
| * @destroy : delete context as well |
| * |
| * RETURN : int32_t type of status |
| * NO_ERROR -- success |
| * none-zero failure code |
| *==========================================================================*/ |
| int32_t QCamera2HardwareInterface::delChannel(qcamera_ch_type_enum_t ch_type, |
| bool destroy) |
| { |
| if (m_channels[ch_type] != NULL) { |
| if (destroy) { |
| delete m_channels[ch_type]; |
| m_channels[ch_type] = NULL; |
| } else { |
| m_channels[ch_type]->deleteChannel(); |
| } |
| } |
| |
| return NO_ERROR; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : startChannel |
| * |
| * DESCRIPTION: start a channel by its type |
| * |
| * PARAMETERS : |
| * @ch_type : channel type |
| * |
| * RETURN : int32_t type of status |
| * NO_ERROR -- success |
| * none-zero failure code |
| *==========================================================================*/ |
| int32_t QCamera2HardwareInterface::startChannel(qcamera_ch_type_enum_t ch_type) |
| { |
| int32_t rc = UNKNOWN_ERROR; |
| if (m_channels[ch_type] != NULL) { |
| rc = m_channels[ch_type]->start(); |
| } |
| return rc; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : stopChannel |
| * |
| * DESCRIPTION: stop a channel by its type |
| * |
| * PARAMETERS : |
| * @ch_type : channel type |
| * |
| * RETURN : int32_t type of status |
| * NO_ERROR -- success |
| * none-zero failure code |
| *==========================================================================*/ |
| int32_t QCamera2HardwareInterface::stopChannel(qcamera_ch_type_enum_t ch_type) |
| { |
| int32_t rc = UNKNOWN_ERROR; |
| if (m_channels[ch_type] != NULL) { |
| rc = m_channels[ch_type]->stop(); |
| } |
| |
| return rc; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : preparePreview |
| * |
| * DESCRIPTION: add channels needed for preview |
| * |
| * PARAMETERS : none |
| * |
| * RETURN : int32_t type of status |
| * NO_ERROR -- success |
| * none-zero failure code |
| *==========================================================================*/ |
| int32_t QCamera2HardwareInterface::preparePreview() |
| { |
| ATRACE_CALL(); |
| int32_t rc = NO_ERROR; |
| |
| LOGI("E"); |
| rc = mParameters.setStreamConfigure(false, false, false); |
| if (rc != NO_ERROR) { |
| LOGE("setStreamConfigure failed %d", rc); |
| return rc; |
| } |
| |
| if (mParameters.isZSLMode() && mParameters.getRecordingHintValue() != true) { |
| rc = addChannel(QCAMERA_CH_TYPE_ZSL); |
| if (rc != NO_ERROR) { |
| LOGE("failed!! rc = %d", rc); |
| return rc; |
| } |
| |
| if (mParameters.isUBWCEnabled()) { |
| cam_format_t fmt; |
| mParameters.getStreamFormat(CAM_STREAM_TYPE_PREVIEW, fmt); |
| if (fmt == CAM_FORMAT_YUV_420_NV12_UBWC) { |
| rc = addChannel(QCAMERA_CH_TYPE_CALLBACK); |
| if (rc != NO_ERROR) { |
| delChannel(QCAMERA_CH_TYPE_ZSL); |
| LOGE("failed!! rc = %d", rc); |
| return rc; |
| } |
| } |
| } |
| |
| if (mParameters.getofflineRAW() && !mParameters.getQuadraCfa()) { |
| addChannel(QCAMERA_CH_TYPE_RAW); |
| } |
| } else { |
| bool recordingHint = mParameters.getRecordingHintValue(); |
| if(!isRdiMode() && recordingHint) { |
| //stop face detection,longshot,etc if turned ON in Camera mode |
| #ifndef VANILLA_HAL |
| int32_t arg; //dummy arg |
| if (isLongshotEnabled()) { |
| sendCommand(CAMERA_CMD_LONGSHOT_OFF, arg, arg); |
| } |
| if (mParameters.isFaceDetectionEnabled() |
| && (!mParameters.fdModeInVideo())) { |
| sendCommand(CAMERA_CMD_STOP_FACE_DETECTION, arg, arg); |
| } |
| if (mParameters.isHistogramEnabled()) { |
| sendCommand(CAMERA_CMD_HISTOGRAM_OFF, arg, arg); |
| } |
| #endif |
| //Don't create snapshot channel for liveshot, if low power mode is set. |
| //Use video stream instead. |
| if (!isLowPowerMode()) { |
| rc = addChannel(QCAMERA_CH_TYPE_SNAPSHOT); |
| if (rc != NO_ERROR) { |
| return rc; |
| } |
| } |
| |
| rc = addChannel(QCAMERA_CH_TYPE_VIDEO); |
| if (rc != NO_ERROR) { |
| delChannel(QCAMERA_CH_TYPE_SNAPSHOT); |
| LOGE("failed!! rc = %d", rc); |
| return rc; |
| } |
| } |
| |
| rc = addChannel(QCAMERA_CH_TYPE_PREVIEW); |
| if (!isRdiMode() && (rc != NO_ERROR)) { |
| if (recordingHint) { |
| delChannel(QCAMERA_CH_TYPE_SNAPSHOT); |
| delChannel(QCAMERA_CH_TYPE_VIDEO); |
| } |
| } |
| |
| if (mParameters.isUBWCEnabled() && !recordingHint) { |
| cam_format_t fmt; |
| mParameters.getStreamFormat(CAM_STREAM_TYPE_PREVIEW, fmt); |
| if (fmt == CAM_FORMAT_YUV_420_NV12_UBWC) { |
| rc = addChannel(QCAMERA_CH_TYPE_CALLBACK); |
| if (rc != NO_ERROR) { |
| delChannel(QCAMERA_CH_TYPE_PREVIEW); |
| if (!isRdiMode()) { |
| delChannel(QCAMERA_CH_TYPE_SNAPSHOT); |
| delChannel(QCAMERA_CH_TYPE_VIDEO); |
| } |
| LOGE("failed!! rc = %d", rc); |
| return rc; |
| } |
| } |
| } |
| |
| if (NO_ERROR != rc) { |
| delChannel(QCAMERA_CH_TYPE_PREVIEW); |
| LOGE("failed!! rc = %d", rc); |
| } |
| } |
| |
| LOGI("X rc = %d", rc); |
| return rc; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : unpreparePreview |
| * |
| * DESCRIPTION: delete channels for preview |
| * |
| * PARAMETERS : none |
| * |
| * RETURN : none |
| *==========================================================================*/ |
| void QCamera2HardwareInterface::unpreparePreview() |
| { |
| delChannel(QCAMERA_CH_TYPE_ZSL); |
| delChannel(QCAMERA_CH_TYPE_PREVIEW); |
| delChannel(QCAMERA_CH_TYPE_VIDEO); |
| delChannel(QCAMERA_CH_TYPE_SNAPSHOT); |
| delChannel(QCAMERA_CH_TYPE_CALLBACK); |
| delChannel(QCAMERA_CH_TYPE_RAW); |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : playShutter |
| * |
| * DESCRIPTION: send request to play shutter sound |
| * |
| * PARAMETERS : none |
| * |
| * RETURN : none |
| *==========================================================================*/ |
| void QCamera2HardwareInterface::playShutter(){ |
| if (mNotifyCb == NULL || |
| msgTypeEnabledWithLock(CAMERA_MSG_SHUTTER) == 0){ |
| LOGD("shutter msg not enabled or NULL cb"); |
| return; |
| } |
| LOGH("CAMERA_MSG_SHUTTER "); |
| qcamera_callback_argm_t cbArg; |
| memset(&cbArg, 0, sizeof(qcamera_callback_argm_t)); |
| cbArg.cb_type = QCAMERA_NOTIFY_CALLBACK; |
| cbArg.msg_type = CAMERA_MSG_SHUTTER; |
| cbArg.ext1 = 0; |
| cbArg.ext2 = false; |
| m_cbNotifier.notifyCallback(cbArg); |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : getChannelByHandle |
| * |
| * DESCRIPTION: return a channel by its handle |
| * |
| * PARAMETERS : |
| * @channelHandle : channel handle |
| * |
| * RETURN : a channel obj if found, NULL if not found |
| *==========================================================================*/ |
| QCameraChannel *QCamera2HardwareInterface::getChannelByHandle(uint32_t channelHandle) |
| { |
| for(int i = 0; i < QCAMERA_CH_TYPE_MAX; i++) { |
| if (m_channels[i] != NULL && |
| (validate_handle(m_channels[i]->getMyHandle(), channelHandle))) { |
| return m_channels[i]; |
| } |
| } |
| |
| return NULL; |
| } |
| /*=========================================================================== |
| * FUNCTION : needPreviewFDCallback |
| * |
| * DESCRIPTION: decides if needPreviewFDCallback |
| * |
| * PARAMETERS : |
| * @num_faces : number of faces |
| * |
| * RETURN : bool type of status |
| * true -- success |
| * fale -- failure code |
| *==========================================================================*/ |
| bool QCamera2HardwareInterface::needPreviewFDCallback(uint8_t num_faces) |
| { |
| if (num_faces == 0 && mNumPreviewFaces == 0) { |
| return false; |
| } |
| |
| return true; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : processFaceDetectionReuslt |
| * |
| * DESCRIPTION: process face detection reuslt |
| * |
| * PARAMETERS : |
| * @faces_data : ptr to face processing result struct |
| * |
| * RETURN : int32_t type of status |
| * NO_ERROR -- success |
| * none-zero failure code |
| *==========================================================================*/ |
| int32_t QCamera2HardwareInterface::processFaceDetectionResult(cam_faces_data_t *faces_data) |
| { |
| if (!mParameters.isFaceDetectionEnabled()) { |
| LOGH("FaceDetection not enabled, no ops here"); |
| return NO_ERROR; |
| } |
| |
| qcamera_face_detect_type_t fd_type = faces_data->detection_data.fd_type; |
| cam_face_detection_data_t *detect_data = &(faces_data->detection_data); |
| if ((NULL == mDataCb) || |
| (fd_type == QCAMERA_FD_PREVIEW && !msgTypeEnabled(CAMERA_MSG_PREVIEW_METADATA)) || |
| (!needPreviewFDCallback(detect_data->num_faces_detected)) |
| #ifndef VANILLA_HAL |
| || (fd_type == QCAMERA_FD_SNAPSHOT && !msgTypeEnabled(CAMERA_MSG_META_DATA)) |
| #endif |
| ) { |
| LOGH("metadata msgtype not enabled, no ops here"); |
| return NO_ERROR; |
| } |
| |
| if ((fd_type == QCAMERA_FD_PREVIEW) && (detect_data->update_flag == FALSE)) { |
| // Don't send callback to app if this is skipped by fd at backend |
| return NO_ERROR; |
| } |
| |
| cam_dimension_t display_dim; |
| mParameters.getStreamDimension(CAM_STREAM_TYPE_PREVIEW, display_dim); |
| if (display_dim.width <= 0 || display_dim.height <= 0) { |
| LOGE("Invalid preview width or height (%d x %d)", |
| display_dim.width, display_dim.height); |
| return UNKNOWN_ERROR; |
| } |
| |
| // process face detection result |
| // need separate face detection in preview or snapshot type |
| size_t faceResultSize = 0; |
| size_t data_len = 0; |
| if(fd_type == QCAMERA_FD_PREVIEW){ |
| //fd for preview frames |
| faceResultSize = sizeof(camera_frame_metadata_t); |
| faceResultSize += sizeof(camera_face_t) * MAX_ROI; |
| }else if(fd_type == QCAMERA_FD_SNAPSHOT){ |
| #ifndef VANILLA_HAL |
| // fd for snapshot frames |
| //check if face is detected in this frame |
| if(detect_data->num_faces_detected > 0){ |
| data_len = sizeof(camera_frame_metadata_t) + |
| sizeof(camera_face_t) * detect_data->num_faces_detected; |
| }else{ |
| //no face |
| data_len = 0; |
| } |
| #endif |
| faceResultSize = 1 *sizeof(int) //meta data type |
| + 1 *sizeof(int) // meta data len |
| + data_len; //data |
| } |
| |
| camera_memory_t *faceResultBuffer = mGetMemory(-1, |
| faceResultSize, |
| 1, |
| mCallbackCookie); |
| if ( NULL == faceResultBuffer ) { |
| LOGE("Not enough memory for face result data"); |
| return NO_MEMORY; |
| } |
| |
| unsigned char *pFaceResult = ( unsigned char * ) faceResultBuffer->data; |
| memset(pFaceResult, 0, faceResultSize); |
| unsigned char *faceData = NULL; |
| if(fd_type == QCAMERA_FD_PREVIEW){ |
| faceData = pFaceResult; |
| mNumPreviewFaces = detect_data->num_faces_detected; |
| }else if(fd_type == QCAMERA_FD_SNAPSHOT){ |
| #ifndef VANILLA_HAL |
| //need fill meta type and meta data len first |
| int *data_header = (int* )pFaceResult; |
| data_header[0] = CAMERA_META_DATA_FD; |
| data_header[1] = (int)data_len; |
| |
| if(data_len <= 0){ |
| //if face is not valid or do not have face, return |
| qcamera_callback_argm_t cbArg; |
| memset(&cbArg, 0, sizeof(qcamera_callback_argm_t)); |
| cbArg.cb_type = QCAMERA_DATA_CALLBACK; |
| cbArg.msg_type = CAMERA_MSG_META_DATA; |
| cbArg.data = faceResultBuffer; |
| cbArg.user_data = faceResultBuffer; |
| cbArg.cookie = this; |
| cbArg.release_cb = releaseCameraMemory; |
| int32_t rc = m_cbNotifier.notifyCallback(cbArg); |
| if (rc != NO_ERROR) { |
| LOGE("fail sending notification"); |
| faceResultBuffer->release(faceResultBuffer); |
| } |
| return rc; |
| } |
| #endif |
| faceData = pFaceResult + 2 *sizeof(int); //skip two int length |
| } |
| |
| camera_frame_metadata_t *roiData = (camera_frame_metadata_t * ) faceData; |
| camera_face_t *faces = (camera_face_t *) ( faceData + sizeof(camera_frame_metadata_t) ); |
| |
| roiData->number_of_faces = detect_data->num_faces_detected; |
| roiData->faces = faces; |
| if (roiData->number_of_faces > 0) { |
| for (int i = 0; i < roiData->number_of_faces; i++) { |
| faces[i].id = detect_data->faces[i].face_id; |
| faces[i].score = detect_data->faces[i].score; |
| |
| // left |
| faces[i].rect[0] = MAP_TO_DRIVER_COORDINATE( |
| detect_data->faces[i].face_boundary.left, |
| display_dim.width, 2000, -1000); |
| |
| // top |
| faces[i].rect[1] = MAP_TO_DRIVER_COORDINATE( |
| detect_data->faces[i].face_boundary.top, |
| display_dim.height, 2000, -1000); |
| |
| // right |
| faces[i].rect[2] = faces[i].rect[0] + |
| MAP_TO_DRIVER_COORDINATE( |
| detect_data->faces[i].face_boundary.width, |
| display_dim.width, 2000, 0); |
| |
| // bottom |
| faces[i].rect[3] = faces[i].rect[1] + |
| MAP_TO_DRIVER_COORDINATE( |
| detect_data->faces[i].face_boundary.height, |
| display_dim.height, 2000, 0); |
| |
| if (faces_data->landmark_valid) { |
| // Center of left eye |
| if (faces_data->landmark_data.face_landmarks[i].is_left_eye_valid) { |
| faces[i].left_eye[0] = MAP_TO_DRIVER_COORDINATE( |
| faces_data->landmark_data.face_landmarks[i].left_eye_center.x, |
| display_dim.width, 2000, -1000); |
| faces[i].left_eye[1] = MAP_TO_DRIVER_COORDINATE( |
| faces_data->landmark_data.face_landmarks[i].left_eye_center.y, |
| display_dim.height, 2000, -1000); |
| } else { |
| faces[i].left_eye[0] = FACE_INVALID_POINT; |
| faces[i].left_eye[1] = FACE_INVALID_POINT; |
| } |
| |
| // Center of right eye |
| if (faces_data->landmark_data.face_landmarks[i].is_right_eye_valid) { |
| faces[i].right_eye[0] = MAP_TO_DRIVER_COORDINATE( |
| faces_data->landmark_data.face_landmarks[i].right_eye_center.x, |
| display_dim.width, 2000, -1000); |
| faces[i].right_eye[1] = MAP_TO_DRIVER_COORDINATE( |
| faces_data->landmark_data.face_landmarks[i].right_eye_center.y, |
| display_dim.height, 2000, -1000); |
| } else { |
| faces[i].right_eye[0] = FACE_INVALID_POINT; |
| faces[i].right_eye[1] = FACE_INVALID_POINT; |
| } |
| |
| // Center of mouth |
| if (faces_data->landmark_data.face_landmarks[i].is_mouth_valid) { |
| faces[i].mouth[0] = MAP_TO_DRIVER_COORDINATE( |
| faces_data->landmark_data.face_landmarks[i].mouth_center.x, |
| display_dim.width, 2000, -1000); |
| faces[i].mouth[1] = MAP_TO_DRIVER_COORDINATE( |
| faces_data->landmark_data.face_landmarks[i].mouth_center.y, |
| display_dim.height, 2000, -1000); |
| } else { |
| faces[i].mouth[0] = FACE_INVALID_POINT; |
| faces[i].mouth[1] = FACE_INVALID_POINT; |
| } |
| } else { |
| // return -2000 if invalid |
| faces[i].left_eye[0] = FACE_INVALID_POINT; |
| faces[i].left_eye[1] = FACE_INVALID_POINT; |
| |
| faces[i].right_eye[0] = FACE_INVALID_POINT; |
| faces[i].right_eye[1] = FACE_INVALID_POINT; |
| |
| faces[i].mouth[0] = FACE_INVALID_POINT; |
| faces[i].mouth[1] = FACE_INVALID_POINT; |
| } |
| |
| #ifndef VANILLA_HAL |
| #ifdef TARGET_TS_MAKEUP |
| mFaceRect.left = detect_data->faces[i].face_boundary.left; |
| mFaceRect.top = detect_data->faces[i].face_boundary.top; |
| mFaceRect.right = detect_data->faces[i].face_boundary.width+mFaceRect.left; |
| mFaceRect.bottom = detect_data->faces[i].face_boundary.height+mFaceRect.top; |
| #endif |
| if (faces_data->smile_valid) { |
| faces[i].smile_degree = faces_data->smile_data.smile[i].smile_degree; |
| faces[i].smile_score = faces_data->smile_data.smile[i].smile_confidence; |
| } |
| if (faces_data->blink_valid) { |
| faces[i].blink_detected = faces_data->blink_data.blink[i].blink_detected; |
| faces[i].leye_blink = faces_data->blink_data.blink[i].left_blink; |
| faces[i].reye_blink = faces_data->blink_data.blink[i].right_blink; |
| } |
| if (faces_data->recog_valid) { |
| faces[i].face_recognised = faces_data->recog_data.face_rec[i].face_recognised; |
| } |
| if (faces_data->gaze_valid) { |
| faces[i].gaze_angle = faces_data->gaze_data.gaze[i].gaze_angle; |
| faces[i].updown_dir = faces_data->gaze_data.gaze[i].updown_dir; |
| faces[i].leftright_dir = faces_data->gaze_data.gaze[i].leftright_dir; |
| faces[i].roll_dir = faces_data->gaze_data.gaze[i].roll_dir; |
| faces[i].left_right_gaze = faces_data->gaze_data.gaze[i].left_right_gaze; |
| faces[i].top_bottom_gaze = faces_data->gaze_data.gaze[i].top_bottom_gaze; |
| } |
| #endif |
| |
| } |
| } |
| else{ |
| #ifdef TARGET_TS_MAKEUP |
| memset(&mFaceRect,-1,sizeof(mFaceRect)); |
| #endif |
| } |
| qcamera_callback_argm_t cbArg; |
| memset(&cbArg, 0, sizeof(qcamera_callback_argm_t)); |
| cbArg.cb_type = QCAMERA_DATA_CALLBACK; |
| if(fd_type == QCAMERA_FD_PREVIEW){ |
| cbArg.msg_type = CAMERA_MSG_PREVIEW_METADATA; |
| } |
| #ifndef VANILLA_HAL |
| else if(fd_type == QCAMERA_FD_SNAPSHOT){ |
| cbArg.msg_type = CAMERA_MSG_META_DATA; |
| } |
| #endif |
| cbArg.data = faceResultBuffer; |
| cbArg.metadata = roiData; |
| cbArg.user_data = faceResultBuffer; |
| cbArg.cookie = this; |
| cbArg.release_cb = releaseCameraMemory; |
| int32_t rc = m_cbNotifier.notifyCallback(cbArg); |
| if (rc != NO_ERROR) { |
| LOGE("fail sending notification"); |
| faceResultBuffer->release(faceResultBuffer); |
| } |
| |
| return rc; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : releaseCameraMemory |
| * |
| * DESCRIPTION: releases camera memory objects |
| * |
| * PARAMETERS : |
| * @data : buffer to be released |
| * @cookie : context data |
| * @cbStatus: callback status |
| * |
| * RETURN : None |
| *==========================================================================*/ |
| void QCamera2HardwareInterface::releaseCameraMemory(void *data, |
| void */*cookie*/, |
| int32_t /*cbStatus*/) |
| { |
| camera_memory_t *mem = ( camera_memory_t * ) data; |
| if ( NULL != mem ) { |
| mem->release(mem); |
| } |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : returnStreamBuffer |
| * |
| * DESCRIPTION: returns back a stream buffer |
| * |
| * PARAMETERS : |
| * @data : buffer to be released |
| * @cookie : context data |
| * @cbStatus: callback status |
| * |
| * RETURN : None |
| *==========================================================================*/ |
| void QCamera2HardwareInterface::returnStreamBuffer(void *data, |
| void *cookie, |
| int32_t /*cbStatus*/) |
| { |
| QCameraStream *stream = ( QCameraStream * ) cookie; |
| int idx = *((int *)data); |
| if ((NULL != stream) && (0 <= idx)) { |
| stream->bufDone((uint32_t)idx); |
| } else { |
| LOGE("Cannot return buffer %d %p", idx, cookie); |
| } |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : processHistogramStats |
| * |
| * DESCRIPTION: process histogram stats |
| * |
| * PARAMETERS : |
| * @hist_data : ptr to histogram stats struct |
| * |
| * RETURN : int32_t type of status |
| * NO_ERROR -- success |
| * none-zero failure code |
| *==========================================================================*/ |
| int32_t QCamera2HardwareInterface::processHistogramStats( |
| __unused cam_hist_stats_t &stats_data) |
| { |
| #ifndef VANILLA_HAL |
| if (!mParameters.isHistogramEnabled()) { |
| LOGH("Histogram not enabled, no ops here"); |
| return NO_ERROR; |
| } |
| |
| camera_memory_t *histBuffer = mGetMemory(-1, |
| sizeof(cam_histogram_data_t), |
| 1, |
| mCallbackCookie); |
| if ( NULL == histBuffer ) { |
| LOGE("Not enough memory for histogram data"); |
| return NO_MEMORY; |
| } |
| |
| cam_histogram_data_t *pHistData = (cam_histogram_data_t *)histBuffer->data; |
| if (pHistData == NULL) { |
| LOGE("memory data ptr is NULL"); |
| return UNKNOWN_ERROR; |
| } |
| |
| switch (stats_data.type) { |
| case CAM_HISTOGRAM_TYPE_BAYER: |
| switch (stats_data.bayer_stats.data_type) { |
| case CAM_STATS_CHANNEL_Y: |
| case CAM_STATS_CHANNEL_R: |
| *pHistData = stats_data.bayer_stats.r_stats; |
| break; |
| case CAM_STATS_CHANNEL_GR: |
| *pHistData = stats_data.bayer_stats.gr_stats; |
| break; |
| case CAM_STATS_CHANNEL_GB: |
| case CAM_STATS_CHANNEL_ALL: |
| *pHistData = stats_data.bayer_stats.gb_stats; |
| break; |
| case CAM_STATS_CHANNEL_B: |
| *pHistData = stats_data.bayer_stats.b_stats; |
| break; |
| default: |
| *pHistData = stats_data.bayer_stats.r_stats; |
| break; |
| } |
| break; |
| case CAM_HISTOGRAM_TYPE_YUV: |
| *pHistData = stats_data.yuv_stats; |
| break; |
| } |
| |
| qcamera_callback_argm_t cbArg; |
| memset(&cbArg, 0, sizeof(qcamera_callback_argm_t)); |
| cbArg.cb_type = QCAMERA_DATA_CALLBACK; |
| cbArg.msg_type = CAMERA_MSG_STATS_DATA; |
| cbArg.data = histBuffer; |
| cbArg.user_data = histBuffer; |
| cbArg.cookie = this; |
| cbArg.release_cb = releaseCameraMemory; |
| int32_t rc = m_cbNotifier.notifyCallback(cbArg); |
| if (rc != NO_ERROR) { |
| LOGE("fail sending notification"); |
| histBuffer->release(histBuffer); |
| } |
| #endif |
| return NO_ERROR; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : calcThermalLevel |
| * |
| * DESCRIPTION: Calculates the target fps range depending on |
| * the thermal level. |
| * Note that this function can be called from QCameraParametersIntf |
| * while mutex is held. So it should not call back into |
| * QCameraParametersIntf causing deadlock. |
| * |
| * PARAMETERS : |
| * @level : received thermal level |
| * @minFPS : minimum configured fps range |
| * @maxFPS : maximum configured fps range |
| * @minVideoFps: minimum configured fps range |
| * @maxVideoFps: maximum configured fps range |
| * @adjustedRange : target fps range |
| * @skipPattern : target skip pattern |
| * |
| * RETURN : int32_t type of status |
| * NO_ERROR -- success |
| * none-zero failure code |
| *==========================================================================*/ |
| int QCamera2HardwareInterface::calcThermalLevel( |
| qcamera_thermal_level_enum_t level, |
| const int minFPSi, |
| const int maxFPSi, |
| const float &minVideoFps, |
| const float &maxVideoFps, |
| cam_fps_range_t &adjustedRange, |
| enum msm_vfe_frame_skip_pattern &skipPattern) |
| { |
| const float minFPS = (float)minFPSi; |
| const float maxFPS = (float)maxFPSi; |
| |
| LOGH("level: %d, preview minfps %f, preview maxfpS %f, " |
| "video minfps %f, video maxfpS %f", |
| level, minFPS, maxFPS, minVideoFps, maxVideoFps); |
| |
| switch(level) { |
| case QCAMERA_THERMAL_NO_ADJUSTMENT: |
| { |
| adjustedRange.min_fps = minFPS / 1000.0f; |
| adjustedRange.max_fps = maxFPS / 1000.0f; |
| adjustedRange.video_min_fps = minVideoFps / 1000.0f; |
| adjustedRange.video_max_fps = maxVideoFps / 1000.0f; |
| skipPattern = NO_SKIP; |
| } |
| break; |
| case QCAMERA_THERMAL_SLIGHT_ADJUSTMENT: |
| { |
| adjustedRange.min_fps = minFPS / 1000.0f; |
| adjustedRange.max_fps = maxFPS / 1000.0f; |
| adjustedRange.min_fps -= 0.1f * adjustedRange.min_fps; |
| adjustedRange.max_fps -= 0.1f * adjustedRange.max_fps; |
| adjustedRange.video_min_fps = minVideoFps / 1000.0f; |
| adjustedRange.video_max_fps = maxVideoFps / 1000.0f; |
| adjustedRange.video_min_fps -= 0.1f * adjustedRange.video_min_fps; |
| adjustedRange.video_max_fps -= 0.1f * adjustedRange.video_max_fps; |
| if ( adjustedRange.min_fps < 1 ) { |
| adjustedRange.min_fps = 1; |
| } |
| if ( adjustedRange.max_fps < 1 ) { |
| adjustedRange.max_fps = 1; |
| } |
| if ( adjustedRange.video_min_fps < 1 ) { |
| adjustedRange.video_min_fps = 1; |
| } |
| if ( adjustedRange.video_max_fps < 1 ) { |
| adjustedRange.video_max_fps = 1; |
| } |
| skipPattern = EVERY_2FRAME; |
| } |
| break; |
| case QCAMERA_THERMAL_BIG_ADJUSTMENT: |
| { |
| adjustedRange.min_fps = minFPS / 1000.0f; |
| adjustedRange.max_fps = maxFPS / 1000.0f; |
| adjustedRange.min_fps -= 0.2f * adjustedRange.min_fps; |
| adjustedRange.max_fps -= 0.2f * adjustedRange.max_fps; |
| adjustedRange.video_min_fps = minVideoFps / 1000.0f; |
| adjustedRange.video_max_fps = maxVideoFps / 1000.0f; |
| adjustedRange.video_min_fps -= 0.2f * adjustedRange.video_min_fps; |
| adjustedRange.video_max_fps -= 0.2f * adjustedRange.video_max_fps; |
| if ( adjustedRange.min_fps < 1 ) { |
| adjustedRange.min_fps = 1; |
| } |
| if ( adjustedRange.max_fps < 1 ) { |
| adjustedRange.max_fps = 1; |
| } |
| if ( adjustedRange.video_min_fps < 1 ) { |
| adjustedRange.video_min_fps = 1; |
| } |
| if ( adjustedRange.video_max_fps < 1 ) { |
| adjustedRange.video_max_fps = 1; |
| } |
| skipPattern = EVERY_4FRAME; |
| } |
| break; |
| case QCAMERA_THERMAL_MAX_ADJUSTMENT: |
| { |
| // Stop Preview? |
| // Set lowest min FPS for now |
| adjustedRange.min_fps = minFPS/1000.0f; |
| adjustedRange.max_fps = minFPS/1000.0f; |
| cam_capability_t *capability = gCamCapability[mCameraId]; |
| for (size_t i = 0; |
| i < capability->fps_ranges_tbl_cnt; |
| i++) { |
| if (capability->fps_ranges_tbl[i].min_fps < |
| adjustedRange.min_fps) { |
| adjustedRange.min_fps = |
| capability->fps_ranges_tbl[i].min_fps; |
| adjustedRange.max_fps = adjustedRange.min_fps; |
| } |
| } |
| skipPattern = MAX_SKIP; |
| adjustedRange.video_min_fps = adjustedRange.min_fps; |
| adjustedRange.video_max_fps = adjustedRange.max_fps; |
| } |
| break; |
| case QCAMERA_THERMAL_SHUTDOWN: |
| { |
| // send error notify |
| LOGE("Received shutdown thermal level. Closing camera"); |
| sendEvtNotify(CAMERA_MSG_ERROR, CAMERA_ERROR_SERVER_DIED, 0); |
| } |
| break; |
| default: |
| { |
| LOGW("Invalid thermal level %d", level); |
| return BAD_VALUE; |
| } |
| break; |
| } |
| |
| return NO_ERROR; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : recalcFPSRange |
| * |
| * DESCRIPTION: adjust the configured fps range regarding |
| * the last thermal level. |
| * |
| * PARAMETERS : |
| * @minFPS : minimum configured fps range |
| * @maxFPS : maximum configured fps range |
| * @minVideoFPS : minimum configured video fps |
| * @maxVideoFPS : maximum configured video fps |
| * @adjustedRange : target fps range |
| * |
| * RETURN : int32_t type of status |
| * NO_ERROR -- success |
| * none-zero failure code |
| *==========================================================================*/ |
| int QCamera2HardwareInterface::recalcFPSRange(int &minFPS, int &maxFPS, |
| const float &minVideoFPS, const float &maxVideoFPS, |
| cam_fps_range_t &adjustedRange) |
| { |
| enum msm_vfe_frame_skip_pattern skipPattern; |
| calcThermalLevel(mThermalLevel, |
| minFPS, |
| maxFPS, |
| minVideoFPS, |
| maxVideoFPS, |
| adjustedRange, |
| skipPattern); |
| return NO_ERROR; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : updateThermalLevel |
| * |
| * DESCRIPTION: update thermal level depending on thermal events |
| * |
| * PARAMETERS : |
| * @level : thermal level |
| * |
| * RETURN : int32_t type of status |
| * NO_ERROR -- success |
| * none-zero failure code |
| *==========================================================================*/ |
| int QCamera2HardwareInterface::updateThermalLevel(void *thermal_level) |
| { |
| int ret = NO_ERROR; |
| cam_fps_range_t adjustedRange; |
| int minFPS, maxFPS; |
| float minVideoFPS, maxVideoFPS; |
| enum msm_vfe_frame_skip_pattern skipPattern; |
| qcamera_thermal_level_enum_t level = *(qcamera_thermal_level_enum_t *)thermal_level; |
| |
| |
| if (!mCameraOpened) { |
| LOGH("Camera is not opened, no need to update camera parameters"); |
| return NO_ERROR; |
| } |
| if (mParameters.getRecordingHintValue()) { |
| LOGH("Thermal mitigation isn't enabled in camcorder mode"); |
| return NO_ERROR; |
| } |
| |
| mParameters.getPreviewFpsRange(&minFPS, &maxFPS); |
| qcamera_thermal_mode thermalMode = mParameters.getThermalMode(); |
| if (mParameters.isHfrMode()) { |
| cam_fps_range_t hfrFpsRange; |
| mParameters.getHfrFps(hfrFpsRange); |
| minVideoFPS = hfrFpsRange.video_min_fps; |
| maxVideoFPS = hfrFpsRange.video_max_fps; |
| } else { |
| minVideoFPS = minFPS; |
| maxVideoFPS = maxFPS; |
| } |
| |
| calcThermalLevel(level, minFPS, maxFPS, minVideoFPS, maxVideoFPS, |
| adjustedRange, skipPattern); |
| mThermalLevel = level; |
| |
| if (thermalMode == QCAMERA_THERMAL_ADJUST_FPS) |
| ret = mParameters.adjustPreviewFpsRange(&adjustedRange); |
| else if (thermalMode == QCAMERA_THERMAL_ADJUST_FRAMESKIP) |
| ret = mParameters.setFrameSkip(skipPattern); |
| else |
| LOGW("Incorrect thermal mode %d", thermalMode); |
| |
| return ret; |
| |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : updateParameters |
| * |
| * DESCRIPTION: update parameters |
| * |
| * PARAMETERS : |
| * @parms : input parameters string |
| * @needRestart : output, flag to indicate if preview restart is needed |
| * |
| * RETURN : int32_t type of status |
| * NO_ERROR -- success |
| * none-zero failure code |
| *==========================================================================*/ |
| int QCamera2HardwareInterface::updateParameters(const char *parms, bool &needRestart) |
| { |
| int rc = NO_ERROR; |
| |
| String8 str = String8(parms); |
| rc = mParameters.updateParameters(str, needRestart); |
| setNeedRestart(needRestart); |
| |
| // update stream based parameter settings |
| for (int i = 0; i < QCAMERA_CH_TYPE_MAX; i++) { |
| if (m_channels[i] != NULL) { |
| m_channels[i]->UpdateStreamBasedParameters(mParameters); |
| } |
| } |
| |
| return rc; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : commitParameterChanges |
| * |
| * DESCRIPTION: commit parameter changes to the backend to take effect |
| * |
| * PARAMETERS : none |
| * |
| * RETURN : int32_t type of status |
| * NO_ERROR -- success |
| * none-zero failure code |
| * NOTE : This function must be called after updateParameters. |
| * Otherwise, no change will be passed to backend to take effect. |
| *==========================================================================*/ |
| int QCamera2HardwareInterface::commitParameterChanges() |
| { |
| int rc = NO_ERROR; |
| rc = mParameters.commitParameters(); |
| if (rc == NO_ERROR) { |
| // update number of snapshot based on committed parameters setting |
| rc = mParameters.setNumOfSnapshot(); |
| } |
| return rc; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : needDebugFps |
| * |
| * DESCRIPTION: if fps log info need to be printed out |
| * |
| * PARAMETERS : none |
| * |
| * RETURN : true: need print out fps log |
| * false: no need to print out fps log |
| *==========================================================================*/ |
| bool QCamera2HardwareInterface::needDebugFps() |
| { |
| bool needFps = false; |
| needFps = mParameters.isFpsDebugEnabled(); |
| return needFps; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : isCACEnabled |
| * |
| * DESCRIPTION: if CAC is enabled |
| * |
| * PARAMETERS : none |
| * |
| * RETURN : true: needed |
| * false: no need |
| *==========================================================================*/ |
| bool QCamera2HardwareInterface::isCACEnabled() |
| { |
| char prop[PROPERTY_VALUE_MAX]; |
| memset(prop, 0, sizeof(prop)); |
| property_get("persist.camera.feature.cac", prop, "0"); |
| int enableCAC = atoi(prop); |
| return enableCAC == 1; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : is4k2kResolution |
| * |
| * DESCRIPTION: if resolution is 4k x 2k or true 4k x 2k |
| * |
| * PARAMETERS : none |
| * |
| * RETURN : true: needed |
| * false: no need |
| *==========================================================================*/ |
| bool QCamera2HardwareInterface::is4k2kResolution(cam_dimension_t* resolution) |
| { |
| bool enabled = false; |
| if ((resolution->width == 4096 && resolution->height == 2160) || |
| (resolution->width == 3840 && resolution->height == 2160) ) { |
| enabled = true; |
| } |
| return enabled; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : isPreviewRestartEnabled |
| * |
| * DESCRIPTION: Check whether preview should be restarted automatically |
| * during image capture. |
| * |
| * PARAMETERS : none |
| * |
| * RETURN : true: needed |
| * false: no need |
| *==========================================================================*/ |
| bool QCamera2HardwareInterface::isPreviewRestartEnabled() |
| { |
| char prop[PROPERTY_VALUE_MAX]; |
| memset(prop, 0, sizeof(prop)); |
| property_get("persist.camera.feature.restart", prop, "0"); |
| int earlyRestart = atoi(prop); |
| return earlyRestart == 1; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : needReprocess |
| * |
| * DESCRIPTION: if reprocess is needed |
| * |
| * PARAMETERS : none |
| * |
| * RETURN : true: needed |
| * false: no need |
| *==========================================================================*/ |
| bool QCamera2HardwareInterface::needReprocess() |
| { |
| bool needReprocess = false; |
| |
| if (!mParameters.isJpegPictureFormat() && |
| !mParameters.isNV21PictureFormat()) { |
| // RAW image, no need to reprocess |
| return false; |
| } |
| |
| //Disable reprocess for 4K liveshot case but enable if lowpower mode |
| if (mParameters.is4k2kVideoResolution() && mParameters.getRecordingHintValue() |
| && !isLowPowerMode()) { |
| return false; |
| } |
| |
| // pp feature config |
| cam_pp_feature_config_t pp_config; |
| memset(&pp_config, 0, sizeof(cam_pp_feature_config_t)); |
| |
| //Decide whether to do reprocess or not based on |
| //ppconfig obtained in the first pass. |
| getPPConfig(pp_config); |
| |
| if (pp_config.feature_mask > 0) { |
| needReprocess = true; |
| } |
| |
| LOGH("needReprocess %s", needReprocess ? "true" : "false"); |
| return needReprocess; |
| } |
| |
| |
| /*=========================================================================== |
| * FUNCTION : needRotationReprocess |
| * |
| * DESCRIPTION: if rotation needs to be done by reprocess in pp |
| * |
| * PARAMETERS : none |
| * |
| * RETURN : true: needed |
| * false: no need |
| *==========================================================================*/ |
| bool QCamera2HardwareInterface::needRotationReprocess() |
| { |
| if (!mParameters.isJpegPictureFormat() && |
| !mParameters.isNV21PictureFormat()) { |
| // RAW image, no need to reprocess |
| return false; |
| } |
| |
| //Disable reprocess for 4K liveshot case |
| if (mParameters.is4k2kVideoResolution() && mParameters.getRecordingHintValue() |
| && !isLowPowerMode()) { |
| //Disable reprocess for 4K liveshot case |
| return false; |
| } |
| |
| if ((gCamCapability[mCameraId]->qcom_supported_feature_mask & |
| CAM_QCOM_FEATURE_ROTATION) > 0 && |
| (mParameters.getJpegRotation() > 0)) { |
| // current rotation is not zero, and pp has the capability to process rotation |
| LOGH("need to do reprocess for rotation=%d", |
| mParameters.getJpegRotation()); |
| return true; |
| } |
| |
| return false; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : getThumbnailSize |
| * |
| * DESCRIPTION: get user set thumbnail size |
| * |
| * PARAMETERS : |
| * @dim : output of thumbnail dimension |
| * |
| * RETURN : none |
| *==========================================================================*/ |
| void QCamera2HardwareInterface::getThumbnailSize(cam_dimension_t &dim) |
| { |
| mParameters.getThumbnailSize(&dim.width, &dim.height); |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : getJpegQuality |
| * |
| * DESCRIPTION: get user set jpeg quality |
| * |
| * PARAMETERS : none |
| * |
| * RETURN : jpeg quality setting |
| *==========================================================================*/ |
| uint32_t QCamera2HardwareInterface::getJpegQuality() |
| { |
| uint32_t quality = 0; |
| quality = mParameters.getJpegQuality(); |
| return quality; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : getExifData |
| * |
| * DESCRIPTION: get exif data to be passed into jpeg encoding |
| * |
| * PARAMETERS : none |
| * |
| * RETURN : exif data from user setting and GPS |
| *==========================================================================*/ |
| QCameraExif *QCamera2HardwareInterface::getExifData() |
| { |
| QCameraExif *exif = new QCameraExif(); |
| if (exif == NULL) { |
| LOGE("No memory for QCameraExif"); |
| return NULL; |
| } |
| |
| int32_t rc = NO_ERROR; |
| |
| // add exif entries |
| String8 dateTime, subSecTime; |
| rc = mParameters.getExifDateTime(dateTime, subSecTime); |
| if(rc == NO_ERROR) { |
| exif->addEntry(EXIFTAGID_DATE_TIME, EXIF_ASCII, |
| (uint32_t)(dateTime.length() + 1), (void *)dateTime.string()); |
| exif->addEntry(EXIFTAGID_EXIF_DATE_TIME_ORIGINAL, EXIF_ASCII, |
| (uint32_t)(dateTime.length() + 1), (void *)dateTime.string()); |
| exif->addEntry(EXIFTAGID_EXIF_DATE_TIME_DIGITIZED, EXIF_ASCII, |
| (uint32_t)(dateTime.length() + 1), (void *)dateTime.string()); |
| exif->addEntry(EXIFTAGID_SUBSEC_TIME, EXIF_ASCII, |
| (uint32_t)(subSecTime.length() + 1), (void *)subSecTime.string()); |
| exif->addEntry(EXIFTAGID_SUBSEC_TIME_ORIGINAL, EXIF_ASCII, |
| (uint32_t)(subSecTime.length() + 1), (void *)subSecTime.string()); |
| exif->addEntry(EXIFTAGID_SUBSEC_TIME_DIGITIZED, EXIF_ASCII, |
| (uint32_t)(subSecTime.length() + 1), (void *)subSecTime.string()); |
| } else { |
| LOGW("getExifDateTime failed"); |
| } |
| |
| rat_t focalLength; |
| rc = mParameters.getExifFocalLength(&focalLength); |
| if (rc == NO_ERROR) { |
| exif->addEntry(EXIFTAGID_FOCAL_LENGTH, |
| EXIF_RATIONAL, |
| 1, |
| (void *)&(focalLength)); |
| } else { |
| LOGW("getExifFocalLength failed"); |
| } |
| |
| uint16_t isoSpeed = mParameters.getExifIsoSpeed(); |
| if (getSensorType() != CAM_SENSOR_YUV) { |
| exif->addEntry(EXIFTAGID_ISO_SPEED_RATING, |
| EXIF_SHORT, |
| 1, |
| (void *)&(isoSpeed)); |
| } |
| |
| char gpsProcessingMethod[EXIF_ASCII_PREFIX_SIZE + GPS_PROCESSING_METHOD_SIZE]; |
| uint32_t count = 0; |
| |
| /*gps data might not be available */ |
| rc = mParameters.getExifGpsProcessingMethod(gpsProcessingMethod, count); |
| if(rc == NO_ERROR) { |
| exif->addEntry(EXIFTAGID_GPS_PROCESSINGMETHOD, |
| EXIF_ASCII, |
| count, |
| (void *)gpsProcessingMethod); |
| } else { |
| LOGW("getExifGpsProcessingMethod failed"); |
| } |
| |
| rat_t latitude[3]; |
| char latRef[2]; |
| rc = mParameters.getExifLatitude(latitude, latRef); |
| if(rc == NO_ERROR) { |
| exif->addEntry(EXIFTAGID_GPS_LATITUDE, |
| EXIF_RATIONAL, |
| 3, |
| (void *)latitude); |
| exif->addEntry(EXIFTAGID_GPS_LATITUDE_REF, |
| EXIF_ASCII, |
| 2, |
| (void *)latRef); |
| } else { |
| LOGW("getExifLatitude failed"); |
| } |
| |
| rat_t longitude[3]; |
| char lonRef[2]; |
| rc = mParameters.getExifLongitude(longitude, lonRef); |
| if(rc == NO_ERROR) { |
| exif->addEntry(EXIFTAGID_GPS_LONGITUDE, |
| EXIF_RATIONAL, |
| 3, |
| (void *)longitude); |
| |
| exif->addEntry(EXIFTAGID_GPS_LONGITUDE_REF, |
| EXIF_ASCII, |
| 2, |
| (void *)lonRef); |
| } else { |
| LOGW("getExifLongitude failed"); |
| } |
| |
| rat_t altitude; |
| char altRef; |
| rc = mParameters.getExifAltitude(&altitude, &altRef); |
| if(rc == NO_ERROR) { |
| exif->addEntry(EXIFTAGID_GPS_ALTITUDE, |
| EXIF_RATIONAL, |
| 1, |
| (void *)&(altitude)); |
| |
| exif->addEntry(EXIFTAGID_GPS_ALTITUDE_REF, |
| EXIF_BYTE, |
| 1, |
| (void *)&altRef); |
| } else { |
| LOGW("getExifAltitude failed"); |
| } |
| |
| char gpsDateStamp[20]; |
| rat_t gpsTimeStamp[3]; |
| rc = mParameters.getExifGpsDateTimeStamp(gpsDateStamp, 20, gpsTimeStamp); |
| if(rc == NO_ERROR) { |
| exif->addEntry(EXIFTAGID_GPS_DATESTAMP, |
| EXIF_ASCII, |
| (uint32_t)(strlen(gpsDateStamp) + 1), |
| (void *)gpsDateStamp); |
| |
| exif->addEntry(EXIFTAGID_GPS_TIMESTAMP, |
| EXIF_RATIONAL, |
| 3, |
| (void *)gpsTimeStamp); |
| } else { |
| LOGW("getExifGpsDataTimeStamp failed"); |
| } |
| |
| #ifdef ENABLE_MODEL_INFO_EXIF |
| |
| char value[PROPERTY_VALUE_MAX]; |
| if (property_get("persist.sys.exif.make", value, "") > 0 || |
| property_get("ro.product.manufacturer", value, "QCOM-AA") > 0) { |
| exif->addEntry(EXIFTAGID_MAKE, |
| EXIF_ASCII, strlen(value) + 1, (void *)value); |
| } else { |
| LOGW("getExifMaker failed"); |
| } |
| |
| if (property_get("persist.sys.exif.model", value, "") > 0 || |
| property_get("ro.product.model", value, "QCAM-AA") > 0) { |
| exif->addEntry(EXIFTAGID_MODEL, |
| EXIF_ASCII, strlen(value) + 1, (void *)value); |
| } else { |
| LOGW("getExifModel failed"); |
| } |
| |
| if (property_get("ro.build.description", value, "QCAM-AA") > 0) { |
| exif->addEntry(EXIFTAGID_SOFTWARE, EXIF_ASCII, |
| (uint32_t)(strlen(value) + 1), (void *)value); |
| } else { |
| LOGW("getExifSoftware failed"); |
| } |
| |
| #endif |
| |
| if (mParameters.useJpegExifRotation()) { |
| int16_t orientation; |
| switch (mParameters.getJpegExifRotation()) { |
| case 0: |
| orientation = 1; |
| break; |
| case 90: |
| orientation = 6; |
| break; |
| case 180: |
| orientation = 3; |
| break; |
| case 270: |
| orientation = 8; |
| break; |
| default: |
| orientation = 1; |
| break; |
| } |
| exif->addEntry(EXIFTAGID_ORIENTATION, |
| EXIF_SHORT, |
| 1, |
| (void *)&orientation); |
| exif->addEntry(EXIFTAGID_TN_ORIENTATION, |
| EXIF_SHORT, |
| 1, |
| (void *)&orientation); |
| } |
| |
| return exif; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : setHistogram |
| * |
| * DESCRIPTION: set if histogram should be enabled |
| * |
| * PARAMETERS : |
| * @histogram_en : bool flag if histogram should be enabled |
| * |
| * RETURN : int32_t type of status |
| * NO_ERROR -- success |
| * none-zero failure code |
| *==========================================================================*/ |
| int32_t QCamera2HardwareInterface::setHistogram(bool histogram_en) |
| { |
| return mParameters.setHistogram(histogram_en); |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : setFaceDetection |
| * |
| * DESCRIPTION: set if face detection should be enabled |
| * |
| * PARAMETERS : |
| * @enabled : bool flag if face detection should be enabled |
| * |
| * RETURN : int32_t type of status |
| * NO_ERROR -- success |
| * none-zero failure code |
| *==========================================================================*/ |
| int32_t QCamera2HardwareInterface::setFaceDetection(bool enabled) |
| { |
| return mParameters.setFaceDetection(enabled, true); |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : isCaptureShutterEnabled |
| * |
| * DESCRIPTION: Check whether shutter should be triggered immediately after |
| * capture |
| * |
| * PARAMETERS : |
| * |
| * RETURN : true - regular capture |
| * false - other type of capture |
| *==========================================================================*/ |
| bool QCamera2HardwareInterface::isCaptureShutterEnabled() |
| { |
| char prop[PROPERTY_VALUE_MAX]; |
| memset(prop, 0, sizeof(prop)); |
| property_get("persist.camera.feature.shutter", prop, "0"); |
| int enableShutter = atoi(prop); |
| return enableShutter == 1; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : needProcessPreviewFrame |
| * |
| * DESCRIPTION: returns whether preview frame need to be displayed |
| * |
| * PARAMETERS : |
| * @frameID : frameID of frame to be processed |
| * |
| * RETURN : int32_t type of status |
| * NO_ERROR -- success |
| * none-zero failure code |
| *==========================================================================*/ |
| bool QCamera2HardwareInterface::needProcessPreviewFrame(uint32_t frameID) |
| { |
| return (((m_stateMachine.isPreviewRunning()) && |
| (!isDisplayFrameToSkip(frameID)) && |
| (!mParameters.isInstantAECEnabled())) || |
| (isPreviewRestartEnabled())); |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : needSendPreviewCallback |
| * |
| * DESCRIPTION: returns whether preview frame need to callback to APP |
| * |
| * PARAMETERS : |
| * |
| * RETURN : true - need preview frame callbck |
| * false - not send preview frame callback |
| *==========================================================================*/ |
| bool QCamera2HardwareInterface::needSendPreviewCallback() |
| { |
| return m_stateMachine.isPreviewRunning() |
| && (mDataCb != NULL) |
| && (msgTypeEnabledWithLock(CAMERA_MSG_PREVIEW_FRAME) > 0) |
| && m_stateMachine.isPreviewCallbackNeeded(); |
| }; |
| |
| /*=========================================================================== |
| * FUNCTION : setDisplaySkip |
| * |
| * DESCRIPTION: set range of frames to skip for preview |
| * |
| * PARAMETERS : |
| * @enabled : TRUE to start skipping frame to display |
| FALSE to stop skipping frame to display |
| * @skipCnt : Number of frame to skip. 0 by default |
| * |
| * RETURN : None |
| *==========================================================================*/ |
| void QCamera2HardwareInterface::setDisplaySkip(bool enabled, uint8_t skipCnt) |
| { |
| pthread_mutex_lock(&mGrallocLock); |
| if (enabled) { |
| setDisplayFrameSkip(); |
| setDisplayFrameSkip(mLastPreviewFrameID + skipCnt + 1); |
| } else { |
| setDisplayFrameSkip(mFrameSkipStart, (mLastPreviewFrameID + skipCnt + 1)); |
| } |
| pthread_mutex_unlock(&mGrallocLock); |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : setDisplayFrameSkip |
| * |
| * DESCRIPTION: set range of frames to skip for preview |
| * |
| * PARAMETERS : |
| * @start : frameId to start skip |
| * @end : frameId to stop skip |
| * |
| * RETURN : None |
| *==========================================================================*/ |
| void QCamera2HardwareInterface::setDisplayFrameSkip(uint32_t start, |
| uint32_t end) |
| { |
| if (start == 0) { |
| mFrameSkipStart = 0; |
| mFrameSkipEnd = 0; |
| return; |
| } |
| if ((mFrameSkipStart == 0) || (mFrameSkipStart > start)) { |
| mFrameSkipStart = start; |
| } |
| if ((end == 0) || (end > mFrameSkipEnd)) { |
| mFrameSkipEnd = end; |
| } |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : isDisplayFrameToSkip |
| * |
| * DESCRIPTION: function to determin if input frame falls under skip range |
| * |
| * PARAMETERS : |
| * @frameId : frameId to verify |
| * |
| * RETURN : true : need to skip |
| * false: no need to skip |
| *==========================================================================*/ |
| bool QCamera2HardwareInterface::isDisplayFrameToSkip(uint32_t frameId) |
| { |
| return ((mFrameSkipStart != 0) && (frameId >= mFrameSkipStart) && |
| (frameId <= mFrameSkipEnd || mFrameSkipEnd == 0)) ? TRUE : FALSE; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : prepareHardwareForSnapshot |
| * |
| * DESCRIPTION: prepare hardware for snapshot, such as LED |
| * |
| * PARAMETERS : |
| * @afNeeded: flag indicating if Auto Focus needs to be done during preparation |
| * |
| * RETURN : int32_t type of status |
| * NO_ERROR -- success |
| * none-zero failure code |
| *==========================================================================*/ |
| int32_t QCamera2HardwareInterface::prepareHardwareForSnapshot(int32_t afNeeded) |
| { |
| ATRACE_CALL(); |
| LOGI("[KPI Perf]: Send PREPARE SANSPHOT event"); |
| return mCameraHandle->ops->prepare_snapshot(mCameraHandle->camera_handle, |
| afNeeded); |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : needFDMetadata |
| * |
| * DESCRIPTION: check whether we need process Face Detection metadata in this chanel |
| * |
| * PARAMETERS : |
| * @channel_type: channel type |
| * |
| * RETURN : true: needed |
| * false: no need |
| *==========================================================================*/ |
| bool QCamera2HardwareInterface::needFDMetadata(qcamera_ch_type_enum_t channel_type) |
| { |
| //Note: Currently we only process ZSL channel |
| bool value = false; |
| if(channel_type == QCAMERA_CH_TYPE_ZSL){ |
| //check if FD requirement is enabled |
| if(mParameters.isSnapshotFDNeeded() && |
| mParameters.isFaceDetectionEnabled()){ |
| value = true; |
| LOGH("Face Detection metadata is required in ZSL mode."); |
| } |
| } |
| |
| return value; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : deferredWorkRoutine |
| * |
| * DESCRIPTION: data process routine that executes deferred tasks |
| * |
| * PARAMETERS : |
| * @data : user data ptr (QCamera2HardwareInterface) |
| * |
| * RETURN : None |
| *==========================================================================*/ |
| void *QCamera2HardwareInterface::deferredWorkRoutine(void *obj) |
| { |
| int running = 1; |
| int ret; |
| uint8_t is_active = FALSE; |
| int32_t job_status = 0; |
| |
| QCamera2HardwareInterface *pme = (QCamera2HardwareInterface *)obj; |
| QCameraCmdThread *cmdThread = &pme->mDeferredWorkThread; |
| cmdThread->setName("CAM_defrdWrk"); |
| |
| do { |
| do { |
| ret = cam_sem_wait(&cmdThread->cmd_sem); |
| if (ret != 0 && errno != EINVAL) { |
| LOGE("cam_sem_wait error (%s)", |
| strerror(errno)); |
| return NULL; |
| } |
| } while (ret != 0); |
| |
| // we got notified about new cmd avail in cmd queue |
| camera_cmd_type_t cmd = cmdThread->getCmd(); |
| LOGD("cmd: %d", cmd); |
| switch (cmd) { |
| case CAMERA_CMD_TYPE_START_DATA_PROC: |
| LOGH("start data proc"); |
| is_active = TRUE; |
| break; |
| case CAMERA_CMD_TYPE_STOP_DATA_PROC: |
| LOGH("stop data proc"); |
| is_active = FALSE; |
| // signal cmd is completed |
| cam_sem_post(&cmdThread->sync_sem); |
| break; |
| case CAMERA_CMD_TYPE_DO_NEXT_JOB: |
| { |
| DefWork *dw = |
| reinterpret_cast<DefWork *>(pme->mCmdQueue.dequeue()); |
| |
| if ( NULL == dw ) { |
| LOGE("Invalid deferred work"); |
| break; |
| } |
| |
| switch( dw->cmd ) { |
| case CMD_DEF_ALLOCATE_BUFF: |
| { |
| QCameraChannel * pChannel = dw->args.allocArgs.ch; |
| |
| if ( NULL == pChannel ) { |
| LOGE("Invalid deferred work channel"); |
| job_status = BAD_VALUE; |
| break; |
| } |
| |
| cam_stream_type_t streamType = dw->args.allocArgs.type; |
| LOGH("Deferred buffer allocation started for stream type: %d", |
| streamType); |
| |
| uint32_t iNumOfStreams = pChannel->getNumOfStreams(); |
| QCameraStream *pStream = NULL; |
| for ( uint32_t i = 0; i < iNumOfStreams; ++i) { |
| pStream = pChannel->getStreamByIndex(i); |
| |
| if ( NULL == pStream ) { |
| job_status = BAD_VALUE; |
| break; |
| } |
| |
| if ( pStream->isTypeOf(streamType)) { |
| if ( pStream->allocateBuffers() ) { |
| LOGE("Error allocating buffers !!!"); |
| job_status = NO_MEMORY; |
| pme->sendEvtNotify(CAMERA_MSG_ERROR, |
| CAMERA_ERROR_UNKNOWN, 0); |
| } |
| break; |
| } |
| } |
| } |
| break; |
| case CMD_DEF_PPROC_START: |
| { |
| int32_t ret = pme->getDefJobStatus(pme->mInitPProcJob); |
| if (ret != NO_ERROR) { |
| job_status = ret; |
| LOGE("PPROC Start failed"); |
| pme->sendEvtNotify(CAMERA_MSG_ERROR, |
| CAMERA_ERROR_UNKNOWN, 0); |
| break; |
| } |
| QCameraChannel * pChannel = dw->args.pprocArgs; |
| assert(pChannel); |
| |
| if (pme->m_postprocessor.start(pChannel) != NO_ERROR) { |
| LOGE("cannot start postprocessor"); |
| job_status = BAD_VALUE; |
| pme->sendEvtNotify(CAMERA_MSG_ERROR, |
| CAMERA_ERROR_UNKNOWN, 0); |
| } |
| } |
| break; |
| case CMD_DEF_METADATA_ALLOC: |
| { |
| int32_t ret = pme->getDefJobStatus(pme->mParamAllocJob); |
| if (ret != NO_ERROR) { |
| job_status = ret; |
| LOGE("Metadata alloc failed"); |
| pme->sendEvtNotify(CAMERA_MSG_ERROR, |
| CAMERA_ERROR_UNKNOWN, 0); |
| break; |
| } |
| pme->mMetadataMem = new QCameraMetadataStreamMemory( |
| QCAMERA_ION_USE_CACHE); |
| |
| if (pme->mMetadataMem == NULL) { |
| LOGE("Unable to allocate metadata buffers"); |
| job_status = BAD_VALUE; |
| pme->sendEvtNotify(CAMERA_MSG_ERROR, |
| CAMERA_ERROR_UNKNOWN, 0); |
| } else { |
| int32_t rc = pme->mMetadataMem->allocate( |
| dw->args.metadataAllocArgs.bufferCnt, |
| dw->args.metadataAllocArgs.size, |
| NON_SECURE); |
| if (rc < 0) { |
| delete pme->mMetadataMem; |
| pme->mMetadataMem = NULL; |
| } |
| } |
| } |
| break; |
| case CMD_DEF_CREATE_JPEG_SESSION: |
| { |
| QCameraChannel * pChannel = dw->args.pprocArgs; |
| assert(pChannel); |
| |
| int32_t ret = pme->getDefJobStatus(pme->mReprocJob); |
| if (ret != NO_ERROR) { |
| job_status = ret; |
| LOGE("Jpeg create failed"); |
| break; |
| } |
| |
| if (pme->m_postprocessor.createJpegSession(pChannel) |
| != NO_ERROR) { |
| LOGE("cannot create JPEG session"); |
| job_status = UNKNOWN_ERROR; |
| pme->sendEvtNotify(CAMERA_MSG_ERROR, |
| CAMERA_ERROR_UNKNOWN, 0); |
| } |
| } |
| break; |
| case CMD_DEF_PPROC_INIT: |
| { |
| int32_t rc = NO_ERROR; |
| |
| jpeg_encode_callback_t jpegEvtHandle = |
| dw->args.pprocInitArgs.jpeg_cb; |
| void* user_data = dw->args.pprocInitArgs.user_data; |
| QCameraPostProcessor *postProcessor = |
| &(pme->m_postprocessor); |
| uint32_t cameraId = pme->mCameraId; |
| cam_capability_t *capability = |
| gCamCapability[cameraId]; |
| cam_padding_info_t padding_info; |
| cam_padding_info_t& cam_capability_padding_info = |
| capability->padding_info; |
| |
| if(!pme->mJpegClientHandle) { |
| rc = pme->initJpegHandle(); |
| if (rc != NO_ERROR) { |
| LOGE("Error!! creating JPEG handle failed"); |
| job_status = UNKNOWN_ERROR; |
| pme->sendEvtNotify(CAMERA_MSG_ERROR, |
| CAMERA_ERROR_UNKNOWN, 0); |
| break; |
| } |
| } |
| LOGH("mJpegClientHandle : %d", pme->mJpegClientHandle); |
| |
| rc = postProcessor->setJpegHandle(&pme->mJpegHandle, |
| &pme->mJpegMpoHandle, |
| pme->mJpegClientHandle); |
| if (rc != 0) { |
| LOGE("Error!! set JPEG handle failed"); |
| job_status = UNKNOWN_ERROR; |
| pme->sendEvtNotify(CAMERA_MSG_ERROR, |
| CAMERA_ERROR_UNKNOWN, 0); |
| break; |
| } |
| |
| /* get max pic size for jpeg work buf calculation*/ |
| rc = postProcessor->init(jpegEvtHandle, user_data); |
| |
| if (rc != NO_ERROR) { |
| LOGE("cannot init postprocessor"); |
| job_status = UNKNOWN_ERROR; |
| pme->sendEvtNotify(CAMERA_MSG_ERROR, |
| CAMERA_ERROR_UNKNOWN, 0); |
| break; |
| } |
| |
| // update padding info from jpeg |
| postProcessor->getJpegPaddingReq(padding_info); |
| if (cam_capability_padding_info.width_padding < |
| padding_info.width_padding) { |
| cam_capability_padding_info.width_padding = |
| padding_info.width_padding; |
| } |
| if (cam_capability_padding_info.height_padding < |
| padding_info.height_padding) { |
| cam_capability_padding_info.height_padding = |
| padding_info.height_padding; |
| } |
| if (cam_capability_padding_info.plane_padding != |
| padding_info.plane_padding) { |
| cam_capability_padding_info.plane_padding = |
| mm_stream_calc_lcm( |
| cam_capability_padding_info.plane_padding, |
| padding_info.plane_padding); |
| } |
| if (cam_capability_padding_info.offset_info.offset_x |
| != padding_info.offset_info.offset_x) { |
| cam_capability_padding_info.offset_info.offset_x = |
| mm_stream_calc_lcm ( |
| cam_capability_padding_info.offset_info.offset_x, |
| padding_info.offset_info.offset_x); |
| } |
| if (cam_capability_padding_info.offset_info.offset_y |
| != padding_info.offset_info.offset_y) { |
| cam_capability_padding_info.offset_info.offset_y = |
| mm_stream_calc_lcm ( |
| cam_capability_padding_info.offset_info.offset_y, |
| padding_info.offset_info.offset_y); |
| } |
| } |
| break; |
| case CMD_DEF_PARAM_ALLOC: |
| { |
| int32_t rc = NO_ERROR; |
| if (pme->isDualCamera()) { |
| rc = pme->mParameters.allocate(MM_CAMERA_MAX_CAM_CNT); |
| } else { |
| rc = pme->mParameters.allocate(); |
| } |
| // notify routine would not be initialized by this time. |
| // So, just update error job status |
| if (rc != NO_ERROR) { |
| job_status = rc; |
| LOGE("Param allocation failed"); |
| break; |
| } |
| } |
| break; |
| case CMD_DEF_PARAM_INIT: |
| { |
| int32_t rc = pme->getDefJobStatus(pme->mParamAllocJob); |
| if (rc != NO_ERROR) { |
| job_status = rc; |
| LOGE("Param init failed"); |
| pme->sendEvtNotify(CAMERA_MSG_ERROR, |
| CAMERA_ERROR_UNKNOWN, 0); |
| break; |
| } |
| |
| uint32_t camId = pme->mCameraId; |
| cam_capability_t * cap = gCamCapability[camId]; |
| |
| if (pme->mCameraHandle == NULL) { |
| LOGE("Camera handle is null"); |
| job_status = BAD_VALUE; |
| pme->sendEvtNotify(CAMERA_MSG_ERROR, |
| CAMERA_ERROR_UNKNOWN, 0); |
| break; |
| } |
| |
| // Now PostProc need calibration data as initialization |
| // time for jpeg_open and calibration data is a |
| // get param for now, so params needs to be initialized |
| // before postproc init |
| rc = pme->mParameters.init(cap, |
| pme->mCameraHandle, |
| pme); |
| if (rc != 0) { |
| job_status = UNKNOWN_ERROR; |
| LOGE("Parameter Initialization failed"); |
| pme->sendEvtNotify(CAMERA_MSG_ERROR, |
| CAMERA_ERROR_UNKNOWN, 0); |
| break; |
| } |
| |
| // Get related cam calibration only in |
| // dual camera mode |
| if (pme->getRelatedCamSyncInfo()->sync_control == |
| CAM_SYNC_RELATED_SENSORS_ON) { |
| rc = pme->mParameters.getRelatedCamCalibration( |
| &(pme->mJpegMetadata.otp_calibration_data)); |
| LOGD("Dumping Calibration Data Version Id %f rc %d", |
| pme->mJpegMetadata.otp_calibration_data.calibration_format_version, |
| rc); |
| if (rc != 0) { |
| job_status = UNKNOWN_ERROR; |
| LOGE("getRelatedCamCalibration failed"); |
| pme->sendEvtNotify(CAMERA_MSG_ERROR, |
| CAMERA_ERROR_UNKNOWN, 0); |
| break; |
| } |
| pme->m_bRelCamCalibValid = true; |
| } |
| |
| pme->mJpegMetadata.sensor_mount_angle = |
| cap->sensor_mount_angle; |
| pme->mJpegMetadata.default_sensor_flip = FLIP_NONE; |
| |
| pme->mParameters.setMinPpMask( |
| cap->qcom_supported_feature_mask); |
| pme->mExifParams.debug_params = |
| (mm_jpeg_debug_exif_params_t *) |
| malloc(sizeof(mm_jpeg_debug_exif_params_t)); |
| if (!pme->mExifParams.debug_params) { |
| LOGE("Out of Memory. Allocation failed for " |
| "3A debug exif params"); |
| job_status = NO_MEMORY; |
| pme->sendEvtNotify(CAMERA_MSG_ERROR, |
| CAMERA_ERROR_UNKNOWN, 0); |
| break; |
| } |
| memset(pme->mExifParams.debug_params, 0, |
| sizeof(mm_jpeg_debug_exif_params_t)); |
| } |
| break; |
| case CMD_DEF_GENERIC: |
| { |
| BackgroundTask *bgTask = dw->args.genericArgs; |
| job_status = bgTask->bgFunction(bgTask->bgArgs); |
| } |
| break; |
| default: |
| LOGE("Incorrect command : %d", dw->cmd); |
| } |
| |
| pme->dequeueDeferredWork(dw, job_status); |
| } |
| break; |
| case CAMERA_CMD_TYPE_EXIT: |
| running = 0; |
| break; |
| default: |
| break; |
| } |
| } while (running); |
| |
| return NULL; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : queueDeferredWork |
| * |
| * DESCRIPTION: function which queues deferred tasks |
| * |
| * PARAMETERS : |
| * @cmd : deferred task |
| * @args : deferred task arguments |
| * |
| * RETURN : job id of deferred job |
| * : 0 in case of error |
| *==========================================================================*/ |
| uint32_t QCamera2HardwareInterface::queueDeferredWork(DeferredWorkCmd cmd, |
| DeferWorkArgs args) |
| { |
| Mutex::Autolock l(mDefLock); |
| for (int32_t i = 0; i < MAX_ONGOING_JOBS; ++i) { |
| if (mDefOngoingJobs[i].mDefJobId == 0) { |
| DefWork *dw = new DefWork(cmd, sNextJobId, args); |
| if (!dw) { |
| LOGE("out of memory."); |
| return 0; |
| } |
| if (mCmdQueue.enqueue(dw)) { |
| mDefOngoingJobs[i].mDefJobId = sNextJobId++; |
| mDefOngoingJobs[i].mDefJobStatus = 0; |
| if (sNextJobId == 0) { // handle overflow |
| sNextJobId = 1; |
| } |
| mDeferredWorkThread.sendCmd(CAMERA_CMD_TYPE_DO_NEXT_JOB, |
| FALSE, |
| FALSE); |
| return mDefOngoingJobs[i].mDefJobId; |
| } else { |
| LOGD("Command queue not active! cmd = %d", cmd); |
| delete dw; |
| return 0; |
| } |
| } |
| } |
| return 0; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : initJpegHandle |
| * |
| * DESCRIPTION: Opens JPEG client and gets a handle. |
| * Sends Dual cam calibration info if present |
| * |
| * RETURN : int32_t type of status |
| * NO_ERROR -- success |
| * none-zero failure code |
| *==========================================================================*/ |
| int32_t QCamera2HardwareInterface::initJpegHandle() { |
| // Check if JPEG client handle is present |
| LOGH("E"); |
| if(!mJpegClientHandle) { |
| mm_dimension max_size = {0, 0}; |
| cam_dimension_t size; |
| |
| mParameters.getMaxPicSize(size); |
| max_size.w = size.width; |
| max_size.h = size.height; |
| |
| if (getRelatedCamSyncInfo()->sync_control == CAM_SYNC_RELATED_SENSORS_ON) { |
| if (m_bRelCamCalibValid) { |
| mJpegClientHandle = jpeg_open(&mJpegHandle, &mJpegMpoHandle, |
| max_size, &mJpegMetadata); |
| } else { |
| mJpegClientHandle = jpeg_open(&mJpegHandle, &mJpegMpoHandle, |
| max_size, NULL); |
| } |
| } else { |
| mJpegClientHandle = jpeg_open(&mJpegHandle, NULL, max_size, NULL); |
| } |
| if (!mJpegClientHandle) { |
| LOGE("Error !! jpeg_open failed!! "); |
| return UNKNOWN_ERROR; |
| } |
| // Set JPEG initialized as true to signify that this camera |
| // has initialized the handle |
| mJpegHandleOwner = true; |
| } |
| LOGH("X mJpegHandleOwner: %d, mJpegClientHandle: %d camera id: %d", |
| mJpegHandleOwner, mJpegClientHandle, mCameraId); |
| return NO_ERROR; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : deinitJpegHandle |
| * |
| * DESCRIPTION: Closes JPEG client using handle |
| * |
| * RETURN : int32_t type of status |
| * NO_ERROR -- success |
| * none-zero failure code |
| *==========================================================================*/ |
| int32_t QCamera2HardwareInterface::deinitJpegHandle() { |
| int32_t rc = NO_ERROR; |
| LOGH("E"); |
| // Check if JPEG client handle is present and inited by this camera |
| if(mJpegHandleOwner && mJpegClientHandle) { |
| rc = mJpegHandle.close(mJpegClientHandle); |
| if (rc != NO_ERROR) { |
| LOGE("Error!! Closing mJpegClientHandle: %d failed", |
| mJpegClientHandle); |
| } |
| memset(&mJpegHandle, 0, sizeof(mJpegHandle)); |
| memset(&mJpegMpoHandle, 0, sizeof(mJpegMpoHandle)); |
| mJpegHandleOwner = false; |
| } |
| mJpegClientHandle = 0; |
| LOGH("X rc = %d", rc); |
| return rc; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : setJpegHandleInfo |
| * |
| * DESCRIPTION: sets JPEG client handle info |
| * |
| * PARAMETERS: |
| * @ops : JPEG ops |
| * @mpo_ops : Jpeg MPO ops |
| * @pJpegClientHandle : o/p Jpeg Client Handle |
| * |
| * RETURN : int32_t type of status |
| * NO_ERROR -- success |
| * none-zero failure code |
| *==========================================================================*/ |
| int32_t QCamera2HardwareInterface::setJpegHandleInfo(mm_jpeg_ops_t *ops, |
| mm_jpeg_mpo_ops_t *mpo_ops, uint32_t pJpegClientHandle) { |
| |
| if (pJpegClientHandle && ops && mpo_ops) { |
| LOGH("Setting JPEG client handle %d", |
| pJpegClientHandle); |
| memcpy(&mJpegHandle, ops, sizeof(mm_jpeg_ops_t)); |
| memcpy(&mJpegMpoHandle, mpo_ops, sizeof(mm_jpeg_mpo_ops_t)); |
| mJpegClientHandle = pJpegClientHandle; |
| return NO_ERROR; |
| } |
| else { |
| LOGE("Error!! No Handle found: %d", |
| pJpegClientHandle); |
| return BAD_VALUE; |
| } |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : getJpegHandleInfo |
| * |
| * DESCRIPTION: gets JPEG client handle info |
| * |
| * PARAMETERS: |
| * @ops : JPEG ops |
| * @mpo_ops : Jpeg MPO ops |
| * @pJpegClientHandle : o/p Jpeg Client Handle |
| * |
| * RETURN : int32_t type of status |
| * NO_ERROR -- success |
| * none-zero failure code |
| *==========================================================================*/ |
| int32_t QCamera2HardwareInterface::getJpegHandleInfo(mm_jpeg_ops_t *ops, |
| mm_jpeg_mpo_ops_t *mpo_ops, uint32_t *pJpegClientHandle) { |
| |
| if (NO_ERROR != waitDeferredWork(mInitPProcJob)) { |
| LOGE("Init PProc Deferred work failed"); |
| return UNKNOWN_ERROR; |
| } |
| // Copy JPEG ops if present |
| if (ops && mpo_ops && pJpegClientHandle) { |
| memcpy(ops, &mJpegHandle, sizeof(mm_jpeg_ops_t)); |
| memcpy(mpo_ops, &mJpegMpoHandle, sizeof(mm_jpeg_mpo_ops_t)); |
| *pJpegClientHandle = mJpegClientHandle; |
| LOGH("Getting JPEG client handle %d", |
| pJpegClientHandle); |
| return NO_ERROR; |
| } else { |
| return BAD_VALUE; |
| } |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : dequeueDeferredWork |
| * |
| * DESCRIPTION: function which dequeues deferred tasks |
| * |
| * PARAMETERS : |
| * @dw : deferred work |
| * @jobStatus: deferred task job status |
| * |
| * RETURN : int32_t type of status |
| * NO_ERROR -- success |
| * none-zero failure code |
| *==========================================================================*/ |
| uint32_t QCamera2HardwareInterface::dequeueDeferredWork(DefWork* dw, int32_t jobStatus) |
| { |
| Mutex::Autolock l(mDefLock); |
| for (uint32_t i = 0; i < MAX_ONGOING_JOBS; i++) { |
| if (mDefOngoingJobs[i].mDefJobId == dw->id) { |
| if (jobStatus != NO_ERROR) { |
| mDefOngoingJobs[i].mDefJobStatus = jobStatus; |
| LOGH("updating job status %d for id %d", |
| jobStatus, dw->id); |
| } else { |
| mDefOngoingJobs[i].mDefJobId = 0; |
| mDefOngoingJobs[i].mDefJobStatus = 0; |
| } |
| delete dw; |
| mDefCond.broadcast(); |
| return NO_ERROR; |
| } |
| } |
| |
| return UNKNOWN_ERROR; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : getDefJobStatus |
| * |
| * DESCRIPTION: Gets if a deferred task is success/fail |
| * |
| * PARAMETERS : |
| * @job_id : deferred task id |
| * |
| * RETURN : NO_ERROR if the job success, otherwise false |
| * |
| * PRECONDITION : mDefLock is held by current thread |
| *==========================================================================*/ |
| int32_t QCamera2HardwareInterface::getDefJobStatus(uint32_t &job_id) |
| { |
| for (uint32_t i = 0; i < MAX_ONGOING_JOBS; i++) { |
| if (mDefOngoingJobs[i].mDefJobId == job_id) { |
| if ( NO_ERROR != mDefOngoingJobs[i].mDefJobStatus ) { |
| LOGE("job_id (%d) was failed", job_id); |
| return mDefOngoingJobs[i].mDefJobStatus; |
| } |
| else |
| return NO_ERROR; |
| } |
| } |
| return NO_ERROR; |
| } |
| |
| |
| /*=========================================================================== |
| * FUNCTION : checkDeferredWork |
| * |
| * DESCRIPTION: checks if a deferred task is in progress |
| * |
| * PARAMETERS : |
| * @job_id : deferred task id |
| * |
| * RETURN : true if the task exists, otherwise false |
| * |
| * PRECONDITION : mDefLock is held by current thread |
| *==========================================================================*/ |
| bool QCamera2HardwareInterface::checkDeferredWork(uint32_t &job_id) |
| { |
| for (uint32_t i = 0; i < MAX_ONGOING_JOBS; i++) { |
| if (mDefOngoingJobs[i].mDefJobId == job_id) { |
| return (NO_ERROR == mDefOngoingJobs[i].mDefJobStatus); |
| } |
| } |
| return false; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : waitDeferredWork |
| * |
| * DESCRIPTION: waits for a deferred task to finish |
| * |
| * PARAMETERS : |
| * @job_id : deferred task id |
| * |
| * RETURN : int32_t type of status |
| * NO_ERROR -- success |
| * none-zero failure code |
| *==========================================================================*/ |
| int32_t QCamera2HardwareInterface::waitDeferredWork(uint32_t &job_id) |
| { |
| Mutex::Autolock l(mDefLock); |
| |
| if (job_id == 0) { |
| LOGD("Invalid job id %d", job_id); |
| return NO_ERROR; |
| } |
| |
| while (checkDeferredWork(job_id) == true ) { |
| mDefCond.waitRelative(mDefLock, CAMERA_DEFERRED_THREAD_TIMEOUT); |
| } |
| return getDefJobStatus(job_id); |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : scheduleBackgroundTask |
| * |
| * DESCRIPTION: Run a requested task in the deferred thread |
| * |
| * PARAMETERS : |
| * @bgTask : Task to perform in the background |
| * |
| * RETURN : job id of deferred job |
| * : 0 in case of error |
| *==========================================================================*/ |
| uint32_t QCamera2HardwareInterface::scheduleBackgroundTask(BackgroundTask* bgTask) |
| { |
| DeferWorkArgs args; |
| memset(&args, 0, sizeof(DeferWorkArgs)); |
| args.genericArgs = bgTask; |
| |
| return queueDeferredWork(CMD_DEF_GENERIC, args); |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : waitForBackgroundTask |
| * |
| * DESCRIPTION: Wait for a background task to complete |
| * |
| * PARAMETERS : |
| * @taskId : Task id to wait for |
| * |
| * RETURN : int32_t type of status |
| * NO_ERROR -- success |
| * none-zero failure code |
| *==========================================================================*/ |
| int32_t QCamera2HardwareInterface::waitForBackgroundTask(uint32_t& taskId) |
| { |
| return waitDeferredWork(taskId); |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : needDeferedAllocation |
| * |
| * DESCRIPTION: Function to decide background task for streams |
| * |
| * PARAMETERS : |
| * @stream_type : stream type |
| * |
| * RETURN : true - if background task is needed |
| * false - if background task is NOT needed |
| *==========================================================================*/ |
| bool QCamera2HardwareInterface::needDeferred(cam_stream_type_t stream_type) |
| { |
| if ((stream_type == CAM_STREAM_TYPE_PREVIEW && mPreviewWindow == NULL) |
| || (stream_type == CAM_STREAM_TYPE_ANALYSIS)) { |
| return FALSE; |
| } |
| |
| if ((stream_type == CAM_STREAM_TYPE_RAW) |
| && (mParameters.getofflineRAW())) { |
| return FALSE; |
| } |
| |
| if ((stream_type == CAM_STREAM_TYPE_SNAPSHOT) |
| && (!mParameters.getRecordingHintValue())){ |
| return TRUE; |
| } |
| |
| if ((stream_type == CAM_STREAM_TYPE_PREVIEW) |
| || (stream_type == CAM_STREAM_TYPE_METADATA) |
| || (stream_type == CAM_STREAM_TYPE_RAW) |
| || (stream_type == CAM_STREAM_TYPE_POSTVIEW)) { |
| return TRUE; |
| } |
| |
| if (stream_type == CAM_STREAM_TYPE_VIDEO) { |
| return FALSE; |
| } |
| return FALSE; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : isRegularCapture |
| * |
| * DESCRIPTION: Check configuration for regular catpure |
| * |
| * PARAMETERS : |
| * |
| * RETURN : true - regular capture |
| * false - other type of capture |
| *==========================================================================*/ |
| bool QCamera2HardwareInterface::isRegularCapture() |
| { |
| bool ret = false; |
| |
| if (numOfSnapshotsExpected() == 1 && |
| !isLongshotEnabled() && |
| !mParameters.isHDREnabled() && |
| !mParameters.getRecordingHintValue() && |
| !isZSLMode() && (!mParameters.getofflineRAW()|| mParameters.getQuadraCfa())) { |
| ret = true; |
| } |
| return ret; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : needOfflineReprocessing |
| * |
| * DESCRIPTION: Check for offline reprocessing |
| * |
| * PARAMETERS : |
| * |
| * RETURN : true - regular capture |
| * false - other type of capture |
| *==========================================================================*/ |
| bool QCamera2HardwareInterface::needOfflineReprocessing() |
| { |
| bool ret = false; |
| if (isRegularCapture() |
| || isDualCamera()) { |
| ret = true; |
| } |
| return ret; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : getLogLevel |
| * |
| * DESCRIPTION: Reads the log level property into a variable |
| * |
| * PARAMETERS : |
| * None |
| * |
| * RETURN : |
| * None |
| *==========================================================================*/ |
| void QCamera2HardwareInterface::getLogLevel() |
| { |
| char prop[PROPERTY_VALUE_MAX]; |
| |
| property_get("persist.camera.kpi.debug", prop, "1"); |
| gKpiDebugLevel = atoi(prop); |
| return; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : getSensorType |
| * |
| * DESCRIPTION: Returns the type of sensor being used whether YUV or Bayer |
| * |
| * PARAMETERS : |
| * None |
| * |
| * RETURN : Type of sensor - bayer or YUV |
| * |
| *==========================================================================*/ |
| cam_sensor_t QCamera2HardwareInterface::getSensorType() |
| { |
| return gCamCapability[mCameraId]->sensor_type.sens_type; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : startRAWChannel |
| * |
| * DESCRIPTION: start RAW Channel |
| * |
| * PARAMETERS : |
| * @pChannel : Src channel to link this RAW channel. |
| * |
| * RETURN : int32_t type of status |
| * NO_ERROR -- success |
| * none-zero failure code |
| *==========================================================================*/ |
| int32_t QCamera2HardwareInterface::startRAWChannel(QCameraChannel *pMetaChannel) |
| { |
| int32_t rc = NO_ERROR; |
| QCameraChannel *pChannel = m_channels[QCAMERA_CH_TYPE_RAW]; |
| if ((NULL != pChannel) && (mParameters.getofflineRAW())) { |
| // Find and try to link a metadata stream from preview channel |
| QCameraStream *pMetaStream = NULL; |
| |
| if (pMetaChannel != NULL) { |
| uint32_t streamNum = pMetaChannel->getNumOfStreams(); |
| QCameraStream *pStream = NULL; |
| for (uint32_t i = 0 ; i < streamNum ; i++ ) { |
| pStream = pMetaChannel->getStreamByIndex(i); |
| if ((NULL != pStream) && |
| (CAM_STREAM_TYPE_METADATA == pStream->getMyType())) { |
| pMetaStream = pStream; |
| break; |
| } |
| } |
| |
| if (NULL != pMetaStream) { |
| rc = pChannel->linkStream(pMetaChannel, pMetaStream); |
| if (NO_ERROR != rc) { |
| LOGE("Metadata stream link failed %d", rc); |
| } |
| } |
| } |
| rc = pChannel->start(); |
| } |
| return rc; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : startRecording |
| * |
| * DESCRIPTION: start recording impl |
| * |
| * PARAMETERS : none |
| * |
| * RETURN : int32_t type of status |
| * NO_ERROR -- success |
| * none-zero failure code |
| *==========================================================================*/ |
| int32_t QCamera2HardwareInterface::stopRAWChannel() |
| { |
| int32_t rc = NO_ERROR; |
| rc = stopChannel(QCAMERA_CH_TYPE_RAW); |
| return rc; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : isLowPowerMode |
| * |
| * DESCRIPTION: Returns TRUE if low power mode settings are to be applied for video recording |
| * |
| * PARAMETERS : |
| * None |
| * |
| * RETURN : TRUE/FALSE |
| * |
| *==========================================================================*/ |
| bool QCamera2HardwareInterface::isLowPowerMode() |
| { |
| cam_dimension_t dim; |
| mParameters.getStreamDimension(CAM_STREAM_TYPE_VIDEO, dim); |
| |
| char prop[PROPERTY_VALUE_MAX]; |
| property_get("camera.lowpower.record.enable", prop, "0"); |
| int enable = atoi(prop); |
| |
| //Enable low power mode if : |
| //1. Video resolution is 2k (2048x1080) or above and |
| //2. camera.lowpower.record.enable is set |
| |
| bool isLowpower = mParameters.getRecordingHintValue() && enable |
| && ((dim.width * dim.height) >= (2048 * 1080)); |
| return isLowpower; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : getBootToMonoTimeOffset |
| * |
| * DESCRIPTION: Calculate offset that is used to convert from |
| * clock domain of boot to monotonic |
| * |
| * PARAMETERS : |
| * None |
| * |
| * RETURN : clock offset between boottime and monotonic time. |
| * |
| *==========================================================================*/ |
| nsecs_t QCamera2HardwareInterface::getBootToMonoTimeOffset() |
| { |
| // try three times to get the clock offset, choose the one |
| // with the minimum gap in measurements. |
| const int tries = 3; |
| nsecs_t bestGap, measured; |
| for (int i = 0; i < tries; ++i) { |
| const nsecs_t tmono = systemTime(SYSTEM_TIME_MONOTONIC); |
| const nsecs_t tbase = systemTime(SYSTEM_TIME_BOOTTIME); |
| const nsecs_t tmono2 = systemTime(SYSTEM_TIME_MONOTONIC); |
| const nsecs_t gap = tmono2 - tmono; |
| if (i == 0 || gap < bestGap) { |
| bestGap = gap; |
| measured = tbase - ((tmono + tmono2) >> 1); |
| } |
| } |
| return measured; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : fillDualCameraFOVControl |
| * |
| * DESCRIPTION: Function to process FOV ctrl event from statemachine thread. |
| * |
| * PARAMETERS : none |
| * |
| * RETURN : none |
| *==========================================================================*/ |
| void QCamera2HardwareInterface::fillDualCameraFOVControl() |
| { |
| qcamera_sm_internal_evt_payload_t *payload = |
| (qcamera_sm_internal_evt_payload_t *) |
| malloc(sizeof(qcamera_sm_internal_evt_payload_t)); |
| if (NULL != payload) { |
| memset(payload, 0, sizeof(qcamera_sm_internal_evt_payload_t)); |
| payload->evt_type = QCAMERA_INTERNAL_EVT_DUAL_CAMERA_FOV_CONTROL; |
| int32_t rc = processEvt(QCAMERA_SM_EVT_EVT_INTERNAL, payload); |
| if (rc != NO_ERROR) { |
| LOGE("processEvt Dual camera fill FOV control failed"); |
| free(payload); |
| payload = NULL; |
| } |
| } else { |
| LOGE("No memory for Dual camera fill FOV control event"); |
| } |
| } |
| |
| }; // namespace qcamera |