Camera2: Enable LED in ZSL
If LED Flash needs to be fired for ZSL capture, prepareSnapshot
needs to be called for AEC estimation with Flash on to take place.
Add a new state in the state machine to handle this case.
Change-Id: I5882e568cb2bf84b9a4944023a9927e8ff3063cb
diff --git a/QCamera2/HAL/QCamera2HWI.cpp b/QCamera2/HAL/QCamera2HWI.cpp
index 1f2f8b9..056344c 100644
--- a/QCamera2/HAL/QCamera2HWI.cpp
+++ b/QCamera2/HAL/QCamera2HWI.cpp
@@ -577,14 +577,28 @@
ALOGE("NULL camera device");
return BAD_VALUE;
}
+
hw->lockAPI();
+
+ /* 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);
+ ret = hw->m_apiResult.status;
+ }
+
+ /* Regardless what the result value for prepare_snapshot,
+ * go ahead with capture anyway. Just like the way autofocus
+ * is handled in capture case. */
+
+ /* capture */
ret = hw->processAPI(QCAMERA_SM_EVT_TAKE_PICTURE, NULL);
if (ret == NO_ERROR) {
hw->waitAPIResult(QCAMERA_SM_EVT_TAKE_PICTURE);
ret = hw->m_apiResult.status;
}
- hw->unlockAPI();
+ hw->unlockAPI();
return ret;
}
@@ -904,6 +918,7 @@
m_cbNotifier(this),
m_bShutterSoundPlayed(false),
m_bAutoFocusRunning(false),
+ m_bStartZSLSnapshotCalled(false),
m_pPowerModule(NULL)
{
mCameraDevice.common.tag = HARDWARE_DEVICE_TAG;
@@ -1792,9 +1807,6 @@
}
} else {
// normal capture case
- // prepare snapshot, e.g LED
- prepareHardwareForSnapshot( );
-
// need to stop preview channel
stopChannel(QCAMERA_CH_TYPE_PREVIEW);
delChannel(QCAMERA_CH_TYPE_PREVIEW);
@@ -1860,6 +1872,11 @@
QCameraPicChannel *pZSLChannel =
(QCameraPicChannel *)m_channels[QCAMERA_CH_TYPE_ZSL];
if (NULL != pZSLChannel) {
+ if (m_bStartZSLSnapshotCalled) {
+ mCameraHandle->ops->stop_zsl_snapshot(
+ mCameraHandle->camera_handle);
+ m_bStartZSLSnapshotCalled = false;
+ }
pZSLChannel->cancelPicture();
}
} else {
@@ -2370,6 +2387,39 @@
}
/*===========================================================================
+ * 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;
+
+ if (m_channels[QCAMERA_CH_TYPE_ZSL] &&
+ prep_snapshot_state == NEED_FUTURE_FRAME) {
+
+ ret = mCameraHandle->ops->start_zsl_snapshot(
+ mCameraHandle->camera_handle);
+ if (ret < 0) {
+ ALOGE("%s: start_led_zsl_capture failed %d",
+ __func__, ret);
+ return ret;
+ }
+ m_bStartZSLSnapshotCalled = true;
+ }
+ return ret;
+}
+
+/*===========================================================================
* FUNCTION : processJpegNotify
*
* DESCRIPTION: process jpeg event
diff --git a/QCamera2/HAL/QCamera2HWI.h b/QCamera2/HAL/QCamera2HWI.h
index 31393e1..316c2a4 100644
--- a/QCamera2/HAL/QCamera2HWI.h
+++ b/QCamera2/HAL/QCamera2HWI.h
@@ -266,6 +266,7 @@
int32_t processAutoFocusEvent(cam_auto_focus_data_t &focus_data);
int32_t processZoomEvent(cam_crop_data_t &crop_info);
+ int32_t processPrepSnapshotDoneEvent(cam_prep_snapshot_state_t prep_snapshot_state);
int32_t processJpegNotify(qcamera_jpeg_evt_payload_t *jpeg_job);
int32_t sendEvtNotify(int32_t msg_type, int32_t ext1, int32_t ext2);
@@ -389,6 +390,9 @@
// of whether lens is moving or not.
bool m_bAutoFocusRunning;
+ // If start_zsl_snapshot is called to notify camera daemon about zsl snapshot
+ bool m_bStartZSLSnapshotCalled;
+
power_module_t *m_pPowerModule; // power module
};
diff --git a/QCamera2/HAL/QCamera2HWICallbacks.cpp b/QCamera2/HAL/QCamera2HWICallbacks.cpp
index 1db83c2..c7a52ba 100644
--- a/QCamera2/HAL/QCamera2HWICallbacks.cpp
+++ b/QCamera2/HAL/QCamera2HWICallbacks.cpp
@@ -714,6 +714,25 @@
pme->processZoomEvent(pMetaData->crop_data);
}
+ if (pMetaData->is_prep_snapshot_done_valid) {
+ 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_PREP_SNAPSHOT_DONE;
+ payload->prep_snapshot_state = pMetaData->prep_snapshot_done_state;
+ int32_t rc = pme->processEvt(QCAMERA_SM_EVT_EVT_INTERNAL, payload);
+ if (rc != NO_ERROR) {
+ ALOGE("%s: processEVt failed", __func__);
+ free(payload);
+ payload = NULL;
+
+ }
+ } else {
+ ALOGE("%s: No memory for qcamera_sm_internal_evt_payload_t", __func__);
+ }
+ }
+
stream->bufDone(frame->buf_idx);
free(super_frame);
diff --git a/QCamera2/HAL/QCameraStateMachine.cpp b/QCamera2/HAL/QCameraStateMachine.cpp
index 904130c..1c8b1e3 100644
--- a/QCamera2/HAL/QCameraStateMachine.cpp
+++ b/QCamera2/HAL/QCameraStateMachine.cpp
@@ -253,6 +253,9 @@
case QCAMERA_SM_STATE_PREVIEWING:
rc = procEvtPreviewingState(evt, payload);
break;
+ case QCAMERA_SM_STATE_PREPARE_SNAPSHOT:
+ rc = procEvtPrepareSnapshotState(evt, payload);
+ break;
case QCAMERA_SM_STATE_PIC_TAKING:
rc = procEvtPicTakingState(evt, payload);
break;
@@ -486,6 +489,7 @@
case QCAMERA_SM_EVT_START_RECORDING:
case QCAMERA_SM_EVT_STOP_RECORDING:
case QCAMERA_SM_EVT_RELEASE_RECORIDNG_FRAME:
+ case QCAMERA_SM_EVT_PREPARE_SNAPSHOT:
case QCAMERA_SM_EVT_TAKE_PICTURE:
case QCAMERA_SM_EVT_START_AUTO_FOCUS:
{
@@ -773,6 +777,7 @@
case QCAMERA_SM_EVT_START_NODISPLAY_PREVIEW:
case QCAMERA_SM_EVT_START_RECORDING:
case QCAMERA_SM_EVT_STOP_RECORDING:
+ case QCAMERA_SM_EVT_PREPARE_SNAPSHOT:
case QCAMERA_SM_EVT_TAKE_PICTURE:
case QCAMERA_SM_EVT_CANCEL_PICTURE:
case QCAMERA_SM_EVT_RELEASE_RECORIDNG_FRAME:
@@ -1017,16 +1022,35 @@
m_parent->signalAPIResult(&result);
}
break;
- case QCAMERA_SM_EVT_TAKE_PICTURE:
+ case QCAMERA_SM_EVT_PREPARE_SNAPSHOT:
{
- rc = m_parent->takePicture();
+ rc = m_parent->prepareHardwareForSnapshot();
if (rc == NO_ERROR) {
- // move state to picture taking state
- if (m_parent->isZSLMode()) {
- m_state = QCAMERA_SM_STATE_PREVIEW_PIC_TAKING;
- } else {
- m_state = QCAMERA_SM_STATE_PIC_TAKING;
- }
+ // Do not signal API result in this case.
+ // Need to wait for snapshot done in metadta.
+ m_state = QCAMERA_SM_STATE_PREPARE_SNAPSHOT;
+ } else {
+ // Do not change state in this case.
+ ALOGE("%s: prepareHardwareForSnapshot failed %d",
+ __func__, rc);
+
+ result.status = rc;
+ result.request_api = evt;
+ result.result_type = QCAMERA_API_RESULT_TYPE_DEF;
+ m_parent->signalAPIResult(&result);
+ }
+ }
+ break;
+ case QCAMERA_SM_EVT_TAKE_PICTURE:
+ {
+ rc = m_parent->takePicture();
+ if (rc == NO_ERROR) {
+ // move state to picture taking state
+ if (m_parent->isZSLMode()) {
+ m_state = QCAMERA_SM_STATE_PREVIEW_PIC_TAKING;
+ } else {
+ m_state = QCAMERA_SM_STATE_PIC_TAKING;
+ }
} else {
// move state to preview stopped state
m_state = QCAMERA_SM_STATE_PREVIEW_STOPPED;
@@ -1087,6 +1111,8 @@
rc = m_parent->processAutoFocusEvent(internal_evt->focus_data);
break;
default:
+ ALOGE("%s: Invalid internal event %d in state(%d)",
+ __func__, internal_evt->evt_type, m_state);
break;
}
}
@@ -1119,6 +1145,96 @@
}
/*===========================================================================
+ * FUNCTION : procEvtPrepareSnapshotState
+ *
+ * DESCRIPTION: finite state machine function to handle event in state of
+ * QCAMERA_SM_STATE_PREPARE_SNAPSHOT.
+ *
+ * PARAMETERS :
+ * @evt : event to be processed
+ * @payload : event payload. Can be NULL if not needed.
+ *
+ * RETURN : int32_t type of status
+ * NO_ERROR -- success
+ * none-zero failure code
+ *==========================================================================*/
+int32_t QCameraStateMachine::procEvtPrepareSnapshotState(qcamera_sm_evt_enum_t evt,
+ void *payload)
+{
+ int32_t rc = NO_ERROR;
+ qcamera_api_result_t result;
+ memset(&result, 0, sizeof(qcamera_api_result_t));
+
+ switch (evt) {
+ case QCAMERA_SM_EVT_SET_PREVIEW_WINDOW:
+ case QCAMERA_SM_EVT_SET_CALLBACKS:
+ case QCAMERA_SM_EVT_ENABLE_MSG_TYPE:
+ case QCAMERA_SM_EVT_DISABLE_MSG_TYPE:
+ case QCAMERA_SM_EVT_MSG_TYPE_ENABLED:
+ case QCAMERA_SM_EVT_SET_PARAMS:
+ case QCAMERA_SM_EVT_GET_PARAMS:
+ case QCAMERA_SM_EVT_PUT_PARAMS:
+ case QCAMERA_SM_EVT_START_PREVIEW:
+ case QCAMERA_SM_EVT_START_NODISPLAY_PREVIEW:
+ case QCAMERA_SM_EVT_STOP_PREVIEW:
+ case QCAMERA_SM_EVT_PREVIEW_ENABLED:
+ case QCAMERA_SM_EVT_RECORDING_ENABLED:
+ case QCAMERA_SM_EVT_STORE_METADATA_IN_BUFS:
+ case QCAMERA_SM_EVT_DUMP:
+ case QCAMERA_SM_EVT_START_AUTO_FOCUS:
+ case QCAMERA_SM_EVT_STOP_AUTO_FOCUS:
+ case QCAMERA_SM_EVT_START_RECORDING:
+ case QCAMERA_SM_EVT_TAKE_PICTURE:
+ case QCAMERA_SM_EVT_SEND_COMMAND:
+ case QCAMERA_SM_EVT_CANCEL_PICTURE:
+ case QCAMERA_SM_EVT_STOP_RECORDING:
+ case QCAMERA_SM_EVT_RELEASE_RECORIDNG_FRAME:
+ case QCAMERA_SM_EVT_RELEASE:
+ {
+ ALOGE("%s: cannot handle evt(%d) in state(%d)", __func__, evt, m_state);
+ rc = INVALID_OPERATION;
+ result.status = rc;
+ result.request_api = evt;
+ result.result_type = QCAMERA_API_RESULT_TYPE_DEF;
+ m_parent->signalAPIResult(&result);
+ }
+ break;
+ case QCAMERA_SM_EVT_EVT_INTERNAL:
+ {
+ qcamera_sm_internal_evt_payload_t *internal_evt =
+ (qcamera_sm_internal_evt_payload_t *)payload;
+ switch (internal_evt->evt_type) {
+ case QCAMERA_INTERNAL_EVT_PREP_SNAPSHOT_DONE:
+ ALOGI("%s: Received QCAMERA_INTERNAL_EVT_PREP_SNAPSHOT_DONE event",
+ __func__);
+ m_parent->processPrepSnapshotDoneEvent(internal_evt->prep_snapshot_state);
+ m_state = QCAMERA_SM_STATE_PREVIEWING;
+
+ result.status = NO_ERROR;
+ result.request_api = QCAMERA_SM_EVT_PREPARE_SNAPSHOT;
+ result.result_type = QCAMERA_API_RESULT_TYPE_DEF;
+ m_parent->signalAPIResult(&result);
+ break;
+ default:
+ ALOGE("%s: Invalid internal event %d in state(%d)",
+ __func__, internal_evt->evt_type, m_state);
+ break;
+ }
+ }
+ break;
+ case QCAMERA_SM_EVT_EVT_NOTIFY:
+ case QCAMERA_SM_EVT_THERMAL_NOTIFY:
+ case QCAMERA_SM_EVT_JPEG_EVT_NOTIFY:
+ case QCAMERA_SM_EVT_SNAPSHOT_DONE:
+ default:
+ ALOGE("%s: cannot handle evt(%d) in state(%d)", __func__, evt, m_state);
+ break;
+ }
+
+ return rc;
+}
+
+/*===========================================================================
* FUNCTION : procEvtPicTakingState
*
* DESCRIPTION: finite state machine function to handle event in state of
@@ -1635,6 +1751,15 @@
m_parent->signalAPIResult(&result);
}
break;
+ case QCAMERA_SM_EVT_PREPARE_SNAPSHOT:
+ {
+ //In Video snapshot, prepare hardware is a no-op.
+ result.status = NO_ERROR;
+ result.request_api = evt;
+ result.result_type = QCAMERA_API_RESULT_TYPE_DEF;
+ m_parent->signalAPIResult(&result);
+ }
+ break;
case QCAMERA_SM_EVT_CANCEL_PICTURE:
case QCAMERA_SM_EVT_START_PREVIEW:
case QCAMERA_SM_EVT_START_NODISPLAY_PREVIEW:
@@ -2179,7 +2304,11 @@
break;
case QCAMERA_SM_EVT_CANCEL_PICTURE:
{
- rc = m_parent->cancelLiveSnapshot();
+ if (m_parent->isZSLMode()) {
+ rc = m_parent->cancelPicture();
+ } else {
+ rc = m_parent->cancelLiveSnapshot();
+ }
m_state = QCAMERA_SM_STATE_PREVIEWING;
result.status = rc;
result.request_api = evt;
@@ -2275,7 +2404,11 @@
break;
case QCAMERA_SM_EVT_SNAPSHOT_DONE:
{
- rc = m_parent->cancelLiveSnapshot();
+ if (m_parent->isZSLMode()) {
+ rc = m_parent->cancelPicture();
+ } else {
+ rc = m_parent->cancelLiveSnapshot();
+ }
m_state = QCAMERA_SM_STATE_PREVIEWING;
}
break;
diff --git a/QCamera2/HAL/QCameraStateMachine.h b/QCamera2/HAL/QCameraStateMachine.h
index 527597e..66eb63b 100644
--- a/QCamera2/HAL/QCameraStateMachine.h
+++ b/QCamera2/HAL/QCameraStateMachine.h
@@ -67,6 +67,7 @@
QCAMERA_SM_EVT_RECORDING_ENABLED, // query if recording is running
QCAMERA_SM_EVT_RELEASE_RECORIDNG_FRAME, // release recording frame
+ QCAMERA_SM_EVT_PREPARE_SNAPSHOT, // prepare snapshot in case LED needs to be flashed
QCAMERA_SM_EVT_TAKE_PICTURE, // take picutre (zsl, regualr capture, live snapshot
QCAMERA_SM_EVT_CANCEL_PICTURE, // cancel picture
@@ -129,7 +130,8 @@
} qcamera_sm_evt_reg_face_payload_t;
typedef enum {
- QCAMERA_INTERNAL_EVT_FOCUS_UPDATE, // internal event for focus updating
+ QCAMERA_INTERNAL_EVT_FOCUS_UPDATE, // focus updating result
+ QCAMERA_INTERNAL_EVT_PREP_SNAPSHOT_DONE, // prepare snapshot done
QCAMERA_INTERNAL_EVT_MAX
} qcamera_internal_evt_type_t;
@@ -137,6 +139,7 @@
qcamera_internal_evt_type_t evt_type;
union {
cam_auto_focus_data_t focus_data;
+ cam_prep_snapshot_state_t prep_snapshot_state;
};
} qcamera_sm_internal_evt_payload_t;
@@ -155,6 +158,8 @@
QCAMERA_SM_STATE_PREVIEW_STOPPED, // preview is stopped
QCAMERA_SM_STATE_PREVIEW_READY, // preview started but preview window is not set yet
QCAMERA_SM_STATE_PREVIEWING, // previewing
+ QCAMERA_SM_STATE_PREPARE_SNAPSHOT, // prepare snapshot in case aec estimation is
+ // needed for LED flash
QCAMERA_SM_STATE_PIC_TAKING, // taking picture (preview stopped)
QCAMERA_SM_STATE_RECORDING, // recording (preview running)
QCAMERA_SM_STATE_VIDEO_PIC_TAKING, // taking live snapshot during recording (preview running)
@@ -179,6 +184,7 @@
int32_t procEvtPreviewStoppedState(qcamera_sm_evt_enum_t evt, void *payload);
int32_t procEvtPreviewReadyState(qcamera_sm_evt_enum_t evt, void *payload);
int32_t procEvtPreviewingState(qcamera_sm_evt_enum_t evt, void *payload);
+ int32_t procEvtPrepareSnapshotState(qcamera_sm_evt_enum_t evt, void *payload);
int32_t procEvtPicTakingState(qcamera_sm_evt_enum_t evt, void *payload);
int32_t procEvtRecordingState(qcamera_sm_evt_enum_t evt, void *payload);
int32_t procEvtVideoPicTakingState(qcamera_sm_evt_enum_t evt, void *payload);