1/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
2 *
3 * Redistribution and use in source and binary forms, with or without
4 * modification, are permitted provided that the following conditions are
5 * met:
6 *     * Redistributions of source code must retain the above copyright
7 *       notice, this list of conditions and the following disclaimer.
8 *     * Redistributions in binary form must reproduce the above
9 *       copyright notice, this list of conditions and the following
10 *       disclaimer in the documentation and/or other materials provided
11 *       with the distribution.
12 *     * Neither the name of The Linux Foundation nor the names of its
13 *       contributors may be used to endorse or promote products derived
14 *       from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
19 * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
23 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
25 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
26 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 */
29
30#define LOG_TAG "DualFOVPP"
31// System dependencies
32#include <dlfcn.h>
33#include <utils/Errors.h>
34#include <stdio.h>
35#include <stdlib.h>
36// Camera dependencies
37#include "QCameraDualFOVPP.h"
38#include "QCameraTrace.h"
39#include "cam_intf.h"
40extern "C" {
41#include "mm_camera_dbg.h"
42}
43
44#define LIB_PATH_LENGTH 100
45
46namespace qcamera {
47
48/*===========================================================================
49 * FUNCTION   : QCameraDualFOVPP
50 *
51 * DESCRIPTION: constructor of QCameraDualFOVPP.
52 *
53 * PARAMETERS : None
54 *
55 * RETURN     : None
56 *==========================================================================*/
57QCameraDualFOVPP::QCameraDualFOVPP()
58    : QCameraHALPP()
59{
60    m_dlHandle = NULL;
61    m_pCaps = NULL;
62}
63
64/*===========================================================================
65 * FUNCTION   : ~QCameraDualFOVPP
66 *
67 * DESCRIPTION: destructor of QCameraDualFOVPP.
68 *
69 * PARAMETERS : None
70 *
71 * RETURN     : None
72 *==========================================================================*/
73QCameraDualFOVPP::~QCameraDualFOVPP()
74{
75}
76
77/*===========================================================================
78 * FUNCTION   : init
79 *
80 * DESCRIPTION: initialization of QCameraDualFOVPP
81 *
82 * PARAMETERS :
83 *   @bufNotifyCb      : call back function after HALPP process
84 *   @getOutputCb      : call back function to request output buffe
85 *   @pUserData        : Parent of HALPP, i.e. QCameraPostProc
86 *   @pStaticParam     : holds dual camera calibration data in an array and its size
87 *                       (expected size is 264 bytes)
88 *
89 * RETURN     : int32_t type of status
90 *              NO_ERROR  -- success
91 *              none-zero failure code
92 *==========================================================================*/
93int32_t QCameraDualFOVPP::init(halPPBufNotify bufNotifyCb, halPPGetOutput getOutputCb,
94        void *pUserData, void *pStaticParam)
95{
96    LOGD("E");
97    int32_t rc = NO_ERROR;
98    QCameraHALPP::init(bufNotifyCb, getOutputCb, pUserData);
99
100    m_pCaps = (cam_capability_t *)pStaticParam;
101
102    /* we should load 3rd libs here, with dlopen/dlsym */
103    doDualFovPPInit();
104
105    LOGD("X");
106    return rc;
107}
108
109/*===========================================================================
110 * FUNCTION   : deinit
111 *
112 * DESCRIPTION: de initialization of QCameraDualFOVPP
113 *
114 * PARAMETERS : None
115 *
116 * RETURN     : int32_t type of status
117 *              NO_ERROR  -- success
118 *              none-zero failure code
119 *==========================================================================*/
120int32_t QCameraDualFOVPP::deinit()
121{
122    int32_t rc = NO_ERROR;
123    LOGD("E");
124
125    m_dlHandle = NULL;
126
127    QCameraHALPP::deinit();
128    LOGD("X");
129    return rc;
130}
131
132/*===========================================================================
133 * FUNCTION   : start
134 *
135 * DESCRIPTION: starting QCameraDualFOVPP
136 *
137 * PARAMETERS :
138 *
139 * RETURN     : int32_t type of status
140 *              NO_ERROR  -- success
141 *              none-zero failure code
142 *==========================================================================*/
143int32_t QCameraDualFOVPP::start()
144{
145    int32_t rc = NO_ERROR;
146    LOGD("E");
147
148    rc = QCameraHALPP::start();
149
150    LOGD("X");
151    return rc;
152}
153
154
155/*===========================================================================
156 * FUNCTION   : feedInput
157 *
158 * DESCRIPTION: function to feed input data.
159 *              Enqueue the frame index to inputQ if it is new frame
160 *              Also, add the input image data to frame hash map
161 *
162 * PARAMETERS :
163 *   @pInput  : ptr to input data
164 *
165 * RETURN     : int32_t type of status
166 *              NO_ERROR  -- success
167 *              none-zero failure code
168 *==========================================================================*/
169int32_t QCameraDualFOVPP::feedInput(qcamera_hal_pp_data_t *pInputData)
170{
171    int32_t rc = NO_ERROR;
172    LOGD("E");
173    if (NULL != pInputData) {
174        QCameraStream* pSnapshotStream = NULL;
175        mm_camera_buf_def_t *pInputSnapshotBuf = getSnapshotBuf(pInputData, pSnapshotStream);
176        if (pInputSnapshotBuf != NULL) {
177            uint32_t frameIndex = pInputSnapshotBuf->frame_idx;
178            std::vector<qcamera_hal_pp_data_t*> *pVector = getFrameVector(frameIndex);
179            if(pVector == NULL) {
180                LOGD("insert new frame index = %d", frameIndex);
181                uint32_t *pFrameIndex = new uint32_t;
182                *pFrameIndex = frameIndex;
183                // new the vector first
184                pVector = new std::vector<qcamera_hal_pp_data_t*>(WIDE_TELE_CAMERA_NUMBER);
185                pVector->at(WIDE_INPUT) = NULL;
186                pVector->at(TELE_INPUT) = NULL;
187                // Add vector to the hash map
188                m_frameMap[frameIndex] = pVector;
189                // Enqueue the frame index (i.e. key of vector) to queue
190                if (false == m_iuputQ.enqueue((void*)pFrameIndex)) {
191                    LOGE("Input Q is not active!!!");
192                    releaseData(pInputData);
193                    m_frameMap.erase(frameIndex);
194                    delete pFrameIndex;
195                    delete pVector;
196                    rc = INVALID_OPERATION;
197                    return rc;
198                }
199            }
200            pInputData->frameIndex = frameIndex;
201            // Check if frame is from main wide camera
202            bool bIsMain = true;
203            uint32_t mainHandle = get_main_camera_handle(
204                    pInputData->src_reproc_frame->camera_handle);
205            if (mainHandle == 0) {
206                bIsMain = false;
207            }
208            LOGD("mainHandle = %d, is main frame = %d", mainHandle, bIsMain);
209            // Add input data to vector
210            if (bIsMain) {
211                pVector->at(WIDE_INPUT) = pInputData;
212            } else {
213                pVector->at(TELE_INPUT) = pInputData;
214            }
215
216            // request output buffer only if both wide and tele input data are recieved
217            if (pVector->at(0) != NULL && pVector->at(1) != NULL) {
218                m_halPPGetOutputCB(frameIndex, m_pQCameraPostProc);
219            }
220        }
221    } else {
222        LOGE("pInput is NULL");
223        rc = UNEXPECTED_NULL;
224    }
225    LOGD("X");
226    return rc;
227}
228
229/*===========================================================================
230 * FUNCTION   : feedOutput
231 *
232 * DESCRIPTION: function to feed output buffer and metadata
233 *
234 * PARAMETERS :
235 *   @pOutput     : ptr to output data
236 *
237 * RETURN     : int32_t type of status
238 *              NO_ERROR  -- success
239 *              none-zero failure code
240 *==========================================================================*/
241int32_t QCameraDualFOVPP::feedOutput(qcamera_hal_pp_data_t *pOutputData)
242{
243    int32_t rc = NO_ERROR;
244    LOGD("E");
245    if (NULL != pOutputData) {
246        uint32_t frameIndex = pOutputData->frameIndex;
247        std::vector<qcamera_hal_pp_data_t*> *pVector = getFrameVector(frameIndex);
248        // Get the main (Wide) input frame in order to get output buffer len,
249        // and copy metadata buffer.
250        if (pVector != NULL && pVector->at(WIDE_INPUT) != NULL) {
251            qcamera_hal_pp_data_t *pInputData = pVector->at(WIDE_INPUT);
252            mm_camera_super_buf_t *pInputFrame = pInputData->frame;
253            QCameraStream* pSnapshotStream = NULL;
254            QCameraStream* pMetadataStream = NULL;
255            mm_camera_buf_def_t *pInputSnapshotBuf = getSnapshotBuf(pInputData, pSnapshotStream);
256            mm_camera_buf_def_t *pInputMetadataBuf = getMetadataBuf(pInputData, pMetadataStream);
257            mm_camera_super_buf_t *pOutputFrame = pOutputData->frame;
258            mm_camera_buf_def_t *pOutputBufDefs = pOutputData->bufs;
259
260            if (pInputSnapshotBuf == NULL || pInputMetadataBuf == NULL) {
261                LOGE("cannot get sanpshot or metadata buf def");
262                releaseData(pOutputData);
263                return UNEXPECTED_NULL;
264            }
265            if (pSnapshotStream == NULL || pMetadataStream == NULL) {
266                LOGE("cannot get sanpshot or metadata stream");
267                releaseData(pOutputData);
268                return UNEXPECTED_NULL;
269            }
270
271            // Copy main input frame info to output frame
272            pOutputFrame->camera_handle = pInputFrame->camera_handle;
273            pOutputFrame->ch_id = pInputFrame->ch_id;
274            pOutputFrame->num_bufs = HAL_PP_NUM_BUFS;//snapshot and metadata
275            pOutputFrame->bUnlockAEC = pInputFrame->bUnlockAEC;
276            pOutputFrame->bReadyForPrepareSnapshot = pInputFrame->bReadyForPrepareSnapshot;
277
278            // Reconstruction of output_frame super buffer
279            pOutputFrame->bufs[0] = &pOutputBufDefs[0];
280            pOutputFrame->bufs[1] = &pOutputBufDefs[1];
281
282            // Allocate heap buffer for output image frame
283            cam_frame_len_offset_t offset;
284            memset(&offset, 0, sizeof(cam_frame_len_offset_t));
285            LOGD("pInputSnapshotBuf->frame_len = %d", pInputSnapshotBuf->frame_len);
286            rc = pOutputData->snapshot_heap->allocate(1, pInputSnapshotBuf->frame_len);
287            if (rc < 0) {
288                LOGE("Unable to allocate heap memory for image buf");
289                releaseData(pOutputData);
290                return NO_MEMORY;
291            }
292            pSnapshotStream->getFrameOffset(offset);
293            memcpy(&pOutputBufDefs[0], pInputSnapshotBuf, sizeof(mm_camera_buf_def_t));
294            LOGD("pOutputFrame->bufs[0]->fd = %d, pOutputFrame->bufs[0]->buffer = %x",
295                    pOutputFrame->bufs[0]->fd, pOutputFrame->bufs[0]->buffer);
296            pOutputData->snapshot_heap->getBufDef(offset, pOutputBufDefs[0], 0);
297            LOGD("pOutputFrame->bufs[0]->fd = %d, pOutputFrame->bufs[0]->buffer = %x",
298                    pOutputFrame->bufs[0]->fd, pOutputFrame->bufs[0]->buffer);
299
300            // Allocate heap buffer for output metadata
301            LOGD("pInputMetadataBuf->frame_len = %d", pInputMetadataBuf->frame_len);
302            rc = pOutputData->metadata_heap->allocate(1, pInputMetadataBuf->frame_len);
303            if (rc < 0) {
304                LOGE("Unable to allocate heap memory for metadata buf");
305                releaseData(pOutputData);
306                return NO_MEMORY;
307            }
308            memset(&offset, 0, sizeof(cam_frame_len_offset_t));
309            pMetadataStream->getFrameOffset(offset);
310            memcpy(&pOutputBufDefs[1], pInputMetadataBuf, sizeof(mm_camera_buf_def_t));
311            pOutputData->metadata_heap->getBufDef(offset, pOutputBufDefs[1], 0);
312            // copy the whole metadata
313            memcpy(pOutputBufDefs[1].buffer, pInputMetadataBuf->buffer,
314                    pInputMetadataBuf->frame_len);
315
316            // Enqueue output_data to m_outgoingQ
317            if (false == m_outgoingQ.enqueue((void *)pOutputData)) {
318                LOGE("outgoing Q is not active!!!");
319                releaseData(pOutputData);
320                rc = INVALID_OPERATION;
321            }
322        }
323    } else {
324        LOGE("pOutput is NULL");
325        rc = UNEXPECTED_NULL;
326    }
327    LOGD("X");
328    return rc;
329}
330
331/*===========================================================================
332 * FUNCTION   : process
333 *
334 * DESCRIPTION: function to start CP FOV blending process
335 *
336 * PARAMETERS : None
337 *
338 * RETURN     : int32_t type of status
339 *              NO_ERROR  -- success
340 *              none-zero failure code
341 *==========================================================================*/
342int32_t QCameraDualFOVPP::process()
343{
344    int32_t rc = NO_ERROR;
345
346    /* dump in/out frames */
347    char prop[PROPERTY_VALUE_MAX];
348    memset(prop, 0, sizeof(prop));
349    property_get("persist.camera.dualfov.dumpimg", prop, "0");
350    int dumpimg = atoi(prop);
351
352    LOGD("E");
353
354    // TODO: dequeue from m_inputQ and start process logic
355    // Start the blending process when it is ready
356    if (canProcess()) {
357        LOGI("start Dual FOV process");
358        uint32_t *pFrameIndex = (uint32_t *)m_iuputQ.dequeue();
359        if (pFrameIndex == NULL) {
360            LOGE("frame index is null");
361            return UNEXPECTED_NULL;
362        }
363        uint32_t frameIndex = *pFrameIndex;
364        std::vector<qcamera_hal_pp_data_t*> *pVector = getFrameVector(frameIndex);
365        // Search vector of input frames in frame map
366        if (pVector == NULL) {
367            LOGE("Cannot find vecotr of input frames");
368            return UNEXPECTED_NULL;
369        }
370        // Get input and output frame buffer
371        qcamera_hal_pp_data_t *pInputMainData =
372                (qcamera_hal_pp_data_t *)pVector->at(WIDE_INPUT);
373        if (pInputMainData == NULL) {
374            LOGE("Cannot find input main data");
375            return UNEXPECTED_NULL;
376        }
377        if (pInputMainData->src_reproc_frame == NULL) {
378            LOGI("process pInputMainData->src_reproc_frame = NULL");
379        }
380        //mm_camera_super_buf_t *input_main_frame = input_main_data->frame;
381        qcamera_hal_pp_data_t *pInputAuxData =
382                (qcamera_hal_pp_data_t *)pVector->at(TELE_INPUT);
383        if (pInputAuxData == NULL) {
384            LOGE("Cannot find input aux data");
385            return UNEXPECTED_NULL;
386        }
387
388        //mm_camera_super_buf_t *input_aux_frame = input_aux_data->frame;
389        qcamera_hal_pp_data_t *pOutputData =
390                (qcamera_hal_pp_data_t*)m_outgoingQ.dequeue();
391        if (pOutputData == NULL) {
392            LOGE("Cannot find output data");
393            return UNEXPECTED_NULL;
394        }
395
396        QCameraStream* pMainSnapshotStream = NULL;
397        QCameraStream* pMainMetadataStream = NULL;
398        QCameraStream* pAuxSnapshotStream  = NULL;
399        QCameraStream* pAuxMetadataStream  = NULL;
400
401        mm_camera_buf_def_t *main_snapshot_buf =
402                getSnapshotBuf(pInputMainData, pMainSnapshotStream);
403        if (main_snapshot_buf == NULL) {
404            LOGE("main_snapshot_buf is NULL");
405            return UNEXPECTED_NULL;
406        }
407        mm_camera_buf_def_t *main_meta_buf = getMetadataBuf(pInputMainData, pMainMetadataStream);
408        if (main_meta_buf == NULL) {
409            LOGE("main_meta_buf is NULL");
410            return UNEXPECTED_NULL;
411        }
412        mm_camera_buf_def_t *aux_snapshot_buf = getSnapshotBuf(pInputAuxData, pAuxSnapshotStream);
413        if (aux_snapshot_buf == NULL) {
414            LOGE("aux_snapshot_buf is NULL");
415            return UNEXPECTED_NULL;
416        }
417        mm_camera_buf_def_t *aux_meta_buf = getMetadataBuf(pInputAuxData, pAuxMetadataStream);
418        if (aux_meta_buf == NULL) {
419            LOGE("aux_meta_buf is NULL");
420            return UNEXPECTED_NULL;
421        }
422
423        mm_camera_super_buf_t *output_frame = pOutputData->frame;
424        mm_camera_buf_def_t *output_snapshot_buf = output_frame->bufs[0];
425
426        // Use offset info from reproc stream
427        if (pMainSnapshotStream == NULL) {
428            LOGE("pMainSnapshotStream is NULL");
429            return UNEXPECTED_NULL;
430        }
431        cam_frame_len_offset_t frm_offset;
432        pMainSnapshotStream->getFrameOffset(frm_offset);
433        LOGI("Stream type:%d, stride:%d, scanline:%d, frame len:%d",
434                pMainSnapshotStream->getMyType(),
435                frm_offset.mp[0].stride, frm_offset.mp[0].scanline,
436                frm_offset.frame_len);
437
438        if (dumpimg) {
439            dumpYUVtoFile((uint8_t *)main_snapshot_buf->buffer, frm_offset,
440                    main_snapshot_buf->frame_idx, "wide");
441            dumpYUVtoFile((uint8_t *)aux_snapshot_buf->buffer,  frm_offset,
442                    aux_snapshot_buf->frame_idx,  "tele");
443        }
444
445        //Get input and output parameter
446        dualfov_input_params_t inParams;
447        if (pAuxSnapshotStream == NULL) {
448            LOGE("pAuxSnapshotStream is NULL");
449            return UNEXPECTED_NULL;
450        }
451        getInputParams(main_meta_buf, aux_meta_buf, pMainSnapshotStream, pAuxSnapshotStream,
452                inParams);
453        dumpInputParams(inParams);
454
455        doDualFovPPProcess((const uint8_t *)main_snapshot_buf->buffer,
456                        (const uint8_t *)aux_snapshot_buf->buffer,
457                        inParams,
458                        (uint8_t *)output_snapshot_buf->buffer);
459
460        if (dumpimg) {
461            dumpYUVtoFile((uint8_t *)output_snapshot_buf->buffer, frm_offset,
462                    main_snapshot_buf->frame_idx, "out");
463        }
464
465        /* clean and invalidate caches, for input and output buffers*/
466        pOutputData->snapshot_heap->cleanInvalidateCache(0);
467
468        QCameraMemory *pMem = (QCameraMemory *)main_snapshot_buf->mem_info;
469        pMem->invalidateCache(main_snapshot_buf->buf_idx);
470
471        pMem = (QCameraMemory *)aux_snapshot_buf->mem_info;
472        pMem->invalidateCache(aux_snapshot_buf->buf_idx);
473
474
475        // Calling cb function to return output_data after processed.
476        m_halPPBufNotifyCB(pOutputData, m_pQCameraPostProc);
477
478        // also send input buffer to postproc.
479        m_halPPBufNotifyCB(pInputMainData, m_pQCameraPostProc);
480        m_halPPBufNotifyCB(pInputAuxData, m_pQCameraPostProc);
481        //releaseData(pInputMainData);
482        //releaseData(pInputAuxData);
483
484        // Release internal resource
485        m_frameMap.erase(frameIndex);
486        delete pFrameIndex;
487        delete pVector;
488    }
489    LOGD("X");
490    return rc;
491}
492
493/*===========================================================================
494 * FUNCTION   : getSnapshotBuf
495 *
496 * DESCRIPTION: function to get snapshot buf def and the stream from frame
497 * PARAMETERS :
498 *   @pData           : input frame super buffer
499 *   @pSnapshotStream : stream of snapshot that found
500 * RETURN             : snapshot buf def
501 *==========================================================================*/
502mm_camera_buf_def_t* QCameraDualFOVPP::getSnapshotBuf(qcamera_hal_pp_data_t* pData,
503        QCameraStream* &pSnapshotStream)
504{
505    mm_camera_buf_def_t *pBufDef = NULL;
506    if (pData == NULL) {
507        LOGE("Cannot find input frame super buffer");
508        return pBufDef;
509    }
510    mm_camera_super_buf_t *pFrame = pData->frame;
511    QCameraChannel *pChannel = m_pQCameraPostProc->getChannelByHandle(pFrame->ch_id);
512    if (pChannel == NULL) {
513        LOGE("Cannot find channel");
514        return pBufDef;
515    }
516    // Search for input snapshot frame buf
517    for (uint32_t i = 0; i < pFrame->num_bufs; i++) {
518        pSnapshotStream = pChannel->getStreamByHandle(pFrame->bufs[i]->stream_id);
519        if (pSnapshotStream != NULL) {
520            if (pSnapshotStream->isTypeOf(CAM_STREAM_TYPE_SNAPSHOT) ||
521                pSnapshotStream->isOrignalTypeOf(CAM_STREAM_TYPE_SNAPSHOT)) {
522                    pBufDef = pFrame->bufs[i];
523                    break;
524            }
525        }
526    }
527    return pBufDef;
528}
529
530/*===========================================================================
531 * FUNCTION   : getMetadataBuf
532 *
533 * DESCRIPTION: function to get metadata buf def and the stream from frame
534 * PARAMETERS :
535 *   @pData     : input frame super buffer
536 *   @pMetadataStream : stream of metadata that found
537 * RETURN     : metadata buf def
538 *==========================================================================*/
539mm_camera_buf_def_t* QCameraDualFOVPP::getMetadataBuf(qcamera_hal_pp_data_t *pData,
540        QCameraStream* &pMetadataStream)
541{
542    mm_camera_buf_def_t *pBufDef = NULL;
543    if (pData == NULL) {
544        LOGE("Cannot find input frame super buffer");
545        return pBufDef;
546    }
547    mm_camera_super_buf_t* pFrame = pData->frame;
548    QCameraChannel *pChannel =
549            m_pQCameraPostProc->getChannelByHandle(pData->src_reproc_frame->ch_id);
550    LOGD("src_reproc_frame num_bufs = %d", pFrame->num_bufs);
551    if (pChannel == NULL) {
552            LOGE("Cannot find src_reproc_frame channel");
553            return pBufDef;
554    }
555    for (uint32_t i = 0;
556            (i < pData->src_reproc_frame->num_bufs); i++) {
557        pMetadataStream = pChannel->getStreamByHandle(pData->src_reproc_frame->bufs[i]->stream_id);
558        if (pData->src_reproc_frame->bufs[i]->stream_type == CAM_STREAM_TYPE_METADATA) {
559            pBufDef = pData->src_reproc_frame->bufs[i];
560            LOGD("find metadata stream and buf from src_reproc_frame");
561            break;
562        }
563    }
564    if (pBufDef == NULL) {
565        LOGD("frame num_bufs = %d", pFrame->num_bufs);
566        pChannel = m_pQCameraPostProc->getChannelByHandle(pFrame->ch_id);
567        if (pChannel == NULL) {
568            LOGE("Cannot find frame channel");
569            return pBufDef;
570        }
571        for (uint32_t i = 0; i < pFrame->num_bufs; i++) {
572            pMetadataStream = pChannel->getStreamByHandle(pFrame->bufs[i]->stream_id);
573            if (pMetadataStream != NULL) {
574                LOGD("bufs[%d] stream_type = %d", i, pFrame->bufs[i]->stream_type);
575                if (pFrame->bufs[i]->stream_type == CAM_STREAM_TYPE_METADATA) {
576                    pBufDef = pFrame->bufs[i];
577                    break;
578                }
579            }
580        }
581    }
582    return pBufDef;
583}
584
585/*===========================================================================
586 * FUNCTION   : canProcess
587 *
588 * DESCRIPTION: function to release internal resources
589 * RETURN     : If CP FOV can start blending process
590 *==========================================================================*/
591bool QCameraDualFOVPP::canProcess()
592{
593    LOGD("E");
594    bool ready = false;
595    if(!m_iuputQ.isEmpty() && !m_outgoingQ.isEmpty()) {
596        ready = true;
597    }
598    LOGD("X");
599    return ready;
600}
601
602/*===========================================================================
603 * FUNCTION   : getInputParams
604 *
605 * DESCRIPTION: Helper function to get input params from input metadata
606 *==========================================================================*/
607void QCameraDualFOVPP::getInputParams(mm_camera_buf_def_t *pMainMetaBuf,
608        mm_camera_buf_def_t *pAuxMetaBuf, QCameraStream* pMainSnapshotStream,
609        QCameraStream* pAuxSnapshotStream, dualfov_input_params_t& inParams)
610{
611    LOGD("E");
612    memset(&inParams, 0, sizeof(dualfov_input_params_t));
613    metadata_buffer_t *pMainMeta = (metadata_buffer_t *)pMainMetaBuf->buffer;
614    metadata_buffer_t *pAuxMeta = (metadata_buffer_t *)pAuxMetaBuf->buffer;
615
616    // Wide frame size
617    cam_frame_len_offset_t offset;
618    pMainSnapshotStream->getFrameOffset(offset);
619    inParams.wide.width     = offset.mp[0].width;
620    inParams.wide.height    = offset.mp[0].height;
621    inParams.wide.stride    = offset.mp[0].stride;
622    inParams.wide.scanline  = offset.mp[0].scanline;
623    inParams.wide.frame_len = offset.frame_len;
624
625    // Tele frame size
626    pAuxSnapshotStream->getFrameOffset(offset);
627    inParams.tele.width     = offset.mp[0].width;
628    inParams.tele.height    = offset.mp[0].height;
629    inParams.tele.stride    = offset.mp[0].stride;
630    inParams.tele.scanline  = offset.mp[0].scanline;
631    inParams.tele.frame_len = offset.frame_len;
632
633    // user_zoom
634    int32_t zoom_level = -1; // 0 means zoom 1x.
635    IF_META_AVAILABLE(int32_t, userZoom, CAM_INTF_PARM_ZOOM, pMainMeta) {
636        zoom_level = *userZoom;
637        LOGD("zoom level in main meta:%d", zoom_level);
638    }
639    inParams.user_zoom= getUserZoomRatio(zoom_level);
640    LOGI("dual fov total zoom ratio: %d", inParams.user_zoom);
641
642    IF_META_AVAILABLE(int32_t, auxUserZoom, CAM_INTF_PARM_ZOOM, pAuxMeta) {
643        LOGD("zoom level in aux meta:%d", *auxUserZoom);
644    }
645
646    IF_META_AVAILABLE(uint32_t, afState, CAM_INTF_META_AF_STATE, pMainMeta) {
647        if (((*afState) == CAM_AF_STATE_FOCUSED_LOCKED) ||
648            ((*afState) == CAM_AF_STATE_PASSIVE_FOCUSED)) {
649            inParams.af_status = AF_STATUS_VALID;
650        } else {
651            inParams.af_status = AF_STATUS_INVALID;
652        }
653        LOGD("af state:%d, output af status:%d", *afState, inParams.af_status);
654    }
655
656    IF_META_AVAILABLE(uint32_t, auxAfState, CAM_INTF_META_AF_STATE, pAuxMeta) {
657        int aux_af_status = 0;
658        if (((*auxAfState) == CAM_AF_STATE_FOCUSED_LOCKED) ||
659            ((*auxAfState) == CAM_AF_STATE_PASSIVE_FOCUSED)) {
660            aux_af_status = AF_STATUS_VALID;
661        } else {
662            aux_af_status = AF_STATUS_INVALID;
663        }
664        LOGD("aux af state:%d, output af status:%d", *auxAfState, aux_af_status);
665    }
666
667
668    LOGD("X");
669}
670
671
672int32_t QCameraDualFOVPP::doDualFovPPInit()
673{
674    LOGD("E");
675    int rc = NO_ERROR;
676
677    LOGD("X");
678    return rc;
679}
680
681int32_t QCameraDualFOVPP::doDualFovPPProcess(const uint8_t* pWide, const uint8_t* pTele,
682                                                    dualfov_input_params_t inParams,
683                                                    uint8_t* pOut)
684{
685    LOGW("E.");
686
687    // trace begin
688
689    // half image from main, and half image from tele
690
691    // Y
692    memcpy(pOut, pWide, inParams.wide.stride * inParams.wide.scanline / 2);
693    memcpy(pOut  + inParams.wide.stride * inParams.wide.scanline / 2,
694           pTele + inParams.wide.stride * inParams.wide.scanline / 2,
695           inParams.wide.stride * inParams.wide.scanline / 2);
696
697    // UV
698    uint32_t uv_offset = inParams.wide.stride * inParams.wide.scanline;
699    memcpy(pOut  + uv_offset,
700           pWide + uv_offset,
701           inParams.wide.stride * (inParams.wide.scanline / 2) / 2);
702    memcpy(pOut  + uv_offset + inParams.wide.stride * (inParams.wide.scanline / 2) / 2,
703           pTele + uv_offset + inParams.wide.stride * (inParams.wide.scanline / 2) / 2,
704           inParams.wide.stride * (inParams.wide.scanline / 2) / 2);
705
706    // trace end
707
708    LOGW("X.");
709    return NO_ERROR;
710}
711
712uint32_t QCameraDualFOVPP::getUserZoomRatio(int32_t zoom_level)
713{
714    uint32_t zoom_ratio = 4096;
715
716    LOGD("E. input zoom level:%d", zoom_level);
717
718    if (zoom_level < 0) {
719        LOGW("invalid zoom evel!");
720        /* got the zoom value from QCamera2HWI Parameters */
721        zoom_level = 0;
722    }
723
724    // user_zoom_ratio = qcom_zoom_ratio * 4096 / 100
725    if (m_pCaps != NULL) {
726        zoom_ratio *= m_pCaps->zoom_ratio_tbl[zoom_level];
727        zoom_ratio /= 100;
728        LOGD("converted zoom ratio:%d", zoom_ratio);
729    }
730
731    LOGD("X. zoom_ratio:%d", zoom_ratio);
732    return zoom_ratio;
733}
734
735void QCameraDualFOVPP::dumpYUVtoFile(const uint8_t* pBuf, cam_frame_len_offset_t offset, uint32_t idx, const char* name_prefix)
736{
737    LOGD("E.");
738    char filename[256];
739
740    snprintf(filename, sizeof(filename), QCAMERA_DUMP_FRM_LOCATION"%s_%dx%d_%d.yuv",
741                name_prefix, offset.mp[0].stride, offset.mp[0].scanline, idx);
742
743    QCameraHALPP::dumpYUVtoFile(pBuf,(const char*)filename, offset.frame_len);
744
745    LOGD("X.");
746}
747
748void QCameraDualFOVPP::dumpInputParams(const dualfov_input_params_t& p)
749{
750    LOGD("E");
751
752    const cam_frame_size_t* s = NULL;
753
754    s = &p.wide;
755    LOGD("wide frame size: %d, %d, stride:%d, scanline:%d",
756            s->width, s->height, s->stride, s->scanline);
757
758    s = &p.tele;
759    LOGD("wide frame size: %d, %d, stride:%d, scanline:%d",
760            s->width, s->height, s->stride, s->scanline);
761
762    LOGD("zoom ratio: %f", p.user_zoom / 4096.0);
763    LOGD("X");
764}
765
766
767/*===========================================================================
768 * FUNCTION   : dumpOISData
769 *
770 * DESCRIPTION: Read Sensor OIS data from metadata and dump it
771 *
772 * PARAMETERS :
773 * @pMetadata : Frame metadata
774 *
775 * RETURN     : None
776 *
777 *==========================================================================*/
778void QCameraDualFOVPP::dumpOISData(metadata_buffer_t*  pMetadata)
779{
780    if (!pMetadata) {
781        LOGD("OIS data not available");
782        return;
783    }
784
785    IF_META_AVAILABLE(cam_ois_data_t, pOisData, CAM_INTF_META_OIS_READ_DATA, pMetadata) {
786        LOGD("Ois Data: data size: %d", pOisData->size);
787        uint8_t *data = pOisData->data;
788        if (pOisData->size == 8) {
789            LOGD("Ois Data Buffer : %d %d %d %d %d %d %d %d ",
790                    data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7]);
791        }
792    }
793    return;
794}
795
796
797} // namespace qcamera
798