diff options
| author | Susmitha Gummalla <vgummall@codeaurora.org> | 2016-10-12 12:37:47 -0700 |
|---|---|---|
| committer | Shuzhen Wang <shuzhenwang@google.com> | 2017-08-11 13:59:39 -0700 |
| commit | dfd518b9a2caf943a1b7b44a02e30b0dc420d539 (patch) | |
| tree | 8cbfafa6edb26b8bd2e2d4da7ccf1a9cf6699b6d /camera | |
| parent | 3ddb2b1b54db36e76d0e30d4b1d198086e89d7de (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.cpp | 15 | ||||
| -rw-r--r-- | camera/QCamera2/HAL/QCamera2HWI.h | 1 | ||||
| -rw-r--r-- | camera/QCamera2/HAL/QCamera2HWICallbacks.cpp | 11 | ||||
| -rw-r--r-- | camera/QCamera2/HAL/QCameraChannel.cpp | 13 | ||||
| -rw-r--r-- | camera/QCamera2/HAL/QCameraPostProc.cpp | 11 | ||||
| -rw-r--r-- | camera/QCamera2/HAL/QCameraStream.cpp | 113 | ||||
| -rw-r--r-- | camera/QCamera2/HAL/QCameraStream.h | 3 | ||||
| -rw-r--r-- | camera/QCamera2/HAL3/QCamera3Channel.cpp | 14 | ||||
| -rw-r--r-- | camera/QCamera2/HAL3/QCamera3PostProc.cpp | 8 | ||||
| -rw-r--r-- | camera/QCamera2/HAL3/QCamera3Stream.cpp | 83 | ||||
| -rw-r--r-- | camera/QCamera2/HAL3/QCamera3Stream.h | 2 | ||||
| -rw-r--r-- | camera/QCamera2/HAL3/QCamera3StreamMem.cpp | 23 | ||||
| -rw-r--r-- | camera/QCamera2/HAL3/QCamera3StreamMem.h | 1 | ||||
| -rw-r--r-- | camera/QCamera2/stack/common/cam_intf.h | 3 | ||||
| -rw-r--r-- | camera/QCamera2/stack/common/cam_types.h | 10 | ||||
| -rw-r--r-- | camera/QCamera2/stack/common/mm_camera_interface.h | 3 | ||||
| -rw-r--r-- | camera/QCamera2/stack/common/mm_jpeg_interface.h | 27 | ||||
| -rw-r--r-- | camera/QCamera2/stack/mm-camera-interface/src/mm_camera_stream.c | 109 |
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(¶m, 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(¶m, 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; +} + |
