camera: update AU_LINUX_ANDROID_LA.BF64.1.2.9.05.01.00.089.199
Camera3: Enable offline postprocessing for large YUV streams
QCamera2/HAL3: Silence dynamicblackLevel logs
Bug: 22843933
Change-Id: I28ae0512f1817736c3804e6fa2d2833b8681d2c8
diff --git a/QCamera2/Android.mk b/QCamera2/Android.mk
index 4de60e0..bb3e846 100644
--- a/QCamera2/Android.mk
+++ b/QCamera2/Android.mk
@@ -19,7 +19,8 @@
HAL3/QCamera3Channel.cpp \
HAL3/QCamera3VendorTags.cpp \
HAL3/QCamera3PostProc.cpp \
- HAL3/QCamera3CropRegionMapper.cpp
+ HAL3/QCamera3CropRegionMapper.cpp \
+ HAL3/QCamera3StreamMem.cpp
#HAL 1.0 source
LOCAL_SRC_FILES += \
diff --git a/QCamera2/HAL3/QCamera3Channel.cpp b/QCamera2/HAL3/QCamera3Channel.cpp
index cbe404e..eba928b 100644
--- a/QCamera2/HAL3/QCamera3Channel.cpp
+++ b/QCamera2/HAL3/QCamera3Channel.cpp
@@ -572,13 +572,16 @@
QCamera3Channel(cam_handle, cam_ops, cb_routine,
paddingInfo, postprocess_mask, userData, numBuffers),
m_postprocessor(this),
+ mMemory(numBuffers),
mCamera3Stream(stream),
mNumBufs(CAM_MAX_NUM_BUFS_PER_STREAM),
mStreamType(stream_type),
mPostProcStarted(false),
mInputBufferConfig(false),
m_pMetaChannel(metadataChannel),
- mMetaFrame(NULL)
+ mMetaFrame(NULL),
+ mOfflineMemory(0),
+ mOfflineMetaMemory(1)
{
int32_t rc = m_postprocessor.init(&mMemory, mPostProcMask);
if (rc != 0) {
@@ -638,26 +641,11 @@
int32_t resultFrameNumber;
camera3_stream_buffer_t result;
- if (NULL == stream) {
- ALOGE("%s: Invalid stream", __func__);
+ if (checkStreamCbErrors(super_frame, stream) != NO_ERROR) {
+ ALOGE("%s: Error with the stream callback", __func__);
return;
}
- if(NULL == super_frame) {
- ALOGE("%s: Invalid Super buffer",__func__);
- return;
- }
-
- if(super_frame->num_bufs != 1) {
- ALOGE("%s: Multiple streams are not supported",__func__);
- return;
- }
- if(NULL == super_frame->bufs[0]) {
- ALOGE("%s: Error, Super buffer frame does not contain valid buffer",
- __func__);
- return;
- }
-
frameIndex = (uint8_t)super_frame->bufs[0]->buf_idx;
if(frameIndex >= mNumBufs) {
ALOGE("%s: Error, Invalid index for buffer",__func__);
@@ -704,10 +692,10 @@
* output request
*
* PARAMETERS :
- * @buffer : pointer to the output buffer
- * @frameNumber : frame number of the request
- * @pInputBuffer : pointer to input buffer if an input request
- * @metadata : parameters associated with the request
+ * @buffer : pointer to the output buffer
+ * @frameNumber : frame number of the request
+ * @pInputBuffer : pointer to input buffer if an input request
+ * @metadata : parameters associated with the request
*
* RETURN : 0 on a success start of capture
* -EINVAL on invalid input
@@ -730,8 +718,10 @@
//need to send to reprocessing
CDBG("%s: Got a request with input buffer, output streamType = %d", __func__, mStreamType);
reprocess_config_t reproc_cfg;
+ cam_dimension_t dim;
memset(&reproc_cfg, 0, sizeof(reprocess_config_t));
- setReprocConfig(reproc_cfg, pInputBuffer, metadata, mStreamFormat);
+ memset(&dim, 0, sizeof(dim));
+ setReprocConfig(reproc_cfg, pInputBuffer, metadata, mStreamFormat, dim);
startPostProc((NULL != pInputBuffer), reproc_cfg);
qcamera_fwk_input_pp_data_t *src_frame = NULL;
@@ -942,6 +932,44 @@
}
/*===========================================================================
+ * FUNCTION : checkStreamCbErrors
+ *
+ * DESCRIPTION: check the stream callback for errors
+ *
+ * PARAMETERS :
+ * @super_frame : the super frame with filled buffer
+ * @stream : stream on which the buffer was requested and filled
+ *
+ * RETURN : int32_t type of status
+ * NO_ERROR -- success
+ * none-zero failure code
+ *==========================================================================*/
+int32_t QCamera3ProcessingChannel::checkStreamCbErrors(mm_camera_super_buf_t *super_frame,
+ QCamera3Stream *stream)
+{
+ if (NULL == stream) {
+ ALOGE("%s: Invalid stream", __func__);
+ return BAD_VALUE;
+ }
+
+ if(NULL == super_frame) {
+ ALOGE("%s: Invalid Super buffer",__func__);
+ return BAD_VALUE;
+ }
+
+ if(super_frame->num_bufs != 1) {
+ ALOGE("%s: Multiple streams are not supported",__func__);
+ return BAD_VALUE;
+ }
+ if(NULL == super_frame->bufs[0]) {
+ ALOGE("%s: Error, Super buffer frame does not contain valid buffer",
+ __func__);
+ return BAD_VALUE;
+ }
+ return NO_ERROR;
+}
+
+/*===========================================================================
* FUNCTION : getStreamBufs
*
* DESCRIPTION: get the buffers allocated to the stream
@@ -953,7 +981,7 @@
* NO_ERROR -- success
* none-zero failure code
*==========================================================================*/
-QCamera3Memory* QCamera3ProcessingChannel::getStreamBufs(uint32_t /*len*/)
+QCamera3StreamMem* QCamera3ProcessingChannel::getStreamBufs(uint32_t /*len*/)
{
return &mMemory;
}
@@ -1101,7 +1129,10 @@
streamType = CAM_STREAM_TYPE_VIDEO;
streamFormat = VIDEO_FORMAT;
} else if(stream->stream_type == CAMERA3_STREAM_INPUT ||
- stream->stream_type == CAMERA3_STREAM_BIDIRECTIONAL){
+ stream->stream_type == CAMERA3_STREAM_BIDIRECTIONAL ||
+ (stream->usage & GRALLOC_USAGE_HW_CAMERA_ZSL) ==
+ GRALLOC_USAGE_HW_CAMERA_ZSL){
+ //TODO: Fix HW_CAMERA_ZSL check logic in other places as well
streamType = CAM_STREAM_TYPE_SNAPSHOT;
streamFormat = SNAPSHOT_FORMAT;
} else {
@@ -1141,7 +1172,7 @@
int32_t QCamera3ProcessingChannel::setReprocConfig(reprocess_config_t &reproc_cfg,
camera3_stream_buffer_t *pInputBuffer,
metadata_buffer_t *metadata,
- cam_format_t streamFormat)
+ cam_format_t streamFormat, cam_dimension_t dim)
{
int32_t rc = 0;
reproc_cfg.padding = mPaddingInfo;
@@ -1156,14 +1187,12 @@
reproc_cfg.input_stream_dim.width = (int32_t)pInputBuffer->stream->width;
reproc_cfg.input_stream_dim.height = (int32_t)pInputBuffer->stream->height;
} else {
- reproc_cfg.input_stream_dim.width = (int32_t)mCamera3Stream->width;
- reproc_cfg.input_stream_dim.height = (int32_t)mCamera3Stream->height;
+ reproc_cfg.input_stream_dim.width = (int32_t)dim.width;
+ reproc_cfg.input_stream_dim.height = (int32_t)dim.height;
reproc_cfg.src_channel = this;
}
reproc_cfg.output_stream_dim.width = mCamera3Stream->width;
reproc_cfg.output_stream_dim.height = mCamera3Stream->height;
- reproc_cfg.stream_type = mStreamType;
- reproc_cfg.stream_format = streamFormat;
reproc_cfg.reprocess_type = getReprocessType();
//offset calculation
@@ -1175,35 +1204,36 @@
pInputBuffer->stream->format);
return rc;
}
- CDBG("%s: reproc_cfg.stream_type = %d, reproc_cfg.stream_format = %d", __func__,
- reproc_cfg.stream_type, reproc_cfg.stream_format);
-
- switch (reproc_cfg.stream_type) {
- case CAM_STREAM_TYPE_CALLBACK:
- case CAM_STREAM_TYPE_PREVIEW:
- rc = mm_stream_calc_offset_preview(streamFormat,
- &reproc_cfg.input_stream_dim,
- &reproc_cfg.input_stream_plane_info);
- break;
- case CAM_STREAM_TYPE_VIDEO:
- rc = mm_stream_calc_offset_video(&reproc_cfg.input_stream_dim,
- &reproc_cfg.input_stream_plane_info);
- break;
- case CAM_STREAM_TYPE_RAW:
- rc = mm_stream_calc_offset_raw(streamFormat, &reproc_cfg.input_stream_dim,
- reproc_cfg.padding, &reproc_cfg.input_stream_plane_info);
- break;
- case CAM_STREAM_TYPE_SNAPSHOT:
- default:
- rc = mm_stream_calc_offset_snapshot(streamFormat, &reproc_cfg.input_stream_dim,
- reproc_cfg.padding, &reproc_cfg.input_stream_plane_info);
- break;
- }
- if (rc != 0) {
- ALOGE("%s: Stream %d plane info calculation failed!", __func__, mStreamType);
- return rc;
- }
+ } else {
+ reproc_cfg.stream_type = mStreamType;
+ reproc_cfg.stream_format = streamFormat;
}
+
+ switch (reproc_cfg.stream_type) {
+ case CAM_STREAM_TYPE_CALLBACK:
+ case CAM_STREAM_TYPE_PREVIEW:
+ rc = mm_stream_calc_offset_preview(streamFormat,
+ &reproc_cfg.input_stream_dim,
+ &reproc_cfg.input_stream_plane_info);
+ break;
+ case CAM_STREAM_TYPE_VIDEO:
+ rc = mm_stream_calc_offset_video(&reproc_cfg.input_stream_dim,
+ &reproc_cfg.input_stream_plane_info);
+ break;
+ case CAM_STREAM_TYPE_RAW:
+ rc = mm_stream_calc_offset_raw(streamFormat, &reproc_cfg.input_stream_dim,
+ reproc_cfg.padding, &reproc_cfg.input_stream_plane_info);
+ break;
+ case CAM_STREAM_TYPE_SNAPSHOT:
+ default:
+ rc = mm_stream_calc_offset_snapshot(streamFormat, &reproc_cfg.input_stream_dim,
+ reproc_cfg.padding, &reproc_cfg.input_stream_plane_info);
+ break;
+ }
+ if (rc != 0) {
+ ALOGE("%s: Stream %d plane info calculation failed!", __func__, mStreamType);
+ }
+
return rc;
}
@@ -1235,6 +1265,7 @@
result.release_fence = -1;
mChannelCB(NULL, &result, resultFrameNumber, mUserData);
+
return;
}
@@ -1632,7 +1663,7 @@
mChannelCB(super_frame, NULL, requestNumber, mUserData);
}
-QCamera3Memory* QCamera3MetadataChannel::getStreamBufs(uint32_t len)
+QCamera3StreamMem* QCamera3MetadataChannel::getStreamBufs(uint32_t len)
{
int rc;
if (len < sizeof(metadata_buffer_t)) {
@@ -1642,7 +1673,7 @@
sizeof(metadata_buffer_t));
return NULL;
}
- mMemory = new QCamera3HeapMemory();
+ mMemory = new QCamera3StreamMem(MIN_STREAMING_BUFFER_NUM);
if (!mMemory) {
ALOGE("%s: unable to create metadata memory", __func__);
return NULL;
@@ -2011,12 +2042,12 @@
* @len : Length of each buffer to be allocated
*
* RETURN : NULL on buffer allocation failure
- * QCamera3Memory object on sucess
+ * QCamera3StreamMem object on sucess
*==========================================================================*/
-QCamera3Memory* QCamera3RawDumpChannel::getStreamBufs(uint32_t len)
+QCamera3StreamMem* QCamera3RawDumpChannel::getStreamBufs(uint32_t len)
{
int rc;
- mMemory = new QCamera3HeapMemory();
+ mMemory = new QCamera3StreamMem(mNumBuffers);
if (!mMemory) {
ALOGE("%s: unable to create heap memory", __func__);
@@ -2137,6 +2168,12 @@
paddingInfo, userData, stream, stream_type, postprocess_mask,
metadataChannel)
{
+
+ mBypass = (postprocess_mask == CAM_QCOM_FEATURE_NONE);
+ mEdgeMode.edge_mode = CAM_EDGE_MODE_OFF;
+ mEdgeMode.sharpness = 0;
+ mNoiseRedMode = CAM_NOISE_REDUCTION_MODE_OFF;
+ memset(&mCropRegion, 0, sizeof(mCropRegion));
}
/*===========================================================================
@@ -2151,6 +2188,8 @@
*==========================================================================*/
QCamera3YUVChannel::~QCamera3YUVChannel()
{
+ // Deallocation of heap buffers allocated in mMemory is freed
+ // automatically by its destructor
}
/*===========================================================================
@@ -2199,6 +2238,34 @@
mNumBufs,
mPostProcMask,
mIsType);
+ if (rc < 0) {
+ ALOGE("%s: addStream failed", __func__);
+ return rc;
+ }
+
+ if (mBypass) {
+ // Allocate heap buffers up front
+ cam_stream_buf_plane_info_t buf_planes;
+ memset(&buf_planes, 0, sizeof(buf_planes));
+ rc = mm_stream_calc_offset_preview(mStreamFormat, &streamDim, &buf_planes);
+ if (rc < 0) {
+ ALOGE("%s: mm_stream_calc_offset_preview failed", __func__);
+ return rc;
+ }
+
+ // TODO: Do not queue heap buffers up front because we don't know whether
+ // heap buffers will be used or not. It depends on the actual request
+ rc = mMemory.allocate(mNumBuffers, buf_planes.plane_info.frame_len, false);
+ if (rc == NO_ERROR) {
+
+ Mutex::Autolock lock(mOfflinePpLock);
+ mFreeHeapBufferList.clear();
+
+ for (uint32_t i = 0; i < mNumBuffers; i++) {
+ mFreeHeapBufferList.push_back(i);
+ }
+ }
+ }
return rc;
}
@@ -2226,6 +2293,320 @@
}
/*===========================================================================
+ * FUNCTION : request
+ *
+ * DESCRIPTION: entry function for a request on a YUV stream. This function
+ * has the logic to service a request based on its type
+ *
+ * PARAMETERS :
+ * @buffer : pointer to the output buffer
+ * @frameNumber : frame number of the request
+ * @pInputBuffer : pointer to input buffer if an input request
+ * @metadata : parameters associated with the request
+ *
+ * RETURN : 0 on a success start of capture
+ * -EINVAL on invalid input
+ * -ENODEV on serious error
+ *==========================================================================*/
+int32_t QCamera3YUVChannel::request(buffer_handle_t *buffer,
+ uint32_t frameNumber,
+ camera3_stream_buffer_t* pInputBuffer,
+ metadata_buffer_t* metadata, bool &needMetadata)
+{
+ int32_t rc = NO_ERROR;
+ int index;
+ Mutex::Autolock lock(mOfflinePpLock);
+
+ CDBG("%s: pInputBuffer is %p", __func__, pInputBuffer);
+ CDBG("%s, frame number %d", __func__, frameNumber);
+ if (NULL == buffer || NULL == metadata) {
+ ALOGE("%s: Invalid buffer/metadata in channel request", __func__);
+ return BAD_VALUE;
+ }
+
+ PpInfo ppInfo;
+ memset(&ppInfo, 0, sizeof(ppInfo));
+ ppInfo.frameNumber = frameNumber;
+ ppInfo.offlinePpFlag = false;
+ if (mBypass && !pInputBuffer ) {
+ ppInfo.offlinePpFlag = needsFramePostprocessing(metadata);
+ ppInfo.output = buffer;
+ mOfflinePpInfoList.push_back(ppInfo);
+ }
+
+ CDBG("%s: offlinePpFlag is %d", __func__, ppInfo.offlinePpFlag);
+ needMetadata = ppInfo.offlinePpFlag;
+ if (!ppInfo.offlinePpFlag) {
+ // regular request
+ return QCamera3ProcessingChannel::request(buffer, frameNumber, pInputBuffer, metadata);
+ } else {
+ //we need to send this frame through the CPP
+ //Allocate heap memory, then buf done on the buffer
+ if (mFreeHeapBufferList.empty()) {
+ ALOGE("%s: mFreeHeapBufferList is null. Fatal", __func__);
+ return BAD_VALUE;
+ }
+
+ /* Configure and start postproc if necessary */
+ reprocess_config_t reproc_cfg;
+ cam_dimension_t dim;
+ memset(&reproc_cfg, 0, sizeof(reprocess_config_t));
+ memset(&dim, 0, sizeof(dim));
+ mStreams[0]->getFrameDimension(dim);
+ setReprocConfig(reproc_cfg, NULL, metadata, mStreamFormat, dim);
+
+ // Start postprocessor without input buffer
+ startPostProc(false, reproc_cfg);
+
+ uint32_t bufIdx = *(mFreeHeapBufferList.begin());
+ mFreeHeapBufferList.erase(mFreeHeapBufferList.begin());
+ CDBG("%s: erasing %d", __func__, bufIdx);
+
+ mMemory.markFrameNumber(bufIdx, frameNumber);
+ mStreams[0]->bufDone(bufIdx);
+ }
+ return rc;
+}
+
+/*===========================================================================
+ * FUNCTION : streamCbRoutine
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS :
+ * @super_frame : the super frame with filled buffer
+ * @stream : stream on which the buffer was requested and filled
+ *
+ * RETURN : none
+ *==========================================================================*/
+void QCamera3YUVChannel::streamCbRoutine(mm_camera_super_buf_t *super_frame,
+ QCamera3Stream *stream)
+{
+ ATRACE_CALL();
+ uint8_t frameIndex;
+ int32_t resultFrameNumber;
+
+ if (checkStreamCbErrors(super_frame, stream) != NO_ERROR) {
+ ALOGE("%s: Error with the stream callback", __func__);
+ return;
+ }
+
+ frameIndex = (uint8_t)super_frame->bufs[0]->buf_idx;
+ if(frameIndex >= mNumBufs) {
+ ALOGE("%s: Error, Invalid index for buffer",__func__);
+ stream->bufDone(frameIndex);
+ return;
+ }
+
+ if (mBypass) {
+ List<PpInfo>::iterator ppInfo;
+
+ Mutex::Autolock lock(mOfflinePpLock);
+ resultFrameNumber = mMemory.getFrameNumber(frameIndex);
+ for (ppInfo = mOfflinePpInfoList.begin();
+ ppInfo != mOfflinePpInfoList.end(); ppInfo++) {
+ if (ppInfo->frameNumber == (uint32_t)resultFrameNumber) {
+ break;
+ }
+ }
+ CDBG("%s, frame index %d, frame number %d", __func__, frameIndex, resultFrameNumber);
+ //check the reprocessing required flag against the frame number
+ if (ppInfo == mOfflinePpInfoList.end()) {
+ ALOGE("%s: Error, request for frame number is a reprocess.", __func__);
+ stream->bufDone(frameIndex);
+ return;
+ }
+
+ if (ppInfo->offlinePpFlag) {
+ mm_camera_super_buf_t *frame =
+ (mm_camera_super_buf_t *)malloc(sizeof(mm_camera_super_buf_t));
+ if (frame == NULL) {
+ ALOGE("%s: Error allocating memory to save received_frame structure.",
+ __func__);
+ if(stream) {
+ stream->bufDone(frameIndex);
+ }
+ return;
+ }
+
+ *frame = *super_frame;
+ m_postprocessor.processData(frame, ppInfo->output, resultFrameNumber);
+ free(super_frame);
+ return;
+ } else {
+ if (ppInfo != mOfflinePpInfoList.begin()) {
+ // There is pending reprocess buffer, cache current buffer
+ if (ppInfo->callback_buffer != NULL) {
+ ALOGE("%s: Fatal: cached callback_buffer is already present",
+ __func__);
+
+ }
+ ppInfo->callback_buffer = super_frame;
+ return;
+ } else {
+ mOfflinePpInfoList.erase(ppInfo);
+ }
+ }
+ }
+
+ QCamera3ProcessingChannel::streamCbRoutine(super_frame, stream);
+ return;
+}
+
+/*===========================================================================
+ * FUNCTION : reprocessCbRoutine
+ *
+ * DESCRIPTION: callback function for the reprocessed frame. This frame now
+ * should be returned to the framework. This same callback is
+ * used during input reprocessing or offline postprocessing
+ *
+ * PARAMETERS :
+ * @resultBuffer : buffer containing the reprocessed data
+ * @resultFrameNumber : frame number on which the buffer was requested
+ *
+ * RETURN : NONE
+ *
+ *==========================================================================*/
+void QCamera3YUVChannel::reprocessCbRoutine(buffer_handle_t *resultBuffer,
+ uint32_t resultFrameNumber)
+{
+ CDBG("%s E: frame number %d", __func__, resultFrameNumber);
+ Vector<mm_camera_super_buf_t *> pendingCbs;
+
+ if (mBypass) {
+ int32_t rc = handleOfflinePpCallback(resultFrameNumber, pendingCbs);
+ if (rc != NO_ERROR) {
+ return;
+ }
+ }
+
+ // Call all pending callbacks to return buffers
+ for (size_t i = 0; i < pendingCbs.size(); i++) {
+ QCamera3ProcessingChannel::streamCbRoutine(
+ pendingCbs[i], mStreams[0]);
+ }
+
+
+ QCamera3ProcessingChannel::reprocessCbRoutine(
+ resultBuffer, resultFrameNumber);
+}
+
+/*===========================================================================
+ * FUNCTION : needsFramePostprocessing
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS :
+ *
+ * RETURN :
+ * TRUE if frame needs to be postprocessed
+ * FALSE is frame does not need to be postprocessed
+ *
+ *==========================================================================*/
+bool QCamera3YUVChannel::needsFramePostprocessing(metadata_buffer_t *meta)
+{
+ bool ppNeeded = false;
+
+ //sharpness
+ IF_META_AVAILABLE(cam_edge_application_t, edgeMode, CAM_INTF_META_EDGE_MODE, meta) {
+ mEdgeMode = *edgeMode;
+ }
+
+ //wnr
+ IF_META_AVAILABLE(uint32_t, noiseRedMode, CAM_INTF_META_NOISE_REDUCTION_MODE, meta) {
+ mNoiseRedMode = *noiseRedMode;
+ }
+
+ IF_META_AVAILABLE(cam_crop_region_t, scalerCropRegion, CAM_INTF_META_SCALER_CROP_REGION, meta) {
+ //check the crop against the max downscale factor and then set ppNeeded
+ //gCamCapability[cameraId]->max_downscale_factor
+ }
+
+ if (!(CAM_EDGE_MODE_OFF == mEdgeMode.edge_mode) ||
+ (CAM_EDGE_MODE_ZERO_SHUTTER_LAG == mEdgeMode.edge_mode)) {
+ ppNeeded = true;
+ }
+ if (!((CAM_NOISE_REDUCTION_MODE_ZERO_SHUTTER_LAG == mNoiseRedMode) ||
+ (CAM_NOISE_REDUCTION_MODE_OFF == mNoiseRedMode))) {
+ ppNeeded = true;
+ }
+
+ return ppNeeded;
+}
+
+/*===========================================================================
+ * FUNCTION : handleOfflinePpCallback
+ *
+ * DESCRIPTION: callback function for the reprocessed frame from offline
+ * postprocessing.
+ *
+ * PARAMETERS :
+ * @resultFrameNumber : frame number on which the buffer was requested
+ * @pendingCbs : pending buffers to be returned first
+ *
+ * RETURN : int32_t type of status
+ * NO_ERROR -- success
+ * none-zero failure code
+ *==========================================================================*/
+int32_t QCamera3YUVChannel::handleOfflinePpCallback(uint32_t resultFrameNumber,
+ Vector<mm_camera_super_buf_t *>& pendingCbs)
+{
+ Mutex::Autolock lock(mOfflinePpLock);
+ List<PpInfo>::iterator ppInfo;
+
+ for (ppInfo = mOfflinePpInfoList.begin();
+ ppInfo != mOfflinePpInfoList.end(); ppInfo++) {
+ if (ppInfo->frameNumber == resultFrameNumber) {
+ break;
+ }
+ }
+
+ if (ppInfo == mOfflinePpInfoList.end()) {
+ ALOGI("%s: Request of frame number %d is reprocessing",
+ __func__, resultFrameNumber);
+ return NO_ERROR;
+ }
+
+ // Return pending buffer callbacks
+ while (ppInfo != mOfflinePpInfoList.begin()) {
+ List<PpInfo>::iterator pending = mOfflinePpInfoList.begin();
+
+ // Call streamCbRoutine for cached callbacks
+ if (!(pending->callback_buffer)) {
+ ALOGE("%s: Fatal: cached callback info is NULL.", __func__);
+ return BAD_VALUE;
+ }
+
+ pendingCbs.push_back(pending->callback_buffer);
+
+ mOfflinePpInfoList.erase(pending);
+ }
+
+ if (ppInfo->offlinePpFlag) {
+ // Need to get the input buffer frame index from the
+ // mMemory object and add that to the free heap buffers list.
+ int32_t bufferIndex =
+ mMemory.getHeapBufferIndex(resultFrameNumber);
+ if (bufferIndex < 0) {
+ ALOGE("%s: Fatal %d: no buffer index for frame number %d",
+ __func__, bufferIndex, resultFrameNumber);
+ return BAD_VALUE;
+ }
+ mFreeHeapBufferList.push_back(bufferIndex);
+ mOfflinePpInfoList.erase(ppInfo);
+
+ } else {
+ ALOGE("%s: Fatal: request of frame number %d doesn't need"
+ " offline postprocessing. However there is"
+ " reprocessing callback.", __func__,
+ resultFrameNumber);
+ return BAD_VALUE;
+ }
+
+ return NO_ERROR;
+}
+
+/*===========================================================================
* FUNCTION : getReprocessType
*
* DESCRIPTION: get the type of reprocess output supported by this channel
@@ -2403,7 +2784,6 @@
paddingInfo, userData, stream, CAM_STREAM_TYPE_SNAPSHOT,
postprocess_mask, metadataChannel, numBuffers),
mNumSnapshotBufs(0),
- mCurrentBufIndex(-1),
mYuvMemory(NULL)
{
QCamera3HardwareInterface* hal_obj = (QCamera3HardwareInterface*)mUserData;
@@ -2500,19 +2880,13 @@
int32_t rc = NO_ERROR;
reprocess_config_t reproc_cfg;
+ cam_dimension_t dim;
memset(&reproc_cfg, 0, sizeof(reprocess_config_t));
- setReprocConfig(reproc_cfg, pInputBuffer, metadata, mStreamFormat);
//make sure to set the correct input stream dim in case of YUV size override
//and recalculate the plane info
- if (pInputBuffer == NULL) {
- reproc_cfg.input_stream_dim.width = (int32_t)mYuvWidth;
- reproc_cfg.input_stream_dim.height = (int32_t)mYuvHeight;
- rc = mm_stream_calc_offset_snapshot(mStreamFormat, &reproc_cfg.input_stream_dim,
- reproc_cfg.padding, &reproc_cfg.input_stream_plane_info);
- if (rc != 0) {
- ALOGE("%s: Stream %d plane info calculation failed!", __func__, mStreamType);
- }
- }
+ dim.width = (int32_t)mYuvWidth;
+ dim.height = (int32_t)mYuvHeight;
+ setReprocConfig(reproc_cfg, pInputBuffer, metadata, mStreamFormat, dim);
// Picture stream has already been started before any request comes in
if (!m_bIsActive) {
@@ -2540,9 +2914,6 @@
rc = mMemory.markFrameNumber((uint32_t)index, frameNumber);
- //Start the postprocessor for jpeg encoding. Pass mMemory as dest buffer
- mCurrentBufIndex = (uint32_t)index;
-
// Start postprocessor
startPostProc((NULL != pInputBuffer), reproc_cfg);
@@ -2625,6 +2996,17 @@
return;
}
+/*===========================================================================
+ * FUNCTION : streamCbRoutine
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS :
+ * @super_frame : the super frame with filled buffer
+ * @stream : stream on which the buffer was requested and filled
+ *
+ * RETURN : none
+ *==========================================================================*/
void QCamera3PicChannel::streamCbRoutine(mm_camera_super_buf_t *super_frame,
QCamera3Stream *stream)
{
@@ -2636,19 +3018,10 @@
//Got the yuv callback. Calling yuv callback handler in PostProc
uint8_t frameIndex;
mm_camera_super_buf_t* frame = NULL;
- if(!super_frame) {
- ALOGE("%s: Invalid Super buffer",__func__);
- return;
- }
- if(super_frame->num_bufs != 1) {
- ALOGE("%s: Multiple streams are not supported",__func__);
- return;
- }
- if(super_frame->bufs[0] == NULL ) {
- ALOGE("%s: Error, Super buffer frame does not contain valid buffer",
- __func__);
- return;
+ if (checkStreamCbErrors(super_frame, stream) != NO_ERROR) {
+ ALOGE("%s: Error with the stream callback", __func__);
+ return;
}
frameIndex = (uint8_t)super_frame->bufs[0]->buf_idx;
@@ -2692,11 +3065,11 @@
return;
}
-QCamera3Memory* QCamera3PicChannel::getStreamBufs(uint32_t len)
+QCamera3StreamMem* QCamera3PicChannel::getStreamBufs(uint32_t len)
{
int rc = 0;
- mYuvMemory = new QCamera3HeapMemory();
+ mYuvMemory = new QCamera3StreamMem(mCamera3Stream->max_buffers);
if (!mYuvMemory) {
ALOGE("%s: unable to create metadata memory", __func__);
return NULL;
@@ -2834,10 +3207,12 @@
mReprocessType(REPROCESS_TYPE_NONE),
m_pSrcChannel(NULL),
m_pMetaChannel(NULL),
- mMemory(NULL)
+ mMemory(NULL),
+ mGrallocMemory(0)
{
memset(mSrcStreamHandles, 0, sizeof(mSrcStreamHandles));
- mOfflineMetaIndex = (int32_t) (mNumBuffers -1);
+ mOfflineBuffersIndex = mNumBuffers -1;
+ mOfflineMetaIndex = (int32_t) (2*mNumBuffers -1);
}
@@ -3001,6 +3376,15 @@
__func__, rc, frameIndex);
}
obj->reprocessCbRoutine(resultBuffer, resultFrameNumber);
+
+ // TODO: Do we need to deallcoate mOfflineMetaMemory and
+ // mOfflineMemory for framework reprocessing?
+ obj->m_postprocessor.releaseOfflineBuffers();
+ qcamera_hal3_pp_data_t *pp_job = obj->m_postprocessor.dequeuePPJob(resultFrameNumber);
+ if (pp_job != NULL) {
+ obj->m_postprocessor.releasePPJobData(pp_job);
+ }
+ free(pp_job);
}
free(super_frame);
return;
@@ -3017,7 +3401,8 @@
*==========================================================================*/
QCamera3ReprocessChannel::QCamera3ReprocessChannel() :
m_pSrcChannel(NULL),
- m_pMetaChannel(NULL)
+ m_pMetaChannel(NULL),
+ mGrallocMemory(0)
{
}
@@ -3028,13 +3413,13 @@
*
* PARAMETERS : none
*
- * RETURN : QCamera3Memory *
+ * RETURN : QCamera3StreamMem *
*==========================================================================*/
-QCamera3Memory* QCamera3ReprocessChannel::getStreamBufs(uint32_t len)
+QCamera3StreamMem* QCamera3ReprocessChannel::getStreamBufs(uint32_t len)
{
int rc = 0;
if (mReprocessType == REPROCESS_TYPE_JPEG) {
- mMemory = new QCamera3HeapMemory();
+ mMemory = new QCamera3StreamMem(mNumBuffers);
if (!mMemory) {
ALOGE("%s: unable to create reproc memory", __func__);
return NULL;
@@ -3233,18 +3618,19 @@
* NO_ERROR -- success
* none-zero failure code
*==========================================================================*/
-int32_t QCamera3ReprocessChannel::extractFrameCropAndRotation(mm_camera_super_buf_t *frame,
+int32_t QCamera3ReprocessChannel::extractFrameCropAndRotation(qcamera_hal3_pp_buffer_t *pp_buffer,
mm_camera_buf_def_t *meta_buffer, jpeg_settings_t *jpeg_settings,
qcamera_fwk_input_pp_data_t &fwk_frame)
{
int32_t rc = NO_ERROR;
QCamera3HardwareInterface* hal_obj = (QCamera3HardwareInterface*)mUserData;
- if ((NULL == meta_buffer) || (NULL == frame) || (NULL == jpeg_settings) ||
+ if ((NULL == meta_buffer) || (NULL == pp_buffer) || (NULL == pp_buffer->input) ||
(NULL == hal_obj)) {
return BAD_VALUE;
}
metadata_buffer_t *meta = (metadata_buffer_t *)meta_buffer->buffer;
+ mm_camera_super_buf_t *frame = pp_buffer->input;
if (NULL == meta) {
return BAD_VALUE;
}
@@ -3254,20 +3640,22 @@
QCamera3Stream *pSrcStream = getSrcStreamBySrcHandle(frame->bufs[i]->stream_id);
if (pStream != NULL && pSrcStream != NULL) {
- // Find rotation info for reprocess stream
- cam_rotation_info_t rotation_info;
- memset(&rotation_info, 0, sizeof(rotation_info));
- if (jpeg_settings->jpeg_orientation == 0) {
- rotation_info.rotation = ROTATE_0;
- } else if (jpeg_settings->jpeg_orientation == 90) {
- rotation_info.rotation = ROTATE_90;
- } else if (jpeg_settings->jpeg_orientation == 180) {
- rotation_info.rotation = ROTATE_180;
- } else if (jpeg_settings->jpeg_orientation == 270) {
- rotation_info.rotation = ROTATE_270;
+ if (jpeg_settings) {
+ // Find rotation info for reprocess stream
+ cam_rotation_info_t rotation_info;
+ memset(&rotation_info, 0, sizeof(rotation_info));
+ if (jpeg_settings->jpeg_orientation == 0) {
+ rotation_info.rotation = ROTATE_0;
+ } else if (jpeg_settings->jpeg_orientation == 90) {
+ rotation_info.rotation = ROTATE_90;
+ } else if (jpeg_settings->jpeg_orientation == 180) {
+ rotation_info.rotation = ROTATE_180;
+ } else if (jpeg_settings->jpeg_orientation == 270) {
+ rotation_info.rotation = ROTATE_270;
+ }
+ rotation_info.streamId = mStreams[0]->getMyServerID();
+ ADD_SET_PARAM_ENTRY_TO_BATCH(meta, CAM_INTF_PARM_ROTATION, rotation_info);
}
- rotation_info.streamId = mStreams[0]->getMyServerID();
- ADD_SET_PARAM_ENTRY_TO_BATCH(meta, CAM_INTF_PARM_ROTATION, rotation_info);
// Find and insert crop info for reprocess stream
IF_META_AVAILABLE(cam_crop_data_t, crop_data, CAM_INTF_META_CROP_DATA, meta) {
@@ -3312,6 +3700,7 @@
fwk_frame.input_buffer = *frame->bufs[i];
fwk_frame.metadata_buffer = *meta_buffer;
+ fwk_frame.output_buffer = pp_buffer->output;
break;
} else {
ALOGE("%s: Source/Re-process streams are invalid", __func__);
@@ -3657,6 +4046,7 @@
m_pSrcChannel = src_config.src_channel;
m_pMetaChannel = pMetaChannel;
mReprocessType = src_config.reprocess_type;
+ CDBG("%s: mReprocessType is %d", __func__, mReprocessType);
}
if(m_camOps->request_super_buf(m_camHandle,m_handle,1,0) < 0) {
ALOGE("%s: Request for super buffer failed",__func__);
@@ -3738,10 +4128,10 @@
free(super_frame);
}
-QCamera3Memory* QCamera3SupportChannel::getStreamBufs(uint32_t len)
+QCamera3StreamMem* QCamera3SupportChannel::getStreamBufs(uint32_t len)
{
int rc;
- mMemory = new QCamera3HeapMemory();
+ mMemory = new QCamera3StreamMem(MIN_STREAMING_BUFFER_NUM);
if (!mMemory) {
ALOGE("%s: unable to create heap memory", __func__);
return NULL;
diff --git a/QCamera2/HAL3/QCamera3Channel.h b/QCamera2/HAL3/QCamera3Channel.h
index 8417301..bb13c30 100644
--- a/QCamera2/HAL3/QCamera3Channel.h
+++ b/QCamera2/HAL3/QCamera3Channel.h
@@ -33,6 +33,7 @@
#include <hardware/camera3.h>
#include "QCamera3Stream.h"
#include "QCamera3Mem.h"
+#include "QCamera3StreamMem.h"
#include "QCamera3PostProc.h"
#include "QCamera3HALHeader.h"
#include "utils/Vector.h"
@@ -83,7 +84,7 @@
QCamera3Stream *stream) = 0;
virtual int32_t registerBuffer(buffer_handle_t *buffer, cam_is_type_t isType) = 0;
- virtual QCamera3Memory *getStreamBufs(uint32_t len) = 0;
+ virtual QCamera3StreamMem *getStreamBufs(uint32_t len) = 0;
virtual void putStreamBufs() = 0;
QCamera3Stream *getStreamByHandle(uint32_t streamHandle);
@@ -165,13 +166,15 @@
metadata_buffer_t* metadata);
virtual void streamCbRoutine(mm_camera_super_buf_t *super_frame,
QCamera3Stream *stream);
- virtual QCamera3Memory *getStreamBufs(uint32_t len);
+ virtual QCamera3StreamMem *getStreamBufs(uint32_t len);
virtual void putStreamBufs();
virtual int32_t registerBuffer(buffer_handle_t *buffer, cam_is_type_t isType);
+ virtual int32_t stop();
+
virtual reprocess_type_t getReprocessType() = 0;
- void reprocessCbRoutine(buffer_handle_t *resultBuffer,
+ virtual void reprocessCbRoutine(buffer_handle_t *resultBuffer,
uint32_t resultFrameNumber);
int32_t queueReprocMetadata(mm_camera_super_buf_t *metadata);
@@ -182,13 +185,15 @@
int32_t setReprocConfig(reprocess_config_t &reproc_cfg,
camera3_stream_buffer_t *pInputBuffer,
metadata_buffer_t *metadata,
- cam_format_t streamFormat);
+ cam_format_t streamFormat, cam_dimension_t dim);
int32_t setFwkInputPPData(qcamera_fwk_input_pp_data_t *src_frame,
camera3_stream_buffer_t *pInputBuffer,
reprocess_config_t *reproc_cfg,
metadata_buffer_t *metadata,
buffer_handle_t *output_buffer,
uint32_t frameNumber);
+ int32_t checkStreamCbErrors(mm_camera_super_buf_t *super_frame,
+ QCamera3Stream *stream);
QCamera3PostProcessor m_postprocessor; // post processor
@@ -197,7 +202,7 @@
void startPostProc(bool inputBufExists,
const reprocess_config_t &reproc_cfg);
- QCamera3GrallocMemory mMemory; //output buffer allocated by fwk
+ QCamera3StreamMem mMemory; //output buffer allocated by fwk
camera3_stream_t *mCamera3Stream;
uint32_t mNumBufs;
cam_stream_type_t mStreamType;
@@ -210,11 +215,10 @@
QCamera3Channel *m_pMetaChannel;
mm_camera_super_buf_t *mMetaFrame;
- QCamera3GrallocMemory mOfflineMemory; //reprocessing input buffer
- QCamera3HeapMemory mOfflineMetaMemory; //reprocessing metadata buffer
+ QCamera3StreamMem mOfflineMemory; //reprocessing input buffer
+ QCamera3StreamMem mOfflineMetaMemory; //reprocessing metadata buffer
private:
- int32_t stop();
bool m_bWNROn;
};
@@ -273,13 +277,13 @@
virtual void streamCbRoutine(mm_camera_super_buf_t *super_frame,
QCamera3Stream *stream);
- virtual QCamera3Memory *getStreamBufs(uint32_t le);
+ virtual QCamera3StreamMem *getStreamBufs(uint32_t le);
virtual void putStreamBufs();
virtual int32_t registerBuffer(buffer_handle_t * /*buffer*/, cam_is_type_t /*isType*/)
{ return NO_ERROR; };
private:
- QCamera3HeapMemory *mMemory;
+ QCamera3StreamMem *mMemory;
};
/* QCamera3RawChannel is for opaqueu/cross-platform raw stream containing
@@ -333,7 +337,7 @@
virtual int32_t initialize(cam_is_type_t isType);
virtual void streamCbRoutine(mm_camera_super_buf_t *super_frame,
QCamera3Stream *stream);
- virtual QCamera3Memory *getStreamBufs(uint32_t le);
+ virtual QCamera3StreamMem *getStreamBufs(uint32_t le);
virtual void putStreamBufs();
virtual int32_t registerBuffer(buffer_handle_t * /*buffer*/, cam_is_type_t /*isType*/)
{ return NO_ERROR; };
@@ -345,7 +349,7 @@
private:
bool mRawDump;
- QCamera3HeapMemory *mMemory;
+ QCamera3StreamMem *mMemory;
};
/* QCamera3YUVChannel is used to handle flexible YUV streams that are directly
@@ -355,19 +359,54 @@
{
public:
QCamera3YUVChannel(uint32_t cam_handle,
- mm_camera_ops_t *cam_ops,
- channel_cb_routine cb_routine,
- cam_padding_info_t *paddingInfo,
- void *userData,
- camera3_stream_t *stream,
- cam_stream_type_t stream_type,
- uint32_t postprocess_mask,
- QCamera3Channel *metadataChannel);
- ~QCamera3YUVChannel();
+ mm_camera_ops_t *cam_ops,
+ channel_cb_routine cb_routine,
+ cam_padding_info_t *paddingInfo,
+ void *userData,
+ camera3_stream_t *stream,
+ cam_stream_type_t stream_type,
+ uint32_t postprocess_mask,
+ QCamera3Channel *metadataChannel);
+ ~QCamera3YUVChannel();
virtual int32_t initialize(cam_is_type_t isType);
+ virtual int32_t request(buffer_handle_t *buffer,
+ uint32_t frameNumber,
+ camera3_stream_buffer_t* pInputBuffer,
+ metadata_buffer_t* metadata, bool &needMetadata);
virtual reprocess_type_t getReprocessType();
virtual int32_t start();
+ virtual void streamCbRoutine(mm_camera_super_buf_t *super_frame,
+ QCamera3Stream *stream);
+ virtual void reprocessCbRoutine(buffer_handle_t *resultBuffer,
+ uint32_t resultFrameNumber);
+private:
+ typedef struct {
+ uint32_t frameNumber;
+ bool offlinePpFlag;
+ buffer_handle_t *output;
+ mm_camera_super_buf_t *callback_buffer;
+ } PpInfo;
+
+ // Whether offline postprocessing is required for this channel
+ bool mBypass;
+ // Current edge, noise, and crop region setting
+ cam_edge_application_t mEdgeMode;
+ uint32_t mNoiseRedMode;
+ cam_crop_region_t mCropRegion;
+
+ // Mutex to protect mOfflinePpFlagMap and mFreeHeapBufferList
+ Mutex mOfflinePpLock;
+ // Map between free number and whether the request needs to be
+ // postprocessed.
+ List<PpInfo> mOfflinePpInfoList;
+ // Heap buffer index list
+ List<uint32_t> mFreeHeapBufferList;
+
+private:
+ bool needsFramePostprocessing(metadata_buffer_t* meta);
+ int32_t handleOfflinePpCallback(uint32_t resultFrameNumber,
+ Vector<mm_camera_super_buf_t *>& pendingCbs);
};
/* QCamera3PicChannel is for JPEG stream, which contains a YUV stream generated
@@ -395,7 +434,7 @@
virtual void streamCbRoutine(mm_camera_super_buf_t *super_frame,
QCamera3Stream *stream);
- virtual QCamera3Memory *getStreamBufs(uint32_t le);
+ virtual QCamera3StreamMem *getStreamBufs(uint32_t le);
virtual void putStreamBufs();
virtual reprocess_type_t getReprocessType();
@@ -420,7 +459,7 @@
uint32_t mNumSnapshotBufs;
uint32_t mYuvWidth, mYuvHeight;
int32_t mCurrentBufIndex;
- QCamera3HeapMemory *mYuvMemory;
+ QCamera3StreamMem *mYuvMemory;
// Keep a list of free buffers
Mutex mFreeBuffersLock;
List<uint32_t> mFreeBufferList;
@@ -442,12 +481,12 @@
int32_t doReprocessOffline(qcamera_fwk_input_pp_data_t *frame);
int32_t doReprocess(int buf_fd, size_t buf_length, int32_t &ret_val,
mm_camera_super_buf_t *meta_buf);
- int32_t extractFrameCropAndRotation(mm_camera_super_buf_t *frame,
+ int32_t extractFrameCropAndRotation(qcamera_hal3_pp_buffer_t *pp_buffer,
mm_camera_buf_def_t *meta_buffer,
jpeg_settings_t *jpeg_settings,
qcamera_fwk_input_pp_data_t &fwk_frame);
int32_t extractCrop(qcamera_fwk_input_pp_data_t *frame);
- virtual QCamera3Memory *getStreamBufs(uint32_t len);
+ virtual QCamera3StreamMem *getStreamBufs(uint32_t len);
virtual void putStreamBufs();
virtual int32_t initialize(cam_is_type_t isType);
int32_t unmapOfflineBuffers(bool all);
@@ -482,8 +521,8 @@
uint32_t mSrcStreamHandles[MAX_STREAM_NUM_IN_BUNDLE];
QCamera3ProcessingChannel *m_pSrcChannel; // ptr to source channel for reprocess
QCamera3Channel *m_pMetaChannel;
- QCamera3HeapMemory *mMemory;
- QCamera3GrallocMemory mGrallocMemory;
+ QCamera3StreamMem *mMemory;
+ QCamera3StreamMem mGrallocMemory;
};
@@ -507,14 +546,14 @@
virtual void streamCbRoutine(mm_camera_super_buf_t *super_frame,
QCamera3Stream *stream);
- virtual QCamera3Memory *getStreamBufs(uint32_t le);
+ virtual QCamera3StreamMem *getStreamBufs(uint32_t le);
virtual void putStreamBufs();
virtual int32_t registerBuffer(buffer_handle_t * /*buffer*/, cam_is_type_t /*isType*/)
{ return NO_ERROR; };
static cam_dimension_t kDim;
private:
- QCamera3HeapMemory *mMemory;
+ QCamera3StreamMem *mMemory;
cam_dimension_t mDim;
cam_stream_type_t mStreamType;
};
diff --git a/QCamera2/HAL3/QCamera3HWI.cpp b/QCamera2/HAL3/QCamera3HWI.cpp
index 8c53123..2e497c4 100755
--- a/QCamera2/HAL3/QCamera3HWI.cpp
+++ b/QCamera2/HAL3/QCamera3HWI.cpp
@@ -412,7 +412,7 @@
// this stage by the framework
for (List<stream_info_t *>::iterator it = mStreamInfo.begin();
it != mStreamInfo.end(); it++) {
- QCamera3Channel *channel = (*it)->channel;
+ QCamera3ProcessingChannel *channel = (*it)->channel;
if (channel) {
channel->stop();
}
@@ -429,7 +429,7 @@
for (List<stream_info_t *>::iterator it = mStreamInfo.begin();
it != mStreamInfo.end(); it++) {
- QCamera3Channel *channel = (*it)->channel;
+ QCamera3ProcessingChannel *channel = (*it)->channel;
if (channel)
delete channel;
free (*it);
@@ -1029,7 +1029,7 @@
* if they appear again, they will be validated */
for (List<stream_info_t*>::iterator it = mStreamInfo.begin();
it != mStreamInfo.end(); it++) {
- QCamera3Channel *channel = (QCamera3Channel*)(*it)->stream->priv;
+ QCamera3ProcessingChannel *channel = (QCamera3ProcessingChannel*)(*it)->stream->priv;
channel->stop();
(*it)->status = INVALID;
}
@@ -1065,12 +1065,17 @@
size_t processedStreamCnt = 0;
// Number of streams on ISP encoder path
size_t numStreamsOnEncoder = 0;
- cam_dimension_t maxViewfinderSize;
+ size_t numYuv888OnEncoder = 0;
+ bool bYuv888OverrideJpeg = false;
+ cam_dimension_t largeYuv888Size = {0, 0};
+ cam_dimension_t maxViewfinderSize = {0, 0};
bool bJpegExceeds4K = false;
bool bUseCommonFeatureMask = false;
uint32_t commonFeatureMask = 0;
maxViewfinderSize = gCamCapability[mCameraId]->max_viewfinder_size;
camera3_stream_t *inputStream = NULL;
+ bool isJpeg = false;
+ cam_dimension_t jpegSize = {0, 0};
/*EIS configuration*/
bool eisSupported = false;
@@ -1117,9 +1122,10 @@
for (size_t i = 0; i < streamList->num_streams; i++) {
camera3_stream_t *newStream = streamList->streams[i];
ALOGI("%s: stream[%d] type = %d, format = %d, width = %d, "
- "height = %d, rotation = %d",
+ "height = %d, rotation = %d, usage = 0x%x",
__func__, i, newStream->stream_type, newStream->format,
- newStream->width, newStream->height, newStream->rotation);
+ newStream->width, newStream->height, newStream->rotation,
+ newStream->usage);
if (newStream->stream_type == CAMERA3_STREAM_BIDIRECTIONAL ||
newStream->stream_type == CAMERA3_STREAM_INPUT){
isZsl = true;
@@ -1129,6 +1135,9 @@
}
if (newStream->format == HAL_PIXEL_FORMAT_BLOB) {
+ isJpeg = true;
+ jpegSize.width = newStream->width;
+ jpegSize.height = newStream->height;
if (newStream->width > VIDEO_4K_WIDTH ||
newStream->height > VIDEO_4K_HEIGHT)
bJpegExceeds4K = true;
@@ -1151,8 +1160,8 @@
switch (newStream->format) {
case HAL_PIXEL_FORMAT_BLOB:
stallStreamCnt++;
- if (((int32_t)newStream->width > maxViewfinderSize.width) ||
- ((int32_t)newStream->height > maxViewfinderSize.height)) {
+ if (isOnEncoder(maxViewfinderSize, newStream->width,
+ newStream->height)) {
commonFeatureMask |= CAM_QCOM_FEATURE_NONE;
numStreamsOnEncoder++;
}
@@ -1164,8 +1173,8 @@
break;
case HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED:
processedStreamCnt++;
- if (((int32_t)newStream->width > maxViewfinderSize.width) ||
- ((int32_t)newStream->height > maxViewfinderSize.height)) {
+ if (isOnEncoder(maxViewfinderSize, newStream->width,
+ newStream->height)) {
if (newStream->stream_type == CAMERA3_STREAM_BIDIRECTIONAL ||
newStream->usage & GRALLOC_USAGE_HW_CAMERA_ZSL) {
commonFeatureMask |= CAM_QCOM_FEATURE_NONE;
@@ -1176,10 +1185,20 @@
}
break;
case HAL_PIXEL_FORMAT_YCbCr_420_888:
+ processedStreamCnt++;
+ if (isOnEncoder(maxViewfinderSize, newStream->width,
+ newStream->height)) {
+ commonFeatureMask |= CAM_QCOM_FEATURE_NONE;
+ numStreamsOnEncoder++;
+ numYuv888OnEncoder++;
+ largeYuv888Size.width = newStream->width;
+ largeYuv888Size.height = newStream->height;
+ }
+ break;
default:
processedStreamCnt++;
- if (((int32_t)newStream->width > maxViewfinderSize.width) ||
- ((int32_t)newStream->height > maxViewfinderSize.height)) {
+ if (isOnEncoder(maxViewfinderSize, newStream->width,
+ newStream->height)) {
commonFeatureMask |= CAM_QCOM_FEATURE_PP_SUPERSET_HAL3;
numStreamsOnEncoder++;
}
@@ -1220,6 +1239,7 @@
CDBG_HIGH("%s: Multiple streams above max viewfinder size, common mask needed",
__func__);
}
+
/* Check if BLOB size is greater than 4k in 4k recording case */
if (m_bIs4KVideo && bJpegExceeds4K) {
ALOGE("%s: HAL doesn't support Blob size greater than 4k in 4k recording",
@@ -1228,6 +1248,16 @@
return -EINVAL;
}
+ // If jpeg stream is available, and a YUV 888 stream is on Encoder path, and
+ // the YUV stream's size is greater or equal to the JPEG size, set common
+ // postprocess mask to NONE, so that we can take advantage of postproc bypass.
+ if (numYuv888OnEncoder && isJpeg &&
+ largeYuv888Size.width >= jpegSize.width &&
+ largeYuv888Size.height >= jpegSize.height) {
+ bYuv888OverrideJpeg = true;
+ commonFeatureMask = CAM_QCOM_FEATURE_NONE;
+ }
+
rc = validateStreamDimensions(streamList);
if (rc == NO_ERROR) {
rc = validateStreamRotations(streamList);
@@ -1251,8 +1281,8 @@
for (List<stream_info_t*>::iterator it=mStreamInfo.begin();
it != mStreamInfo.end(); it++) {
if ((*it)->stream == newStream) {
- QCamera3Channel *channel =
- (QCamera3Channel*)(*it)->stream->priv;
+ QCamera3ProcessingChannel *channel =
+ (QCamera3ProcessingChannel*)(*it)->stream->priv;
stream_exists = true;
if (channel)
delete channel;
@@ -1376,7 +1406,7 @@
mStreamConfigInfo.stream_sizes[mStreamConfigInfo.num_streams].height = (int32_t)newStream->height;
if ((newStream->stream_type == CAMERA3_STREAM_BIDIRECTIONAL
|| newStream->usage & GRALLOC_USAGE_HW_CAMERA_ZSL) &&
- newStream->format == HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED && jpegStream){
+ newStream->format == HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED){
mStreamConfigInfo.type[mStreamConfigInfo.num_streams] = CAM_STREAM_TYPE_SNAPSHOT;
mStreamConfigInfo.postprocess_mask[mStreamConfigInfo.num_streams] = CAM_QCOM_FEATURE_NONE;
} else if(newStream->stream_type == CAMERA3_STREAM_INPUT) {
@@ -1405,7 +1435,18 @@
break;
case HAL_PIXEL_FORMAT_YCbCr_420_888:
mStreamConfigInfo.type[mStreamConfigInfo.num_streams] = CAM_STREAM_TYPE_CALLBACK;
- mStreamConfigInfo.postprocess_mask[mStreamConfigInfo.num_streams] = CAM_QCOM_FEATURE_PP_SUPERSET_HAL3;
+ if (isOnEncoder(maxViewfinderSize, newStream->width,
+ newStream->height)) {
+ if (bUseCommonFeatureMask)
+ mStreamConfigInfo.postprocess_mask[mStreamConfigInfo.num_streams] =
+ commonFeatureMask;
+ else
+ mStreamConfigInfo.postprocess_mask[mStreamConfigInfo.num_streams] =
+ CAM_QCOM_FEATURE_NONE;
+ } else {
+ mStreamConfigInfo.postprocess_mask[mStreamConfigInfo.num_streams] =
+ CAM_QCOM_FEATURE_PP_SUPERSET_HAL3;
+ }
break;
case HAL_PIXEL_FORMAT_BLOB:
mStreamConfigInfo.type[mStreamConfigInfo.num_streams] = CAM_STREAM_TYPE_SNAPSHOT;
@@ -1414,8 +1455,8 @@
= CAM_QCOM_FEATURE_PP_SUPERSET_HAL3;
} else {
if (bUseCommonFeatureMask &&
- (((int32_t)newStream->width > maxViewfinderSize.width) ||
- ((int32_t)newStream->height > maxViewfinderSize.height))) {
+ isOnEncoder(maxViewfinderSize, newStream->width,
+ newStream->height)) {
mStreamConfigInfo.postprocess_mask[mStreamConfigInfo.num_streams] = commonFeatureMask;
} else {
mStreamConfigInfo.postprocess_mask[mStreamConfigInfo.num_streams] = CAM_QCOM_FEATURE_NONE;
@@ -1437,6 +1478,11 @@
(int32_t)videoWidth;
mStreamConfigInfo.stream_sizes[mStreamConfigInfo.num_streams].height =
(int32_t)videoHeight;
+ } else if (bYuv888OverrideJpeg) {
+ mStreamConfigInfo.stream_sizes[mStreamConfigInfo.num_streams].width =
+ (int32_t)largeYuv888Size.width;
+ mStreamConfigInfo.stream_sizes[mStreamConfigInfo.num_streams].height =
+ (int32_t)largeYuv888Size.height;
}
break;
case HAL_PIXEL_FORMAT_RAW_OPAQUE:
@@ -1483,7 +1529,7 @@
if (newStream->stream_type == CAMERA3_STREAM_OUTPUT ||
newStream->stream_type == CAMERA3_STREAM_BIDIRECTIONAL) {
- QCamera3Channel *channel = NULL;
+ QCamera3ProcessingChannel *channel = NULL;
switch (newStream->format) {
case HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED:
/* use higher number of buffers for HFR mode */
@@ -1522,7 +1568,7 @@
newStream->max_buffers = channel->getNumBuffers();
newStream->priv = channel;
break;
- case HAL_PIXEL_FORMAT_YCbCr_420_888:
+ case HAL_PIXEL_FORMAT_YCbCr_420_888: {
channel = new QCamera3YUVChannel(mCameraHandle->camera_handle,
mCameraHandle->ops, captureResultCb,
&gCamCapability[mCameraId]->padding_info,
@@ -1540,6 +1586,7 @@
newStream->max_buffers = channel->getNumBuffers();
newStream->priv = channel;
break;
+ }
case HAL_PIXEL_FORMAT_RAW_OPAQUE:
case HAL_PIXEL_FORMAT_RAW16:
case HAL_PIXEL_FORMAT_RAW10:
@@ -1556,7 +1603,7 @@
return -ENOMEM;
}
newStream->max_buffers = mRawChannel->getNumBuffers();
- newStream->priv = (QCamera3Channel*)mRawChannel;
+ newStream->priv = (QCamera3ProcessingChannel*)mRawChannel;
break;
case HAL_PIXEL_FORMAT_BLOB:
// Max live snapshot inflight buffer is 1. This is to mitigate
@@ -1573,8 +1620,11 @@
pthread_mutex_unlock(&mMutex);
return -ENOMEM;
}
- newStream->priv = (QCamera3Channel*)mPictureChannel;
+ newStream->priv = (QCamera3ProcessingChannel*)mPictureChannel;
newStream->max_buffers = mPictureChannel->getNumBuffers();
+ mPictureChannel->overrideYuvSize(
+ mStreamConfigInfo.stream_sizes[mStreamConfigInfo.num_streams].width,
+ mStreamConfigInfo.stream_sizes[mStreamConfigInfo.num_streams].height);
break;
default:
@@ -1591,7 +1641,7 @@
for (List<stream_info_t*>::iterator it=mStreamInfo.begin();
it != mStreamInfo.end(); it++) {
if ((*it)->stream == newStream) {
- (*it)->channel = (QCamera3Channel*) newStream->priv;
+ (*it)->channel = (QCamera3ProcessingChannel*) newStream->priv;
break;
}
}
@@ -1607,24 +1657,6 @@
mStreamConfigInfo.num_streams++;
}
- if (isZsl) {
- if (zslStream == NULL) {
- ALOGE("%s: Error Zsl stream handle missing", __func__);
- pthread_mutex_unlock(&mMutex);
- return -EINVAL;
- }
- /* This override is possible since the f/w gaurantees that the ZSL
- stream will always be the active array size in case of Bidirectional
- or will be limited to the max i/p stream size which we can control to
- be equal to be the largest YUV/Opaque stream size
- */
- if (mPictureChannel) {
- mPictureChannel->overrideYuvSize(zslStream->width, zslStream->height);
- }
- } else if (mPictureChannel && m_bIs4KVideo) {
- mPictureChannel->overrideYuvSize(videoWidth, videoHeight);
- }
-
//RAW DUMP channel
if (mEnableRawDump && isRawStreamRequested == false){
cam_dimension_t rawDumpSize;
@@ -1806,8 +1838,8 @@
// Validate all buffers
b = request->output_buffers;
do {
- QCamera3Channel *channel =
- static_cast<QCamera3Channel*>(b->stream->priv);
+ QCamera3ProcessingChannel *channel =
+ static_cast<QCamera3ProcessingChannel*>(b->stream->priv);
if (channel == NULL) {
ALOGE("%s: Request %d: Buffer %ld: Unconfigured stream!",
__func__, frameNumber, (long)idx);
@@ -2265,7 +2297,7 @@
}
goto done_metadata;
}
- CDBG("%s: valid frame_number = %u, capture_time = %lld", __func__,
+ CDBG_HIGH("%s: valid frame_number = %u, capture_time = %lld", __func__,
frame_number, capture_time);
for (pendingRequestIterator i = mPendingRequestsList.begin();
@@ -2290,7 +2322,7 @@
for (List<RequestedBufferInfo>::iterator j = i->buffers.begin();
j != i->buffers.end(); j++) {
if (j->stream->format != HAL_PIXEL_FORMAT_BLOB) {
- QCamera3Channel *channel = (QCamera3Channel *)j->stream->priv;
+ QCamera3ProcessingChannel *channel = (QCamera3ProcessingChannel *)j->stream->priv;
uint32_t streamID = channel->getStreamID(channel->getStreamTypeMask());
for (uint32_t k = 0; k < p_cam_frame_drop->cam_stream_ID.num_streams; k++) {
if (streamID == p_cam_frame_drop->cam_stream_ID.streamID[k]) {
@@ -2373,15 +2405,26 @@
frame_number);
}
}
+ }
-
- mPictureChannel->queueReprocMetadata(metadata_buf);
- } else {
+ // Find channel requiring metadata, and queue the current metadata.
+ //TODO: for now, we don't support two streams requiring metadata at the same time.
+ // (because we are not making copies, and metadata buffer is not reference counted.
+ pendingBufferIterator iter = i->buffers.begin();
+ while (iter != i->buffers.end() && !iter->need_metadata)
+ iter++;
+ if (iter == i->buffers.end()) {
+ CDBG("%s: couldn't find need_metadata for this metadata", __func__);
// Return metadata buffer
if (free_and_bufdone_meta_buf) {
mMetadataChannel->bufDone(metadata_buf);
free(metadata_buf);
}
+ } else {
+ CDBG("%s: need_metadata is set for this metadata", __func__);
+ QCamera3ProcessingChannel *channel =
+ (QCamera3ProcessingChannel *)iter->stream->priv;
+ channel->queueReprocMetadata(metadata_buf);
}
}
if (!result.result) {
@@ -2518,7 +2561,7 @@
}
}
result.output_buffers = buffer;
- CDBG("%s: result frame_number = %d, buffer = %p",
+ CDBG_HIGH("%s: result frame_number = %d, buffer = %p",
__func__, frame_number, buffer->buffer);
for (List<PendingBufferInfo>::iterator k =
@@ -2626,7 +2669,7 @@
j->buffer = (camera3_stream_buffer_t *)malloc(
sizeof(camera3_stream_buffer_t));
*(j->buffer) = *buffer;
- CDBG("%s: cache buffer %p at result frame_number %d",
+ CDBG_HIGH("%s: cache buffer %p at result frame_number %d",
__func__, buffer, frame_number);
}
}
@@ -2652,6 +2695,7 @@
pthread_cond_signal(&mRequestCond);
}
+
/*===========================================================================
* FUNCTION : processCaptureRequest
*
@@ -2983,7 +3027,7 @@
request_id = mCurrentRequestId;
}
- CDBG("%s: %d, num_output_buffers = %d input_buffer = %p frame_number = %d",
+ CDBG_HIGH("%s: %d, num_output_buffers = %d input_buffer = %p frame_number = %d",
__func__, __LINE__,
request->num_output_buffers,
request->input_buffer,
@@ -3081,6 +3125,7 @@
/* Update pending request list and pending buffers map */
PendingRequestInfo pendingRequest;
+ pendingRequestIterator latestRequest;
pendingRequest.frame_number = frameNumber;
pendingRequest.num_buffers = request->num_output_buffers;
pendingRequest.request_id = request_id;
@@ -3110,6 +3155,7 @@
for (size_t i = 0; i < request->num_output_buffers; i++) {
RequestedBufferInfo requestedBuf;
+ memset(&requestedBuf, 0, sizeof(requestedBuf));
requestedBuf.stream = request->output_buffers[i].stream;
requestedBuf.buffer = NULL;
pendingRequest.buffers.push_back(requestedBuf);
@@ -3126,11 +3172,8 @@
__func__, frameNumber, bufferInfo.buffer,
channel->getStreamTypeMask(), bufferInfo.stream->format);
}
- CDBG("%s: mPendingBuffersMap.num_buffers = %d",
- __func__, mPendingBuffersMap.num_buffers);
-
- mPendingRequestsList.push_back(pendingRequest);
-
+ latestRequest = mPendingRequestsList.insert(
+ mPendingRequestsList.end(), pendingRequest);
if(mFlush) {
pthread_mutex_unlock(&mMutex);
return NO_ERROR;
@@ -3149,6 +3192,8 @@
}
// Call request on other streams
+ uint32_t streams_need_metadata = 0;
+ pendingBufferIterator pendingBufferIter = latestRequest->buffers.begin();
for (size_t i = 0; i < request->num_output_buffers; i++) {
const camera3_stream_buffer_t& output = request->output_buffers[i];
QCamera3Channel *channel = (QCamera3Channel *)output.stream->priv;
@@ -3182,16 +3227,25 @@
pthread_mutex_unlock(&mMutex);
return rc;
}
+ pendingBufferIter->need_metadata = true;
+ streams_need_metadata++;
}
} else if (output.stream->format == HAL_PIXEL_FORMAT_YCbCr_420_888) {
- rc = channel->request(output.buffer, frameNumber,
+ bool needMetadata = false;
+ QCamera3YUVChannel *yuvChannel = (QCamera3YUVChannel *)channel;
+ rc = yuvChannel->request(output.buffer, frameNumber,
pInputBuffer,
- (pInputBuffer ? &mReprocMeta : mParameters));
+ (pInputBuffer ? &mReprocMeta : mParameters), needMetadata);
if (rc < 0) {
ALOGE("%s: Fail to request on YUV channel", __func__);
pthread_mutex_unlock(&mMutex);
return rc;
}
+ pendingBufferIter->need_metadata = needMetadata;
+ if (needMetadata)
+ streams_need_metadata += 1;
+ CDBG("%s: calling YUV channel request, need_metadata is %d",
+ __func__, needMetadata);
} else {
CDBG("%s: %d, request with buffer %p, frame_number %d", __func__,
__LINE__, output.buffer, frameNumber);
@@ -3209,6 +3263,15 @@
return rc;
}
}
+ pendingBufferIter++;
+ }
+
+ //If 2 streams have need_metadata set to true, fail the request, unless
+ //we copy/reference count the metadata buffer
+ if (streams_need_metadata > 1) {
+ //TODO: Return error from here
+ ALOGE("s: not supporting request in which two streams requires"
+ " 2 HAL metadata for reprocessing", __func__);
}
if(request->input_buffer == NULL) {
@@ -3722,11 +3785,11 @@
fwk_blackLevelInd[2] = blackLevelInd->cam_black_level[2];
fwk_blackLevelInd[3] = blackLevelInd->cam_black_level[3];
- ALOGE("%s: dynamicblackLevel = %d %d %d %d", __func__,
- blackLevelInd->cam_black_level[0],
- blackLevelInd->cam_black_level[1],
- blackLevelInd->cam_black_level[2],
- blackLevelInd->cam_black_level[3]);
+ CDBG("%s: dynamicblackLevel = %d %d %d %d", __func__,
+ blackLevelInd->cam_black_level[0],
+ blackLevelInd->cam_black_level[1],
+ blackLevelInd->cam_black_level[2],
+ blackLevelInd->cam_black_level[3]);
camMetadata.update(QCAMERA3_SENSOR_DYNAMIC_BLACK_LEVEL_PATTERN, fwk_blackLevelInd, 4);
}
@@ -4665,6 +4728,7 @@
thumbnail_size,
frame_settings.find(ANDROID_JPEG_THUMBNAIL_SIZE).count);
}
+
}
/*===========================================================================
@@ -5746,7 +5810,8 @@
uint8_t available_edge_modes[] = {ANDROID_EDGE_MODE_OFF,
ANDROID_EDGE_MODE_FAST,
- ANDROID_EDGE_MODE_HIGH_QUALITY};
+ ANDROID_EDGE_MODE_HIGH_QUALITY,
+ ANDROID_EDGE_MODE_ZERO_SHUTTER_LAG};
staticInfo.update(ANDROID_EDGE_AVAILABLE_EDGE_MODES,
available_edge_modes,
sizeof(available_edge_modes)/sizeof(available_edge_modes[0]));
@@ -5754,7 +5819,8 @@
uint8_t available_noise_red_modes[] = {ANDROID_NOISE_REDUCTION_MODE_OFF,
ANDROID_NOISE_REDUCTION_MODE_FAST,
ANDROID_NOISE_REDUCTION_MODE_HIGH_QUALITY,
- ANDROID_NOISE_REDUCTION_MODE_MINIMAL};
+ ANDROID_NOISE_REDUCTION_MODE_MINIMAL,
+ ANDROID_NOISE_REDUCTION_MODE_ZERO_SHUTTER_LAG};
staticInfo.update(ANDROID_NOISE_REDUCTION_AVAILABLE_NOISE_REDUCTION_MODES,
available_noise_red_modes,
sizeof(available_noise_red_modes)/sizeof(available_noise_red_modes[0]));
@@ -8509,7 +8575,7 @@
pendingRequestIterator i = mPendingRequestsList.begin();
frameNum = i->frame_number;
- CDBG("%s: Oldest frame num on mPendingRequestsList = %d",
+ CDBG_HIGH("%s: Oldest frame num on mPendingRequestsList = %d",
__func__, frameNum);
// Go through the pending buffers and group them depending
@@ -8543,7 +8609,7 @@
// Send Error notify to frameworks for each buffer for which
// metadata buffer is already sent
- CDBG("%s: Sending ERROR BUFFER for frame %d number of buffer %d",
+ CDBG_HIGH("%s: Sending ERROR BUFFER for frame %d number of buffer %d",
__func__, frame_number, pending.size());
pStream_Buf = new camera3_stream_buffer_t[pending.size()];
@@ -8567,7 +8633,7 @@
pStream_Buf[j].status = CAMERA3_BUFFER_STATUS_ERROR;
pStream_Buf[j].stream = info.stream;
mCallbackOps->notify(mCallbackOps, ¬ify_msg);
- CDBG("%s: notify frame_number = %d stream %p", __func__,
+ CDBG_HIGH("%s: notify frame_number = %d stream %p", __func__,
frame_number, info.stream);
}
@@ -8580,7 +8646,7 @@
delete [] pStream_Buf;
}
- CDBG("%s:Sending ERROR REQUEST for all pending requests", __func__);
+ CDBG_HIGH("%s:Sending ERROR REQUEST for all pending requests", __func__);
flushMap.clear();
for (List<PendingBufferInfo>::iterator k =
@@ -8605,7 +8671,7 @@
for (size_t iFlush = 0; iFlush < flushMap.size(); iFlush++) {
uint32_t frame_number = flushMap.keyAt(iFlush);
const Vector<PendingBufferInfo> &pending = flushMap.valueAt(iFlush);
- CDBG("%s:Sending ERROR REQUEST for frame %d",
+ CDBG_HIGH("%s:Sending ERROR REQUEST for frame %d",
__func__, frame_number);
// Send shutter notify to frameworks
@@ -8653,9 +8719,17 @@
mPendingBuffersMap.num_buffers = 0;
mPendingBuffersMap.mPendingBufferList.clear();
mPendingReprocessResultList.clear();
- CDBG("%s: Cleared all the pending buffers ", __func__);
+ CDBG_HIGH("%s: Cleared all the pending buffers ", __func__);
return rc;
}
+bool QCamera3HardwareInterface::isOnEncoder(
+ const cam_dimension_t max_viewfinder_size,
+ uint32_t width, uint32_t height)
+{
+ return (width > (uint32_t)max_viewfinder_size.width ||
+ height > (uint32_t)max_viewfinder_size.height);
+}
+
}; //end namespace qcamera
diff --git a/QCamera2/HAL3/QCamera3HWI.h b/QCamera2/HAL3/QCamera3HWI.h
index e3aae7f..31ffb5e 100644
--- a/QCamera2/HAL3/QCamera3HWI.h
+++ b/QCamera2/HAL3/QCamera3HWI.h
@@ -100,7 +100,7 @@
camera3_stream_buffer_set_t buffer_set;
stream_status_t status;
int registered;
- QCamera3Channel *channel;
+ QCamera3ProcessingChannel *channel;
} stream_info_t;
class QCamera3HardwareInterface {
@@ -246,6 +246,8 @@
metadata_buffer_t *hal_metadata);
int32_t extractSceneMode(const CameraMetadata &frame_settings, uint8_t metaMode,
metadata_buffer_t *hal_metadata);
+ int32_t numOfSizesOnEncoder(const camera3_stream_configuration_t *streamList,
+ const cam_dimension_t &maxViewfinderSize);
void updatePowerHint(bool bWasVideo, bool bIsVideo);
int32_t getSensorOutputSize(cam_dimension_t &sensor_dim);
@@ -254,6 +256,9 @@
int32_t stopAllChannels();
int32_t notifyErrorForPendingRequests();
+ bool isOnEncoder(const cam_dimension_t max_viewfinder_size,
+ uint32_t width, uint32_t height);
+
camera3_device_t mCameraDevice;
uint32_t mCameraId;
mm_camera_vtbl_t *mCameraHandle;
@@ -292,6 +297,9 @@
typedef struct {
camera3_stream_t *stream;
camera3_stream_buffer_t *buffer;
+ // metadata needs to be consumed by the corresponding stream
+ // in order to generate the buffer.
+ bool need_metadata;
} RequestedBufferInfo;
typedef struct {
uint32_t frame_number;
@@ -320,6 +328,7 @@
camera3_stream_t *stream;
// Buffer handle
buffer_handle_t *buffer;
+
} PendingBufferInfo;
typedef struct {
@@ -338,6 +347,8 @@
typedef KeyedVector<uint32_t, Vector<PendingBufferInfo> > FlushMap;
typedef List<QCamera3HardwareInterface::PendingRequestInfo>::iterator
pendingRequestIterator;
+ typedef List<QCamera3HardwareInterface::RequestedBufferInfo>::iterator
+ pendingBufferIterator;
List<PendingReprocessResult> mPendingReprocessResultList;
List<PendingRequestInfo> mPendingRequestsList;
diff --git a/QCamera2/HAL3/QCamera3Mem.cpp b/QCamera2/HAL3/QCamera3Mem.cpp
index 74e328b..1d730b1 100644
--- a/QCamera2/HAL3/QCamera3Mem.cpp
+++ b/QCamera2/HAL3/QCamera3Mem.cpp
@@ -66,6 +66,7 @@
mMemInfo[i].main_ion_fd = -1;
mMemInfo[i].handle = 0;
mMemInfo[i].size = 0;
+ mCurrentFrameNumbers[i] = -1;
}
}
@@ -261,7 +262,25 @@
QCamera3HeapMemory::QCamera3HeapMemory()
: QCamera3Memory()
{
- for (int i = 0; i < MM_CAMERA_MAX_NUM_FRAMES; i ++)
+ mMaxCnt = MM_CAMERA_MAX_NUM_FRAMES;
+ for (uint32_t i = 0; i < mMaxCnt; i ++)
+ mPtr[i] = NULL;
+}
+
+/*===========================================================================
+ * FUNCTION : QCamera3HeapMemory
+ *
+ * DESCRIPTION: constructor of QCamera3HeapMemory for ion memory used internally in HAL
+ *
+ * PARAMETERS : none
+ *
+ * RETURN : none
+ *==========================================================================*/
+QCamera3HeapMemory::QCamera3HeapMemory(uint32_t maxCnt)
+ : QCamera3Memory()
+{
+ mMaxCnt = MIN(maxCnt, MM_CAMERA_MAX_NUM_FRAMES);
+ for (uint32_t i = 0; i < mMaxCnt; i ++)
mPtr[i] = NULL;
}
@@ -279,59 +298,6 @@
}
/*===========================================================================
- * FUNCTION : alloc
- *
- * DESCRIPTION: allocate requested number of buffers of certain size
- *
- * PARAMETERS :
- * @count : number of buffers to be allocated
- * @size : lenght of the buffer to be allocated
- * @heap_id : heap id to indicate where the buffers will be allocated from
- *
- * RETURN : int32_t type of status
- * NO_ERROR -- success
- * none-zero failure code
- *==========================================================================*/
-int QCamera3HeapMemory::alloc(uint32_t count, size_t size, unsigned int heap_id)
-{
- int rc = OK;
- if (count > MM_CAMERA_MAX_NUM_FRAMES) {
- ALOGE("Buffer count %d out of bound. Max is %d", count, MM_CAMERA_MAX_NUM_FRAMES);
- return BAD_INDEX;
- }
- if (mBufferCount) {
- ALOGE("Allocating a already allocated heap memory");
- return INVALID_OPERATION;
- }
-
- for (uint32_t i = 0; i < count; i ++) {
- rc = allocOneBuffer(mMemInfo[i], heap_id, size);
- if (rc < 0) {
- ALOGE("AllocateIonMemory failed");
- for (int32_t j = (int32_t)(i - 1); j >= 0; j--)
- deallocOneBuffer(mMemInfo[j]);
- break;
- }
- }
- return rc;
-}
-
-/*===========================================================================
- * FUNCTION : dealloc
- *
- * DESCRIPTION: deallocate buffers
- *
- * PARAMETERS : none
- *
- * RETURN : none
- *==========================================================================*/
-void QCamera3HeapMemory::dealloc()
-{
- for (uint32_t i = 0U; i < mBufferCount; i++)
- deallocOneBuffer(mMemInfo[i]);
-}
-
-/*===========================================================================
* FUNCTION : allocOneBuffer
*
* DESCRIPTION: impl of allocating one buffers of certain size
@@ -448,6 +414,100 @@
}
/*===========================================================================
+ * FUNCTION : markFrameNumber
+ *
+ * DESCRIPTION: We use this function from the request call path to mark the
+ * buffers with the frame number they are intended for this info
+ * is used later when giving out callback & it is duty of PP to
+ * ensure that data for that particular frameNumber/Request is
+ * written to this buffer.
+ * PARAMETERS :
+ * @index : index of the buffer
+ * @frame# : Frame number from the framework
+ *
+ * RETURN : int32_t type of status
+ * NO_ERROR -- success
+ * none-zero failure code
+ *==========================================================================*/
+int32_t QCamera3HeapMemory::markFrameNumber(uint32_t index, uint32_t frameNumber)
+{
+ Mutex::Autolock lock(mLock);
+
+ if (index >= mBufferCount) {
+ ALOGE("%s: Index %d out of bounds, current buffer count is %d",
+ __func__, index, mBufferCount);
+ return BAD_INDEX;
+ }
+
+ if (0 == mMemInfo[index].handle) {
+ ALOGE("%s: Buffer at %d not allocated", __func__, index);
+ return BAD_INDEX;
+ }
+
+ mCurrentFrameNumbers[index] = (int32_t)frameNumber;
+
+ return NO_ERROR;
+}
+
+/*===========================================================================
+ * FUNCTION : getFrameNumber
+ *
+ * DESCRIPTION: We use this to fetch the frameNumber for the request with which
+ * this buffer was given to HAL
+ *
+ *
+ * PARAMETERS :
+ * @index : index of the buffer
+ *
+ * RETURN : int32_t frameNumber
+ * positive/zero -- success
+ * negative failure
+ *==========================================================================*/
+int32_t QCamera3HeapMemory::getFrameNumber(uint32_t index)
+{
+ Mutex::Autolock lock(mLock);
+
+ if (index >= mBufferCount) {
+ ALOGE("%s: Index %d out of bounds, current buffer count is %d",
+ __func__, index, mBufferCount);
+ return -1;
+ }
+
+ if (0 == mMemInfo[index].handle) {
+ ALOGE("%s: Buffer at %d not registered", __func__, index);
+ return -1;
+ }
+
+ return mCurrentFrameNumbers[index];
+}
+
+/*===========================================================================
+ * FUNCTION : getBufferIndex
+ *
+ * DESCRIPTION: We use this to fetch the buffer index for the request with
+ * a particular frame number
+ *
+ *
+ * PARAMETERS :
+ * @frameNumber : frame number of the buffer
+ *
+ * RETURN : int32_t buffer index
+ * negative failure
+ *==========================================================================*/
+int32_t QCamera3HeapMemory::getBufferIndex(uint32_t frameNumber)
+{
+ Mutex::Autolock lock(mLock);
+
+ for (uint32_t index = 0;
+ index < mBufferCount; index++) {
+ if (mMemInfo[index].handle &&
+ mCurrentFrameNumbers[index] == (int32_t)frameNumber)
+ return (int32_t)index;
+ }
+ return -1;
+}
+
+/*===========================================================================
* FUNCTION : getPtr
*
* DESCRIPTION: Return buffer pointer
@@ -479,30 +539,50 @@
int QCamera3HeapMemory::allocate(uint32_t count, size_t size, bool queueAll)
{
unsigned int heap_id_mask = 0x1 << ION_IOMMU_HEAP_ID;
- int rc = alloc(count, size, heap_id_mask);
- if (rc < 0)
- return rc;
+ uint32_t i;
+ int rc = NO_ERROR;
- for (uint32_t i = 0; i < count; i ++) {
+ //Note that now we allow incremental allocation. In other words, we allow
+ //multiple alloc being called as long as the sum of count does not exceed
+ //mMaxCnt.
+ if (mBufferCount + count > mMaxCnt) {
+ ALOGE("Buffer count %d + %d out of bound. Max is %d",
+ mBufferCount, count, mMaxCnt);
+ return BAD_INDEX;
+ }
+
+ for (i = 0; i < count; i ++) {
+ rc = allocOneBuffer(mMemInfo[mBufferCount+i], heap_id_mask, size);
+ if (rc < 0) {
+ ALOGE("AllocateIonMemory failed");
+ goto ALLOC_FAILED;
+ }
+
void *vaddr = mmap(NULL,
- mMemInfo[i].size,
+ mMemInfo[mBufferCount+i].size,
PROT_READ | PROT_WRITE,
MAP_SHARED,
- mMemInfo[i].fd, 0);
+ mMemInfo[mBufferCount+i].fd, 0);
if (vaddr == MAP_FAILED) {
- for (int32_t j = (int32_t)(i - 1); j >= 0; j --) {
- munmap(mPtr[j], mMemInfo[j].size);
- rc = NO_MEMORY;
- break;
- }
+ deallocOneBuffer(mMemInfo[mBufferCount+i]);
+ ALOGE("%s: mmap failed for buffer %d", __func__, i);
+ goto ALLOC_FAILED;
} else
mPtr[i] = vaddr;
}
if (rc == 0)
- mBufferCount = count;
+ mBufferCount += count;
mQueueAll = queueAll;
return OK;
+
+ALLOC_FAILED:
+ for (uint32_t j = 0; j < i; j++) {
+ munmap(mPtr[mBufferCount+j], mMemInfo[mBufferCount+j].size);
+ mPtr[mBufferCount+j] = NULL;
+ deallocOneBuffer(mMemInfo[mBufferCount+j]);
+ }
+ return NO_MEMORY;
}
/*===========================================================================
@@ -519,8 +599,9 @@
for (uint32_t i = 0; i < mBufferCount; i++) {
munmap(mPtr[i], mMemInfo[i].size);
mPtr[i] = NULL;
+ deallocOneBuffer(mMemInfo[i]);
+ mCurrentFrameNumbers[i] = -1;
}
- dealloc();
mBufferCount = 0;
}
@@ -604,17 +685,16 @@
* preview stream buffers are allocated from gralloc native_windoe
*
* PARAMETERS :
- * @getMemory : camera memory request ops table
+ * @startIdx : start index of array after which we can register buffers in.
*
* RETURN : none
*==========================================================================*/
-QCamera3GrallocMemory::QCamera3GrallocMemory()
- : QCamera3Memory()
+QCamera3GrallocMemory::QCamera3GrallocMemory(uint32_t startIdx)
+ : QCamera3Memory(), mStartIdx(startIdx)
{
for (int i = 0; i < MM_CAMERA_MAX_NUM_FRAMES; i ++) {
mBufferHandle[i] = NULL;
mPrivateHandle[i] = NULL;
- mCurrentFrameNumbers[i] = -1;
}
}
@@ -654,7 +734,7 @@
(type == CAM_STREAM_TYPE_VIDEO) ? ITU_R_709 : ITU_R_601_FR;
int32_t idx = -1;
- CDBG(" %s : E ", __FUNCTION__);
+ CDBG("%s: E", __func__);
memset(&ion_info_fd, 0, sizeof(ion_info_fd));
@@ -664,9 +744,9 @@
}
Mutex::Autolock lock(mLock);
- if (mBufferCount >= (MM_CAMERA_MAX_NUM_FRAMES - 1)) {
+ if (mBufferCount >= (MM_CAMERA_MAX_NUM_FRAMES - 1 - mStartIdx)) {
ALOGE("%s: Number of buffers %d greater than what's supported %d",
- __func__, mBufferCount, MM_CAMERA_MAX_NUM_FRAMES);
+ __func__, mBufferCount, MM_CAMERA_MAX_NUM_FRAMES - mStartIdx);
return BAD_INDEX;
}
@@ -696,8 +776,8 @@
goto end;
}
}
- ALOGV("%s: idx = %d, fd = %d, size = %d, offset = %d",
- __func__, mBufferCount, mPrivateHandle[mBufferCount]->fd,
+ CDBG("%s: idx = %d, fd = %d, size = %d, offset = %d",
+ __func__, idx, mPrivateHandle[idx]->fd,
mPrivateHandle[idx]->size,
mPrivateHandle[idx]->offset);
mMemInfo[idx].fd = mPrivateHandle[idx]->fd;
@@ -752,6 +832,7 @@
mMemInfo[idx].main_ion_fd = -1;
mBufferHandle[idx] = NULL;
mPrivateHandle[idx] = NULL;
+ mCurrentFrameNumbers[idx] = -1;
mBufferCount--;
return NO_ERROR;
@@ -781,6 +862,11 @@
__func__, idx, MM_CAMERA_MAX_NUM_FRAMES);
return BAD_VALUE;
}
+ if (idx < mStartIdx) {
+ ALOGE("%s: buffer index %d less than starting index %d",
+ __func__, idx, mStartIdx);
+ return BAD_INDEX;
+ }
if (0 == mMemInfo[idx].handle) {
ALOGE("%s: Trying to unregister buffer at %d which still not registered",
@@ -811,7 +897,7 @@
CDBG("%s: E ", __FUNCTION__);
- for (uint32_t cnt = 0; cnt < MM_CAMERA_MAX_NUM_FRAMES; cnt++) {
+ for (uint32_t cnt = mStartIdx; cnt < MM_CAMERA_MAX_NUM_FRAMES; cnt++) {
if (0 == mMemInfo[cnt].handle) {
continue;
}
@@ -849,6 +935,11 @@
ALOGE("%s: Index out of bounds", __func__);
return BAD_INDEX;
}
+ if (index < mStartIdx) {
+ ALOGE("%s: buffer index %d less than starting index %d",
+ __func__, index, mStartIdx);
+ return BAD_INDEX;
+ }
if (0 == mMemInfo[index].handle) {
ALOGE("%s: Buffer at %d not registered", __func__, index);
@@ -882,6 +973,11 @@
ALOGE("%s: Index out of bounds", __func__);
return -1;
}
+ if (index < mStartIdx) {
+ ALOGE("%s: buffer index %d less than starting index %d",
+ __func__, index, mStartIdx);
+ return BAD_INDEX;
+ }
if (0 == mMemInfo[index].handle) {
ALOGE("%s: Buffer at %d not registered", __func__, index);
@@ -892,6 +988,30 @@
}
/*===========================================================================
+ * FUNCTION : getBufferIndex
+ *
+ * DESCRIPTION: We use this to fetch the buffer index for the request with
+ * a particular frame number
+ *
+ *
+ * PARAMETERS :
+ * @frameNumber : frame number of the buffer
+ *
+ * RETURN : int32_t buffer index
+ * negative failure
+ *==========================================================================*/
+int32_t QCamera3GrallocMemory::getBufferIndex(uint32_t frameNumber)
+{
+ for (uint32_t index = mStartIdx;
+ index < MM_CAMERA_MAX_NUM_FRAMES; index++) {
+ if (mMemInfo[index].handle &&
+ mCurrentFrameNumbers[index] == (int32_t)frameNumber)
+ return (int32_t)index;
+ }
+ return -1;
+}
+
+/*===========================================================================
* FUNCTION : cacheOps
*
* DESCRIPTION: ion related memory cache operations
@@ -906,6 +1026,16 @@
*==========================================================================*/
int QCamera3GrallocMemory::cacheOps(uint32_t index, unsigned int cmd)
{
+ if (index >= MM_CAMERA_MAX_NUM_FRAMES) {
+ ALOGE("%s: Index out of bounds", __func__);
+ return -1;
+ }
+ if (index < mStartIdx) {
+ ALOGE("%s: buffer index %d less than starting index %d",
+ __func__, index, mStartIdx);
+ return BAD_INDEX;
+ }
+
return cacheOpsInternal(index, cmd, mPtr[index]);
}
@@ -950,7 +1080,7 @@
if (!key) {
return BAD_VALUE;
}
- for (uint32_t i = 0; i < MM_CAMERA_MAX_NUM_FRAMES; i++) {
+ for (uint32_t i = mStartIdx; i < MM_CAMERA_MAX_NUM_FRAMES; i++) {
if (mBufferHandle[i] == key) {
index = (int)i;
break;
@@ -981,7 +1111,7 @@
return index;
}
- for (size_t i = 0; i < MM_CAMERA_MAX_NUM_FRAMES; i++) {
+ for (size_t i = mStartIdx; i < MM_CAMERA_MAX_NUM_FRAMES; i++) {
if (0 == mMemInfo[i].handle) {
index = i;
break;
@@ -1009,6 +1139,12 @@
__func__, index, MM_CAMERA_MAX_NUM_FRAMES);
return NULL;
}
+ if (index < mStartIdx) {
+ ALOGE("%s: buffer index %d less than starting index %d",
+ __func__, index, mStartIdx);
+ return NULL;
+ }
+
if (0 == mMemInfo[index].handle) {
ALOGE("%s: Buffer at %d not registered", __func__, index);
@@ -1054,6 +1190,11 @@
__func__, index, MM_CAMERA_MAX_NUM_FRAMES);
return NULL;
}
+ if (index < mStartIdx) {
+ ALOGE("%s: buffer index %d less than starting index %d",
+ __func__, index, mStartIdx);
+ return NULL;
+ }
if (0 == mMemInfo[index].handle) {
ALOGE("%s: Buffer at %d not registered", __func__, index);
@@ -1062,5 +1203,4 @@
return mBufferHandle[index];
}
-
}; //namespace qcamera
diff --git a/QCamera2/HAL3/QCamera3Mem.h b/QCamera2/HAL3/QCamera3Mem.h
index b32f6dc..e8154cd 100644
--- a/QCamera2/HAL3/QCamera3Mem.h
+++ b/QCamera2/HAL3/QCamera3Mem.h
@@ -67,6 +67,10 @@
virtual int getMatchBufIndex(void *object) = 0;
virtual void *getPtr(uint32_t index) = 0;
+ virtual int32_t markFrameNumber(uint32_t index, uint32_t frameNumber) = 0;
+ virtual int32_t getFrameNumber(uint32_t index) = 0;
+ virtual int32_t getBufferIndex(uint32_t frameNumber) = 0;
+
QCamera3Memory();
virtual ~QCamera3Memory();
@@ -87,6 +91,7 @@
uint32_t mBufferCount;
struct QCamera3MemInfo mMemInfo[MM_CAMERA_MAX_NUM_FRAMES];
void *mPtr[MM_CAMERA_MAX_NUM_FRAMES];
+ int32_t mCurrentFrameNumbers[MM_CAMERA_MAX_NUM_FRAMES];
Mutex mLock;
};
@@ -96,6 +101,7 @@
class QCamera3HeapMemory : public QCamera3Memory {
public:
QCamera3HeapMemory();
+ QCamera3HeapMemory(uint32_t maxCnt);
virtual ~QCamera3HeapMemory();
int allocate(uint32_t count, size_t size, bool queueAll);
@@ -105,22 +111,25 @@
virtual int getRegFlags(uint8_t *regFlags);
virtual int getMatchBufIndex(void *object);
virtual void *getPtr(uint32_t index);
+
+ virtual int32_t markFrameNumber(uint32_t index, uint32_t frameNumber);
+ virtual int32_t getFrameNumber(uint32_t index);
+ virtual int32_t getBufferIndex(uint32_t frameNumber);
+
protected:
virtual void *getPtrLocked(uint32_t index);
private:
- int alloc(uint32_t count, size_t size, unsigned int heap_id);
- void dealloc();
-
int allocOneBuffer(struct QCamera3MemInfo &memInfo,
unsigned int heap_id, size_t size);
void deallocOneBuffer(struct QCamera3MemInfo &memInfo);
bool mQueueAll;
+ uint32_t mMaxCnt;
};
// Gralloc Memory shared with frameworks
class QCamera3GrallocMemory : public QCamera3Memory {
public:
- QCamera3GrallocMemory();
+ QCamera3GrallocMemory(uint32_t startIdx);
virtual ~QCamera3GrallocMemory();
int registerBuffer(buffer_handle_t *buffer, cam_stream_type_t type);
@@ -130,8 +139,11 @@
virtual int getRegFlags(uint8_t *regFlags);
virtual int getMatchBufIndex(void *object);
virtual void *getPtr(uint32_t index);
- int32_t markFrameNumber(uint32_t index, uint32_t frameNumber);
- int32_t getFrameNumber(uint32_t index);
+
+ virtual int32_t markFrameNumber(uint32_t index, uint32_t frameNumber);
+ virtual int32_t getFrameNumber(uint32_t index);
+ virtual int32_t getBufferIndex(uint32_t frameNumber);
+
void *getBufferHandle(uint32_t index);
protected:
virtual void *getPtrLocked(uint32_t index);
@@ -140,8 +152,8 @@
int32_t getFreeIndexLocked();
buffer_handle_t *mBufferHandle[MM_CAMERA_MAX_NUM_FRAMES];
struct private_handle_t *mPrivateHandle[MM_CAMERA_MAX_NUM_FRAMES];
- int32_t mCurrentFrameNumbers[MM_CAMERA_MAX_NUM_FRAMES];
-};
+ uint32_t mStartIdx;
+};
};
#endif
diff --git a/QCamera2/HAL3/QCamera3PostProc.cpp b/QCamera2/HAL3/QCamera3PostProc.cpp
index a9b3a9b..65a6206 100644
--- a/QCamera2/HAL3/QCamera3PostProc.cpp
+++ b/QCamera2/HAL3/QCamera3PostProc.cpp
@@ -74,7 +74,6 @@
m_ongoingPPQ(releaseOngoingPPData, this),
m_inputJpegQ(releaseJpegData, this),
m_ongoingJpegQ(releaseJpegData, this),
- m_inputRawQ(releasePPInputData, this),
m_inputMetaQ(releaseMetadata, this),
m_jpegSettingsQ(NULL, this)
{
@@ -109,7 +108,7 @@
* NO_ERROR -- success
* none-zero failure code
*==========================================================================*/
-int32_t QCamera3PostProcessor::init(QCamera3Memory *memory,
+int32_t QCamera3PostProcessor::init(QCamera3StreamMem *memory,
uint32_t postprocess_mask)
{
ATRACE_CALL();
@@ -421,7 +420,7 @@
// src buf config
//Pass input main image buffer info to encoder.
- QCamera3Memory *pStreamMem = main_stream->getStreamBufs();
+ QCamera3StreamMem *pStreamMem = main_stream->getStreamBufs();
if (pStreamMem == NULL) {
ALOGE("%s: cannot get stream bufs from main stream", __func__);
ret = BAD_VALUE;
@@ -433,7 +432,7 @@
encode_parm.src_main_buf[i].index = i;
bufSize = pStreamMem->getSize(i);
if (BAD_INDEX == bufSize) {
- ALOGE("%s: cannot retrieve buffer size for buffer %u", __func__, i);
+ ALOGE("%s: cannot retrieve buffer size for buffer %u", __func__, i);
ret = BAD_VALUE;
goto on_error;
}
@@ -503,13 +502,18 @@
return ret;
}
+int32_t QCamera3PostProcessor::processData(mm_camera_super_buf_t *input) {
+ return processData(input, NULL, 0);
+}
+
/*===========================================================================
* FUNCTION : processData
*
* DESCRIPTION: enqueue data into dataProc thread
*
* PARAMETERS :
- * @frame : process frame
+ * @frame : process input frame
+ * @output : process output frame
*
* RETURN : int32_t type of status
* NO_ERROR -- success
@@ -518,16 +522,30 @@
* NOTE : depends on if offline reprocess is needed, received frame will
* be sent to either input queue of postprocess or jpeg encoding
*==========================================================================*/
-int32_t QCamera3PostProcessor::processData(mm_camera_super_buf_t *frame)
+int32_t QCamera3PostProcessor::processData(mm_camera_super_buf_t *input,
+ buffer_handle_t *output, uint32_t frameNumber)
{
+ CDBG("%s: E", __func__);
QCamera3HardwareInterface* hal_obj = (QCamera3HardwareInterface*)m_parent->mUserData;
pthread_mutex_lock(&mReprocJobLock);
+
// enqueue to post proc input queue
- m_inputPPQ.enqueue((void *)frame);
- if (!(m_inputMetaQ.isEmpty())) {
- CDBG("%s: meta queue is not empty, do next job", __func__);
- m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_DO_NEXT_JOB, FALSE, FALSE);
+ qcamera_hal3_pp_buffer_t *pp_buffer = (qcamera_hal3_pp_buffer_t *)malloc(
+ sizeof(qcamera_hal3_pp_buffer_t));
+ if (NULL == pp_buffer) {
+ ALOGE("%s: out of memory", __func__);
+ return NO_MEMORY;
}
+ memset(pp_buffer, 0, sizeof(*pp_buffer));
+ pp_buffer->input = input;
+ pp_buffer->output = output;
+ pp_buffer->frameNumber = frameNumber;
+ m_inputPPQ.enqueue((void *)pp_buffer);
+ if (!(m_inputMetaQ.isEmpty())) {
+ CDBG("%s: meta queue is not empty, do next job", __func__);
+ m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_DO_NEXT_JOB, FALSE, FALSE);
+ } else
+ CDBG("%s: metadata queue is empty", __func__);
pthread_mutex_unlock(&mReprocJobLock);
return NO_ERROR;
@@ -603,7 +621,8 @@
*==========================================================================*/
int32_t QCamera3PostProcessor::processPPMetadata(mm_camera_super_buf_t *reproc_meta)
{
- pthread_mutex_lock(&mReprocJobLock);
+ CDBG("%s: E", __func__);
+ pthread_mutex_lock(&mReprocJobLock);
// enqueue to metadata input queue
m_inputMetaQ.enqueue((void *)reproc_meta);
if (!(m_inputPPQ.isEmpty())) {
@@ -640,26 +659,6 @@
}
/*===========================================================================
- * FUNCTION : processRawData
- *
- * DESCRIPTION: enqueue raw data into dataProc thread
- *
- * PARAMETERS :
- * @frame : process frame received from mm-camera-interface
- *
- * RETURN : int32_t type of status
- * NO_ERROR -- success
- * none-zero failure code
- *==========================================================================*/
-int32_t QCamera3PostProcessor::processRawData(mm_camera_super_buf_t *frame)
-{
- // enqueu to raw input queue
- m_inputRawQ.enqueue((void *)frame);
- m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_DO_NEXT_JOB, FALSE, FALSE);
- return NO_ERROR;
-}
-
-/*===========================================================================
* FUNCTION : processPPData
*
* DESCRIPTION: process received frame after reprocess.
@@ -720,6 +719,31 @@
}
/*===========================================================================
+ * FUNCTION : dequeuePPJob
+ *
+ * DESCRIPTION: find a postprocessing job from ongoing pp queue by frame number
+ *
+ * PARAMETERS :
+ * @frameNumber : frame number for the pp job
+ *
+ * RETURN : ptr to a pp job struct. NULL if not found.
+ *==========================================================================*/
+qcamera_hal3_pp_data_t *QCamera3PostProcessor::dequeuePPJob(uint32_t frameNumber) {
+ qcamera_hal3_pp_data_t *pp_job = NULL;
+ pp_job = (qcamera_hal3_pp_data_t *)m_ongoingPPQ.dequeue();
+
+ if (pp_job == NULL) {
+ ALOGE("%s: Fatal: ongoing PP queue is empty", __func__);
+ return NULL;
+ }
+ if (pp_job->fwk_src_frame &&
+ (pp_job->fwk_src_frame->frameNumber != frameNumber)) {
+ ALOGE("%s: head of pp queue doesn't match requested frame number", __func__);
+ }
+ return pp_job;
+}
+
+/*===========================================================================
* FUNCTION : findJpegJobByJobId
*
* DESCRIPTION: find a jpeg job from ongoing Jpeg queue by its job ID
@@ -761,7 +785,14 @@
{
QCamera3PostProcessor *pme = (QCamera3PostProcessor *)user_data;
if (NULL != pme) {
- pme->releaseSuperBuf((mm_camera_super_buf_t *)data);
+ qcamera_hal3_pp_buffer_t *buf = (qcamera_hal3_pp_buffer_t *)data;
+ if (NULL != buf) {
+ if (buf->input) {
+ pme->releaseSuperBuf(buf->input);
+ free(buf->input);
+ buf->input = NULL;
+ }
+ }
}
}
@@ -818,22 +849,13 @@
{
QCamera3PostProcessor *pme = (QCamera3PostProcessor *)user_data;
if (NULL != pme) {
- qcamera_hal3_pp_data_t *pp_job = (qcamera_hal3_pp_data_t *)data;
- if (NULL != pp_job->src_frame) {
- pme->releaseSuperBuf(pp_job->src_frame);
- free(pp_job->src_frame);
- if (NULL != pp_job->src_metadata) {
- pme->m_parent->metadataBufDone(pp_job->src_metadata);
- free(pp_job->src_metadata);
- }
- pp_job->src_frame = NULL;
- pp_job->metadata = NULL;
- }
+ qcamera_hal3_pp_data_t *pp_data = (qcamera_hal3_pp_data_t *)data;
- if (NULL != pp_job->fwk_src_frame) {
- free(pp_job->fwk_src_frame);
- pp_job->fwk_src_frame = NULL;
- }
+ if (pp_data && pp_data->src_frame)
+ pme->releaseSuperBuf(pp_data->src_frame);
+
+ pme->releasePPJobData(pp_data);
+
}
}
@@ -943,6 +965,46 @@
}
/*===========================================================================
+ * FUNCTION : releasePPJobData
+ *
+ * DESCRIPTION: function to release internal resources in p pjob struct
+ *
+ * PARAMETERS :
+ * @job : ptr to pp job struct
+ *
+ * RETURN : None
+ *
+ * NOTE : Original source metadata buffer needs to be released and
+ * queued back to kernel for future use. src_frame, src_metadata,
+ * and fwk_src_frame structures need to be freed.
+ *==========================================================================*/
+void QCamera3PostProcessor::releasePPJobData(qcamera_hal3_pp_data_t *pp_job)
+{
+ ATRACE_CALL();
+ CDBG("%s: E", __func__);
+ if (NULL != pp_job) {
+ if (NULL != pp_job->src_frame) {
+ free(pp_job->src_frame);
+ if (NULL != pp_job->src_metadata) {
+ m_parent->metadataBufDone(pp_job->src_metadata);
+ free(pp_job->src_metadata);
+ }
+ pp_job->src_frame = NULL;
+ pp_job->metadata = NULL;
+ }
+
+ if (NULL != pp_job->fwk_src_frame) {
+ free(pp_job->fwk_src_frame);
+ pp_job->fwk_src_frame = NULL;
+ }
+ }
+
+ /* Additional trigger to process any pending jobs in the input queue */
+ m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_DO_NEXT_JOB, FALSE, FALSE);
+ CDBG("%s: X", __func__);
+}
+
+/*===========================================================================
* FUNCTION : getColorfmtFromImgFmt
*
* DESCRIPTION: function to return jpeg color format based on its image format
@@ -1278,7 +1340,7 @@
return BAD_VALUE;
}
- QCamera3Memory *memObj = (QCamera3Memory *)main_frame->mem_info;
+ QCamera3StreamMem *memObj = (QCamera3StreamMem *)main_frame->mem_info;
if (NULL == memObj) {
ALOGE("%s : Memeory Obj of main frame is NULL", __func__);
return NO_MEMORY;
@@ -1539,7 +1601,6 @@
pme->m_inputJpegQ.init();
pme->m_inputPPQ.init();
pme->m_inputFWKPPQ.init();
- pme->m_inputRawQ.init();
pme->m_inputMetaQ.init();
break;
@@ -1580,9 +1641,6 @@
// flush framework input Postproc Queue
pme->m_inputFWKPPQ.flush();
- // flush input raw Queue
- pme->m_inputRawQ.flush();
-
pme->m_inputMetaQ.flush();
// signal cmd is completed
@@ -1598,7 +1656,7 @@
if (is_active == TRUE) {
// check if there is any ongoing jpeg jobs
if (pme->m_ongoingJpegQ.isEmpty()) {
- CDBG("%s: ongoing jpeg queue is empty so doing the jpeg job", __func__);
+ CDBG("%s: ongoing jpeg queue is empty so doing the jpeg job", __func__);
// no ongoing jpeg job, we are fine to send jpeg encoding job
qcamera_hal3_jpeg_data_t *jpeg_job =
(qcamera_hal3_jpeg_data_t *)pme->m_inputJpegQ.dequeue();
@@ -1671,8 +1729,8 @@
CDBG_HIGH("%s: dequeuing pp frame", __func__);
pthread_mutex_lock(&pme->mReprocJobLock);
if(!pme->m_inputPPQ.isEmpty() && !pme->m_inputMetaQ.isEmpty()) {
- mm_camera_super_buf_t *pp_frame =
- (mm_camera_super_buf_t *)pme->m_inputPPQ.dequeue();
+ qcamera_hal3_pp_buffer_t *pp_buffer =
+ (qcamera_hal3_pp_buffer_t *)pme->m_inputPPQ.dequeue();
meta_buffer =
(mm_camera_super_buf_t *)pme->m_inputMetaQ.dequeue();
jpeg_settings_t *jpeg_settings =
@@ -1690,21 +1748,22 @@
ret = -1;
} else {
memset(pp_job, 0, sizeof(qcamera_hal3_pp_data_t));
- pp_job->src_frame = pp_frame;
+ pp_job->src_frame = pp_buffer->input;
pp_job->src_metadata = meta_buffer;
if (meta_buffer->bufs[0] != NULL) {
pp_job->metadata = (metadata_buffer_t *)
meta_buffer->bufs[0]->buffer;
}
pp_job->jpeg_settings = jpeg_settings;
- pme->m_ongoingPPQ.enqueue((void *)pp_job);
if (pme->m_pReprocChannel != NULL) {
mm_camera_buf_def_t *meta_buffer_arg = NULL;
meta_buffer_arg = meta_buffer->bufs[0];
qcamera_fwk_input_pp_data_t fwk_frame;
memset(&fwk_frame, 0, sizeof(qcamera_fwk_input_pp_data_t));
+ fwk_frame.frameNumber = pp_buffer->frameNumber;
+ pme->m_ongoingPPQ.enqueue((void *)pp_job);
ret = pme->m_pReprocChannel->extractFrameCropAndRotation(
- pp_frame, meta_buffer_arg,
+ pp_buffer, meta_buffer_arg,
pp_job->jpeg_settings,
fwk_frame);
if (NO_ERROR == ret) {
@@ -1717,9 +1776,9 @@
}
}
} else {
- CDBG_HIGH("%s: No reprocess. Calling processPPData directly",
+ ALOGE("%s: No reprocess. Calling processPPData directly",
__func__);
- ret = pme->processPPData(pp_frame);
+ ret = pme->processPPData(pp_buffer->input);
}
}
@@ -1729,9 +1788,12 @@
free(pp_job);
}
// free frame
- if (pp_frame != NULL) {
- pme->releaseSuperBuf(pp_frame);
- free(pp_frame);
+ if (pp_buffer != NULL) {
+ if (pp_buffer->input) {
+ pme->releaseSuperBuf(pp_buffer->input);
+ free(pp_buffer->input);
+ }
+ free(pp_buffer);
}
//free metadata
if (NULL != meta_buffer) {
@@ -1749,16 +1811,16 @@
if (NULL != jpeg_job) {
free(jpeg_job);
}
- mm_camera_super_buf_t *super_buf;
- super_buf = (mm_camera_super_buf_t *)pme->m_inputRawQ.dequeue();
- if (NULL != super_buf) {
- pme->releaseSuperBuf(super_buf);
- free(super_buf);
- }
- super_buf = (mm_camera_super_buf_t *)pme->m_inputPPQ.dequeue();
- if (NULL != super_buf) {
- pme->releaseSuperBuf(super_buf);
- free(super_buf);
+
+ qcamera_hal3_pp_buffer_t* pp_buf =
+ (qcamera_hal3_pp_buffer_t *)pme->m_inputPPQ.dequeue();
+ if (NULL != pp_buf) {
+ if (pp_buf->input) {
+ pme->releaseSuperBuf(pp_buf->input);
+ free(pp_buf->input);
+ pp_buf->input = NULL;
+ }
+ free(pp_buf);
}
mm_camera_super_buf_t *metadata = (mm_camera_super_buf_t *)pme->m_inputMetaQ.dequeue();
if (metadata != NULL) {
diff --git a/QCamera2/HAL3/QCamera3PostProc.h b/QCamera2/HAL3/QCamera3PostProc.h
index 16ba598..1737bb4 100644
--- a/QCamera2/HAL3/QCamera3PostProc.h
+++ b/QCamera2/HAL3/QCamera3PostProc.h
@@ -49,6 +49,7 @@
class QCamera3ReprocessChannel;
class QCamera3Stream;
class QCamera3Memory;
+class QCamera3StreamMem;
typedef struct {
camera3_stream_buffer_t src_frame;// source frame
@@ -81,6 +82,12 @@
mm_camera_super_buf_t *src_metadata;
} qcamera_hal3_pp_data_t;
+typedef struct {
+ mm_camera_super_buf_t *input;
+ buffer_handle_t *output;
+ uint32_t frameNumber;
+} qcamera_hal3_pp_buffer_t;
+
#define MAX_HAL3_EXIF_TABLE_ENTRIES 22
class QCamera3Exif
{
@@ -106,7 +113,7 @@
QCamera3PostProcessor(QCamera3ProcessingChannel *ch_ctrl);
virtual ~QCamera3PostProcessor();
- int32_t init(QCamera3Memory *mMemory,
+ int32_t init(QCamera3StreamMem *mMemory,
uint32_t postprocess_mask);
int32_t initJpeg(jpeg_encode_callback_t jpeg_cb,
cam_dimension_t *m_max_pic_dim,
@@ -115,13 +122,16 @@
int32_t start(const reprocess_config_t &config);
int32_t stop();
int32_t processData(qcamera_fwk_input_pp_data_t *frame);
- int32_t processData(mm_camera_super_buf_t *frame);
- int32_t processRawData(mm_camera_super_buf_t *frame);
+ int32_t processData(mm_camera_super_buf_t *input,
+ buffer_handle_t *output, uint32_t frameNumber);
+ int32_t processData(mm_camera_super_buf_t *input);
int32_t processPPData(mm_camera_super_buf_t *frame);
int32_t processPPMetadata(mm_camera_super_buf_t *reproc_meta);
int32_t processJpegSettingData(jpeg_settings_t *jpeg_settings);
+ qcamera_hal3_pp_data_t *dequeuePPJob(uint32_t frameNumber);
qcamera_hal3_jpeg_data_t *findJpegJobByJobId(uint32_t jobId);
void releaseJpegJobData(qcamera_hal3_jpeg_data_t *job);
+ void releasePPJobData(qcamera_hal3_pp_data_t *job);
int32_t releaseOfflineBuffers();
private:
@@ -161,7 +171,7 @@
uint32_t mPostProcMask;
uint32_t m_bThumbnailNeeded;
- QCamera3Memory *mOutputMem;
+ QCamera3StreamMem *mOutputMem;
QCamera3ReprocessChannel * m_pReprocChannel;
QCameraQueue m_inputPPQ; // input queue for postproc
diff --git a/QCamera2/HAL3/QCamera3Stream.cpp b/QCamera2/HAL3/QCamera3Stream.cpp
index 3f005e0..7e7902c 100644
--- a/QCamera2/HAL3/QCamera3Stream.cpp
+++ b/QCamera2/HAL3/QCamera3Stream.cpp
@@ -745,22 +745,28 @@
return NO_MEMORY;
}
- uint32_t registeredBuffers = mStreamBufs->getCnt();
- for (uint32_t i = 0; i < registeredBuffers; i++) {
- ssize_t bufSize = mStreamBufs->getSize(i);
- if (BAD_INDEX != bufSize) {
- rc = ops_tbl->map_ops(i, -1, mStreamBufs->getFd(i),
- (size_t)bufSize, CAM_MAPPING_BUF_TYPE_STREAM_BUF, ops_tbl->userdata);
- if (rc < 0) {
- ALOGE("%s: map_stream_buf failed: %d", __func__, rc);
- for (uint32_t j = 0; j < i; j++) {
- ops_tbl->unmap_ops(j, -1, CAM_MAPPING_BUF_TYPE_STREAM_BUF, ops_tbl->userdata);
+ for (uint32_t i = 0; i < mNumBufs; i++) {
+ if (mStreamBufs->valid(i)) {
+ ssize_t bufSize = mStreamBufs->getSize(i);
+ if (BAD_INDEX != bufSize) {
+ rc = ops_tbl->map_ops(i, -1, mStreamBufs->getFd(i),
+ (size_t)bufSize, CAM_MAPPING_BUF_TYPE_STREAM_BUF,
+ ops_tbl->userdata);
+ if (rc < 0) {
+ ALOGE("%s: map_stream_buf failed: %d", __func__, rc);
+ for (uint32_t j = 0; j < i; j++) {
+ if (mStreamBufs->valid(j)) {
+ ops_tbl->unmap_ops(j, -1,
+ CAM_MAPPING_BUF_TYPE_STREAM_BUF,
+ ops_tbl->userdata);
+ }
+ }
+ return INVALID_OPERATION;
}
+ } else {
+ ALOGE("Failed to retrieve buffer size (bad index)");
return INVALID_OPERATION;
}
- } else {
- ALOGE("Failed to retrieve buffer size (bad index)");
- return INVALID_OPERATION;
}
}
@@ -768,8 +774,11 @@
regFlags = (uint8_t *)malloc(sizeof(uint8_t) * mNumBufs);
if (!regFlags) {
ALOGE("%s: Out of memory", __func__);
- for (uint32_t i = 0; i < registeredBuffers; i++) {
- ops_tbl->unmap_ops(i, -1, CAM_MAPPING_BUF_TYPE_STREAM_BUF, ops_tbl->userdata);
+ for (uint32_t i = 0; i < mNumBufs; i++) {
+ if (mStreamBufs->valid(i)) {
+ ops_tbl->unmap_ops(i, -1, CAM_MAPPING_BUF_TYPE_STREAM_BUF,
+ ops_tbl->userdata);
+ }
}
return NO_MEMORY;
}
@@ -778,23 +787,31 @@
mBufDefs = (mm_camera_buf_def_t *)malloc(mNumBufs * sizeof(mm_camera_buf_def_t));
if (mBufDefs == NULL) {
ALOGE("%s: Failed to allocate mm_camera_buf_def_t %d", __func__, rc);
- for (uint32_t i = 0; i < registeredBuffers; i++) {
- ops_tbl->unmap_ops(i, -1, CAM_MAPPING_BUF_TYPE_STREAM_BUF, ops_tbl->userdata);
+ for (uint32_t i = 0; i < mNumBufs; i++) {
+ if (mStreamBufs->valid(i)) {
+ ops_tbl->unmap_ops(i, -1, CAM_MAPPING_BUF_TYPE_STREAM_BUF,
+ ops_tbl->userdata);
+ }
}
free(regFlags);
regFlags = NULL;
return INVALID_OPERATION;
}
memset(mBufDefs, 0, mNumBufs * sizeof(mm_camera_buf_def_t));
- for (uint32_t i = 0; i < registeredBuffers; i++) {
- mStreamBufs->getBufDef(mFrameLenOffset, mBufDefs[i], i);
+ for (uint32_t i = 0; i < mNumBufs; i++) {
+ if (mStreamBufs->valid(i)) {
+ mStreamBufs->getBufDef(mFrameLenOffset, mBufDefs[i], i);
+ }
}
rc = mStreamBufs->getRegFlags(regFlags);
if (rc < 0) {
ALOGE("%s: getRegFlags failed %d", __func__, rc);
- for (uint32_t i = 0; i < registeredBuffers; i++) {
- ops_tbl->unmap_ops(i, -1, CAM_MAPPING_BUF_TYPE_STREAM_BUF, ops_tbl->userdata);
+ for (uint32_t i = 0; i < mNumBufs; i++) {
+ if (mStreamBufs->valid(i)) {
+ ops_tbl->unmap_ops(i, -1, CAM_MAPPING_BUF_TYPE_STREAM_BUF,
+ ops_tbl->userdata);
+ }
}
free(mBufDefs);
mBufDefs = NULL;
@@ -827,7 +844,7 @@
Mutex::Autolock lock(mLock);
for (uint32_t i = 0; i < mNumBufs; i++) {
- if (NULL != mBufDefs[i].mem_info) {
+ if (mStreamBufs->valid(i) && NULL != mBufDefs[i].mem_info) {
rc = ops_tbl->unmap_ops(i, -1, CAM_MAPPING_BUF_TYPE_STREAM_BUF, ops_tbl->userdata);
if (rc < 0) {
ALOGE("%s: un-map stream buf failed: %d", __func__, rc);
diff --git a/QCamera2/HAL3/QCamera3Stream.h b/QCamera2/HAL3/QCamera3Stream.h
index 4ba4567..b3abbed 100644
--- a/QCamera2/HAL3/QCamera3Stream.h
+++ b/QCamera2/HAL3/QCamera3Stream.h
@@ -34,6 +34,7 @@
#include "utils/Mutex.h"
#include "QCameraCmdThread.h"
#include "QCamera3Mem.h"
+#include "QCamera3StreamMem.h"
extern "C" {
#include <mm_camera_interface.h>
@@ -82,7 +83,7 @@
int32_t getFrameOffset(cam_frame_len_offset_t &offset);
int32_t getFrameDimension(cam_dimension_t &dim);
int32_t getFormat(cam_format_t &fmt);
- QCamera3Memory *getStreamBufs() {return mStreamBufs;};
+ QCamera3StreamMem *getStreamBufs() {return mStreamBufs;};
uint32_t getMyServerID();
int32_t mapBuf(uint8_t buf_type, uint32_t buf_idx,
@@ -108,7 +109,7 @@
QCameraCmdThread mProcTh; // thread for dataCB
QCamera3HeapMemory *mStreamInfoBuf;
- QCamera3Memory *mStreamBufs;
+ QCamera3StreamMem *mStreamBufs;
mm_camera_buf_def_t *mBufDefs;
cam_frame_len_offset_t mFrameLenOffset;
cam_padding_info_t mPaddingInfo;
diff --git a/QCamera2/HAL3/QCamera3StreamMem.cpp b/QCamera2/HAL3/QCamera3StreamMem.cpp
new file mode 100644
index 0000000..24329e1
--- /dev/null
+++ b/QCamera2/HAL3/QCamera3StreamMem.cpp
@@ -0,0 +1,478 @@
+/* Copyright (c) 2012-2015, The Linux Foundataion. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#define LOG_TAG "QCamera3StreamMem"
+
+#include <string.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+#include <utils/Log.h>
+#include <utils/Errors.h>
+#include <gralloc_priv.h>
+#include <qdMetaData.h>
+#include "QCamera3Mem.h"
+#include "QCamera3HWI.h"
+
+extern "C" {
+#include <mm_camera_interface.h>
+}
+
+using namespace android;
+
+namespace qcamera {
+
+/*===========================================================================
+ * FUNCTION : QCamera3StreamMem
+ *
+ * DESCRIPTION: default constructor of QCamera3StreamMem
+ *
+ * PARAMETERS : none
+ *
+ * RETURN : None
+ *==========================================================================*/
+QCamera3StreamMem::QCamera3StreamMem(uint32_t maxHeapBuffer) :
+ mHeapMem(maxHeapBuffer),
+ mGrallocMem(maxHeapBuffer),
+ mMaxHeapBuffers(maxHeapBuffer)
+{
+}
+
+/*===========================================================================
+ * FUNCTION : QCamera3StreamMem
+ *
+ * DESCRIPTION: destructor of QCamera3StreamMem
+ *
+ * PARAMETERS : none
+ *
+ * RETURN : None
+ *==========================================================================*/
+QCamera3StreamMem::~QCamera3StreamMem()
+{
+ clear();
+}
+
+/*===========================================================================
+ * FUNCTION : getCnt
+ *
+ * DESCRIPTION: query number of buffers allocated/registered
+ *
+ * PARAMETERS : none
+ *
+ * RETURN : number of buffers allocated
+ *==========================================================================*/
+uint32_t QCamera3StreamMem::getCnt()
+{
+ Mutex::Autolock lock(mLock);
+
+ return (mHeapMem.getCnt() + mGrallocMem.getCnt());
+}
+
+/*===========================================================================
+ * FUNCTION : getRegFlags
+ *
+ * DESCRIPTION: query initial reg flags
+ *
+ * PARAMETERS :
+ * @regFlags: initial reg flags of the allocated/registered buffers
+ *
+ * RETURN : int32_t type of status
+ * NO_ERROR -- success
+ * none-zero failure code
+ *==========================================================================*/
+int QCamera3StreamMem::getRegFlags(uint8_t * regFlags)
+{
+ // Assume that all buffers allocated can be queued.
+ mHeapMem.getRegFlags(regFlags);
+ return NO_ERROR;
+}
+
+/*===========================================================================
+ * FUNCTION : getFd
+ *
+ * DESCRIPTION: return file descriptor of the indexed buffer
+ *
+ * PARAMETERS :
+ * @index : index of the buffer
+ *
+ * RETURN : file descriptor
+ *==========================================================================*/
+int QCamera3StreamMem::getFd(uint32_t index)
+{
+ Mutex::Autolock lock(mLock);
+
+ if (index < mMaxHeapBuffers)
+ return mHeapMem.getFd(index);
+ else
+ return mGrallocMem.getFd(index);
+}
+
+/*===========================================================================
+ * FUNCTION : getSize
+ *
+ * DESCRIPTION: return buffer size of the indexed buffer
+ *
+ * PARAMETERS :
+ * @index : index of the buffer
+ *
+ * RETURN : buffer size
+ *==========================================================================*/
+ssize_t QCamera3StreamMem::getSize(uint32_t index)
+{
+ Mutex::Autolock lock(mLock);
+
+ if (index < mMaxHeapBuffers)
+ return mHeapMem.getSize(index);
+ else
+ return mGrallocMem.getSize(index);
+}
+
+/*===========================================================================
+ * FUNCTION : invalidateCache
+ *
+ * DESCRIPTION: invalidate 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::invalidateCache(uint32_t index)
+{
+ Mutex::Autolock lock(mLock);
+
+ if (index < mMaxHeapBuffers)
+ return mHeapMem.invalidateCache(index);
+ else
+ return mGrallocMem.invalidateCache(index);
+}
+
+/*===========================================================================
+ * FUNCTION : cleanInvalidateCache
+ *
+ * DESCRIPTION: clean and invalidate 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::cleanInvalidateCache(uint32_t index)
+{
+ Mutex::Autolock lock(mLock);
+
+ if (index < mMaxHeapBuffers)
+ return mHeapMem.cleanInvalidateCache(index);
+ else
+ return mGrallocMem.cleanInvalidateCache(index);
+}
+
+/*===========================================================================
+ * FUNCTION : getBufDef
+ *
+ * DESCRIPTION: query detailed buffer information
+ *
+ * PARAMETERS :
+ * @offset : [input] frame buffer offset
+ * @bufDef : [output] reference to struct to store buffer definition
+ * @index : [input] index of the buffer
+ *
+ * RETURN : int32_t type of status
+ * NO_ERROR -- success
+ * none-zero failure code
+ *==========================================================================*/
+int32_t QCamera3StreamMem::getBufDef(const cam_frame_len_offset_t &offset,
+ mm_camera_buf_def_t &bufDef, uint32_t index)
+{
+ int32_t ret = NO_ERROR;
+
+ if (index < mMaxHeapBuffers)
+ ret = mHeapMem.getBufDef(offset, bufDef, index);
+ else
+ ret = mGrallocMem.getBufDef(offset, bufDef, index);
+
+ bufDef.mem_info = (void *)this;
+
+ return ret;
+}
+
+/*===========================================================================
+ * FUNCTION : getPtr
+ *
+ * DESCRIPTION: return virtual address of the indexed buffer
+ *
+ * PARAMETERS :
+ * @index : index of the buffer
+ *
+ * RETURN : virtual address
+ *==========================================================================*/
+void* QCamera3StreamMem::getPtr(uint32_t index)
+{
+ Mutex::Autolock lock(mLock);
+
+ if (index < mMaxHeapBuffers)
+ return mHeapMem.getPtr(index);
+ else
+ return mGrallocMem.getPtr(index);
+}
+
+/*===========================================================================
+ * FUNCTION : valid
+ *
+ * DESCRIPTION: return whether there is a valid buffer at the current index
+ *
+ * PARAMETERS :
+ * @index : index of the buffer
+ *
+ * RETURN : true if there is a buffer, false otherwise
+ *==========================================================================*/
+bool QCamera3StreamMem::valid(uint32_t index)
+{
+ Mutex::Autolock lock(mLock);
+
+ if (index < mMaxHeapBuffers)
+ return (mHeapMem.getSize(index) > 0);
+ else
+ return (mGrallocMem.getSize(index) > 0);
+}
+
+/*===========================================================================
+ * FUNCTION : registerBuffer
+ *
+ * DESCRIPTION: registers frameworks-allocated gralloc buffer_handle_t
+ *
+ * PARAMETERS :
+ * @buffers : buffer_handle_t pointer
+ * @type : cam_stream_type_t
+ *
+ * RETURN : int32_t type of status
+ * NO_ERROR -- success
+ * none-zero failure code
+ *==========================================================================*/
+int QCamera3StreamMem::registerBuffer(buffer_handle_t *buffer,
+ cam_stream_type_t type)
+{
+ Mutex::Autolock lock(mLock);
+ return mGrallocMem.registerBuffer(buffer, type);
+}
+
+
+/*===========================================================================
+ * FUNCTION : unregisterBuffer
+ *
+ * DESCRIPTION: unregister buffer
+ *
+ * PARAMETERS :
+ * @idx : unregister buffer at index 'idx'
+ *
+ * RETURN : int32_t type of status
+ * NO_ERROR -- success
+ * none-zero failure code
+ *==========================================================================*/
+int32_t QCamera3StreamMem::unregisterBuffer(size_t idx)
+{
+ Mutex::Autolock lock(mLock);
+ return mGrallocMem.unregisterBuffer(idx);
+}
+
+/*===========================================================================
+ * FUNCTION : getMatchBufIndex
+ *
+ * DESCRIPTION: query buffer index by object ptr
+ *
+ * PARAMETERS :
+ * @opaque : opaque ptr
+ *
+ * RETURN : buffer index if match found,
+ * -1 if failed
+ *==========================================================================*/
+int QCamera3StreamMem::getMatchBufIndex(void *object)
+{
+ Mutex::Autolock lock(mLock);
+ return mGrallocMem.getMatchBufIndex(object);
+}
+
+/*===========================================================================
+ * FUNCTION : getBufferHandle
+ *
+ * DESCRIPTION: return framework pointer
+ *
+ * PARAMETERS :
+ * @index : index of the buffer
+ *
+ * RETURN : buffer ptr if match found
+ NULL if failed
+ *==========================================================================*/
+void *QCamera3StreamMem::getBufferHandle(uint32_t index)
+{
+ Mutex::Autolock lock(mLock);
+ return mGrallocMem.getBufferHandle(index);
+}
+
+/*===========================================================================
+ * FUNCTION : unregisterBuffers
+ *
+ * DESCRIPTION: unregister buffers
+ *
+ * PARAMETERS : none
+ *
+ * RETURN : none
+ *==========================================================================*/
+void QCamera3StreamMem::unregisterBuffers()
+{
+ Mutex::Autolock lock(mLock);
+ mGrallocMem.unregisterBuffers();
+}
+
+
+/*===========================================================================
+ * FUNCTION : allocate
+ *
+ * DESCRIPTION: allocate requested number of buffers of certain size
+ *
+ * PARAMETERS :
+ * @count : number of buffers to be allocated
+ * @size : lenght of the buffer to be allocated
+ * @queueAll: queue all buffers in the beginning
+ *
+ * RETURN : int32_t type of status
+ * NO_ERROR -- success
+ * none-zero failure code
+ *==========================================================================*/
+int QCamera3StreamMem::allocate(uint32_t count, size_t size, bool queueAll)
+{
+ Mutex::Autolock lock(mLock);
+ return mHeapMem.allocate(count, size, queueAll);
+}
+
+/*===========================================================================
+ * FUNCTION : deallocate
+ *
+ * DESCRIPTION: deallocate heap buffers
+ *
+ * PARAMETERS : none
+ *
+ * RETURN : none
+ *==========================================================================*/
+void QCamera3StreamMem::deallocate()
+{
+ Mutex::Autolock lock(mLock);
+ mHeapMem.deallocate();
+}
+
+/*===========================================================================
+ * FUNCTION : markFrameNumber
+ *
+ * DESCRIPTION: We use this function from the request call path to mark the
+ * buffers with the frame number they are intended for this info
+ * is used later when giving out callback & it is duty of PP to
+ * ensure that data for that particular frameNumber/Request is
+ * written to this buffer.
+ * PARAMETERS :
+ * @index : index of the buffer
+ * @frame# : Frame number from the framework
+ *
+ * RETURN : int32_t type of status
+ * NO_ERROR -- success
+ * none-zero failure code
+ *==========================================================================*/
+int32_t QCamera3StreamMem::markFrameNumber(uint32_t index, uint32_t frameNumber)
+{
+ Mutex::Autolock lock(mLock);
+ if (index < mMaxHeapBuffers)
+ return mHeapMem.markFrameNumber(index, frameNumber);
+ else
+ return mGrallocMem.markFrameNumber(index, frameNumber);
+}
+
+/*===========================================================================
+ * FUNCTION : getFrameNumber
+ *
+ * DESCRIPTION: We use this to fetch the frameNumber for the request with which
+ * this buffer was given to HAL
+ *
+ *
+ * PARAMETERS :
+ * @index : index of the buffer
+ *
+ * RETURN : int32_t frameNumber
+ * positive/zero -- success
+ * negative failure
+ *==========================================================================*/
+int32_t QCamera3StreamMem::getFrameNumber(uint32_t index)
+{
+ Mutex::Autolock lock(mLock);
+ if (index < mMaxHeapBuffers)
+ return mHeapMem.getFrameNumber(index);
+ else
+ return mGrallocMem.getFrameNumber(index);
+}
+
+/*===========================================================================
+ * FUNCTION : getGrallocBufferIndex
+ *
+ * DESCRIPTION: We use this to fetch the gralloc buffer index based on frameNumber
+ *
+ * PARAMETERS :
+ * @frameNumber : frame Number
+ *
+ * RETURN : int32_t buffer index
+ * positive/zero -- success
+ * negative failure
+ *==========================================================================*/
+int32_t QCamera3StreamMem::getGrallocBufferIndex(uint32_t frameNumber)
+{
+ Mutex::Autolock lock(mLock);
+ int32_t index = mGrallocMem.getBufferIndex(frameNumber);
+ return index;
+}
+
+/*===========================================================================
+ * FUNCTION : getHeapBufferIndex
+ *
+ * DESCRIPTION: We use this to fetch the heap buffer index based on frameNumber
+ *
+ * PARAMETERS :
+ * @frameNumber : frame Number
+ *
+ * RETURN : int32_t buffer index
+ * positive/zero -- success
+ * negative failure
+ *==========================================================================*/
+int32_t QCamera3StreamMem::getHeapBufferIndex(uint32_t frameNumber)
+{
+ Mutex::Autolock lock(mLock);
+ int32_t index = mHeapMem.getBufferIndex(frameNumber);
+ return index;
+}
+
+}; //namespace qcamera
diff --git a/QCamera2/HAL3/QCamera3StreamMem.h b/QCamera2/HAL3/QCamera3StreamMem.h
new file mode 100644
index 0000000..a9569f8
--- /dev/null
+++ b/QCamera2/HAL3/QCamera3StreamMem.h
@@ -0,0 +1,96 @@
+/* Copyright (c) 2012-2015, The Linux Foundataion. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef __QCAMERA3_STREAMMEM_H__
+#define __QCAMERA3_STREAMMEM_H__
+
+#include <hardware/camera3.h>
+#include <utils/Mutex.h>
+#include "QCamera3Mem.h"
+
+extern "C" {
+#include <sys/types.h>
+#include <linux/msm_ion.h>
+#include <mm_camera_interface.h>
+}
+
+using namespace android;
+
+namespace qcamera {
+
+class QCamera3StreamMem {
+public:
+ QCamera3StreamMem(uint32_t maxHeapBuffer);
+ virtual ~QCamera3StreamMem();
+
+ uint32_t getCnt();
+ int getRegFlags(uint8_t *regFlags);
+
+ // Helper function to access individual QCamera3Buffer object
+ int getFd(uint32_t index);
+ ssize_t getSize(uint32_t index);
+ int invalidateCache(uint32_t index);
+ int cleanInvalidateCache(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);
+
+ bool valid(uint32_t index);
+
+ // Gralloc buffer related functions
+ int registerBuffer(buffer_handle_t *buffer, cam_stream_type_t type);
+ int unregisterBuffer(uint32_t index);
+ int getMatchBufIndex(void *object);
+ void *getBufferHandle(uint32_t index);
+ void unregisterBuffers(); //TODO: relace with unififed clear() function?
+
+ // Heap buffer related functions
+ //TODO: Support returning buffer indices to the caller.
+ int allocate(uint32_t count, size_t size, bool queueAll);
+ void deallocate(); //TODO: replace with unified clear() function?
+
+ // Clear function: unregister for gralloc buffer, and deallocate for heap buffer
+ void clear() {unregisterBuffers(); deallocate(); }
+
+ // Frame number getter and setter
+ int32_t markFrameNumber(uint32_t index, uint32_t frameNumber);
+ int32_t getFrameNumber(uint32_t index);
+ int32_t getGrallocBufferIndex(uint32_t frameNumber);
+ int32_t getHeapBufferIndex(uint32_t frameNumber);
+
+private:
+ //variables
+ QCamera3HeapMemory mHeapMem;
+ QCamera3GrallocMemory mGrallocMem;
+ uint32_t mMaxHeapBuffers;
+ Mutex mLock;
+};
+
+};
+#endif // __QCAMERA3_STREAMMEM_H__
diff --git a/QCamera2/stack/common/cam_types.h b/QCamera2/stack/common/cam_types.h
index e9ffd3c..f2c469d 100644
--- a/QCamera2/stack/common/cam_types.h
+++ b/QCamera2/stack/common/cam_types.h
@@ -705,13 +705,15 @@
CAM_NOISE_REDUCTION_MODE_OFF,
CAM_NOISE_REDUCTION_MODE_FAST,
CAM_NOISE_REDUCTION_MODE_HIGH_QUALITY,
- CAM_NOISE_REDUCTION_MODE_MINIMAL
+ CAM_NOISE_REDUCTION_MODE_MINIMAL,
+ CAM_NOISE_REDUCTION_MODE_ZERO_SHUTTER_LAG
} cam_noise_reduction_mode_t;
typedef enum {
CAM_EDGE_MODE_OFF,
CAM_EDGE_MODE_FAST,
CAM_EDGE_MODE_HIGH_QUALITY,
+ CAM_EDGE_MODE_ZERO_SHUTTER_LAG,
} cam_edge_mode_t;
typedef struct {
diff --git a/QCamera2/stack/mm-camera-interface/src/mm_camera_stream.c b/QCamera2/stack/mm-camera-interface/src/mm_camera_stream.c
index 756413c..2eb27bc 100755
--- a/QCamera2/stack/mm-camera-interface/src/mm_camera_stream.c
+++ b/QCamera2/stack/mm-camera-interface/src/mm_camera_stream.c
@@ -1267,7 +1267,7 @@
buf_info->buf->ts.tv_sec = vb.timestamp.tv_sec;
buf_info->buf->ts.tv_nsec = vb.timestamp.tv_usec * 1000;
- CDBG("%s: VIDIOC_DQBUF buf_index %d, frame_idx %d, stream type %d, rc %d,"
+ CDBG_HIGH("%s: VIDIOC_DQBUF buf_index %d, frame_idx %d, stream type %d, rc %d,"
"queued: %d, buf_type = %d",
__func__, vb.index, buf_info->buf->frame_idx,
my_obj->stream_info->stream_type, rc,
@@ -1512,7 +1512,7 @@
my_obj, my_obj->stream_info->stream_type);
}
} else {
- CDBG("%s: VIDIOC_QBUF buf_index %d, stream type %d, rc %d, queued: %d", __func__,
+ CDBG_HIGH("%s: VIDIOC_QBUF buf_index %d, stream type %d, rc %d, queued: %d", __func__,
buffer.index, my_obj->stream_info->stream_type, rc, my_obj->queued_buffer_count);
}
@@ -1607,6 +1607,9 @@
packet.payload.buf_map.stream_id = my_obj->server_stream_id;
packet.payload.buf_map.frame_idx = frame_idx;
packet.payload.buf_map.plane_idx = plane_idx;
+
+ CDBG("%s: mapping buf_type %d, stream_id %d, frame_idx %d, fd %d, size %d",
+ __func__, buf_type, my_obj->server_stream_id, frame_idx, fd, size);
return mm_camera_util_sendmsg(my_obj->ch_obj->cam_obj,
&packet,
sizeof(cam_sock_packet_t),