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);
diff --git a/QCamera2/stack/common/mm_camera_interface.h b/QCamera2/stack/common/mm_camera_interface.h
index 23bb957..ae0732f 100755
--- a/QCamera2/stack/common/mm_camera_interface.h
+++ b/QCamera2/stack/common/mm_camera_interface.h
@@ -366,6 +366,22 @@
**/
int32_t (*prepare_snapshot) (uint32_t camera_handle);
+ /** start_zsl_snapshot: function definition for starting
+ * zsl snapshot.
+ * @camera_handle : camer handler
+ * Return value: 0 -- success
+ * -1 -- failure
+ **/
+ int32_t (*start_zsl_snapshot) (uint32_t camera_handle);
+
+ /** stop_zsl_snapshot: function definition for stopping
+ * zsl snapshot.
+ * @camera_handle : camer handler
+ * Return value: 0 -- success
+ * -1 -- failure
+ **/
+ int32_t (*stop_zsl_snapshot) (uint32_t camera_handle);
+
/** add_channel: fucntion definition for adding a channel
* @camera_handle : camer handler
* @ch_id : channel handler
@@ -573,15 +589,18 @@
int32_t (*cancel_super_buf_request) (uint32_t camera_handle,
uint32_t ch_id);
- /** flush_super_buf_queue: fucntion definition for flushing out
- * all frames in the superbuf queue
+ /** flush_super_buf_queue: function definition for flushing out
+ * all frames in the superbuf queue up to frame_idx,
+ * even if frames with frame_idx come in later than
+ * this call.
* @camera_handle : camer handler
* @ch_id : channel handler
+ * @frame_idx : frame index up until which all superbufs are flushed
* Return value: 0 -- success
* -1 -- failure
**/
int32_t (*flush_super_buf_queue) (uint32_t camera_handle,
- uint32_t ch_id);
+ uint32_t ch_id, uint32_t frame_idx);
} mm_camera_ops_t;
/** mm_camera_vtbl_t: virtual table for camera operations
diff --git a/QCamera2/stack/mm-camera-interface/inc/mm_camera.h b/QCamera2/stack/mm-camera-interface/inc/mm_camera.h
index 73d7d58..e41753b 100755
--- a/QCamera2/stack/mm-camera-interface/inc/mm_camera.h
+++ b/QCamera2/stack/mm-camera-interface/inc/mm_camera.h
@@ -88,6 +88,7 @@
mm_camera_event_t evt; /* evt if evtCB */
mm_camera_super_buf_t superbuf; /* superbuf if superbuf dataCB*/
mm_camera_req_buf_t req_buf; /* num of buf requested */
+ uint32_t frame_idx; /* frame idx boundary for flush superbuf queue*/
} u;
} mm_camera_cmdcb_t;
@@ -427,6 +428,8 @@
cam_autofocus_cycle_t sweep_mode);
extern cam_autofocus_state_t mm_camera_cancel_auto_focus(mm_camera_obj_t *my_obj);
extern int32_t mm_camera_prepare_snapshot(mm_camera_obj_t *my_obj);
+extern int32_t mm_camera_start_zsl_snapshot(mm_camera_obj_t *my_obj);
+extern int32_t mm_camera_stop_zsl_snapshot(mm_camera_obj_t *my_obj);
extern uint32_t mm_camera_add_channel(mm_camera_obj_t *my_obj,
mm_camera_channel_attr_t *attr,
mm_camera_buf_notify_t channel_cb,
@@ -455,7 +458,8 @@
extern int32_t mm_camera_cancel_super_buf_request(mm_camera_obj_t *my_obj,
uint32_t ch_id);
extern int32_t mm_camera_flush_super_buf_queue(mm_camera_obj_t *my_obj,
- uint32_t ch_id);
+ uint32_t ch_id,
+ uint32_t frame_idx);
extern int32_t mm_camera_set_stream_parms(mm_camera_obj_t *my_obj,
uint32_t ch_id,
uint32_t s_id,
diff --git a/QCamera2/stack/mm-camera-interface/src/mm_camera.c b/QCamera2/stack/mm-camera-interface/src/mm_camera.c
index 3cfa2bf..c95beb6 100755
--- a/QCamera2/stack/mm-camera-interface/src/mm_camera.c
+++ b/QCamera2/stack/mm-camera-interface/src/mm_camera.c
@@ -655,6 +655,52 @@
}
/*===========================================================================
+ * FUNCTION : mm_camera_start_zsl_snapshot
+ *
+ * DESCRIPTION: start zsl snapshot
+ *
+ * PARAMETERS :
+ * @my_obj : camera object
+ *
+ * RETURN : int32_t type of status
+ * 0 -- success
+ * -1 -- failure
+ *==========================================================================*/
+int32_t mm_camera_start_zsl_snapshot(mm_camera_obj_t *my_obj)
+{
+ int32_t rc = -1;
+ int32_t value = 0;
+
+ rc = mm_camera_util_s_ctrl(my_obj->ctrl_fd,
+ CAM_PRIV_START_ZSL_SNAPSHOT, &value);
+
+ pthread_mutex_unlock(&my_obj->cam_lock);
+ return rc;
+}
+
+/*===========================================================================
+ * FUNCTION : mm_camera_stop_zsl_snapshot
+ *
+ * DESCRIPTION: stop zsl capture
+ *
+ * PARAMETERS :
+ * @my_obj : camera object
+ *
+ * RETURN : int32_t type of status
+ * 0 -- success
+ * -1 -- failure
+ *==========================================================================*/
+int32_t mm_camera_stop_zsl_snapshot(mm_camera_obj_t *my_obj)
+{
+ int32_t rc = -1;
+ int32_t value;
+ rc = mm_camera_util_s_ctrl(my_obj->ctrl_fd,
+ CAM_PRIV_STOP_ZSL_SNAPSHOT, &value);
+ pthread_mutex_unlock(&my_obj->cam_lock);
+ return rc;
+}
+
+/*===========================================================================
* FUNCTION : mm_camera_add_channel
*
* DESCRIPTION: add a channel
@@ -1053,7 +1099,8 @@
* 0 -- success
* -1 -- failure
*==========================================================================*/
-int32_t mm_camera_flush_super_buf_queue(mm_camera_obj_t *my_obj, uint32_t ch_id)
+int32_t mm_camera_flush_super_buf_queue(mm_camera_obj_t *my_obj, uint32_t ch_id,
+ uint32_t frame_idx)
{
int32_t rc = -1;
mm_channel_t * ch_obj =
@@ -1065,7 +1112,7 @@
rc = mm_channel_fsm_fn(ch_obj,
MM_CHANNEL_EVT_FLUSH_SUPER_BUF_QUEUE,
- NULL,
+ (void *)frame_idx,
NULL);
} else {
pthread_mutex_unlock(&my_obj->cam_lock);
diff --git a/QCamera2/stack/mm-camera-interface/src/mm_camera_channel.c b/QCamera2/stack/mm-camera-interface/src/mm_camera_channel.c
index d96eb43..1a56e57 100644
--- a/QCamera2/stack/mm-camera-interface/src/mm_camera_channel.c
+++ b/QCamera2/stack/mm-camera-interface/src/mm_camera_channel.c
@@ -65,7 +65,9 @@
int32_t mm_channel_request_super_buf(mm_channel_t *my_obj,
uint32_t num_buf_requested);
int32_t mm_channel_cancel_super_buf_request(mm_channel_t *my_obj);
-int32_t mm_channel_flush_super_buf_queue(mm_channel_t *my_obj);
+int32_t mm_channel_flush_super_buf_queue(mm_channel_t *my_obj,
+ uint32_t frame_idx);
+int32_t mm_channel_superbuf_flush(mm_channel_t* my_obj, mm_channel_queue_t * queue);
int32_t mm_channel_set_stream_parm(mm_channel_t *my_obj,
mm_evt_paylod_set_get_stream_parms_t *payload);
int32_t mm_channel_get_stream_parm(mm_channel_t *my_obj,
@@ -170,7 +172,7 @@
* FUNCTION : mm_channel_process_stream_buf
*
* DESCRIPTION: handle incoming buffer from stream in a bundle. In this function,
- * matching logic will be performed on imcoming stream frames.
+ * matching logic will be performed on incoming stream frames.
* Will depends on the bundle attribute, either storing matched frames
* in the superbuf queue, or sending matched superbuf frames to upper
* layer through registered callback.
@@ -202,6 +204,8 @@
ch_obj->pending_cnt = cmd_cb->u.req_buf.num_buf_requested;
mm_channel_superbuf_skip(ch_obj, &ch_obj->bundle.superbuf_queue);
} else if (MM_CAMERA_CMD_TYPE_FLUSH_QUEUE == cmd_cb->cmd_type) {
+ ch_obj->bundle.superbuf_queue.expected_frame_id = cmd_cb->u.frame_idx;
+ mm_channel_superbuf_flush(ch_obj, &ch_obj->bundle.superbuf_queue);
return;
}
@@ -510,7 +514,8 @@
break;
case MM_CHANNEL_EVT_FLUSH_SUPER_BUF_QUEUE:
{
- rc = mm_channel_flush_super_buf_queue(my_obj);
+ uint32_t frame_idx = (uint32_t)in_val;
+ rc = mm_channel_flush_super_buf_queue(my_obj, frame_idx);
}
break;
case MM_CHANNEL_EVT_SET_STREAM_PARM:
@@ -1118,12 +1123,13 @@
*
* PARAMETERS :
* @my_obj : channel object
+ * @frame_idx : frame idx until which to flush all superbufs
*
* RETURN : int32_t type of status
* 0 -- success
* -1 -- failure
*==========================================================================*/
-int32_t mm_channel_flush_super_buf_queue(mm_channel_t *my_obj)
+int32_t mm_channel_flush_super_buf_queue(mm_channel_t *my_obj, uint32_t frame_idx)
{
int32_t rc = 0;
mm_camera_cmdcb_t* node = NULL;
@@ -1132,6 +1138,7 @@
if (NULL != node) {
memset(node, 0, sizeof(mm_camera_cmdcb_t));
node->cmd_type = MM_CAMERA_CMD_TYPE_FLUSH_QUEUE;
+ node->u.frame_idx = frame_idx;
/* enqueue to cmd thread */
cam_queue_enq(&(my_obj->cmd_thread.cmd_queue), node);
@@ -1399,6 +1406,85 @@
}
/*===========================================================================
+ * FUNCTION : mm_channel_handle_metadata
+ *
+ * DESCRIPTION: Handle frame matching logic change due to metadata
+ *
+ * PARAMETERS :
+ * @ch_obj : channel object
+ * @queue : superbuf queue
+ * @buf_info: new buffer from stream
+ *
+ * RETURN : int32_t type of status
+ * 0 -- success
+ * -1 -- failure
+ *==========================================================================*/
+int32_t mm_channel_handle_metadata(
+ mm_channel_t* ch_obj,
+ mm_channel_queue_t * queue,
+ mm_camera_buf_info_t *buf_info)
+{
+ int rc = 0 ;
+ mm_stream_t* stream_obj = NULL;
+ stream_obj = mm_channel_util_get_stream_by_handler(ch_obj,
+ buf_info->stream_id);
+
+ if (NULL == stream_obj) {
+ CDBG_ERROR("%s: Invalid Stream Object for stream_id = %d",
+ __func__, buf_info->stream_id);
+ rc = -1;
+ goto end;
+ }
+ if (NULL == stream_obj->stream_info) {
+ CDBG_ERROR("%s: NULL stream info for stream_id = %d",
+ __func__, buf_info->stream_id);
+ rc = -1;
+ goto end;
+ }
+
+ if (CAM_STREAM_TYPE_METADATA == stream_obj->stream_info->stream_type) {
+ const cam_metadata_info_t *metadata;
+ metadata = (const cam_metadata_info_t *)buf_info->buf->buffer;
+
+ if (NULL == metadata) {
+ CDBG_ERROR("%s: NULL metadata buffer for metadata stream",
+ __func__);
+ rc = -1;
+ goto end;
+ }
+
+ if (metadata->is_prep_snapshot_done_valid &&
+ metadata->is_good_frame_idx_range_valid) {
+ CDBG_ERROR("%s: prep_snapshot_done and good_idx_range shouldn't be valid at the same time", __func__);
+ rc = -1;
+ goto end;
+ }
+
+ if (metadata->is_prep_snapshot_done_valid &&
+ metadata->prep_snapshot_done_state == NEED_FUTURE_FRAME) {
+
+ /* Set expected frame id to a future frame idx, large enough to wait
+ * for good_frame_idx_range, and small enough to still capture an image */
+ const int max_future_frame_offset = 100;
+ queue->expected_frame_id += max_future_frame_offset;
+
+ mm_channel_superbuf_flush(ch_obj, queue);
+ } else if (metadata->is_good_frame_idx_range_valid) {
+ if (metadata->good_frame_idx_range.min_frame_idx >
+ queue->expected_frame_id) {
+ CDBG_HIGH("%s: min_frame_idx %d is greater than expected_frame_id %d",
+ __func__, metadata->good_frame_idx_range.min_frame_idx,
+ queue->expected_frame_id);
+ }
+ queue->expected_frame_id =
+ metadata->good_frame_idx_range.min_frame_idx;
+ }
+ }
+end:
+ return rc;
+}
+
+/*===========================================================================
* FUNCTION : mm_channel_superbuf_comp_and_enqueue
*
* DESCRIPTION: implementation for matching logic for superbuf
@@ -1414,7 +1500,7 @@
*==========================================================================*/
int32_t mm_channel_superbuf_comp_and_enqueue(
mm_channel_t* ch_obj,
- mm_channel_queue_t * queue,
+ mm_channel_queue_t *queue,
mm_camera_buf_info_t *buf_info)
{
cam_node_t* node = NULL;
@@ -1434,6 +1520,10 @@
return -1;
}
+ if (mm_channel_handle_metadata(ch_obj, queue, buf_info) < 0) {
+ return -1;
+ }
+
if (mm_channel_util_seq_comp_w_rollover(buf_info->frame_idx,
queue->expected_frame_id) < 0) {
/* incoming buf is older than expected buf id, will discard it */
@@ -1468,8 +1558,8 @@
}
if (pos == head) {
- CDBG("%s: all nodes in queue are mtached, or no node in queue, create a new node", __func__);
- /* all nodes in queue are mtached, or no node in queue
+ CDBG("%s: all nodes in queue are matched, or no node in queue, create a new node", __func__);
+ /* all nodes in queue are matched, or no node in queue
* create a new node */
mm_channel_queue_node_t *new_buf = NULL;
cam_node_t* new_node = NULL;
@@ -1484,7 +1574,6 @@
new_buf->super_buf[buf_s_idx] = *buf_info;
/* enqueue */
- //cam_list_add_tail_node(&node->list, &queue->que.head.list);
cam_list_add_tail_node(&new_node->list, &queue->que.head.list);
queue->que.size++;
@@ -1533,7 +1622,7 @@
is_new = 0;
break;
}else{
- //TODO: reveiw again
+ //TODO: review again
break;
}
}
diff --git a/QCamera2/stack/mm-camera-interface/src/mm_camera_interface.c b/QCamera2/stack/mm-camera-interface/src/mm_camera_interface.c
index 6f5637e..7dc736b 100644
--- a/QCamera2/stack/mm-camera-interface/src/mm_camera_interface.c
+++ b/QCamera2/stack/mm-camera-interface/src/mm_camera_interface.c
@@ -329,6 +329,66 @@
}
/*===========================================================================
+ * FUNCTION : mm_camera_intf_start_zsl_snapshot
+ *
+ * DESCRIPTION: start zsl snapshot
+ *
+ * PARAMETERS :
+ * @camera_handle: camera handle
+ *
+ * RETURN : int32_t type of status
+ * 0 -- success
+ * -1 -- failure
+ *==========================================================================*/
+static int32_t mm_camera_intf_start_zsl_snapshot(uint32_t camera_handle)
+{
+ int32_t rc = -1;
+ mm_camera_obj_t * my_obj = NULL;
+
+ pthread_mutex_lock(&g_intf_lock);
+ my_obj = mm_camera_util_get_camera_by_handler(camera_handle);
+
+ if(my_obj) {
+ pthread_mutex_lock(&my_obj->cam_lock);
+ pthread_mutex_unlock(&g_intf_lock);
+ rc = mm_camera_start_zsl_snapshot(my_obj);
+ } else {
+ pthread_mutex_unlock(&g_intf_lock);
+ }
+ return rc;
+}
+
+/*===========================================================================
+ * FUNCTION : mm_camera_intf_stop_zsl_snapshot
+ *
+ * DESCRIPTION: stop zsl snapshot
+ *
+ * PARAMETERS :
+ * @camera_handle: camera handle
+ *
+ * RETURN : int32_t type of status
+ * 0 -- success
+ * -1 -- failure
+ *==========================================================================*/
+static int32_t mm_camera_intf_stop_zsl_snapshot(uint32_t camera_handle)
+{
+ int32_t rc = -1;
+ mm_camera_obj_t * my_obj = NULL;
+
+ pthread_mutex_lock(&g_intf_lock);
+ my_obj = mm_camera_util_get_camera_by_handler(camera_handle);
+
+ if(my_obj) {
+ pthread_mutex_lock(&my_obj->cam_lock);
+ pthread_mutex_unlock(&g_intf_lock);
+ rc = mm_camera_stop_zsl_snapshot(my_obj);
+ } else {
+ pthread_mutex_unlock(&g_intf_lock);
+ }
+ return rc;
+}
+
+/*===========================================================================
* FUNCTION : mm_camera_intf_close
*
* DESCRIPTION: close a camera by its handle
@@ -831,13 +891,14 @@
* PARAMETERS :
* @camera_handle: camera handle
* @ch_id : channel handle
+ * @frame_idx : frame index
*
* RETURN : int32_t type of status
* 0 -- success
* -1 -- failure
*==========================================================================*/
static int32_t mm_camera_intf_flush_super_buf_queue(uint32_t camera_handle,
- uint32_t ch_id)
+ uint32_t ch_id, uint32_t frame_idx)
{
int32_t rc = -1;
mm_camera_obj_t * my_obj = NULL;
@@ -850,7 +911,7 @@
if(my_obj) {
pthread_mutex_lock(&my_obj->cam_lock);
pthread_mutex_unlock(&g_intf_lock);
- rc = mm_camera_flush_super_buf_queue(my_obj, ch_id);
+ rc = mm_camera_flush_super_buf_queue(my_obj, ch_id, frame_idx);
} else {
pthread_mutex_unlock(&g_intf_lock);
}
@@ -1219,6 +1280,8 @@
.do_auto_focus = mm_camera_intf_do_auto_focus,
.cancel_auto_focus = mm_camera_intf_cancel_auto_focus,
.prepare_snapshot = mm_camera_intf_prepare_snapshot,
+ .start_zsl_snapshot = mm_camera_intf_start_zsl_snapshot,
+ .stop_zsl_snapshot = mm_camera_intf_stop_zsl_snapshot,
.map_buf = mm_camera_intf_map_buf,
.unmap_buf = mm_camera_intf_unmap_buf,
.add_channel = mm_camera_intf_add_channel,