aboutsummaryrefslogtreecommitdiff
path: root/camera/QCamera2/HAL/QCameraChannel.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--camera/QCamera2/HAL/QCameraChannel.cpp1601
1 files changed, 1601 insertions, 0 deletions
diff --git a/camera/QCamera2/HAL/QCameraChannel.cpp b/camera/QCamera2/HAL/QCameraChannel.cpp
new file mode 100644
index 0000000..73378d0
--- /dev/null
+++ b/camera/QCamera2/HAL/QCameraChannel.cpp
@@ -0,0 +1,1601 @@
+/* Copyright (c) 2012-2016, The Linux Foundation. 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 "QCameraChannel"
+
+// System dependencies
+#include <utils/Errors.h>
+
+// Camera dependencies
+#include "QCamera2HWI.h"
+
+extern "C" {
+#include "mm_camera_dbg.h"
+}
+
+using namespace android;
+
+namespace qcamera {
+
+/*===========================================================================
+ * FUNCTION : QCameraChannel
+ *
+ * DESCRIPTION: constrcutor of QCameraChannel
+ *
+ * PARAMETERS :
+ * @cam_handle : camera handle
+ * @cam_ops : ptr to camera ops table
+ *
+ * RETURN : none
+ *==========================================================================*/
+QCameraChannel::QCameraChannel(uint32_t cam_handle,
+ mm_camera_ops_t *cam_ops)
+{
+ m_camHandle = cam_handle;
+ m_camOps = cam_ops;
+ m_bIsActive = false;
+ m_bAllowDynBufAlloc = false;
+
+ m_handle = 0;
+}
+
+/*===========================================================================
+ * FUNCTION : QCameraChannel
+ *
+ * DESCRIPTION: default constrcutor of QCameraChannel
+ *
+ * PARAMETERS : none
+ *
+ * RETURN : none
+ *==========================================================================*/
+QCameraChannel::QCameraChannel()
+{
+ m_camHandle = 0;
+ m_camOps = NULL;
+ m_bIsActive = false;
+
+ m_handle = 0;
+}
+
+/*===========================================================================
+ * FUNCTION : ~QCameraChannel
+ *
+ * DESCRIPTION: destructor of QCameraChannel
+ *
+ * PARAMETERS : none
+ *
+ * RETURN : none
+ *==========================================================================*/
+QCameraChannel::~QCameraChannel()
+{
+ if (m_bIsActive) {
+ stop();
+ }
+ for (size_t i = 0; i < mStreams.size(); i++) {
+ if (mStreams[i] != NULL) {
+ if (m_handle == mStreams[i]->getChannelHandle()) {
+ delete mStreams[i];
+ }
+ }
+ }
+ mStreams.clear();
+ m_camOps->delete_channel(m_camHandle, m_handle);
+ m_handle = 0;
+}
+
+/*===========================================================================
+ * FUNCTION : deleteChannel
+ *
+ * DESCRIPTION: deletes a camera channel
+ *
+ * PARAMETERS : none
+ *
+ * RETURN : none
+ *==========================================================================*/
+void QCameraChannel::deleteChannel()
+{
+ if (m_bIsActive) {
+ stop();
+ }
+ for (size_t i = 0; i < mStreams.size(); i++) {
+ if ((mStreams[i] != NULL) && (m_handle == mStreams[i]->getChannelHandle())) {
+ mStreams[i]->deleteStream();
+ }
+ }
+ m_camOps->delete_channel(m_camHandle, m_handle);
+}
+
+/*===========================================================================
+ * FUNCTION : setStreamSyncCB
+ *
+ * DESCRIPTION: reg callback function to stream of stream type
+ *
+ * PARAMETERS :
+ * @stream_type : Stream type for which callback needs to be registered.
+ * @stream_cb : Callback function
+
+ * RETURN : int32_t type of status
+ * NO_ERROR -- success
+ * non-zero failure code
+ *==========================================================================*/
+int32_t QCameraChannel::setStreamSyncCB (cam_stream_type_t stream_type,
+ stream_cb_routine stream_cb)
+{
+ int32_t rc = UNKNOWN_ERROR;
+ for (size_t i = 0; i < mStreams.size(); i++) {
+ if ((mStreams[i] != NULL) && (stream_type == mStreams[i]->getMyType())) {
+ rc = mStreams[i]->setSyncDataCB(stream_cb);
+ break;
+ }
+ }
+ return rc;
+}
+
+/*===========================================================================
+ * FUNCTION : init
+ *
+ * DESCRIPTION: initialization of channel
+ *
+ * PARAMETERS :
+ * @attr : channel bundle attribute setting
+ * @dataCB : data notify callback
+ * @userData: user data ptr
+ *
+ * RETURN : int32_t type of status
+ * NO_ERROR -- success
+ * none-zero failure code
+ *==========================================================================*/
+int32_t QCameraChannel::init(mm_camera_channel_attr_t *attr,
+ mm_camera_buf_notify_t dataCB,
+ void *userData)
+{
+ m_handle = m_camOps->add_channel(m_camHandle,
+ attr,
+ dataCB,
+ userData);
+ if (m_handle == 0) {
+ LOGE("Add channel failed");
+ return UNKNOWN_ERROR;
+ }
+ return NO_ERROR;
+}
+
+/*===========================================================================
+ * FUNCTION : addStream
+ *
+ * DESCRIPTION: add a stream into channel
+ *
+ * PARAMETERS :
+ * @allocator : stream related buffer allocator
+ * @streamInfoBuf : ptr to buf that contains stream info
+ * @miscBuf : ptr to buf that contains misc buffers
+ * @minStreamBufNum: number of stream buffers needed
+ * @paddingInfo : padding information
+ * @stream_cb : stream data notify callback
+ * @userdata : user data ptr
+ * @bDynAllocBuf : flag indicating if allow allocate buffers in 2 steps
+ * @online_rotation: rotation applied online
+ *
+ * RETURN : int32_t type of status
+ * NO_ERROR -- success
+ * none-zero failure code
+ *==========================================================================*/
+int32_t QCameraChannel::addStream(QCameraAllocator &allocator,
+ QCameraHeapMemory *streamInfoBuf, QCameraHeapMemory *miscBuf,
+ uint8_t minStreamBufNum, cam_padding_info_t *paddingInfo,
+ stream_cb_routine stream_cb, void *userdata, bool bDynAllocBuf,
+ bool bDeffAlloc, cam_rotation_t online_rotation)
+{
+ int32_t rc = NO_ERROR;
+ if (mStreams.size() >= MAX_STREAM_NUM_IN_BUNDLE) {
+ LOGE("stream number (%zu) exceeds max limit (%d)",
+ mStreams.size(), MAX_STREAM_NUM_IN_BUNDLE);
+ if (streamInfoBuf != NULL) {
+ streamInfoBuf->deallocate();
+ delete streamInfoBuf;
+ streamInfoBuf = NULL;
+ }
+ return BAD_VALUE;
+ }
+ QCameraStream *pStream = new QCameraStream(allocator,
+ m_camHandle, m_handle, m_camOps, paddingInfo, bDeffAlloc,
+ online_rotation);
+ if (pStream == NULL) {
+ LOGE("No mem for Stream");
+ if (streamInfoBuf != NULL) {
+ streamInfoBuf->deallocate();
+ delete streamInfoBuf;
+ streamInfoBuf = NULL;
+ }
+ return NO_MEMORY;
+ }
+
+ rc = pStream->init(streamInfoBuf, miscBuf, minStreamBufNum,
+ stream_cb, userdata, bDynAllocBuf);
+ if (rc == 0) {
+ mStreams.add(pStream);
+ } else {
+ delete pStream;
+ }
+ return rc;
+}
+
+/*===========================================================================
+ * FUNCTION : linkStream
+ *
+ * DESCRIPTION: link a stream into channel
+ *
+ * PARAMETERS :
+ * @ch : Channel which the stream belongs to
+ * @stream : Stream which needs to be linked
+ *
+ * RETURN : int32_t type of status
+ * NO_ERROR -- success
+ * none-zero failure code
+ *==========================================================================*/
+int32_t QCameraChannel::linkStream(QCameraChannel *ch, QCameraStream *stream)
+{
+ int32_t rc = NO_ERROR;
+
+ if ((0 == m_handle) || (NULL == ch) || (NULL == stream)) {
+ return NO_INIT;
+ }
+
+ int32_t handle = m_camOps->link_stream(m_camHandle,
+ ch->getMyHandle(),
+ stream->getMyHandle(),
+ m_handle);
+ if (0 == handle) {
+ LOGE("Linking of stream failed");
+ rc = INVALID_OPERATION;
+ } else {
+ mStreams.add(stream);
+ }
+
+ return rc;
+}
+
+/*===========================================================================
+ * FUNCTION : start
+ *
+ * DESCRIPTION: start channel, which will start all streams belong to this channel
+ *
+ * PARAMETERS : None
+ *
+ * RETURN : int32_t type of status
+ * NO_ERROR -- success
+ * none-zero failure code
+ *==========================================================================*/
+int32_t QCameraChannel::start()
+{
+ int32_t rc = NO_ERROR;
+
+ if(m_bIsActive) {
+ LOGW("Attempt to start active channel");
+ return rc;
+ }
+ if (mStreams.size() > 1) {
+ // there is more than one stream in the channel
+ // we need to notify mctl that all streams in this channel need to be bundled
+ cam_bundle_config_t bundleInfo;
+ memset(&bundleInfo, 0, sizeof(bundleInfo));
+ rc = m_camOps->get_bundle_info(m_camHandle, m_handle, &bundleInfo);
+ if (rc != NO_ERROR) {
+ LOGE("get_bundle_info failed");
+ return rc;
+ }
+ if (bundleInfo.num_of_streams > 1) {
+ for (int i = 0; i < bundleInfo.num_of_streams; i++) {
+ QCameraStream *pStream = getStreamByServerID(bundleInfo.stream_ids[i]);
+ if (pStream != NULL) {
+ if ((pStream->isTypeOf(CAM_STREAM_TYPE_METADATA))
+ || (pStream->isTypeOf(CAM_STREAM_TYPE_OFFLINE_PROC))) {
+ // Skip metadata for reprocess now because PP module cannot handle meta data
+ // May need furthur discussion if Imaginglib need meta data
+ continue;
+ }
+
+ cam_stream_parm_buffer_t param;
+ memset(&param, 0, sizeof(cam_stream_parm_buffer_t));
+ param.type = CAM_STREAM_PARAM_TYPE_SET_BUNDLE_INFO;
+ param.bundleInfo = bundleInfo;
+ rc = pStream->setParameter(param);
+ if (rc != NO_ERROR) {
+ LOGE("stream setParameter for set bundle failed");
+ return rc;
+ }
+ }
+ }
+ }
+ }
+
+ for (size_t i = 0; i < mStreams.size(); i++) {
+ if ((mStreams[i] != NULL) &&
+ (m_handle == mStreams[i]->getChannelHandle())) {
+ mStreams[i]->start();
+ }
+ }
+ rc = m_camOps->start_channel(m_camHandle, m_handle);
+
+ if (rc != NO_ERROR) {
+ for (size_t i = 0; i < mStreams.size(); i++) {
+ if ((mStreams[i] != NULL) &&
+ (m_handle == mStreams[i]->getChannelHandle())) {
+ mStreams[i]->stop();
+ }
+ }
+ } else {
+ m_bIsActive = true;
+ for (size_t i = 0; i < mStreams.size(); i++) {
+ if (mStreams[i] != NULL) {
+ mStreams[i]->cond_signal();
+ }
+ }
+ }
+
+ return rc;
+}
+
+/*===========================================================================
+ * FUNCTION : stop
+ *
+ * DESCRIPTION: stop a channel, which will stop all streams belong to this channel
+ *
+ * PARAMETERS : none
+ *
+ * RETURN : int32_t type of status
+ * NO_ERROR -- success
+ * none-zero failure code
+ *==========================================================================*/
+int32_t QCameraChannel::stop()
+{
+ int32_t rc = NO_ERROR;
+ size_t i = 0;
+
+ if (!m_bIsActive) {
+ return NO_INIT;
+ }
+
+ while(i < mStreams.size()) {
+ if (mStreams[i] != NULL) {
+ if (m_handle == mStreams[i]->getChannelHandle()) {
+ mStreams[i]->stop();
+ i++;
+ } else {
+ // Remove linked stream from stream list
+ mStreams.removeAt(i);
+ }
+ }
+ }
+
+ rc = m_camOps->stop_channel(m_camHandle, m_handle);
+
+ m_bIsActive = false;
+ return rc;
+}
+
+/*===========================================================================
+ * FUNCTION : bufDone
+ *
+ * DESCRIPTION: return a stream buf back to kernel
+ *
+ * PARAMETERS :
+ * @recvd_frame : stream buf frame to be returned
+ *
+ * RETURN : int32_t type of status
+ * NO_ERROR -- success
+ * none-zero failure code
+ *==========================================================================*/
+int32_t QCameraChannel::bufDone(mm_camera_super_buf_t *recvd_frame)
+{
+ int32_t rc = NO_ERROR;
+ for (uint32_t i = 0; i < recvd_frame->num_bufs; i++) {
+ if (recvd_frame->bufs[i] != NULL) {
+ for (size_t j = 0; j < mStreams.size(); j++) {
+ if (mStreams[j] != NULL &&
+ mStreams[j]->getMyHandle() == recvd_frame->bufs[i]->stream_id) {
+ rc = mStreams[j]->bufDone(recvd_frame->bufs[i]->buf_idx);
+ break; // break loop j
+ }
+ }
+ }
+ }
+
+ return rc;
+}
+
+/*===========================================================================
+ * FUNCTION : bufDone
+ *
+ * DESCRIPTION: return specified buffer from super buffer to kernel
+ *
+ * PARAMETERS :
+ * @recvd_frame : stream buf frame to be returned
+ * @stream_id : stream ID of the buffer to be released
+ *
+ * RETURN : int32_t type of status
+ * NO_ERROR -- success
+ * none-zero failure code
+ *==========================================================================*/
+int32_t QCameraChannel::bufDone(mm_camera_super_buf_t *recvd_frame, uint32_t stream_id)
+{
+ int32_t rc = NO_ERROR;
+ int32_t index;
+ for (int32_t i = 0; i < (int32_t)recvd_frame->num_bufs; i++) {
+ index = -1;
+ if ((recvd_frame->bufs[i] != NULL) &&
+ (recvd_frame->bufs[i]->stream_id == stream_id)) {
+ for (size_t j = 0; j < mStreams.size(); j++) {
+ if ((mStreams[j] != NULL) &&
+ (mStreams[j]->getMyHandle() == stream_id)) {
+ rc = mStreams[j]->bufDone(recvd_frame->bufs[i]->buf_idx);
+ index = i;
+ break; // break loop j
+ }
+ }
+ if ((index >= 0) && (index < (int32_t)recvd_frame->num_bufs)) {
+ for (int32_t j = index; j < (int32_t)(recvd_frame->num_bufs - 1); j++) {
+ recvd_frame->bufs[j] = recvd_frame->bufs[j + 1];
+ }
+ recvd_frame->num_bufs--;
+ i--;
+ }
+ }
+ }
+
+ return rc;
+}
+
+/*===========================================================================
+ * FUNCTION : processZoomDone
+ *
+ * DESCRIPTION: process zoom done event
+ *
+ * PARAMETERS :
+ * @previewWindoe : ptr to preview window ops table, needed to set preview
+ * crop information
+ * @crop_info : crop info as a result of zoom operation
+ *
+ * RETURN : int32_t type of status
+ * NO_ERROR -- success
+ * none-zero failure code
+ *==========================================================================*/
+int32_t QCameraChannel::processZoomDone(preview_stream_ops_t *previewWindow,
+ cam_crop_data_t &crop_info)
+{
+ int32_t rc = NO_ERROR;
+ for (size_t i = 0; i < mStreams.size(); i++) {
+ if ((mStreams[i] != NULL) &&
+ (m_handle == mStreams[i]->getChannelHandle())) {
+ rc = mStreams[i]->processZoomDone(previewWindow, crop_info);
+ }
+ }
+ return rc;
+}
+
+/*===========================================================================
+ * FUNCTION : getStreamByHandle
+ *
+ * DESCRIPTION: return stream object by stream handle
+ *
+ * PARAMETERS :
+ * @streamHandle : stream handle
+ *
+ * RETURN : stream object. NULL if not found
+ *==========================================================================*/
+QCameraStream *QCameraChannel::getStreamByHandle(uint32_t streamHandle)
+{
+ for (size_t i = 0; i < mStreams.size(); i++) {
+ if (mStreams[i] != NULL && mStreams[i]->getMyHandle() == streamHandle) {
+ return mStreams[i];
+ }
+ }
+ return NULL;
+}
+
+/*===========================================================================
+ * FUNCTION : getStreamByServerID
+ *
+ * DESCRIPTION: return stream object by stream server ID from daemon
+ *
+ * PARAMETERS :
+ * @serverID : stream server ID
+ *
+ * RETURN : stream object. NULL if not found
+ *==========================================================================*/
+QCameraStream *QCameraChannel::getStreamByServerID(uint32_t serverID)
+{
+ for (size_t i = 0; i < mStreams.size(); i++) {
+ if (mStreams[i] != NULL && mStreams[i]->getMyServerID() == serverID) {
+ return mStreams[i];
+ }
+ }
+ return NULL;
+}
+
+/*===========================================================================
+ * FUNCTION : getStreamByIndex
+ *
+ * DESCRIPTION: return stream object by index of streams in the channel
+ *
+ * PARAMETERS :
+ * @index : index of stream in the channel
+ *
+ * RETURN : stream object. NULL if not found
+ *==========================================================================*/
+QCameraStream *QCameraChannel::getStreamByIndex(uint32_t index)
+{
+ if (index >= MAX_STREAM_NUM_IN_BUNDLE) {
+ return NULL;
+ }
+
+ if (index < mStreams.size()) {
+ return mStreams[index];
+ }
+ return NULL;
+}
+
+/*===========================================================================
+ * FUNCTION : UpdateStreamBasedParameters
+ *
+ * DESCRIPTION: update any stream based settings from parameters
+ *
+ * PARAMETERS :
+ * @param : reference to parameters object
+ *
+ * RETURN : int32_t type of status
+ * NO_ERROR -- success
+ * none-zero failure code
+ *==========================================================================*/
+int32_t QCameraChannel::UpdateStreamBasedParameters(QCameraParametersIntf &param)
+{
+ int32_t rc = NO_ERROR;
+ if (param.isPreviewFlipChanged()) {
+ // try to find preview stream
+ for (size_t i = 0; i < mStreams.size(); i++) {
+ if ((mStreams[i] != NULL) &&
+ (m_handle == mStreams[i]->getChannelHandle()) &&
+ (mStreams[i]->isTypeOf(CAM_STREAM_TYPE_PREVIEW) ||
+ (mStreams[i]->isOrignalTypeOf(CAM_STREAM_TYPE_PREVIEW))) ) {
+ cam_stream_parm_buffer_t param_buf;
+ memset(&param_buf, 0, sizeof(cam_stream_parm_buffer_t));
+ param_buf.type = CAM_STREAM_PARAM_TYPE_SET_FLIP;
+ param_buf.flipInfo.flip_mask =
+ (uint32_t)param.getFlipMode(CAM_STREAM_TYPE_PREVIEW);
+ rc = mStreams[i]->setParameter(param_buf);
+ if (rc != NO_ERROR) {
+ LOGW("set preview stream flip failed");
+ }
+ }
+ }
+ }
+ if (param.isVideoFlipChanged()) {
+ // try to find video stream
+ for (size_t i = 0; i < mStreams.size(); i++) {
+ if ((mStreams[i] != NULL) &&
+ (m_handle == mStreams[i]->getChannelHandle()) &&
+ (mStreams[i]->isTypeOf(CAM_STREAM_TYPE_VIDEO) ||
+ (mStreams[i]->isOrignalTypeOf(CAM_STREAM_TYPE_VIDEO))) ) {
+ cam_stream_parm_buffer_t param_buf;
+ memset(&param_buf, 0, sizeof(cam_stream_parm_buffer_t));
+ param_buf.type = CAM_STREAM_PARAM_TYPE_SET_FLIP;
+ param_buf.flipInfo.flip_mask =
+ (uint32_t)param.getFlipMode(CAM_STREAM_TYPE_VIDEO);
+ rc = mStreams[i]->setParameter(param_buf);
+ if (rc != NO_ERROR) {
+ LOGW("set video stream flip failed");
+ }
+ }
+ }
+ }
+ if (param.isSnapshotFlipChanged()) {
+ // try to find snapshot/postview stream
+ for (size_t i = 0; i < mStreams.size(); i++) {
+ if (mStreams[i] != NULL &&
+ (m_handle == mStreams[i]->getChannelHandle()) &&
+ (mStreams[i]->isTypeOf(CAM_STREAM_TYPE_SNAPSHOT) ||
+ mStreams[i]->isOrignalTypeOf(CAM_STREAM_TYPE_SNAPSHOT) ||
+ mStreams[i]->isTypeOf(CAM_STREAM_TYPE_POSTVIEW) ||
+ mStreams[i]->isOrignalTypeOf(CAM_STREAM_TYPE_POSTVIEW) ) ) {
+ cam_stream_parm_buffer_t param_buf;
+ memset(&param_buf, 0, sizeof(cam_stream_parm_buffer_t));
+ param_buf.type = CAM_STREAM_PARAM_TYPE_SET_FLIP;
+ param_buf.flipInfo.flip_mask =
+ (uint32_t)param.getFlipMode(CAM_STREAM_TYPE_SNAPSHOT);
+ rc = mStreams[i]->setParameter(param_buf);
+ if (rc != NO_ERROR) {
+ LOGW("set snapshot stream flip failed");
+ }
+ }
+ }
+ }
+ return rc;
+}
+
+/*===========================================================================
+ * FUNCTION : QCameraPicChannel
+ *
+ * DESCRIPTION: constructor of QCameraPicChannel
+ *
+ * PARAMETERS :
+ * @cam_handle : camera handle
+ * @cam_ops : ptr to camera ops table
+ *
+ * RETURN : none
+ *==========================================================================*/
+QCameraPicChannel::QCameraPicChannel(uint32_t cam_handle,
+ mm_camera_ops_t *cam_ops) :
+ QCameraChannel(cam_handle, cam_ops)
+{
+ m_bAllowDynBufAlloc = true;
+}
+
+/*===========================================================================
+ * FUNCTION : QCameraPicChannel
+ *
+ * DESCRIPTION: default constructor of QCameraPicChannel
+ *
+ * PARAMETERS : none
+ *
+ * RETURN : none
+ *==========================================================================*/
+QCameraPicChannel::QCameraPicChannel()
+{
+ m_bAllowDynBufAlloc = true;
+}
+
+/*===========================================================================
+ * FUNCTION : ~QCameraPicChannel
+ *
+ * DESCRIPTION: destructor of QCameraPicChannel
+ *
+ * PARAMETERS : none
+ *
+ * RETURN : none
+ *==========================================================================*/
+QCameraPicChannel::~QCameraPicChannel()
+{
+}
+
+/*===========================================================================
+ * FUNCTION : takePicture
+ *
+ * DESCRIPTION: send request for queued snapshot frames
+ *
+ * PARAMETERS :
+ * @buf : request buf info
+ *
+ * RETURN : int32_t type of status
+ * NO_ERROR -- success
+ * none-zero failure code
+ *==========================================================================*/
+int32_t QCameraPicChannel::takePicture (mm_camera_req_buf_t *buf)
+{
+ int32_t rc = m_camOps->request_super_buf(m_camHandle, m_handle, buf);
+ return rc;
+}
+
+/*===========================================================================
+ * FUNCTION : cancelPicture
+ *
+ * DESCRIPTION: cancel request for queued snapshot frames
+ *
+ * PARAMETERS : none
+ *
+ * RETURN : int32_t type of status
+ * NO_ERROR -- success
+ * none-zero failure code
+ *==========================================================================*/
+int32_t QCameraPicChannel::cancelPicture()
+{
+ int32_t rc = m_camOps->cancel_super_buf_request(m_camHandle, m_handle);
+ return rc;
+}
+
+/*===========================================================================
+ * FUNCTION : stopAdvancedCapture
+ *
+ * DESCRIPTION: stop advanced capture based on advanced capture type.
+ *
+ * PARAMETERS :
+ * @type : advanced capture type.
+ *
+ * RETURN : int32_t type of status
+ * NO_ERROR -- success
+ * none-zero failure code
+ *==========================================================================*/
+int32_t QCameraPicChannel::stopAdvancedCapture(mm_camera_advanced_capture_t type)
+{
+ int32_t rc = m_camOps->process_advanced_capture(m_camHandle,
+ m_handle, type, 0, NULL);
+ return rc;
+}
+
+/*===========================================================================
+ * FUNCTION : startAdvancedCapture
+ *
+ * DESCRIPTION: start advanced capture based on advanced capture type.
+ *
+ * PARAMETERS :
+ * @type : advanced capture type.
+ * @config: advance capture config
+ *
+ * RETURN : int32_t type of status
+ * NO_ERROR -- success
+ * none-zero failure code
+ *==========================================================================*/
+int32_t QCameraPicChannel::startAdvancedCapture(mm_camera_advanced_capture_t type,
+ cam_capture_frame_config_t *config)
+{
+ int32_t rc = NO_ERROR;
+
+ rc = m_camOps->process_advanced_capture(m_camHandle, m_handle, type,
+ 1, config);
+ return rc;
+}
+
+/*===========================================================================
+* FUNCTION : flushSuperbuffer
+ *
+ * DESCRIPTION: flush the all superbuffer frames.
+ *
+ * PARAMETERS :
+ * @frame_idx : frame index of focused frame
+ *
+ * RETURN : int32_t type of status
+ * NO_ERROR -- success
+ * none-zero failure code
+ *==========================================================================*/
+int32_t QCameraPicChannel::flushSuperbuffer(uint32_t frame_idx)
+{
+ int32_t rc = m_camOps->flush_super_buf_queue(m_camHandle, m_handle, frame_idx);
+ return rc;
+}
+
+/*===========================================================================
+ * FUNCTION : QCameraVideoChannel
+ *
+ * DESCRIPTION: constructor of QCameraVideoChannel
+ *
+ * PARAMETERS :
+ * @cam_handle : camera handle
+ * @cam_ops : ptr to camera ops table
+ *
+ * RETURN : none
+ *==========================================================================*/
+QCameraVideoChannel::QCameraVideoChannel(uint32_t cam_handle,
+ mm_camera_ops_t *cam_ops) :
+ QCameraChannel(cam_handle, cam_ops)
+{
+}
+
+/*===========================================================================
+ * FUNCTION : QCameraVideoChannel
+ *
+ * DESCRIPTION: default constructor of QCameraVideoChannel
+ *
+ * PARAMETERS : none
+ *
+ * RETURN : none
+ *==========================================================================*/
+QCameraVideoChannel::QCameraVideoChannel()
+{
+}
+
+/*===========================================================================
+ * FUNCTION : ~QCameraVideoChannel
+ *
+ * DESCRIPTION: destructor of QCameraVideoChannel
+ *
+ * PARAMETERS : none
+ *
+ * RETURN : none
+ *==========================================================================*/
+QCameraVideoChannel::~QCameraVideoChannel()
+{
+}
+
+/*===========================================================================
+ * FUNCTION : takePicture
+ *
+ * DESCRIPTION: send request for queued snapshot frames
+ *
+ * PARAMETERS :
+ * @mm_camera_req_buf_t : request buf info
+ *
+ * RETURN : int32_t type of status
+ * NO_ERROR -- success
+ * none-zero failure code
+ *==========================================================================*/
+int32_t QCameraVideoChannel::takePicture(mm_camera_req_buf_t *buf)
+{
+ int32_t rc = m_camOps->request_super_buf(m_camHandle, m_handle, buf);
+ return rc;
+}
+
+/*===========================================================================
+ * FUNCTION : cancelPicture
+ *
+ * DESCRIPTION: cancel request for queued snapshot frames
+ *
+ * PARAMETERS : none
+ *
+ * RETURN : int32_t type of status
+ * NO_ERROR -- success
+ * none-zero failure code
+ *==========================================================================*/
+int32_t QCameraVideoChannel::cancelPicture()
+{
+ int32_t rc = m_camOps->cancel_super_buf_request(m_camHandle, m_handle);
+ return rc;
+}
+
+/*===========================================================================
+ * FUNCTION : releaseFrame
+ *
+ * DESCRIPTION: return video frame from app
+ *
+ * PARAMETERS :
+ * @opaque : ptr to video frame to be returned
+ * @isMetaData : if frame is a metadata or real frame
+ *
+ * RETURN : int32_t type of status
+ * NO_ERROR -- success
+ * none-zero failure code
+ *==========================================================================*/
+int32_t QCameraVideoChannel::releaseFrame(const void * opaque, bool isMetaData)
+{
+ QCameraStream *pVideoStream = NULL;
+ for (size_t i = 0; i < mStreams.size(); i++) {
+ if (mStreams[i] != NULL && mStreams[i]->isTypeOf(CAM_STREAM_TYPE_VIDEO)) {
+ pVideoStream = mStreams[i];
+ break;
+ }
+ }
+
+ if (NULL == pVideoStream) {
+ LOGE("No video stream in the channel");
+ return BAD_VALUE;
+ }
+
+ int32_t rc = pVideoStream->bufDone(opaque, isMetaData);
+ return rc;
+}
+
+/*===========================================================================
+ * FUNCTION : QCameraReprocessChannel
+ *
+ * DESCRIPTION: constructor of QCameraReprocessChannel
+ *
+ * PARAMETERS :
+ * @cam_handle : camera handle
+ * @cam_ops : ptr to camera ops table
+ *
+ * RETURN : none
+ *==========================================================================*/
+QCameraReprocessChannel::QCameraReprocessChannel(uint32_t cam_handle,
+ mm_camera_ops_t *cam_ops) :
+ QCameraChannel(cam_handle, cam_ops),
+ m_pSrcChannel(NULL),
+ mPassCount(0)
+{
+ memset(mSrcStreamHandles, 0, sizeof(mSrcStreamHandles));
+}
+
+/*===========================================================================
+ * FUNCTION : QCameraReprocessChannel
+ *
+ * DESCRIPTION: default constructor of QCameraReprocessChannel
+ *
+ * PARAMETERS : none
+ *
+ * RETURN : none
+ *==========================================================================*/
+QCameraReprocessChannel::QCameraReprocessChannel() :
+ m_pSrcChannel(NULL),
+ mPassCount(0)
+{
+}
+
+/*===========================================================================
+ * FUNCTION : ~QCameraReprocessChannel
+ *
+ * DESCRIPTION: destructor of QCameraReprocessChannel
+ *
+ * PARAMETERS : none
+ *
+ * RETURN : none
+ *==========================================================================*/
+QCameraReprocessChannel::~QCameraReprocessChannel()
+{
+}
+
+/*===========================================================================
+ * FUNCTION : addReprocStreamsFromSource
+ *
+ * DESCRIPTION: add reprocess streams from input source channel
+ *
+ * PARAMETERS :
+ * @allocator : stream related buffer allocator
+ * @featureConfig : pp feature configuration
+ * @pSrcChannel : ptr to input source channel that needs reprocess
+ * @minStreamBufNum: number of stream buffers needed
+ * @burstNum : number of burst captures needed
+ * @paddingInfo : padding information
+ * @param : reference to parameters
+ * @contStream : continous streaming mode or burst
+ * @offline : configure for offline reprocessing
+ *
+ * RETURN : int32_t type of status
+ * NO_ERROR -- success
+ * none-zero failure code
+ *==========================================================================*/
+int32_t QCameraReprocessChannel::addReprocStreamsFromSource(
+ QCameraAllocator& allocator, cam_pp_feature_config_t &featureConfig,
+ QCameraChannel *pSrcChannel, uint8_t minStreamBufNum, uint8_t burstNum,
+ cam_padding_info_t *paddingInfo, QCameraParametersIntf &param, bool contStream,
+ bool offline)
+{
+ int32_t rc = 0;
+ QCameraStream *pStream = NULL;
+ QCameraHeapMemory *pStreamInfoBuf = NULL;
+ QCameraHeapMemory *pMiscBuf = NULL;
+ cam_stream_info_t *streamInfo = NULL;
+ cam_padding_info_t padding;
+
+ memset(mSrcStreamHandles, 0, sizeof(mSrcStreamHandles));
+ if (NULL == paddingInfo) {
+ return BAD_VALUE;
+ }
+ padding = *paddingInfo;
+ //Use maximum padding so that the buffer
+ //can be rotated
+ padding.width_padding = MAX(padding.width_padding, padding.height_padding);
+ padding.height_padding = padding.width_padding;
+ padding.offset_info.offset_x = 0;
+ padding.offset_info.offset_y = 0;
+
+ LOGD("num of src stream = %d", pSrcChannel->getNumOfStreams());
+
+ for (uint32_t i = 0; i < pSrcChannel->getNumOfStreams(); i++) {
+ cam_pp_feature_config_t pp_featuremask = featureConfig;
+ pStream = pSrcChannel->getStreamByIndex(i);
+ if (pStream != NULL) {
+ if (param.getofflineRAW() && !((pStream->isTypeOf(CAM_STREAM_TYPE_RAW))
+ || (pStream->isTypeOf(CAM_STREAM_TYPE_POSTVIEW))
+ || (pStream->isTypeOf(CAM_STREAM_TYPE_METADATA))
+ || (pStream->isOrignalTypeOf(CAM_STREAM_TYPE_RAW)))) {
+ //Skip all the stream other than RAW and POSTVIEW incase of offline of RAW
+ continue;
+ }
+
+ if (pStream->isTypeOf(CAM_STREAM_TYPE_RAW)
+ && (!param.getofflineRAW())) {
+ // Skip raw for reprocess now because PP module cannot handle
+ // meta data&raw. May need furthur discussion if Imaginglib need meta data
+ continue;
+ }
+
+ if (((pStream->isTypeOf(CAM_STREAM_TYPE_METADATA))
+ && !(param.getManualCaptureMode() >=
+ CAM_MANUAL_CAPTURE_TYPE_3))
+ || (pStream->isTypeOf(CAM_STREAM_TYPE_ANALYSIS))) {
+ // Skip metadata
+ continue;
+ }
+
+ if (pStream->isTypeOf(CAM_STREAM_TYPE_PREVIEW) ||
+ pStream->isTypeOf(CAM_STREAM_TYPE_POSTVIEW) ||
+ pStream->isOrignalTypeOf(CAM_STREAM_TYPE_PREVIEW) ||
+ pStream->isOrignalTypeOf(CAM_STREAM_TYPE_POSTVIEW)) {
+ cam_feature_mask_t feature_mask = featureConfig.feature_mask;
+
+ // skip thumbnail reprocessing if not needed
+ if (!param.needThumbnailReprocess(&feature_mask)) {
+ continue;
+ }
+ // CAC, SHARPNESS, FLIP and WNR would have been already applied -
+ // on preview/postview stream in realtime.
+ // So, need not apply again.
+ feature_mask &= ~(CAM_QCOM_FEATURE_DENOISE2D |
+ CAM_QCOM_FEATURE_CAC |
+ CAM_QCOM_FEATURE_SHARPNESS |
+ CAM_QCOM_FEATURE_FLIP |
+ CAM_QCOM_FEATURE_RAW_PROCESSING);
+ if (!feature_mask) {
+ // Skip thumbnail stream reprocessing since no other
+ //reprocessing is enabled.
+ continue;
+ }
+ }
+
+ if (pStream->isTypeOf(CAM_STREAM_TYPE_METADATA)) {
+ pp_featuremask.feature_mask = 0;
+ pp_featuremask.feature_mask |= CAM_QCOM_FEATURE_METADATA_PROCESSING;
+ }
+
+ pStreamInfoBuf = allocator.allocateStreamInfoBuf(CAM_STREAM_TYPE_OFFLINE_PROC);
+ if (pStreamInfoBuf == NULL) {
+ LOGE("no mem for stream info buf");
+ rc = NO_MEMORY;
+ break;
+ }
+
+ streamInfo = (cam_stream_info_t *)pStreamInfoBuf->getPtr(0);
+ memset(streamInfo, 0, sizeof(cam_stream_info_t));
+ streamInfo->stream_type = CAM_STREAM_TYPE_OFFLINE_PROC;
+ // Enable CPP high performance mode to put it in turbo frequency mode for
+ // burst/longshot/HDR snapshot cases
+ streamInfo->perf_mode = CAM_PERF_HIGH_PERFORMANCE;
+ if (param.getofflineRAW() && (pStream->isTypeOf(CAM_STREAM_TYPE_RAW)
+ || pStream->isOrignalTypeOf(CAM_STREAM_TYPE_RAW))) {
+ if (pp_featuremask.feature_mask & CAM_QCOM_FEATURE_QUADRA_CFA) {
+ param.getStreamFormat(CAM_STREAM_TYPE_OFFLINE_PROC, streamInfo->fmt);
+ } else {
+ streamInfo->fmt = CAM_FORMAT_YUV_420_NV21;
+ }
+ } else {
+ rc = pStream->getFormat(streamInfo->fmt);
+ }
+
+ if (pStream->isTypeOf(CAM_STREAM_TYPE_POSTVIEW) ||
+ pStream->isTypeOf(CAM_STREAM_TYPE_PREVIEW)) {
+ param.getThumbnailSize(&(streamInfo->dim.width), &(streamInfo->dim.height));
+ } else {
+ if ((param.isPostProcScaling()) &&
+ (pp_featuremask.feature_mask & CAM_QCOM_FEATURE_SCALE)) {
+ rc = param.getStreamDimension(CAM_STREAM_TYPE_OFFLINE_PROC,
+ streamInfo->dim);
+ } else if ((param.getofflineRAW()) &&
+ ((pStream->isTypeOf(CAM_STREAM_TYPE_RAW)) ||
+ (pStream->isOrignalTypeOf(CAM_STREAM_TYPE_RAW)))) {
+ if ((param.getQuadraCfa()) &&
+ (pp_featuremask.feature_mask & CAM_QCOM_FEATURE_QUADRA_CFA)) {
+ rc = pStream->getFrameDimension(streamInfo->dim);
+ } else {
+ param.getStreamDimension(CAM_STREAM_TYPE_SNAPSHOT,streamInfo->dim);
+ }
+ } else {
+ rc = pStream->getFrameDimension(streamInfo->dim);
+ }
+ }
+
+ if ( contStream ) {
+ streamInfo->streaming_mode = CAM_STREAMING_MODE_CONTINUOUS;
+ streamInfo->num_of_burst = 0;
+ } else {
+ streamInfo->streaming_mode = CAM_STREAMING_MODE_BURST;
+ streamInfo->num_of_burst = burstNum;
+ }
+ streamInfo->num_bufs = minStreamBufNum;
+
+ cam_stream_reproc_config_t rp_cfg;
+ memset(&rp_cfg, 0, sizeof(cam_stream_reproc_config_t));
+ if (offline) {
+ cam_frame_len_offset_t offset;
+ memset(&offset, 0, sizeof(cam_frame_len_offset_t));
+
+ rp_cfg.pp_type = CAM_OFFLINE_REPROCESS_TYPE;
+ pStream->getFormat(rp_cfg.offline.input_fmt);
+ pStream->getFrameDimension(rp_cfg.offline.input_dim);
+ pStream->getFrameOffset(offset);
+ rp_cfg.offline.input_buf_planes.plane_info = offset;
+ rp_cfg.offline.input_type = pStream->getMyOriginalType();
+ //For input metadata + input buffer
+ rp_cfg.offline.num_of_bufs = 2;
+ } else {
+ rp_cfg.pp_type = CAM_ONLINE_REPROCESS_TYPE;
+ rp_cfg.online.input_stream_id = pStream->getMyServerID();
+ rp_cfg.online.input_stream_type = pStream->getMyOriginalType();
+ }
+ param.getStreamRotation(streamInfo->stream_type,
+ streamInfo->pp_config, streamInfo->dim);
+ streamInfo->reprocess_config = rp_cfg;
+ streamInfo->reprocess_config.pp_feature_config = pp_featuremask;
+
+ if (!(pStream->isTypeOf(CAM_STREAM_TYPE_SNAPSHOT)
+ || pStream->isOrignalTypeOf(CAM_STREAM_TYPE_SNAPSHOT)
+ || pStream->isTypeOf(CAM_STREAM_TYPE_RAW)
+ || pStream->isOrignalTypeOf(CAM_STREAM_TYPE_RAW))) {
+ // CAC, SHARPNESS, FLIP and WNR would have been already applied -
+ // on preview/postview stream in realtime. Need not apply again.
+ streamInfo->reprocess_config.pp_feature_config.feature_mask &=
+ ~CAM_QCOM_FEATURE_CAC;
+ streamInfo->reprocess_config.pp_feature_config.feature_mask &=
+ ~CAM_QCOM_FEATURE_SHARPNESS;
+ streamInfo->reprocess_config.pp_feature_config.feature_mask &=
+ ~CAM_QCOM_FEATURE_FLIP;
+ //Don't do WNR for thumbnail
+ streamInfo->reprocess_config.pp_feature_config.feature_mask &=
+ ~CAM_QCOM_FEATURE_DENOISE2D;
+ streamInfo->reprocess_config.pp_feature_config.feature_mask &=
+ ~CAM_QCOM_FEATURE_CDS;
+ streamInfo->reprocess_config.pp_feature_config.feature_mask &=
+ ~CAM_QCOM_FEATURE_DSDN;
+ //No need of RAW processing for other than RAW streams
+ streamInfo->reprocess_config.pp_feature_config.feature_mask &=
+ ~CAM_QCOM_FEATURE_RAW_PROCESSING;
+
+ if (param.isHDREnabled()
+ && !param.isHDRThumbnailProcessNeeded()){
+ streamInfo->reprocess_config.pp_feature_config.feature_mask
+ &= ~CAM_QCOM_FEATURE_HDR;
+ }
+ }
+
+ cam_stream_type_t type = CAM_STREAM_TYPE_DEFAULT;
+ if (offline) {
+ type = streamInfo->reprocess_config.offline.input_type;
+ } else {
+ type = streamInfo->reprocess_config.online.input_stream_type;
+ }
+ if (type == CAM_STREAM_TYPE_SNAPSHOT) {
+ int flipMode = param.getFlipMode(type);
+ if (flipMode > 0) {
+ streamInfo->reprocess_config.pp_feature_config.feature_mask |=
+ CAM_QCOM_FEATURE_FLIP;
+ streamInfo->reprocess_config.pp_feature_config.flip = (uint32_t)flipMode;
+ }
+ }
+
+ if ((streamInfo->reprocess_config.pp_feature_config.feature_mask
+ & CAM_QCOM_FEATURE_SCALE)
+ && param.isReprocScaleEnabled()
+ && param.isUnderReprocScaling()) {
+ //we only Scale Snapshot frame
+ if (pStream->isTypeOf(CAM_STREAM_TYPE_SNAPSHOT)) {
+ streamInfo->dim.width =
+ streamInfo->reprocess_config.pp_feature_config.scale_param.output_width;
+ streamInfo->dim.height =
+ streamInfo->reprocess_config.pp_feature_config.scale_param.output_height;
+ }
+ LOGH("stream width=%d, height=%d.",
+ streamInfo->dim.width, streamInfo->dim.height);
+ }
+
+ // save source stream handler
+ mSrcStreamHandles[mStreams.size()] = pStream->getMyHandle();
+
+ pMiscBuf = allocator.allocateMiscBuf(streamInfo);
+
+ LOGH("Configure Reprocessing: stream = %d, res = %dX%d, fmt = %d, type = %d",
+ pStream->getMyOriginalType(), streamInfo->dim.width,
+ streamInfo->dim.height, streamInfo->fmt, type);
+
+ // add reprocess stream
+ if (streamInfo->reprocess_config.pp_feature_config.feature_mask
+ & CAM_QCOM_FEATURE_ROTATION) {
+ rc = addStream(allocator, pStreamInfoBuf, pMiscBuf,
+ minStreamBufNum, &padding, NULL, NULL, false, false,
+ streamInfo->reprocess_config.pp_feature_config.rotation);
+ } else {
+ rc = addStream(allocator, pStreamInfoBuf, pMiscBuf,
+ minStreamBufNum, &padding, NULL, NULL, false, false);
+ }
+ if (rc != NO_ERROR) {
+ LOGE("add reprocess stream failed, ret = %d", rc);
+ break;
+ }
+ }
+ }
+
+ if (rc == NO_ERROR) {
+ m_pSrcChannel = pSrcChannel;
+ }
+ return rc;
+}
+
+/*===========================================================================
+ * FUNCTION : getStreamBySrouceHandle
+ *
+ * DESCRIPTION: find reprocess stream by its source stream handle
+ *
+ * PARAMETERS :
+ * @srcHandle : source stream handle
+ *
+ * RETURN : ptr to reprocess stream if found. NULL if not found
+ *==========================================================================*/
+QCameraStream * QCameraReprocessChannel::getStreamBySrouceHandle(uint32_t srcHandle)
+{
+ QCameraStream *pStream = NULL;
+
+ for (size_t i = 0; i < mStreams.size(); i++) {
+ if (mSrcStreamHandles[i] == srcHandle) {
+ pStream = mStreams[i];
+ break;
+ }
+ }
+
+ return pStream;
+}
+
+/*===========================================================================
+ * FUNCTION : stop
+ *
+ * DESCRIPTION: stop channel and unmap offline buffers
+ *
+ * PARAMETERS : none
+ *
+ * RETURN : int32_t type of status
+ * NO_ERROR -- success
+ * none-zero failure code
+ *==========================================================================*/
+int32_t QCameraReprocessChannel::stop()
+{
+ int32_t rc = QCameraChannel::stop();
+
+ if (!mOfflineBuffers.empty()) {
+ QCameraStream *stream = NULL;
+ List<OfflineBuffer>::iterator it = mOfflineBuffers.begin();
+ int error = NO_ERROR;
+ for( ; it != mOfflineBuffers.end(); it++) {
+ stream = (*it).stream;
+ if (NULL != stream) {
+ error = stream->unmapBuf((*it).type,
+ (*it).index,
+ -1);
+ if (NO_ERROR != error) {
+ LOGE("Error during offline buffer unmap %d",
+ error);
+ }
+ }
+ }
+ mOfflineBuffers.clear();
+ }
+ return rc;
+}
+
+/*===========================================================================
+ * FUNCTION : doReprocessOffline
+ *
+ * DESCRIPTION: request to do offline reprocess on the frame
+ *
+ * PARAMETERS :
+ * @frame : frame to be performed a reprocess
+ * @meta_buf : Metadata buffer for reprocessing
+ * @pStream : Actual reprocess stream
+ *
+ * RETURN : int32_t type of status
+ * NO_ERROR -- success
+ * none-zero failure code
+ *==========================================================================*/
+int32_t QCameraReprocessChannel::doReprocessOffline(mm_camera_buf_def_t *frame,
+ mm_camera_buf_def_t *meta_buf, QCameraStream *pStream)
+{
+ int32_t rc = 0;
+ OfflineBuffer mappedBuffer;
+ uint32_t buf_index = 0;
+ uint32_t meta_buf_index = 0;
+
+ if ((frame == NULL) || (meta_buf == NULL)) {
+ LOGE("Invalid Input Paramters");
+ return INVALID_OPERATION;
+ }
+
+ if (pStream == NULL) {
+ pStream = getStreamBySrouceHandle(frame->stream_id);
+ if (pStream == NULL) {
+ LOGE("Input validation failed.");
+ return INVALID_OPERATION;
+ }
+ }
+
+ if (!mOfflineBuffers.empty()) {
+ List<OfflineBuffer>::iterator it = mOfflineBuffers.begin();
+ for( ; it != mOfflineBuffers.end(); it++) {
+ buf_index = (buf_index < ((*it).index)) ? ((*it).index) : buf_index;
+ }
+ buf_index += 1;
+ }
+
+ meta_buf_index = buf_index;
+ if (meta_buf != NULL) {
+ rc = pStream->mapBuf(CAM_MAPPING_BUF_TYPE_OFFLINE_META_BUF,
+ meta_buf_index,
+ -1,
+ meta_buf->fd,
+ meta_buf->frame_len);
+ if (NO_ERROR != rc ) {
+ LOGE("Error during metadata buffer mapping");
+ rc = -1;
+ return rc;
+ }
+
+ mappedBuffer.index = meta_buf_index;
+ mappedBuffer.stream = pStream;
+ mappedBuffer.type = CAM_MAPPING_BUF_TYPE_OFFLINE_META_BUF;
+ mOfflineBuffers.push_back(mappedBuffer);
+ buf_index += 1;
+ }
+
+ rc = pStream->mapBuf(CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF,
+ buf_index,
+ -1,
+ frame->fd,
+ frame->frame_len);
+ if (NO_ERROR != rc ) {
+ LOGE("Error during reprocess input buffer mapping");
+ rc = -1;
+ return rc;
+ }
+ mappedBuffer.index = buf_index;
+ mappedBuffer.stream = pStream;
+ mappedBuffer.type = CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF;
+ mOfflineBuffers.push_back(mappedBuffer);
+
+ cam_stream_parm_buffer_t param;
+ memset(&param, 0, sizeof(cam_stream_parm_buffer_t));
+
+ param.type = CAM_STREAM_PARAM_TYPE_DO_REPROCESS;
+ param.reprocess.buf_index = buf_index;
+ param.reprocess.frame_idx = frame->frame_idx;
+
+ if (meta_buf != NULL) {
+ param.reprocess.meta_present = 1;
+ param.reprocess.meta_buf_index = meta_buf_index;
+ }
+
+ LOGI("Offline reprocessing id = %d buf Id = %d meta index = %d type = %d",
+ param.reprocess.frame_idx, param.reprocess.buf_index,
+ param.reprocess.meta_buf_index, pStream->getMyOriginalType());
+
+ rc = pStream->setParameter(param);
+ if (rc != NO_ERROR) {
+ LOGE("stream setParameter for reprocess failed");
+ return rc;
+ }
+ return rc;
+}
+
+/*===========================================================================
+ * FUNCTION : doReprocessOffline
+ *
+ * DESCRIPTION: request to do offline reprocess on the frame
+ *
+ * PARAMETERS :
+ * @frame : frame to be performed a reprocess
+ * @meta_buf : Metadata buffer for reprocessing
+ * @mParameter : camera parameters
+ *
+ * RETURN : int32_t type of status
+ * NO_ERROR -- success
+ * none-zero failure code
+ *==========================================================================*/
+int32_t QCameraReprocessChannel::doReprocessOffline(mm_camera_super_buf_t *frame,
+ mm_camera_buf_def_t *meta_buf, QCameraParametersIntf &mParameter)
+{
+ int32_t rc = 0;
+ QCameraStream *pStream = NULL;
+
+ if (mStreams.size() < 1) {
+ LOGE("No reprocess streams");
+ return -1;
+ }
+ if (m_pSrcChannel == NULL) {
+ LOGE("No source channel for reprocess");
+ return -1;
+ }
+
+ if (frame == NULL) {
+ LOGE("Invalid source frame");
+ return BAD_VALUE;
+ }
+
+ for (uint32_t i = 0; i < frame->num_bufs; i++) {
+ pStream = getStreamBySrouceHandle(frame->bufs[i]->stream_id);
+ if ((pStream != NULL) &&
+ (m_handle == pStream->getChannelHandle())) {
+ if (mParameter.getofflineRAW() &&
+ !((pStream->isOrignalTypeOf(CAM_STREAM_TYPE_RAW))
+ || (pStream->isOrignalTypeOf(CAM_STREAM_TYPE_METADATA)))) {
+ continue;
+ }
+
+ if ((pStream->isOrignalTypeOf(CAM_STREAM_TYPE_METADATA)
+ && (mParameter.getManualCaptureMode()
+ < CAM_MANUAL_CAPTURE_TYPE_3))
+ || (pStream->isTypeOf(CAM_STREAM_TYPE_ANALYSIS))) {
+ // Skip metadata for reprocess now because PP module cannot handle meta data
+ // May need furthur discussion if Imaginglib need meta data
+ continue;
+ }
+
+ // Update Metadata
+ if (meta_buf != NULL) {
+ uint32_t stream_id = frame->bufs[i]->stream_id;
+ QCameraStream *srcStream =
+ m_pSrcChannel->getStreamByHandle(stream_id);
+ metadata_buffer_t *pMetaData =
+ (metadata_buffer_t *)meta_buf->buffer;
+ if ((NULL != pMetaData) && (NULL != srcStream)) {
+ IF_META_AVAILABLE(cam_crop_data_t, crop,
+ CAM_INTF_META_CROP_DATA, pMetaData) {
+ if (MAX_NUM_STREAMS > crop->num_of_streams) {
+ for (int j = 0; j < MAX_NUM_STREAMS; j++) {
+ if (crop->crop_info[j].stream_id ==
+ srcStream->getMyServerID()) {
+ // Store crop/roi information for offline reprocess
+ // in the reprocess stream slot
+ crop->crop_info[crop->num_of_streams].crop =
+ crop->crop_info[j].crop;
+ crop->crop_info[crop->num_of_streams].roi_map =
+ crop->crop_info[j].roi_map;
+ for (uint8_t k = 0; k < mStreams.size(); k++) {
+ if (srcStream->getMyType() ==
+ mStreams[k]->getMyOriginalType()) {
+ crop->crop_info[crop->num_of_streams].stream_id =
+ mStreams[k]->getMyServerID();
+ break;
+ }
+ }
+ crop->num_of_streams++;
+ break;
+ }
+ }
+ } else {
+ LOGE("No space to add reprocess stream crop/roi information");
+ }
+ }
+ }
+ }
+
+ rc = doReprocessOffline (frame->bufs[i], meta_buf, pStream);
+ }
+ }
+ return rc;
+}
+
+/*===========================================================================
+ * FUNCTION : doReprocess
+ *
+ * DESCRIPTION: request to do a reprocess on the frame
+ *
+ * PARAMETERS :
+ * @frame : frame to be performed a reprocess
+ * @mParameter : camera parameters
+ * @pMetaStream: Metadata stream handle
+ * @meta_buf_index : Metadata buffer index
+ *
+ * RETURN : int32_t type of status
+ * NO_ERROR -- success
+ * none-zero failure code
+ *==========================================================================*/
+int32_t QCameraReprocessChannel::doReprocess(mm_camera_super_buf_t *frame,
+ QCameraParametersIntf &mParameter, QCameraStream *pMetaStream,
+ uint8_t meta_buf_index)
+{
+ int32_t rc = 0;
+ if (mStreams.size() < 1) {
+ LOGE("No reprocess streams");
+ return -1;
+ }
+ if (m_pSrcChannel == NULL) {
+ LOGE("No source channel for reprocess");
+ return -1;
+ }
+
+ if (pMetaStream == NULL) {
+ LOGW("Null Metadata buffer for processing");
+ }
+
+ for (uint32_t i = 0; i < frame->num_bufs; i++) {
+ QCameraStream *pStream = getStreamBySrouceHandle(frame->bufs[i]->stream_id);
+ if ((pStream != NULL) && (m_handle == pStream->getChannelHandle())) {
+ if (mParameter.getofflineRAW() && !((pStream->isOrignalTypeOf(CAM_STREAM_TYPE_RAW))
+ || (pStream->isOrignalTypeOf(CAM_STREAM_TYPE_POSTVIEW))
+ || (pStream->isOrignalTypeOf(CAM_STREAM_TYPE_METADATA)))) {
+ //Skip all the stream other than RAW and POSTVIEW incase of offline of RAW
+ continue;
+ }
+ if ((pStream->isOrignalTypeOf(CAM_STREAM_TYPE_METADATA)
+ && (mParameter.getManualCaptureMode()
+ < CAM_MANUAL_CAPTURE_TYPE_3))
+ || (pStream->isTypeOf(CAM_STREAM_TYPE_ANALYSIS))) {
+ // Skip metadata for reprocess now because PP module cannot handle meta data
+ // May need furthur discussion if Imaginglib need meta data
+ continue;
+ }
+
+ cam_stream_parm_buffer_t param;
+ memset(&param, 0, sizeof(cam_stream_parm_buffer_t));
+ param.type = CAM_STREAM_PARAM_TYPE_DO_REPROCESS;
+ param.reprocess.buf_index = frame->bufs[i]->buf_idx;
+ param.reprocess.frame_idx = frame->bufs[i]->frame_idx;
+ if (pMetaStream != NULL) {
+ // we have meta data frame bundled, sent together with reprocess frame
+ param.reprocess.meta_present = 1;
+ param.reprocess.meta_stream_handle = pMetaStream->getMyServerID();
+ param.reprocess.meta_buf_index = meta_buf_index;
+ }
+
+ LOGI("Online reprocessing id = %d buf Id = %d meta index = %d type = %d",
+ param.reprocess.frame_idx, param.reprocess.buf_index,
+ param.reprocess.meta_buf_index, pStream->getMyOriginalType());
+
+ rc = pStream->setParameter(param);
+ if (rc != NO_ERROR) {
+ LOGE("stream setParameter for reprocess failed");
+ break;
+ }
+ }
+ }
+ return rc;
+}
+
+/*===========================================================================
+ * FUNCTION : doReprocess
+ *
+ * DESCRIPTION: request to do a reprocess on the frame
+ *
+ * PARAMETERS :
+ * @buf_fd : fd to the input buffer that needs reprocess
+ * @buf_lenght : length of the input buffer
+ * @ret_val : result of reprocess.
+ * Example: Could be faceID in case of register face image.
+ *
+ * RETURN : int32_t type of status
+ * NO_ERROR -- success
+ * none-zero failure code
+ *==========================================================================*/
+int32_t QCameraReprocessChannel::doReprocess(int buf_fd,
+ size_t buf_length, int32_t &ret_val)
+{
+ int32_t rc = 0;
+ if (mStreams.size() < 1) {
+ LOGE("No reprocess streams");
+ return -1;
+ }
+
+ uint32_t buf_idx = 0;
+ for (size_t i = 0; i < mStreams.size(); i++) {
+ if ((mStreams[i] != NULL) &&
+ (m_handle != mStreams[i]->getChannelHandle())) {
+ continue;
+ }
+ rc = mStreams[i]->mapBuf(CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF,
+ buf_idx, -1,
+ buf_fd, buf_length);
+
+ if (rc == NO_ERROR) {
+ cam_stream_parm_buffer_t param;
+ memset(&param, 0, sizeof(cam_stream_parm_buffer_t));
+ param.type = CAM_STREAM_PARAM_TYPE_DO_REPROCESS;
+ param.reprocess.buf_index = buf_idx;
+ rc = mStreams[i]->setParameter(param);
+ if (rc == NO_ERROR) {
+ ret_val = param.reprocess.ret_val;
+ }
+ mStreams[i]->unmapBuf(CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF,
+ buf_idx, -1);
+ }
+ }
+ return rc;
+}
+
+}; // namespace qcamera