diff options
author | Prateek Chaubey <chaubeyprateek@gmail.com> | 2018-01-07 20:55:14 +0530 |
---|---|---|
committer | Davide Garberi <dade.garberi@gmail.com> | 2018-01-19 14:09:15 +0100 |
commit | 6616278131edd80a12545085e06ee6b0e0a0a788 (patch) | |
tree | 0aef88ed11809a9d67f6abe4dc2ff782a14737e2 /camera/QCamera2/HAL/QCameraChannel.cpp | |
parent | cc4ccf34871da343111bf68d16ba4e4c67cac1dc (diff) |
msm8996-common: zuk: Import OSS Camera HAL
Tag: LA.HB.1.3.2-32600-8x96.0
Signed-off-by: Davide Garberi <dade.garberi@gmail.com>
Diffstat (limited to 'camera/QCamera2/HAL/QCameraChannel.cpp')
-rw-r--r-- | camera/QCamera2/HAL/QCameraChannel.cpp | 1601 |
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(¶m, 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 ¶m) +{ + 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(¶m_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(¶m_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(¶m_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 ¶m, 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(¶m, 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(¶m, 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(¶m, 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 |