summaryrefslogtreecommitdiff
path: root/camera
diff options
context:
space:
mode:
authorSusmitha Gummalla <vgummall@codeaurora.org>2016-10-12 12:37:47 -0700
committerShuzhen Wang <shuzhenwang@google.com>2017-08-11 13:59:39 -0700
commitdfd518b9a2caf943a1b7b44a02e30b0dc420d539 (patch)
tree8cbfafa6edb26b8bd2e2d4da7ccf1a9cf6699b6d /camera
parent3ddb2b1b54db36e76d0e30d4b1d198086e89d7de (diff)
QCamera2: Add cache flags to frame buffer
Store the flags recevied from v4l2 buffers and pass them to reprocess channel through param. CRs-Fixed: 1035387 Change-Id: Ic52824c036ba5f849f1feedbe0424238575ee502 mm-jpeg-interface: Jpeg cache ops cmd interface to HAL Add Jpeg cache ops command interface to HAL. CRs-Fixed: 1035387 Change-Id: Iebf5920675583db32da01e64142093a7400a52d9 QCamera2: Cache Op changes for stream buffers Do not invalidate/clean invalidate by default on the stream buffers. Assume buffers coming from kernel are clean and do required cache invalidate, clean if HAL touches the buffers in CPU. Test: Camera CTS Bug: 64605640 CRs-Fixed: 1035387 Change-Id: Ic39a73f1a759ed726002aa413df202387c1ee370
Diffstat (limited to 'camera')
-rw-r--r--camera/QCamera2/HAL/QCamera2HWI.cpp15
-rw-r--r--camera/QCamera2/HAL/QCamera2HWI.h1
-rw-r--r--camera/QCamera2/HAL/QCamera2HWICallbacks.cpp11
-rw-r--r--camera/QCamera2/HAL/QCameraChannel.cpp13
-rw-r--r--camera/QCamera2/HAL/QCameraPostProc.cpp11
-rw-r--r--camera/QCamera2/HAL/QCameraStream.cpp113
-rw-r--r--camera/QCamera2/HAL/QCameraStream.h3
-rw-r--r--camera/QCamera2/HAL3/QCamera3Channel.cpp14
-rw-r--r--camera/QCamera2/HAL3/QCamera3PostProc.cpp8
-rw-r--r--camera/QCamera2/HAL3/QCamera3Stream.cpp83
-rw-r--r--camera/QCamera2/HAL3/QCamera3Stream.h2
-rw-r--r--camera/QCamera2/HAL3/QCamera3StreamMem.cpp23
-rw-r--r--camera/QCamera2/HAL3/QCamera3StreamMem.h1
-rw-r--r--camera/QCamera2/stack/common/cam_intf.h3
-rw-r--r--camera/QCamera2/stack/common/cam_types.h10
-rw-r--r--camera/QCamera2/stack/common/mm_camera_interface.h3
-rw-r--r--camera/QCamera2/stack/common/mm_jpeg_interface.h27
-rw-r--r--camera/QCamera2/stack/mm-camera-interface/src/mm_camera_stream.c109
18 files changed, 429 insertions, 21 deletions
diff --git a/camera/QCamera2/HAL/QCamera2HWI.cpp b/camera/QCamera2/HAL/QCamera2HWI.cpp
index 55260af7..e486b8b2 100644
--- a/camera/QCamera2/HAL/QCamera2HWI.cpp
+++ b/camera/QCamera2/HAL/QCamera2HWI.cpp
@@ -1968,6 +1968,10 @@ int QCamera2HardwareInterface::openCamera()
pthread_mutex_unlock(&gCamLock);
}
+ memset(value, 0, sizeof(value));
+ property_get("persist.camera.cache.optimize", value, "1");
+ m_bOptimizeCacheOps = atoi(value);
+
return NO_ERROR;
error_exit3:
@@ -3016,6 +3020,12 @@ QCameraHeapMemory *QCamera2HardwareInterface::allocateStreamInfoBuf(
streamInfo->num_bufs = getBufNumRequired(stream_type);
streamInfo->streaming_mode = CAM_STREAMING_MODE_CONTINUOUS;
streamInfo->is_secure = NON_SECURE;
+ // Initialize cache ops
+ if (!m_bOptimizeCacheOps) {
+ streamInfo->cache_ops = CAM_STREAM_CACHE_OPS_DISABLED;
+ } else {
+ streamInfo->cache_ops = CAM_STREAM_CACHE_OPS_HONOUR_FLAGS;
+ }
switch (stream_type) {
case CAM_STREAM_TYPE_SNAPSHOT:
@@ -3088,6 +3098,9 @@ QCameraHeapMemory *QCamera2HardwareInterface::allocateStreamInfoBuf(
case CAM_STREAM_TYPE_ANALYSIS:
streamInfo->noFrameExpected = 1;
break;
+ case CAM_STREAM_TYPE_METADATA:
+ streamInfo->cache_ops = CAM_STREAM_CACHE_OPS_CLEAR_FLAGS;
+ break;
default:
break;
}
@@ -5738,6 +5751,8 @@ int QCamera2HardwareInterface::registerFaceImage(void *img_ptr,
return NO_MEMORY;
}
memcpy(pBufPtr, img_ptr, config->input_buf_planes.plane_info.frame_len);
+ //Do cache ops before sending for reprocess
+ imgBuf->cacheOps(0, ION_IOC_CLEAN_INV_CACHES);
cam_pp_feature_config_t pp_feature;
memset(&pp_feature, 0, sizeof(cam_pp_feature_config_t));
diff --git a/camera/QCamera2/HAL/QCamera2HWI.h b/camera/QCamera2/HAL/QCamera2HWI.h
index 0c1a00a0..9ab198c1 100644
--- a/camera/QCamera2/HAL/QCamera2HWI.h
+++ b/camera/QCamera2/HAL/QCamera2HWI.h
@@ -788,6 +788,7 @@ private:
/*FrameID to stop frameskip. If this is not set,
all frames are skipped till we set this*/
uint32_t mFrameSkipEnd;
+ bool m_bOptimizeCacheOps;
};
}; // namespace qcamera
diff --git a/camera/QCamera2/HAL/QCamera2HWICallbacks.cpp b/camera/QCamera2/HAL/QCamera2HWICallbacks.cpp
index 5c7d280c..dc24364c 100644
--- a/camera/QCamera2/HAL/QCamera2HWICallbacks.cpp
+++ b/camera/QCamera2/HAL/QCamera2HWICallbacks.cpp
@@ -339,6 +339,7 @@ int32_t QCamera2HardwareInterface::selectScene(QCameraChannel *pChannel,
if (preview_frame) {
QCameraGrallocMemory *memory = (QCameraGrallocMemory *)preview_frame->mem_info;
uint32_t idx = preview_frame->buf_idx;
+ preview_frame->cache_flags |= CPU_HAS_READ;
rc = sendPreviewCallback(pStream, memory, idx);
if (NO_ERROR != rc) {
LOGE("Error triggering scene select preview callback");
@@ -907,6 +908,7 @@ void QCamera2HardwareInterface::preview_stream_cb_routine(mm_camera_super_buf_t
if (pme->m_channels[QCAMERA_CH_TYPE_CALLBACK] == NULL) {
if (pme->needSendPreviewCallback() &&
(!pme->mParameters.isSceneSelectionEnabled())) {
+ frame->cache_flags |= CPU_HAS_READ;
int32_t rc = pme->sendPreviewCallback(stream, memory, idx);
if (NO_ERROR != rc) {
LOGW("Preview callback was not sent succesfully");
@@ -1168,6 +1170,8 @@ void QCamera2HardwareInterface::nodisplay_preview_stream_cb_routine(
cbArg.user_data = (void *) &frame->buf_idx;
cbArg.cookie = stream;
cbArg.release_cb = returnStreamBuffer;
+ // Preset cache flags to be handled when the buffer comes back
+ frame->cache_flags |= CPU_HAS_READ;
int32_t rc = pme->m_cbNotifier.notifyCallback(cbArg);
if (rc != NO_ERROR) {
LOGE ("fail sending data notify");
@@ -1251,6 +1255,8 @@ void QCamera2HardwareInterface::rdi_mode_stream_cb_routine(
cbArg.user_data = (void *) &frame->buf_idx;
cbArg.cookie = stream;
cbArg.release_cb = returnStreamBuffer;
+ // Preset cache flags to be handled when the buffer comes back
+ frame->cache_flags |= CPU_HAS_READ;
pme->m_cbNotifier.notifyCallback(cbArg);
} else {
LOGE("preview_mem is NULL");
@@ -1288,6 +1294,8 @@ void QCamera2HardwareInterface::rdi_mode_stream_cb_routine(
cbArg.user_data = (void *) &frame->buf_idx;
cbArg.cookie = stream;
cbArg.release_cb = returnStreamBuffer;
+ // Preset cache flags to be handled when the buffer comes back
+ frame->cache_flags |= CPU_HAS_READ;
pme->m_cbNotifier.notifyCallback(cbArg);
} else {
LOGH("No need to process preview frame, return buffer");
@@ -2529,6 +2537,8 @@ void QCamera2HardwareInterface::callback_stream_cb_routine(mm_camera_super_buf_t
if (pme->mDataCb != NULL &&
(pme->msgTypeEnabledWithLock(CAMERA_MSG_PREVIEW_FRAME) > 0) &&
(!pme->mParameters.isSceneSelectionEnabled())) {
+ // Preset cache flags to be handled when the buffer comes back
+ frame->cache_flags |= CPU_HAS_READ;
int32_t rc = pme->sendPreviewCallback(stream, previewMemObj, frame->buf_idx);
if (NO_ERROR != rc) {
LOGE("Preview callback was not sent succesfully");
@@ -2876,6 +2886,7 @@ void QCamera2HardwareInterface::dumpFrameToFile(QCameraStream *stream,
LOGH("written number of bytes %zd\n",
written_len);
close(file_fd);
+ frame->cache_flags |= CPU_HAS_READ;
} else {
LOGE("fail to open file for image dumping");
}
diff --git a/camera/QCamera2/HAL/QCameraChannel.cpp b/camera/QCamera2/HAL/QCameraChannel.cpp
index 7ceb58cb..1e97f73b 100644
--- a/camera/QCamera2/HAL/QCameraChannel.cpp
+++ b/camera/QCamera2/HAL/QCameraChannel.cpp
@@ -1456,6 +1456,14 @@ int32_t QCameraReprocessChannel::doReprocessOffline(mm_camera_super_buf_t *frame
}
}
+ if (mParameter.getofflineRAW()) {
+ //For offline RAW reprocessing, make sure cache is clean & invalidated
+ frame->bufs[i]->cache_flags |= CPU_HAS_READ_WRITTEN;
+ }
+ //Do Cache ops before sending to reprocess
+ if (frame->bufs[i] != NULL) {
+ pStream->handleCacheOps(frame->bufs[i]);
+ }
rc = doReprocessOffline (frame->bufs[i], meta_buf, pStream);
}
}
@@ -1513,6 +1521,11 @@ int32_t QCameraReprocessChannel::doReprocess(mm_camera_super_buf_t *frame,
continue;
}
+ //Do Cache ops before sending to reprocess
+ if (frame->bufs[i] != NULL) {
+ pStream->handleCacheOps(frame->bufs[i]);
+ }
+
cam_stream_parm_buffer_t param;
memset(&param, 0, sizeof(cam_stream_parm_buffer_t));
param.type = CAM_STREAM_PARAM_TYPE_DO_REPROCESS;
diff --git a/camera/QCamera2/HAL/QCameraPostProc.cpp b/camera/QCamera2/HAL/QCameraPostProc.cpp
index 8eddccf2..c054fd07 100644
--- a/camera/QCamera2/HAL/QCameraPostProc.cpp
+++ b/camera/QCamera2/HAL/QCameraPostProc.cpp
@@ -2153,6 +2153,8 @@ int32_t QCameraPostProcessor::encodeData(qcamera_jpeg_data_t *jpeg_job_data,
cbArg.msg_type = CAMERA_MSG_RAW_IMAGE;
cbArg.data = mem;
cbArg.index = 0;
+ // Data callback, set read/write flags
+ main_frame->cache_flags |= CPU_HAS_READ;
m_parent->m_cbNotifier.notifyCallback(cbArg);
}
if (NULL != m_parent->mNotifyCb &&
@@ -2526,6 +2528,13 @@ int32_t QCameraPostProcessor::encodeData(qcamera_jpeg_data_t *jpeg_job_data,
jpg_job.encode_job.multi_image_info.is_primary = FALSE;
jpg_job.encode_job.multi_image_info.num_of_images = 1;
}
+ //Do Cache ops before sending to encode
+ if (main_frame != NULL) {
+ main_stream->handleCacheOps(main_frame);
+ }
+ if (thumb_frame != NULL) {
+ thumb_stream->handleCacheOps(thumb_frame);
+ }
LOGI("[KPI Perf] : PROFILE_JPEG_JOB_START");
ret = mJpegHandle.start_job(&jpg_job, &jobId);
@@ -2648,6 +2657,7 @@ int32_t QCameraPostProcessor::processRawImageImpl(mm_camera_super_buf_t *recvd_f
cbArg.msg_type = CAMERA_MSG_RAW_IMAGE;
cbArg.data = raw_mem;
cbArg.index = 0;
+ frame->cache_flags |= CPU_HAS_READ;
m_parent->m_cbNotifier.notifyCallback(cbArg);
}
if (NULL != m_parent->mNotifyCb &&
@@ -2658,6 +2668,7 @@ int32_t QCameraPostProcessor::processRawImageImpl(mm_camera_super_buf_t *recvd_f
cbArg.msg_type = CAMERA_MSG_RAW_IMAGE_NOTIFY;
cbArg.ext1 = 0;
cbArg.ext2 = 0;
+ frame->cache_flags |= CPU_HAS_READ;
m_parent->m_cbNotifier.notifyCallback(cbArg);
}
diff --git a/camera/QCamera2/HAL/QCameraStream.cpp b/camera/QCamera2/HAL/QCameraStream.cpp
index a8f44c0f..2974c256 100644
--- a/camera/QCamera2/HAL/QCameraStream.cpp
+++ b/camera/QCamera2/HAL/QCameraStream.cpp
@@ -262,6 +262,44 @@ int32_t QCameraStream::clean_invalidate_buf(uint32_t index, void *user_data)
}
/*===========================================================================
+ * FUNCTION : clean_buf
+ *
+ * DESCRIPTION: static function entry to clean a specific stream buffer
+ *
+ * PARAMETERS :
+ * @index : index of the stream buffer to clean invalidate
+ * @user_data : user data ptr of ops_tbl
+ *
+ * RETURN : int32_t type of status
+ * NO_ERROR -- success
+ * none-zero failure code
+ *==========================================================================*/
+int32_t QCameraStream::clean_buf(uint32_t index, void *user_data)
+{
+ QCameraStream *stream = reinterpret_cast<QCameraStream *>(user_data);
+ if (!stream) {
+ LOGE("invalid stream pointer");
+ return NO_MEMORY;
+ }
+
+ if (stream->mStreamInfo->is_secure == SECURE){
+ return 0;
+ }
+
+ if (stream->mStreamInfo->streaming_mode == CAM_STREAMING_MODE_BATCH) {
+ for (int i = 0; i < stream->mBufDefs[index].user_buf.bufs_used; i++) {
+ uint32_t buf_idx = stream->mBufDefs[index].user_buf.buf_idx[i];
+ stream->cleanBuf(buf_idx);
+ }
+ } else {
+ return stream->cleanBuf(index);
+ }
+
+ return 0;
+}
+
+
+/*===========================================================================
* FUNCTION : set_config_ops
*
* DESCRIPTION: static function update mm-interface ops functions
@@ -352,6 +390,7 @@ QCameraStream::QCameraStream(QCameraAllocator &allocator,
}
mMemVtbl.invalidate_buf = invalidate_buf;
mMemVtbl.clean_invalidate_buf = clean_invalidate_buf;
+ mMemVtbl.clean_buf = clean_buf;
mMemVtbl.set_config_ops = set_config_ops;
memset(&mFrameLenOffset, 0, sizeof(mFrameLenOffset));
memcpy(&mPaddingInfo, paddingInfo, sizeof(cam_padding_info_t));
@@ -2184,6 +2223,27 @@ int32_t QCameraStream::cleanInvalidateBuf(uint32_t index)
}
/*===========================================================================
+ * FUNCTION : cleanBuf
+ *
+ * DESCRIPTION: clean a specific stream buffer
+ *
+ * PARAMETERS :
+ * @index : index of the buffer to clean
+ *
+ * RETURN : int32_t type of status
+ * NO_ERROR -- success
+ * none-zero failure code
+ *==========================================================================*/
+int32_t QCameraStream::cleanBuf(uint32_t index)
+{
+ if (mStreamBufs == NULL) {
+ LOGE("Invalid Operation");
+ return INVALID_OPERATION;
+ }
+ return mStreamBufs->cleanCache(index);
+}
+
+/*===========================================================================
* FUNCTION : isTypeOf
*
* DESCRIPTION: helper function to determine if the stream is of the queried type
@@ -2660,4 +2720,57 @@ int32_t QCameraStream::setSyncDataCB(stream_cb_routine data_cb)
return UNKNOWN_ERROR;
}
+/*===========================================================================
+ * FUNCTION : handleCacheOps
+ *
+ * DESCRIPTION: handle cache ops for this stream buffer
+ *
+ * PARAMETERS :
+ @buf : stream buffer
+ *
+ * RETURN : int32_t type of status
+ * NO_ERROR -- success
+ * non-zero failure code
+ *==========================================================================*/
+int32_t QCameraStream::handleCacheOps(mm_camera_buf_def_t* buf)
+{
+ int32_t rc = 0;
+ if( !buf) {
+ LOGE("Error!! buf_info: %p", buf);
+ rc = -1;
+ return rc;
+ }
+ if ((mMemVtbl.clean_invalidate_buf == NULL) ||
+ (mMemVtbl.invalidate_buf == NULL) ||
+ (mMemVtbl.clean_buf == NULL)) {
+ LOGI("Clean/Invalidate cache ops not supported");
+ rc = -1;
+ return rc;
+ }
+
+ LOGH("[CACHE_OPS] Stream type: %d buf index: %d cache ops flags: 0x%x",
+ buf->stream_type, buf->buf_idx, buf->cache_flags);
+
+ if ((buf->cache_flags & CPU_HAS_READ_WRITTEN) ==
+ CPU_HAS_READ_WRITTEN) {
+ rc = mMemVtbl.clean_invalidate_buf(
+ buf->buf_idx, mMemVtbl.user_data);
+ } else if ((buf->cache_flags & CPU_HAS_READ) ==
+ CPU_HAS_READ) {
+ rc = mMemVtbl.invalidate_buf(
+ buf->buf_idx, mMemVtbl.user_data);
+ } else if ((buf->cache_flags & CPU_HAS_WRITTEN) ==
+ CPU_HAS_WRITTEN) {
+ rc = mMemVtbl.clean_buf(
+ buf->buf_idx, mMemVtbl.user_data);
+ }
+ if (rc != 0) {
+ LOGW("Warning!! Clean/Invalidate cache failed on buffer index: %d",
+ buf->buf_idx);
+ }
+ // Reset buffer cache flags after cache ops
+ buf->cache_flags = 0;
+ return rc;
+}
+
}; // namespace qcamera
diff --git a/camera/QCamera2/HAL/QCameraStream.h b/camera/QCamera2/HAL/QCameraStream.h
index 4200f5d1..0efbc5b4 100644
--- a/camera/QCamera2/HAL/QCameraStream.h
+++ b/camera/QCamera2/HAL/QCameraStream.h
@@ -148,6 +148,7 @@ public:
uint8_t buf_index[CAMERA_MAX_CONSUMER_BATCH_BUFFER_SIZE];
} MetaMemory;
MetaMemory mStreamMetaMemory[CAMERA_MIN_VIDEO_BATCH_BUFFERS];
+ int32_t handleCacheOps(mm_camera_buf_def_t* buf);
private:
uint32_t mCamHandle;
@@ -218,6 +219,7 @@ private:
static int32_t invalidate_buf(uint32_t index, void *user_data);
static int32_t clean_invalidate_buf(uint32_t index, void *user_data);
+ static int32_t clean_buf(uint32_t index, void *user_data);
static int32_t backgroundAllocate(void* data);
static int32_t backgroundMap(void* data);
@@ -244,6 +246,7 @@ private:
int32_t invalidateBuf(uint32_t index);
int32_t cleanInvalidateBuf(uint32_t index);
+ int32_t cleanBuf(uint32_t index);
int32_t calcOffset(cam_stream_info_t *streamInfo);
int32_t unmapStreamInfoBuf();
int32_t releaseStreamInfoBuf();
diff --git a/camera/QCamera2/HAL3/QCamera3Channel.cpp b/camera/QCamera2/HAL3/QCamera3Channel.cpp
index dcc94b56..18d33da7 100644
--- a/camera/QCamera2/HAL3/QCamera3Channel.cpp
+++ b/camera/QCamera2/HAL3/QCamera3Channel.cpp
@@ -569,6 +569,7 @@ void QCamera3Channel::dumpYUV(mm_camera_buf_def_t *frame, cam_dimension_t dim,
}
LOGH("written number of bytes %ld\n", written_len);
mDumpFrmCnt++;
+ frame->cache_flags |= CPU_HAS_READ;
close(file_fd);
} else {
LOGE("failed to open file to dump image");
@@ -2223,6 +2224,7 @@ void QCamera3RawChannel::dumpRawSnapshot(mm_camera_buf_def_t *frame)
if (file_fd >= 0) {
ssize_t written_len = write(file_fd, frame->buffer, frame->frame_len);
LOGD("written number of bytes %zd", written_len);
+ frame->cache_flags |= CPU_HAS_READ;
close(file_fd);
} else {
LOGE("failed to open file to dump image");
@@ -2437,6 +2439,7 @@ void QCamera3RawDumpChannel::dumpRawSnapshot(mm_camera_buf_def_t *frame)
ssize_t written_len =
write(file_fd, frame->buffer, offset.frame_len);
LOGD("written number of bytes %zd", written_len);
+ frame->cache_flags |= CPU_HAS_READ;
close(file_fd);
} else {
LOGE("failed to open file to dump image");
@@ -4733,6 +4736,12 @@ int32_t QCamera3ReprocessChannel::overrideFwkMetadata(
mOfflineBuffersIndex = -1;
}
uint32_t buf_idx = (uint32_t)(mOfflineBuffersIndex + 1);
+
+ //Do cache ops before sending for reprocess
+ if (mMemory != NULL) {
+ mMemory->cleanInvalidateCache(buf_idx);
+ }
+
rc = pStream->mapBuf(
CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF,
buf_idx, -1,
@@ -4855,6 +4864,11 @@ int32_t QCamera3ReprocessChannel::doReprocess(int buf_fd, void *buffer, size_t b
buf_idx, -1,
buf_fd, buffer, buf_length);
+ //Do cache ops before sending for reprocess
+ if (mMemory != NULL) {
+ mMemory->cleanInvalidateCache(buf_idx);
+ }
+
if (rc == NO_ERROR) {
cam_stream_parm_buffer_t param;
memset(&param, 0, sizeof(cam_stream_parm_buffer_t));
diff --git a/camera/QCamera2/HAL3/QCamera3PostProc.cpp b/camera/QCamera2/HAL3/QCamera3PostProc.cpp
index 9934dea3..f890cd35 100644
--- a/camera/QCamera2/HAL3/QCamera3PostProc.cpp
+++ b/camera/QCamera2/HAL3/QCamera3PostProc.cpp
@@ -1185,7 +1185,6 @@ int32_t QCamera3PostProcessor::encodeFWKData(qcamera_hal3_jpeg_data_t *jpeg_job_
// create jpeg encoding session
mm_jpeg_encode_params_t encodeParam;
memset(&encodeParam, 0, sizeof(mm_jpeg_encode_params_t));
- encodeParam.main_dim.src_dim = src_dim;
encodeParam.main_dim.dst_dim = dst_dim;
encodeParam.thumb_dim.src_dim = src_dim;
encodeParam.thumb_dim.dst_dim = jpeg_settings->thumbnail_size;
@@ -1195,6 +1194,13 @@ int32_t QCamera3PostProcessor::encodeFWKData(qcamera_hal3_jpeg_data_t *jpeg_job_
}
getFWKJpegEncodeConfig(encodeParam, recvd_frame, jpeg_settings);
+ QCamera3StreamMem *memObj = (QCamera3StreamMem *)(recvd_frame->input_buffer.mem_info);
+ if (NULL == memObj) {
+ LOGE("Memeory Obj of main frame is NULL");
+ return NO_MEMORY;
+ }
+ // clean and invalidate cache ops through mem obj of the frame
+ memObj->cleanInvalidateCache(recvd_frame->input_buffer.buf_idx);
LOGH("#src bufs:%d # tmb bufs:%d #dst_bufs:%d",
encodeParam.num_src_bufs,encodeParam.num_tmb_bufs,encodeParam.num_dst_bufs);
diff --git a/camera/QCamera2/HAL3/QCamera3Stream.cpp b/camera/QCamera2/HAL3/QCamera3Stream.cpp
index a8ce061f..bc2ea9e7 100644
--- a/camera/QCamera2/HAL3/QCamera3Stream.cpp
+++ b/camera/QCamera2/HAL3/QCamera3Stream.cpp
@@ -33,6 +33,7 @@
#include "QCamera3HWI.h"
#include "QCamera3Stream.h"
#include "QCameraTrace.h"
+#include <cutils/properties.h>
extern "C" {
#include "mm_camera_dbg.h"
@@ -219,6 +220,47 @@ int32_t QCamera3Stream::clean_invalidate_buf(uint32_t index, void *user_data)
}
/*===========================================================================
+ * FUNCTION : clean_buf
+ *
+ * DESCRIPTION: static function entry to clean a specific stream buffer
+ *
+ * PARAMETERS :
+ * @index : index of the stream buffer to invalidate
+ * @user_data : user data ptr of ops_tbl
+ *
+ * RETURN : int32_t type of status
+ * NO_ERROR -- success
+ * none-zero failure code
+ *==========================================================================*/
+int32_t QCamera3Stream::clean_buf(uint32_t index, void *user_data)
+{
+ int32_t rc = NO_ERROR;
+
+ QCamera3Stream *stream = reinterpret_cast<QCamera3Stream *>(user_data);
+ if (!stream) {
+ LOGE("invalid stream pointer");
+ return NO_MEMORY;
+ }
+ if (stream->mBatchSize) {
+ int32_t retVal = NO_ERROR;
+ for (size_t i = 0;
+ i < stream->mBatchBufDefs[index].user_buf.bufs_used; i++) {
+ uint32_t buf_idx = stream->mBatchBufDefs[index].user_buf.buf_idx[i];
+ retVal = stream->cleanBuf(buf_idx);
+ if (NO_ERROR != retVal) {
+ LOGE("invalidateBuf failed for buf_idx: %d err: %d",
+ buf_idx, retVal);
+ }
+ rc |= retVal;
+ }
+ } else {
+ rc = stream->cleanBuf(index);
+ }
+ return rc;
+}
+
+
+/*===========================================================================
* FUNCTION : QCamera3Stream
*
* DESCRIPTION: constructor of QCamera3Stream
@@ -264,6 +306,7 @@ QCamera3Stream::QCamera3Stream(uint32_t camHandle,
mMemVtbl.put_bufs = put_bufs;
mMemVtbl.invalidate_buf = invalidate_buf;
mMemVtbl.clean_invalidate_buf = clean_invalidate_buf;
+ mMemVtbl.clean_buf = clean_buf;
mMemVtbl.set_config_ops = NULL;
memset(&mFrameLenOffset, 0, sizeof(mFrameLenOffset));
memcpy(&mPaddingInfo, paddingInfo, sizeof(cam_padding_info_t));
@@ -333,6 +376,8 @@ int32_t QCamera3Stream::init(cam_stream_type_t streamType,
{
int32_t rc = OK;
ssize_t bufSize = BAD_INDEX;
+ char value[PROPERTY_VALUE_MAX];
+ uint32_t bOptimizeCacheOps = 0;
mm_camera_stream_config_t stream_config;
LOGD("batch size is %d", batchSize);
@@ -367,6 +412,16 @@ int32_t QCamera3Stream::init(cam_stream_type_t streamType,
mStreamInfo->pp_config.feature_mask = postprocess_mask;
mStreamInfo->is_type = is_type;
mStreamInfo->pp_config.rotation = streamRotation;
+
+ memset(value, 0, sizeof(value));
+ property_get("persist.camera.cache.optimize", value, "1");
+ bOptimizeCacheOps = atoi(value);
+
+ if (bOptimizeCacheOps) {
+ mStreamInfo->cache_ops = CAM_STREAM_CACHE_OPS_HONOUR_FLAGS;
+ } else {
+ mStreamInfo->cache_ops = CAM_STREAM_CACHE_OPS_DISABLED;
+ }
LOGD("stream_type is %d, feature_mask is %Ld",
mStreamInfo->stream_type, mStreamInfo->pp_config.feature_mask);
@@ -726,6 +781,13 @@ int32_t QCamera3Stream::bufDone(uint32_t index)
if (UNLIKELY(mBatchSize)) {
rc = aggregateBufToBatch(mBufDefs[index]);
} else {
+ // By default every buffer that goes to camera should be invalidated
+ // except Metadata/Preview/Video buffers
+ if ((getMyType() != CAM_STREAM_TYPE_METADATA) &&
+ (getMyType() != CAM_STREAM_TYPE_PREVIEW) &&
+ (getMyType() != CAM_STREAM_TYPE_VIDEO)) {
+ mBufDefs[index].cache_flags |= CPU_HAS_READ;
+ }
rc = mCamOps->qbuf(mCamHandle, mChannelHandle, &mBufDefs[index]);
if (rc < 0) {
return FAILED_TRANSACTION;
@@ -1029,6 +1091,27 @@ int32_t QCamera3Stream::cleanInvalidateBuf(uint32_t index)
}
/*===========================================================================
+ * FUNCTION : cleanBuf
+ *
+ * DESCRIPTION: clean a specific stream buffer
+ *
+ * PARAMETERS :
+ * @index : index of the buffer to invalidate
+ *
+ * RETURN : int32_t type of status
+ * NO_ERROR -- success
+ * none-zero failure code
+ *==========================================================================*/
+int32_t QCamera3Stream::cleanBuf(uint32_t index)
+{
+ if (mStreamBufs == NULL) {
+ LOGE("putBufs already called");
+ return INVALID_OPERATION;
+ } else
+ return mStreamBufs->cleanCache(index);
+}
+
+/*===========================================================================
* FUNCTION : getFrameOffset
*
* DESCRIPTION: query stream buffer frame offset info
diff --git a/camera/QCamera2/HAL3/QCamera3Stream.h b/camera/QCamera2/HAL3/QCamera3Stream.h
index f4e13466..8cc82aec 100644
--- a/camera/QCamera2/HAL3/QCamera3Stream.h
+++ b/camera/QCamera2/HAL3/QCamera3Stream.h
@@ -148,6 +148,7 @@ private:
void *user_data);
static int32_t invalidate_buf(uint32_t index, void *user_data);
static int32_t clean_invalidate_buf(uint32_t index, void *user_data);
+ static int32_t clean_buf(uint32_t index, void *user_data);
int32_t getBufs(cam_frame_len_offset_t *offset,
uint8_t *num_bufs,
@@ -157,6 +158,7 @@ private:
int32_t putBufs(mm_camera_map_unmap_ops_tbl_t *ops_tbl);
int32_t invalidateBuf(uint32_t index);
int32_t cleanInvalidateBuf(uint32_t index);
+ int32_t cleanBuf(uint32_t index);
int32_t getBatchBufs(
uint8_t *num_bufs, uint8_t **initial_reg_flag,
mm_camera_buf_def_t **bufs,
diff --git a/camera/QCamera2/HAL3/QCamera3StreamMem.cpp b/camera/QCamera2/HAL3/QCamera3StreamMem.cpp
index aa2388e2..5c09d6b4 100644
--- a/camera/QCamera2/HAL3/QCamera3StreamMem.cpp
+++ b/camera/QCamera2/HAL3/QCamera3StreamMem.cpp
@@ -191,6 +191,29 @@ int QCamera3StreamMem::cleanInvalidateCache(uint32_t index)
}
/*===========================================================================
+ * FUNCTION : cleanCache
+ *
+ * DESCRIPTION: clean the cache of the indexed buffer
+ *
+ * PARAMETERS :
+ * @index : index of the buffer
+ *
+ * RETURN : int32_t type of status
+ * NO_ERROR -- success
+ * none-zero failure code
+ *==========================================================================*/
+int QCamera3StreamMem::cleanCache(uint32_t index)
+{
+ Mutex::Autolock lock(mLock);
+
+ if (index < mMaxHeapBuffers)
+ return mHeapMem.cleanCache(index);
+ else
+ return mGrallocMem.cleanCache(index);
+}
+
+
+/*===========================================================================
* FUNCTION : getBufDef
*
* DESCRIPTION: query detailed buffer information
diff --git a/camera/QCamera2/HAL3/QCamera3StreamMem.h b/camera/QCamera2/HAL3/QCamera3StreamMem.h
index 9095bdbb..92713ea6 100644
--- a/camera/QCamera2/HAL3/QCamera3StreamMem.h
+++ b/camera/QCamera2/HAL3/QCamera3StreamMem.h
@@ -57,6 +57,7 @@ public:
ssize_t getSize(uint32_t index);
int invalidateCache(uint32_t index);
int cleanInvalidateCache(uint32_t index);
+ int cleanCache(uint32_t index);
int32_t getBufDef(const cam_frame_len_offset_t &offset,
mm_camera_buf_def_t &bufDef, uint32_t index);
void *getPtr(uint32_t index);
diff --git a/camera/QCamera2/stack/common/cam_intf.h b/camera/QCamera2/stack/common/cam_intf.h
index b99ff627..315f522b 100644
--- a/camera/QCamera2/stack/common/cam_intf.h
+++ b/camera/QCamera2/stack/common/cam_intf.h
@@ -637,6 +637,9 @@ typedef struct {
/* if frames will not be received */
uint8_t noFrameExpected;
+
+ /* Cache ops for this stream */
+ cam_stream_cache_ops_t cache_ops;
} cam_stream_info_t;
/*****************************************************************************
diff --git a/camera/QCamera2/stack/common/cam_types.h b/camera/QCamera2/stack/common/cam_types.h
index 91b73524..b1dd8afe 100644
--- a/camera/QCamera2/stack/common/cam_types.h
+++ b/camera/QCamera2/stack/common/cam_types.h
@@ -149,6 +149,10 @@
/* Index to switch H/W to consume to free-run Q*/
#define CAM_FREERUN_IDX 0xFFFFFFFF
+#define CPU_HAS_READ (1 << 0)
+#define CPU_HAS_WRITTEN (1 << 1)
+#define CPU_HAS_READ_WRITTEN (CPU_HAS_READ |CPU_HAS_WRITTEN)
+
typedef uint64_t cam_feature_mask_t;
typedef enum {
@@ -2805,4 +2809,10 @@ typedef enum {
CAM_CUSTOM_PARM_MAX,
} cam_custom_parm_type;
+typedef enum {
+ CAM_STREAM_CACHE_OPS_CLEAR_FLAGS,
+ CAM_STREAM_CACHE_OPS_HONOUR_FLAGS,
+ CAM_STREAM_CACHE_OPS_DISABLED
+} cam_stream_cache_ops_t;
+
#endif /* __QCAMERA_TYPES_H__ */
diff --git a/camera/QCamera2/stack/common/mm_camera_interface.h b/camera/QCamera2/stack/common/mm_camera_interface.h
index d6bd92e2..f34911bd 100644
--- a/camera/QCamera2/stack/common/mm_camera_interface.h
+++ b/camera/QCamera2/stack/common/mm_camera_interface.h
@@ -120,6 +120,7 @@ typedef struct {
* mem allocation
* @mem_info : user specific pointer to additional mem info
* @flags: v4l2_buffer flags, used to report error in data buffers
+* @cache_flags: Stores cache related read/write flags
**/
typedef struct mm_camera_buf_def {
uint32_t stream_id;
@@ -138,6 +139,7 @@ typedef struct mm_camera_buf_def {
size_t frame_len;
void *mem_info;
uint32_t flags;
+ uint32_t cache_flags;
} mm_camera_buf_def_t;
/** mm_camera_super_buf_t: super buf structure for bundled
@@ -274,6 +276,7 @@ typedef struct {
void *user_data);
int32_t (*invalidate_buf)(uint32_t index, void *user_data);
int32_t (*clean_invalidate_buf)(uint32_t index, void *user_data);
+ int32_t (*clean_buf)(uint32_t index, void *user_data);
} mm_camera_stream_mem_vtbl_t;
/** mm_camera_stream_config_t: structure for stream
diff --git a/camera/QCamera2/stack/common/mm_jpeg_interface.h b/camera/QCamera2/stack/common/mm_jpeg_interface.h
index 73fc7ad0..8ee697be 100644
--- a/camera/QCamera2/stack/common/mm_jpeg_interface.h
+++ b/camera/QCamera2/stack/common/mm_jpeg_interface.h
@@ -43,6 +43,10 @@
#define QTABLE_MAX 2
#define MM_JPEG_MAX_MPO_IMAGES 2
+/* bit mask for buffer usage*/
+#define MM_JPEG_HAS_READ_BUF CPU_HAS_READ
+#define MM_JPEG_HAS_WRITTEN_BUF CPU_HAS_WRITTEN
+
typedef enum {
MM_JPEG_FMT_YUV,
MM_JPEG_FMT_BITSTREAM
@@ -237,6 +241,24 @@ typedef struct {
} mm_jpeg_decode_params_t;
+/* This structure is populated by HAL to notify buffer
+ usage like has read or has written. This info is then
+ used to perform cache ops in jpeg */
+typedef struct {
+ /* main image source buff usage */
+ uint8_t main_src_buf;
+
+ /* thumbnail source buff usage */
+ uint8_t thumb_src_buf;
+
+ /* destination buff usage */
+ uint8_t dest_buf;
+
+ /* work buff usage */
+ uint8_t work_buf;
+
+} mm_jpeg_buf_usage_t;
+
typedef struct {
/* active indices of the buffers for encoding */
int32_t src_index;
@@ -285,6 +307,11 @@ typedef struct {
/* work buf */
mm_jpeg_buf_t work_buf;
+
+ /* Input from HAL notifing the prior usage of buffers,
+ this info will be used to perform cache ops*/
+ mm_jpeg_buf_usage_t buf_usage;
+
} mm_jpeg_encode_job_t;
typedef struct {
diff --git a/camera/QCamera2/stack/mm-camera-interface/src/mm_camera_stream.c b/camera/QCamera2/stack/mm-camera-interface/src/mm_camera_stream.c
index ba5cf020..362cb22a 100644
--- a/camera/QCamera2/stack/mm-camera-interface/src/mm_camera_stream.c
+++ b/camera/QCamera2/stack/mm-camera-interface/src/mm_camera_stream.c
@@ -37,6 +37,7 @@
#include TIME_H
#define IOCTL_H <SYSTEM_HEADER_PREFIX/ioctl.h>
#include IOCTL_H
+#include <cutils/properties.h>
#define ATRACE_TAG ATRACE_TAG_CAMERA
#include <cutils/trace.h>
@@ -138,6 +139,8 @@ int32_t mm_stream_fsm_active(mm_stream_t * my_obj,
void * in_val,
void * out_val);
uint32_t mm_stream_get_v4l2_fmt(cam_format_t fmt);
+int32_t mm_stream_handle_cache_ops(mm_stream_t* my_obj,
+ mm_camera_buf_def_t* buf, bool deque);
/*===========================================================================
@@ -1558,6 +1561,9 @@ int32_t mm_stream_read_msm_frame(mm_stream_t * my_obj,
buf_info->buf->ts.tv_sec = vb.timestamp.tv_sec;
buf_info->buf->ts.tv_nsec = vb.timestamp.tv_usec * 1000;
buf_info->buf->flags = vb.flags;
+ // Buffers are cleaned/invalidated when received by HAL
+ // Cache ops not required on DQBUF
+ buf_info->buf->cache_flags = 0;
LOGH("VIDIOC_DQBUF buf_index %d, frame_idx %d, stream type %d, rc %d,"
"queued: %d, buf_type = %d flags = %d",
@@ -1573,15 +1579,9 @@ int32_t mm_stream_read_msm_frame(mm_stream_t * my_obj,
mm_stream_read_user_buf(my_obj, buf_info);
}
- if ( NULL != my_obj->mem_vtbl.clean_invalidate_buf ) {
- rc = my_obj->mem_vtbl.clean_invalidate_buf(idx,
- my_obj->mem_vtbl.user_data);
- if (0 > rc) {
- LOGE("Clean invalidate cache failed on buffer index: %d",
- idx);
- }
- } else {
- LOGE("Clean invalidate cache op not supported");
+ rc = mm_stream_handle_cache_ops(my_obj, buf_info->buf, TRUE);
+ if (rc != 0) {
+ LOGE("Error cleaning/invalidating the buffer");
}
}
@@ -1776,18 +1776,10 @@ int32_t mm_stream_qbuf(mm_stream_t *my_obj, mm_camera_buf_def_t *buf)
buffer.m.planes = &planes[0];
buffer.length = (__u32)length;
- if ( NULL != my_obj->mem_vtbl.invalidate_buf ) {
- rc = my_obj->mem_vtbl.invalidate_buf(buffer.index,
- my_obj->mem_vtbl.user_data);
- if ( 0 > rc ) {
- LOGE("Cache invalidate failed on buffer index: %d",
- buffer.index);
- return rc;
- }
- } else {
- LOGE("Cache invalidate op not added");
+ rc = mm_stream_handle_cache_ops(my_obj, buf, FALSE);
+ if (rc != 0) {
+ LOGE("Error cleaning/invalidating the buffer");
}
-
pthread_mutex_lock(&my_obj->buf_lock);
my_obj->queued_buffer_count++;
if (1 == my_obj->queued_buffer_count) {
@@ -4789,3 +4781,80 @@ int32_t mm_stream_reg_buf_cb(mm_stream_t *my_obj,
return rc;
}
+
+/*===========================================================================
+ * FUNCTION : mm_stream_handle_cache_ops
+ *
+ * DESCRIPTION: handles cache ops of a stream buffer
+ *
+ * PARAMETERS :
+ * @my_obj : stream object
+ * @buf : ptr to a stream buffer
+ * @deque : specifies if enqueue or dequeue
+ *
+ * RETURN : zero for success
+ * non-zero error value
+ *==========================================================================*/
+int32_t mm_stream_handle_cache_ops(mm_stream_t* my_obj,
+ mm_camera_buf_def_t* buf, bool deque)
+{
+ int32_t rc = 0;
+ if(!my_obj || !buf) {
+ LOGE("Error!! my_obj: %p, buf_info: %p", my_obj, buf);
+ rc = -1;
+ return rc;
+ }
+ if ((my_obj->mem_vtbl.clean_invalidate_buf == NULL) ||
+ (my_obj->mem_vtbl.invalidate_buf == NULL) ||
+ (my_obj->mem_vtbl.clean_buf == NULL)) {
+ LOGI("Clean/Invalidate cache ops not supported");
+ rc = -1;
+ return rc;
+ }
+
+ // Modify clean and invalidate flags depending on cache ops for stream
+ switch (my_obj->stream_info->cache_ops) {
+ case CAM_STREAM_CACHE_OPS_CLEAR_FLAGS:
+ buf->cache_flags = 0;
+ break;
+ case CAM_STREAM_CACHE_OPS_DISABLED:
+ if (deque) {
+ buf->cache_flags = CPU_HAS_READ_WRITTEN;
+ }
+ else {
+ buf->cache_flags = CPU_HAS_READ;
+ }
+ case CAM_STREAM_CACHE_OPS_HONOUR_FLAGS:
+ default:
+ // Do not change flags
+ break;
+ }
+
+ if ((buf->cache_flags & CPU_HAS_READ_WRITTEN) ==
+ CPU_HAS_READ_WRITTEN) {
+ rc = my_obj->mem_vtbl.clean_invalidate_buf(
+ buf->buf_idx, my_obj->mem_vtbl.user_data);
+ } else if ((buf->cache_flags & CPU_HAS_READ) ==
+ CPU_HAS_READ) {
+ rc = my_obj->mem_vtbl.invalidate_buf(
+ buf->buf_idx, my_obj->mem_vtbl.user_data);
+ } else if ((buf->cache_flags & CPU_HAS_WRITTEN) ==
+ CPU_HAS_WRITTEN) {
+ rc = my_obj->mem_vtbl.clean_buf(
+ buf->buf_idx, my_obj->mem_vtbl.user_data);
+ }
+
+ LOGH("[CACHE_OPS] Stream type: %d buf index: %d cache ops flags: 0x%x",
+ buf->stream_type, buf->buf_idx, buf->cache_flags);
+
+ if (rc != 0) {
+ LOGE("Clean/Invalidate cache failed on buffer index: %d",
+ buf->buf_idx);
+ } else {
+ // Reset buffer cache flags after cache ops
+ buf->cache_flags = 0;
+ }
+
+ return rc;
+}
+