QCamera2: Adds support for early preview restart
- This change will internally restart preview
during the jpeg encoding stage in non-zsl.
This feature can be enabled via this property:
"persist.camera.feature.restart -> 0/1"
Change-Id: I3044b99cc0cac6c088d4435583aa2c703ba4ed8c
CRs-fixed: 547748
diff --git a/QCamera2/HAL/QCamera2HWI.cpp b/QCamera2/HAL/QCamera2HWI.cpp
index 41d486f..cd1b820 100644
--- a/QCamera2/HAL/QCamera2HWI.cpp
+++ b/QCamera2/HAL/QCamera2HWI.cpp
@@ -1581,16 +1581,24 @@
break;
case CAM_STREAM_TYPE_POSTVIEW:
{
- cam_dimension_t dim;
- QCameraGrallocMemory *grallocMemory =
- new QCameraGrallocMemory(mGetMemory);
+ if (isPreviewRestartEnabled()) {
+ mem = new QCameraStreamMemory(mGetMemory, bCachedMem);
+ } else {
+ cam_dimension_t dim;
+ QCameraGrallocMemory *grallocMemory =
+ new QCameraGrallocMemory(mGetMemory);
- mParameters.getStreamDimension(stream_type, dim);
- if (grallocMemory)
- grallocMemory->setWindowInfo(mPreviewWindow, dim.width,
- dim.height, stride, scanline,
- mParameters.getPreviewHalPixelFormat());
- mem = grallocMemory;
+ mParameters.getStreamDimension(stream_type, dim);
+ if (grallocMemory) {
+ grallocMemory->setWindowInfo(mPreviewWindow,
+ dim.width,
+ dim.height,
+ stride,
+ scanline,
+ mParameters.getPreviewHalPixelFormat());
+ }
+ mem = grallocMemory;
+ }
}
break;
case CAM_STREAM_TYPE_SNAPSHOT:
@@ -2581,18 +2589,24 @@
*
* DESCRIPTION: Stops capture channel
*
- * PARAMETERS : none
+ * PARAMETERS :
+ * @destroy : Set to true to stop and delete camera channel.
+ * Set to false to only stop capture channel.
*
* RETURN : int32_t type of status
* NO_ERROR -- success
* none-zero failure code
*==========================================================================*/
-int QCamera2HardwareInterface::stopCaptureChannel()
+int QCamera2HardwareInterface::stopCaptureChannel(bool destroy)
{
if (mParameters.isJpegPictureFormat() ||
mParameters.isNV16PictureFormat() ||
mParameters.isNV21PictureFormat()) {
stopChannel(QCAMERA_CH_TYPE_CAPTURE);
+ if (destroy) {
+ // Destroy camera channel but dont release context
+ delChannel(QCAMERA_CH_TYPE_CAPTURE, false);
+ }
}
return NO_ERROR;
@@ -4435,16 +4449,22 @@
*
* PARAMETERS :
* @ch_type : channel type
+ * @destroy : delete context as well
*
* RETURN : int32_t type of status
* NO_ERROR -- success
* none-zero failure code
*==========================================================================*/
-int32_t QCamera2HardwareInterface::delChannel(qcamera_ch_type_enum_t ch_type)
+int32_t QCamera2HardwareInterface::delChannel(qcamera_ch_type_enum_t ch_type,
+ bool destroy)
{
if (m_channels[ch_type] != NULL) {
- delete m_channels[ch_type];
- m_channels[ch_type] = NULL;
+ if (destroy) {
+ delete m_channels[ch_type];
+ m_channels[ch_type] = NULL;
+ } else {
+ m_channels[ch_type]->deleteChannel();
+ }
}
return NO_ERROR;
@@ -5167,6 +5187,26 @@
}
/*===========================================================================
+ * FUNCTION : isPreviewRestartEnabled
+ *
+ * DESCRIPTION: Check whether preview should be restarted automatically
+ * during image capture.
+ *
+ * PARAMETERS : none
+ *
+ * RETURN : true: needed
+ * false: no need
+ *==========================================================================*/
+bool QCamera2HardwareInterface::isPreviewRestartEnabled()
+{
+ char prop[PROPERTY_VALUE_MAX];
+ memset(prop, 0, sizeof(prop));
+ property_get("persist.camera.feature.restart", prop, "0");
+ int earlyRestart = atoi(prop);
+ return earlyRestart == 1;
+}
+
+/*===========================================================================
* FUNCTION : needReprocess
*
* DESCRIPTION: if reprocess is needed
diff --git a/QCamera2/HAL/QCamera2HWI.h b/QCamera2/HAL/QCamera2HWI.h
index 4d427da..f459d69 100644
--- a/QCamera2/HAL/QCamera2HWI.h
+++ b/QCamera2/HAL/QCamera2HWI.h
@@ -275,7 +275,7 @@
int autoFocus();
int cancelAutoFocus();
int takePicture();
- int stopCaptureChannel();
+ int stopCaptureChannel(bool destroy);
int cancelPicture();
int takeLiveSnapshot();
int cancelLiveSnapshot();
@@ -316,6 +316,7 @@
bool needDebugFps();
bool isCACEnabled();
+ bool isPreviewRestartEnabled();
bool needReprocess();
bool needRotationReprocess();
bool needScaleReprocess();
@@ -354,7 +355,7 @@
int32_t addChannel(qcamera_ch_type_enum_t ch_type);
int32_t startChannel(qcamera_ch_type_enum_t ch_type);
int32_t stopChannel(qcamera_ch_type_enum_t ch_type);
- int32_t delChannel(qcamera_ch_type_enum_t ch_type);
+ int32_t delChannel(qcamera_ch_type_enum_t ch_type, bool destroy = true);
int32_t addPreviewChannel();
int32_t addSnapshotChannel();
int32_t addVideoChannel();
diff --git a/QCamera2/HAL/QCameraChannel.cpp b/QCamera2/HAL/QCameraChannel.cpp
index 5fcdd04..b09d71b 100644
--- a/QCamera2/HAL/QCameraChannel.cpp
+++ b/QCamera2/HAL/QCameraChannel.cpp
@@ -109,6 +109,29 @@
}
/*===========================================================================
+ * FUNCTION : deleteChannel
+ *
+ * DESCRIPTION: deletes a camera channel
+ *
+ * PARAMETERS : none
+ *
+ * RETURN : none
+ *==========================================================================*/
+void QCameraChannel::deleteChannel()
+{
+ if (m_bIsActive) {
+ stop();
+ }
+
+ for (int i = 0; i < m_numStreams; i++) {
+ if (mStreams[i] != NULL) {
+ mStreams[i]->deleteStream();
+ }
+ }
+ m_camOps->delete_channel(m_camHandle, m_handle);
+}
+
+/*===========================================================================
* FUNCTION : init
*
* DESCRIPTION: initialization of channel
diff --git a/QCamera2/HAL/QCameraChannel.h b/QCamera2/HAL/QCameraChannel.h
index 53d51ba..6eeb724 100644
--- a/QCamera2/HAL/QCameraChannel.h
+++ b/QCamera2/HAL/QCameraChannel.h
@@ -69,6 +69,7 @@
QCameraStream *getStreamByIndex(uint8_t index);
QCameraStream *getStreamByServerID(uint32_t serverID);
int32_t UpdateStreamBasedParameters(QCameraParameters ¶m);
+ void deleteChannel();
protected:
uint32_t m_camHandle;
diff --git a/QCamera2/HAL/QCameraStateMachine.cpp b/QCamera2/HAL/QCameraStateMachine.cpp
index ed68400..f90e24e 100644
--- a/QCamera2/HAL/QCameraStateMachine.cpp
+++ b/QCamera2/HAL/QCameraStateMachine.cpp
@@ -1687,7 +1687,17 @@
break;
case QCAMERA_SM_EVT_STOP_CAPTURE_CHANNEL:
{
- rc = m_parent->stopCaptureChannel();
+ bool restartPreview = m_parent->isPreviewRestartEnabled();
+ rc = m_parent->stopCaptureChannel(restartPreview);
+
+ if (restartPreview && (NO_ERROR == rc)) {
+ rc = m_parent->preparePreview();
+ if (NO_ERROR == rc) {
+ m_parent->m_bPreviewStarted = true;
+ rc = m_parent->startPreview();
+ }
+ }
+
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_DEF;
@@ -1697,7 +1707,14 @@
case QCAMERA_SM_EVT_SNAPSHOT_DONE:
{
rc = m_parent->cancelPicture();
- m_state = QCAMERA_SM_STATE_PREVIEW_STOPPED;
+
+ bool restartPreview = m_parent->isPreviewRestartEnabled();
+ if (restartPreview) {
+ m_state = QCAMERA_SM_STATE_PREVIEWING;
+ } else {
+ m_state = QCAMERA_SM_STATE_PREVIEW_STOPPED;
+ }
+
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_DEF;
diff --git a/QCamera2/HAL/QCameraStream.cpp b/QCamera2/HAL/QCameraStream.cpp
index f0c4b4d..10c2055 100644
--- a/QCamera2/HAL/QCameraStream.cpp
+++ b/QCamera2/HAL/QCameraStream.cpp
@@ -277,20 +277,14 @@
pthread_mutex_destroy(&mCropLock);
pthread_mutex_destroy(&mParameterLock);
- if (mDefferedAllocation)
+ if (mDefferedAllocation) {
+ mStreamBufsAcquired = false;
releaseBuffs();
-
- if (mStreamInfoBuf != NULL) {
- int rc = mCamOps->unmap_stream_buf(mCamHandle,
- mChannelHandle, mHandle, CAM_MAPPING_BUF_TYPE_STREAM_INFO, 0, -1);
- if (rc < 0) {
- ALOGE("Failed to map stream info buffer");
- }
- mStreamInfoBuf->deallocate();
- delete mStreamInfoBuf;
- mStreamInfoBuf = NULL;
}
+ unmapStreamInfoBuf();
+ releaseStreamInfoBuf();
+
// delete stream
if (mHandle > 0) {
mCamOps->delete_stream(mCamHandle, mChannelHandle, mHandle);
@@ -299,6 +293,80 @@
}
/*===========================================================================
+ * FUNCTION : unmapStreamInfoBuf
+ *
+ * DESCRIPTION: Unmap stream info buffer
+ *
+ * PARAMETERS :
+ *
+ * RETURN : int32_t type of status
+ * NO_ERROR -- success
+ * none-zero failure code
+ *==========================================================================*/
+int32_t QCameraStream::unmapStreamInfoBuf()
+{
+ int rc = NO_ERROR;
+
+ if (mStreamInfoBuf != NULL) {
+ rc = mCamOps->unmap_stream_buf(mCamHandle,
+ mChannelHandle,
+ mHandle,
+ CAM_MAPPING_BUF_TYPE_STREAM_INFO,
+ 0,
+ -1);
+
+ if (rc < 0) {
+ ALOGE("Failed to unmap stream info buffer");
+ }
+ }
+
+ return rc;
+}
+
+/*===========================================================================
+ * FUNCTION : releaseStreamInfoBuf
+ *
+ * DESCRIPTION: Release stream info buffer
+ *
+ * PARAMETERS :
+ *
+ * RETURN : int32_t type of status
+ * NO_ERROR -- success
+ * none-zero failure code
+ *==========================================================================*/
+int32_t QCameraStream::releaseStreamInfoBuf()
+{
+ int rc = NO_ERROR;
+
+ if (mStreamInfoBuf != NULL) {
+ mStreamInfoBuf->deallocate();
+ delete mStreamInfoBuf;
+ mStreamInfoBuf = NULL;
+ }
+
+ return rc;
+}
+
+/*===========================================================================
+ * FUNCTION : deleteStream
+ *
+ * DESCRIPTION: Deletes a camera stream
+ *
+ * PARAMETERS : None
+ *
+ * RETURN : None
+ *==========================================================================*/
+void QCameraStream::deleteStream()
+{
+ if (mHandle > 0) {
+ acquireStreamBufs();
+ releaseBuffs();
+ unmapStreamInfoBuf();
+ mCamOps->delete_stream(mCamHandle, mChannelHandle, mHandle);
+ }
+}
+
+/*===========================================================================
* FUNCTION : init
*
* DESCRIPTION: initialize stream obj
@@ -503,6 +571,11 @@
{
int32_t rc = 0;
+ if (!m_bActive) {
+ ALOGV("%s : Stream not active", __func__);
+ return NO_ERROR;
+ }
+
// get stream param for crop info
for (int i = 0; i < crop_info.num_of_streams; i++) {
if (crop_info.crop_info[i].stream_id == mStreamInfo->stream_svr_id) {
@@ -958,16 +1031,19 @@
{
int rc = NO_ERROR;
- for (int i = 0; i < mNumBufs; i++) {
- rc = unmapBuf(CAM_MAPPING_BUF_TYPE_STREAM_BUF, i, -1);
- if (rc < 0) {
- ALOGE("%s: map_stream_buf failed: %d", __func__, rc);
+ if (NULL != mBufDefs) {
+ for (int i = 0; i < mNumBufs; i++) {
+ rc = unmapBuf(CAM_MAPPING_BUF_TYPE_STREAM_BUF, i, -1);
+ if (rc < 0) {
+ ALOGE("%s: map_stream_buf failed: %d", __func__, rc);
+ }
}
+
+ // mBufDefs just keep a ptr to the buffer
+ // mm-camera-interface owns the buffer, so no need to free
+ mBufDefs = NULL;
+ memset(&mFrameLenOffset, 0, sizeof(mFrameLenOffset));
}
- // mBufDefs just keep a ptr to the buffer
- // mm-camera-interface owns the buffer, so no need to free
- mBufDefs = NULL;
- memset(&mFrameLenOffset, 0, sizeof(mFrameLenOffset));
if ( !mStreamBufsAcquired ) {
mStreamBufs->deallocate();
delete mStreamBufs;
diff --git a/QCamera2/HAL/QCameraStream.h b/QCamera2/HAL/QCameraStream.h
index 699612a..3a6f0dd 100644
--- a/QCamera2/HAL/QCameraStream.h
+++ b/QCamera2/HAL/QCameraStream.h
@@ -98,6 +98,7 @@
static void releaseFrameData(void *data, void *user_data);
int32_t configStream();
bool isDeffered() const { return mDefferedAllocation; }
+ void deleteStream();
int mDumpFrame;
int mDumpMetaFrame;
@@ -170,6 +171,8 @@
int32_t invalidateBuf(int index);
int32_t cleanInvalidateBuf(int index);
int32_t calcOffset(cam_stream_info_t *streamInfo);
+ int32_t unmapStreamInfoBuf();
+ int32_t releaseStreamInfoBuf();
bool mDefferedAllocation;
};