blob: 3843cf5dc98fcf5bafe86d0bb511fe19efded6f5 [file] [log] [blame]
/* 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 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());
//Close and delete duplicated native handle and FD's.
if ((hw->mVideoMem != NULL) && (hw->mStoreMetaDataInFrame)) {
ret = hw->mVideoMem->closeNativeHandle(opaque, TRUE);
if (ret != NO_ERROR) {
LOGE("Invalid video metadata");
return;
}
} else {
LOGW("Possible FD leak. Release recording called after stop");
}
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),
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),
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),
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),
mVideoMem(NULL),
mCACDoneReceived(false),
m_bNeedRestart(false),
mBootToMonoTimestampOffset(0)
{
#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;
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);
}
}
/*===========================================================================
* 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);
}
// 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);
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 : 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 = NO_ERROR;
QCameraHeapMemory *capabilityHeap = NULL;
/* Allocate memory for capability buffer */
capabilityHeap = new QCameraHeapMemory(QCAMERA_ION_USE_CACHE);
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 = cameraHandle->ops->map_bufs(cameraHandle->camera_handle,
&bufMapList);
}
if(rc < 0) {
LOGE("failed to map capability buffer");
goto map_failed;
}
/* Query Capability */
rc = cameraHandle->ops->query_capability(cameraHandle->camera_handle);
if(rc < 0) {
LOGE("failed to query capability");
goto query_failed;
}
gCamCapability[cameraId] =
(cam_capability_t *)malloc(sizeof(cam_capability_t));
if (!gCamCapability[cameraId]) {
LOGE("out of memory");
goto query_failed;
}
memcpy(gCamCapability[cameraId], 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 =
&gCamCapability[cameraId]->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;
}
rc = NO_ERROR;
query_failed:
cameraHandle->ops->unmap_buf(cameraHandle->camera_handle,
CAM_MAPPING_BUF_TYPE_CAPABILITY);
map_failed:
capabilityHeap->deallocate();
delete capabilityHeap;
allocate_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 : 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 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;
}
// 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 : 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;
if (!mParameters.getBufBatchCount()) {
//For batch mode this will be part of user buffer.
mVideoMem = 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())) {