/* Copyright (c) 2017-2018, 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 "ClearSight" // System dependencies #include #include #include #include // Camera dependencies #include "QCameraClearSight.h" #include "QCameraTrace.h" #include "cam_intf.h" extern "C" { #include "mm_camera_dbg.h" } #define NUM_CLEARSIGHT_BUFS 3 namespace qcamera { /*=========================================================================== * FUNCTION : QCameraClearSight * * DESCRIPTION: constructor of QCameraClearSight. * * PARAMETERS : None * * RETURN : None *==========================================================================*/ QCameraClearSight::QCameraClearSight() : QCameraHALPP() { m_dlHandle = NULL; m_pCaps = NULL; } /*=========================================================================== * FUNCTION : ~QCameraClearSight * * DESCRIPTION: destructor of QCameraClearSight. * * PARAMETERS : None * * RETURN : None *==========================================================================*/ QCameraClearSight::~QCameraClearSight() { } /*=========================================================================== * FUNCTION : init * * DESCRIPTION: initialization of QCameraClearSight * * PARAMETERS : * @bufNotifyCb : call back function after HALPP process * @getOutputCb : call back function to request output buffe * @pUserData : Parent of HALPP, i.e. QCameraPostProc * @pStaticParam : holds dual camera calibration data in an array and its size * (expected size is 264 bytes) * * RETURN : int32_t type of status * NO_ERROR -- success * non-zero failure code *==========================================================================*/ int32_t QCameraClearSight::init(halPPBufNotify bufNotifyCb, halPPGetOutput getOutputCb, void *pUserData, void *pStaticParam) { LOGD("E"); int32_t rc = NO_ERROR; QCameraHALPP::init(bufNotifyCb, getOutputCb, pUserData); m_pCaps = (cam_capability_t *)pStaticParam; doClearSightInit(); LOGD("X"); return rc; } /*=========================================================================== * FUNCTION : deinit * * DESCRIPTION: de initialization of QCameraClearSight * * PARAMETERS : None * * RETURN : int32_t type of status * NO_ERROR -- success * none-zero failure code *==========================================================================*/ int32_t QCameraClearSight::deinit() { int32_t rc = NO_ERROR; LOGD("E"); m_dlHandle = NULL; QCameraHALPP::deinit(); LOGD("X"); return rc; } /*=========================================================================== * FUNCTION : start * * DESCRIPTION: starting QCameraClearSight * * PARAMETERS : * * RETURN : int32_t type of status * NO_ERROR -- success * none-zero failure code *==========================================================================*/ int32_t QCameraClearSight::start() { int32_t rc = NO_ERROR; LOGD("E"); rc = QCameraHALPP::start(); LOGD("X"); return rc; } /*=========================================================================== * FUNCTION : feedInput * * DESCRIPTION: function to feed input data. * Enqueue the frame index to inputQ if it is new frame * Also, add the input image data to frame hash map * * PARAMETERS : * @pInput : ptr to input data * * RETURN : int32_t type of status * NO_ERROR -- success * none-zero failure code *==========================================================================*/ int32_t QCameraClearSight::feedInput(qcamera_hal_pp_data_t *pInputData) { int32_t rc = NO_ERROR; LOGD("E"); if (NULL != pInputData) { mm_camera_buf_def_t *pInputSnapshotBuf = getSnapshotBuf(pInputData); if (pInputSnapshotBuf != NULL) { uint32_t frameIndex = pInputSnapshotBuf->frame_idx; std::vector *pVector = getFrameVector(frameIndex); if(pVector == NULL) { LOGD("insert new frame index = %d", frameIndex); // new the vector first pVector = new std::vector(MM_CAMERA_MAX_CAM_CNT); // Add vector to the hash map m_frameMap[frameIndex] = pVector; } else { uint32_t *pFrameIndex = new uint32_t; *pFrameIndex = frameIndex; // Enqueue the frame index (i.e. key of vector) to queue if (false == m_inputQ.enqueue((void*)pFrameIndex)) { LOGE("Input Q is not active!!!"); releaseData(pInputData); m_frameMap.erase(frameIndex); delete pFrameIndex; delete pVector; rc = INVALID_OPERATION; return rc; } if (m_inputQ.getCurrentSize() == MIN_CLEARSIGHT_BUFS) { m_halPPGetOutputCB(frameIndex, m_pHalPPMgr); } } pInputData->frameIndex = frameIndex; // Check if frame is from main camera bool bIsMain = true; uint32_t mainHandle = get_main_camera_handle( pInputData->src_reproc_frame->camera_handle); if (mainHandle == 0) { bIsMain = false; } LOGD("mainHandle = %d, is main frame = %d", mainHandle, bIsMain); // Add input data to vector if (bIsMain) { pVector->at(BAYER_INPUT) = pInputData; } else { pVector->at(MONO_INPUT) = pInputData; } } } else { LOGE("pInput is NULL"); rc = UNEXPECTED_NULL; } LOGD("X"); return rc; } /*=========================================================================== * FUNCTION : feedOutput * * DESCRIPTION: function to feed output buffer and metadata * * PARAMETERS : * @pOutput : ptr to output data * * RETURN : int32_t type of status * NO_ERROR -- success * none-zero failure code *==========================================================================*/ int32_t QCameraClearSight::feedOutput(qcamera_hal_pp_data_t *pOutputData) { int32_t rc = NO_ERROR; LOGD("E"); if (NULL != pOutputData) { uint32_t frameIndex = pOutputData->frameIndex; std::vector *pVector = getFrameVector(frameIndex); // Get the main input frame in order to get output buffer len, // and copy metadata buffer. if (pVector != NULL && pVector->at(BAYER_INPUT) != NULL) { qcamera_hal_pp_data_t *pInputData = pVector->at(BAYER_INPUT); rc = getOutputBuffer(pInputData, pOutputData); // Enqueue output_data to m_outgoingQ if (false == m_outgoingQ.enqueue((void *)pOutputData)) { LOGE("outgoing Q is not active!!!"); releaseData(pOutputData); rc = INVALID_OPERATION; } } } else { LOGE("pOutput is NULL"); rc = UNEXPECTED_NULL; } LOGD("X"); return rc; } /*=========================================================================== * FUNCTION : process * * DESCRIPTION: function to start ClearSight blending process * * PARAMETERS : None * * RETURN : int32_t type of status * NO_ERROR -- success * none-zero failure code *==========================================================================*/ int32_t QCameraClearSight::process() { int32_t rc = NO_ERROR; /* dump in/out frames */ char prop[PROPERTY_VALUE_MAX]; memset(prop, 0, sizeof(prop)); property_get("persist.vendor.camera.dualfov.dumpimg", prop, "0"); int dumpimg = atoi(prop); LOGD("E"); if (!canProcess()) { LOGD("Yet to receive all input/output bufs"); return NO_ERROR; } LOGI("start clearsight process"); // TODO: dequeue from m_inputQ and start process logic // Start the blending process when it is ready while (!m_inputQ.isEmpty()) { uint32_t *pFrameIndex = (uint32_t *)m_inputQ.dequeue(); if (pFrameIndex == NULL) { LOGE("frame index is null"); return UNEXPECTED_NULL; } uint32_t frameIndex = *pFrameIndex; std::vector *pVector = getFrameVector(frameIndex); // Search vector of input frames in frame map if (pVector == NULL) { LOGE("Cannot find vecotr of input frames"); return UNEXPECTED_NULL; } // Get input and output frame buffer qcamera_hal_pp_data_t *pInputMainData = (qcamera_hal_pp_data_t *)pVector->at(BAYER_INPUT); if (pInputMainData == NULL) { LOGE("Cannot find input main data"); return UNEXPECTED_NULL; } if (pInputMainData->src_reproc_frame == NULL) { LOGI("process pInputMainData->src_reproc_frame = NULL"); } //mm_camera_super_buf_t *input_main_frame = input_main_data->frame; qcamera_hal_pp_data_t *pInputAuxData = (qcamera_hal_pp_data_t *)pVector->at(MONO_INPUT); if (pInputAuxData == NULL) { LOGE("Cannot find input aux data"); return UNEXPECTED_NULL; } mm_camera_buf_def_t *main_snapshot_buf = getSnapshotBuf(pInputMainData); if (main_snapshot_buf == NULL) { LOGE("main_snapshot_buf is NULL"); return UNEXPECTED_NULL; } mm_camera_buf_def_t *main_meta_buf = getMetadataBuf(pInputMainData); if (main_meta_buf == NULL) { LOGE("main_meta_buf is NULL"); return UNEXPECTED_NULL; } mm_camera_buf_def_t *aux_snapshot_buf = getSnapshotBuf(pInputAuxData); if (aux_snapshot_buf == NULL) { LOGE("aux_snapshot_buf is NULL"); return UNEXPECTED_NULL; } mm_camera_buf_def_t *aux_meta_buf = getMetadataBuf(pInputAuxData); if (aux_meta_buf == NULL) { LOGE("aux_meta_buf is NULL"); return UNEXPECTED_NULL; } // Use offset info from reproc stream cam_frame_len_offset_t frm_offset = pInputMainData->snap_offset; LOGI("Main stride:%d, scanline:%d, frame len:%d", frm_offset.mp[0].stride, frm_offset.mp[0].scanline, frm_offset.frame_len); if (dumpimg) { dumpYUVtoFile((uint8_t *)main_snapshot_buf->buffer, frm_offset, main_snapshot_buf->frame_idx, "bayer"); dumpYUVtoFile((uint8_t *)aux_snapshot_buf->buffer, frm_offset, aux_snapshot_buf->frame_idx, "mono"); } //Get input and output parameter clearsight_input_params_t inParams; getInputParams(main_meta_buf, aux_meta_buf, pInputMainData->snap_offset, pInputAuxData->snap_offset, inParams); if (main_snapshot_buf->frame_idx == aux_snapshot_buf->frame_idx) inParams.frame_idx = main_snapshot_buf->frame_idx; else { LOGE("something wrong !!!"); } dumpInputParams(inParams); qcamera_hal_pp_data_t *pOutputData = NULL; if (m_inputQ.isEmpty()) { pOutputData = (qcamera_hal_pp_data_t*)m_outgoingQ.dequeue(); if (pOutputData == NULL) { LOGE("Cannot find output data"); return UNEXPECTED_NULL; } mm_camera_super_buf_t *output_frame = pOutputData->frame; mm_camera_buf_def_t *output_snapshot_buf = output_frame->bufs[0]; doClearSightProcess((const uint8_t *)main_snapshot_buf->buffer, (const uint8_t *)aux_snapshot_buf->buffer, inParams, (uint8_t *)output_snapshot_buf->buffer); if (dumpimg) { dumpYUVtoFile((uint8_t *)output_snapshot_buf->buffer, frm_offset, main_snapshot_buf->frame_idx, "out"); } /* clean and invalidate caches, for input and output buffers*/ pOutputData->snapshot_heap->cleanInvalidateCache(0); } QCameraMemory *pMem = (QCameraMemory *)main_snapshot_buf->mem_info; pMem->invalidateCache(main_snapshot_buf->buf_idx); pMem = (QCameraMemory *)aux_snapshot_buf->mem_info; pMem->invalidateCache(aux_snapshot_buf->buf_idx); // Calling cb function to return output_data after processed. if (pOutputData) m_halPPBufNotifyCB(pOutputData, m_pHalPPMgr); // also send input buffer to postproc. m_halPPBufNotifyCB(pInputMainData, m_pHalPPMgr); m_halPPBufNotifyCB(pInputAuxData, m_pHalPPMgr); //releaseData(pInputMainData); //releaseData(pInputAuxData); // Release internal resource m_frameMap.erase(frameIndex); delete pFrameIndex; delete pVector; } LOGD("X"); return rc; } /*=========================================================================== * FUNCTION : canProcess * * DESCRIPTION: function to release internal resources * RETURN : If ClearSight module can start blending process *==========================================================================*/ bool QCameraClearSight::canProcess() { LOGD("E"); bool ready = false; if(!m_inputQ.isEmpty() && !m_outgoingQ.isEmpty()) { ready = true; } LOGD("X: ready = %d", ready); return ready; } /*=========================================================================== * FUNCTION : getInputParams * * DESCRIPTION: Helper function to get input params from input metadata *==========================================================================*/ void QCameraClearSight::getInputParams(__unused mm_camera_buf_def_t *pMainMetaBuf, __unused mm_camera_buf_def_t *pAuxMetaBuf, cam_frame_len_offset_t main_offset, cam_frame_len_offset_t aux_offset, clearsight_input_params_t& inParams) { LOGD("E"); memset(&inParams, 0, sizeof(clearsight_input_params_t)); // bayer frame size inParams.bayer.width = main_offset.mp[0].width; inParams.bayer.height = main_offset.mp[0].height; inParams.bayer.stride = main_offset.mp[0].stride; inParams.bayer.scanline = main_offset.mp[0].scanline; inParams.bayer.frame_len = main_offset.frame_len; // mono frame size inParams.mono.width = aux_offset.mp[0].width; inParams.mono.height = aux_offset.mp[0].height; inParams.mono.stride = aux_offset.mp[0].stride; inParams.mono.scanline = aux_offset.mp[0].scanline; inParams.mono.frame_len = aux_offset.frame_len; LOGD("X"); } /*=========================================================================== * FUNCTION : doClearSightInit * * DESCRIPTION: function to do required initialization for clearsight processing. * RETURN : int32_t type of status * NO_ERROR -- success * non-zero -- failure code *==========================================================================*/ int32_t QCameraClearSight::doClearSightInit() { LOGD("E"); int rc = NO_ERROR; LOGD("X"); return rc; } /*=========================================================================== * FUNCTION : doClearSightProcess * * DESCRIPTION: clearsight processing routine * RETURN : int32_t type of status * NO_ERROR -- success * non-zero -- failure code *==========================================================================*/ int32_t QCameraClearSight::doClearSightProcess(const uint8_t* pBayer, const uint8_t* pMono, clearsight_input_params_t inParams, uint8_t* pOut) { LOGD("E"); // trace begin // half image from bayer, and half image from mono // Y memcpy(pOut, pBayer, inParams.bayer.stride * inParams.bayer.scanline / 2); memcpy(pOut + inParams.bayer.stride * inParams.bayer.scanline / 2, pMono + inParams.bayer.stride * inParams.bayer.scanline / 2, inParams.bayer.stride * inParams.bayer.scanline / 2); // UV uint32_t uv_offset = inParams.bayer.stride * inParams.bayer.scanline; memcpy(pOut + uv_offset, pBayer + uv_offset, inParams.bayer.stride * (inParams.bayer.scanline / 2) / 2); memcpy(pOut + uv_offset + inParams.bayer.stride * (inParams.bayer.scanline / 2) / 2, pMono + uv_offset + inParams.bayer.stride * (inParams.bayer.scanline / 2) / 2, inParams.bayer.stride * (inParams.bayer.scanline / 2) / 2); // trace end LOGW("X."); return NO_ERROR; } /*=========================================================================== * FUNCTION : dumpYUVtoFile * * DESCRIPTION: dumps yuv for debug purpose * RETURN : None *==========================================================================*/ void QCameraClearSight::dumpYUVtoFile(const uint8_t* pBuf, cam_frame_len_offset_t offset, uint32_t idx, const char* name_prefix) { LOGD("E."); char filename[256]; snprintf(filename, sizeof(filename), QCAMERA_DUMP_FRM_LOCATION"%s_%dx%d_%d.yuv", name_prefix, offset.mp[0].stride, offset.mp[0].scanline, idx); QCameraHALPP::dumpYUVtoFile(pBuf,(const char*)filename, offset.frame_len); LOGD("X."); } /*=========================================================================== * FUNCTION : dumpInputParams * * DESCRIPTION: dumps input params for debug purpose * RETURN : None *==========================================================================*/ void QCameraClearSight::dumpInputParams(const clearsight_input_params_t& p) { LOGD("E : frame idx %d", p.frame_idx); const cam_frame_size_t* s = NULL; s = &p.bayer; LOGD("bayer frame size: %d, %d, stride:%d, scanline:%d", s->width, s->height, s->stride, s->scanline); s = &p.mono; LOGD("bayer frame size: %d, %d, stride:%d, scanline:%d", s->width, s->height, s->stride, s->scanline); LOGD("X"); } } // namespace qcamera