QCamera3PostProc.cpp revision 221ef4d6a8613c5ffa33b5a7a8c36a4acb8605ae
1/* Copyright (c) 2012-2013, The Linux Foundataion. 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 "QCamera3PostProc"
31
32#include <stdlib.h>
33#include <utils/Errors.h>
34
35#include "QCamera3PostProc.h"
36#include "QCamera3HWI.h"
37#include "QCamera3Channel.h"
38#include "QCamera3Stream.h"
39
40namespace qcamera {
41
42/*===========================================================================
43 * FUNCTION   : QCamera3PostProcessor
44 *
45 * DESCRIPTION: constructor of QCamera3PostProcessor.
46 *
47 * PARAMETERS :
48 *   @cam_ctrl : ptr to HWI object
49 *
50 * RETURN     : None
51 *==========================================================================*/
52QCamera3PostProcessor::QCamera3PostProcessor(QCamera3PicChannel* ch_ctrl)
53    : m_parent(ch_ctrl),
54      mJpegCB(NULL),
55      mJpegUserData(NULL),
56      mJpegClientHandle(0),
57      mJpegSessionId(0),
58      m_pJpegExifObj(NULL),
59      m_bThumbnailNeeded(TRUE),
60      m_inputPPQ(releasePPInputData, this),
61      m_ongoingPPQ(releaseOngoingPPData, this),
62      m_inputJpegQ(releaseJpegData, this),
63      m_ongoingJpegQ(releaseJpegData, this),
64      m_inputRawQ(releasePPInputData, this)
65{
66    memset(&mJpegHandle, 0, sizeof(mJpegHandle));
67}
68
69/*===========================================================================
70 * FUNCTION   : ~QCamera3PostProcessor
71 *
72 * DESCRIPTION: deconstructor of QCamera3PostProcessor.
73 *
74 * PARAMETERS : None
75 *
76 * RETURN     : None
77 *==========================================================================*/
78QCamera3PostProcessor::~QCamera3PostProcessor()
79{
80    if (m_pJpegExifObj != NULL) {
81        delete m_pJpegExifObj;
82        m_pJpegExifObj = NULL;
83    }
84}
85
86/*===========================================================================
87 * FUNCTION   : init
88 *
89 * DESCRIPTION: initialization of postprocessor
90 *
91 * PARAMETERS :
92 *   @jpeg_cb      : callback to handle jpeg event from mm-camera-interface
93 *   @user_data    : user data ptr for jpeg callback
94 *
95 * RETURN     : int32_t type of status
96 *              NO_ERROR  -- success
97 *              none-zero failure code
98 *==========================================================================*/
99int32_t QCamera3PostProcessor::init(jpeg_encode_callback_t jpeg_cb, void *user_data)
100{
101    mJpegCB = jpeg_cb;
102    mJpegUserData = user_data;
103
104    mJpegClientHandle = jpeg_open(&mJpegHandle);
105    if(!mJpegClientHandle) {
106        ALOGE("%s : jpeg_open did not work", __func__);
107        return UNKNOWN_ERROR;
108    }
109
110    m_dataProcTh.launch(dataProcessRoutine, this);
111
112    return NO_ERROR;
113}
114
115/*===========================================================================
116 * FUNCTION   : deinit
117 *
118 * DESCRIPTION: de-initialization of postprocessor
119 *
120 * PARAMETERS : None
121 *
122 * RETURN     : int32_t type of status
123 *              NO_ERROR  -- success
124 *              none-zero failure code
125 *==========================================================================*/
126int32_t QCamera3PostProcessor::deinit()
127{
128    m_dataProcTh.exit();
129
130    if(mJpegClientHandle > 0) {
131        int rc = mJpegHandle.close(mJpegClientHandle);
132        ALOGD("%s: Jpeg closed, rc = %d, mJpegClientHandle = %x",
133              __func__, rc, mJpegClientHandle);
134        mJpegClientHandle = 0;
135        memset(&mJpegHandle, 0, sizeof(mJpegHandle));
136    }
137
138    return NO_ERROR;
139}
140
141/*===========================================================================
142 * FUNCTION   : start
143 *
144 * DESCRIPTION: start postprocessor. Data process thread and data notify thread
145 *              will be launched.
146 *
147 * PARAMETERS :
148 *   @pSrcChannel : source channel obj ptr that possibly needs reprocess
149 *
150 * RETURN     : int32_t type of status
151 *              NO_ERROR  -- success
152 *              none-zero failure code
153 *
154 * NOTE       : if any reprocess is needed, a reprocess channel/stream
155 *              will be started.
156 *==========================================================================*/
157int32_t QCamera3PostProcessor::start(QCamera3Memory* mMemory, int index)
158{
159    int32_t rc = NO_ERROR;
160    mJpegMem = mMemory;
161    mJpegMemIndex = index;
162    m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_START_DATA_PROC, FALSE, FALSE);
163
164    return rc;
165}
166
167/*===========================================================================
168 * FUNCTION   : stop
169 *
170 * DESCRIPTION: stop postprocessor. Data process and notify thread will be stopped.
171 *
172 * PARAMETERS : None
173 *
174 * RETURN     : int32_t type of status
175 *              NO_ERROR  -- success
176 *              none-zero failure code
177 *
178 * NOTE       : reprocess channel will be stopped and deleted if there is any
179 *==========================================================================*/
180int32_t QCamera3PostProcessor::stop()
181{
182    m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_STOP_DATA_PROC, TRUE, TRUE);
183
184    return NO_ERROR;
185}
186
187/*===========================================================================
188 * FUNCTION   : getJpegEncodingConfig
189 *
190 * DESCRIPTION: function to prepare encoding job information
191 *
192 * PARAMETERS :
193 *   @encode_parm   : param to be filled with encoding configuration
194 *
195 * RETURN     : int32_t type of status
196 *              NO_ERROR  -- success
197 *              none-zero failure code
198 *==========================================================================*/
199int32_t QCamera3PostProcessor::getJpegEncodingConfig(mm_jpeg_encode_params_t& encode_parm,
200                                                    QCamera3Stream *main_stream,
201                                                    QCamera3Stream *thumb_stream)
202{
203    ALOGV("%s : E", __func__);
204    int32_t ret = NO_ERROR;
205
206    encode_parm.jpeg_cb = mJpegCB;
207    encode_parm.userdata = mJpegUserData;
208
209    m_bThumbnailNeeded = TRUE; // need encode thumbnail by default
210    cam_dimension_t thumbnailSize;
211    memset(&thumbnailSize, 0, sizeof(cam_dimension_t));
212    m_parent->getThumbnailSize(thumbnailSize);
213    if (thumbnailSize.width == 0 && thumbnailSize.height == 0) {
214        // (0,0) means no thumbnail
215        m_bThumbnailNeeded = FALSE;
216    }
217    encode_parm.encode_thumbnail = m_bThumbnailNeeded;
218
219    // get color format
220    cam_format_t img_fmt = CAM_FORMAT_YUV_420_NV12;  //default value
221    main_stream->getFormat(img_fmt);
222    encode_parm.color_format = getColorfmtFromImgFmt(img_fmt);
223
224    // get jpeg quality
225    encode_parm.quality = m_parent->getJpegQuality();
226    if (encode_parm.quality <= 0) {
227        encode_parm.quality = 85;
228    }
229
230    // get exif data
231    if (m_pJpegExifObj != NULL) {
232        delete m_pJpegExifObj;
233        m_pJpegExifObj = NULL;
234    }
235    m_pJpegExifObj = m_parent->getExifData();
236    if (m_pJpegExifObj != NULL) {
237        encode_parm.exif_info.exif_data = m_pJpegExifObj->getEntries();
238        encode_parm.exif_info.numOfEntries = m_pJpegExifObj->getNumOfEntries();
239    }
240
241    cam_frame_len_offset_t main_offset;
242    memset(&main_offset, 0, sizeof(cam_frame_len_offset_t));
243    main_stream->getFrameOffset(main_offset);
244
245    // src buf config
246    //Pass input main image buffer info to encoder.
247    QCamera3Memory *pStreamMem = main_stream->getStreamBufs();
248    if (pStreamMem == NULL) {
249        ALOGE("%s: cannot get stream bufs from main stream", __func__);
250        ret = BAD_VALUE;
251        goto on_error;
252    }
253    encode_parm.num_src_bufs = pStreamMem->getCnt();
254    for (uint32_t i = 0; i < encode_parm.num_src_bufs; i++) {
255        if (pStreamMem != NULL) {
256            encode_parm.src_main_buf[i].index = i;
257            encode_parm.src_main_buf[i].buf_size = pStreamMem->getSize(i);
258            encode_parm.src_main_buf[i].buf_vaddr = (uint8_t *)pStreamMem->getPtr(i);
259            encode_parm.src_main_buf[i].fd = pStreamMem->getFd(i);
260            encode_parm.src_main_buf[i].format = MM_JPEG_FMT_YUV;
261            encode_parm.src_main_buf[i].offset = main_offset;
262        }
263    }
264
265    //Pass input thumbnail buffer info to encoder.
266    //Note: In this version thumb_stream = main_stream
267    if (m_bThumbnailNeeded == TRUE) {
268        if (thumb_stream == NULL) {
269            thumb_stream = main_stream;
270        }
271        pStreamMem = thumb_stream->getStreamBufs();
272        if (pStreamMem == NULL) {
273            ALOGE("%s: cannot get stream bufs from thumb stream", __func__);
274            ret = BAD_VALUE;
275            goto on_error;
276        }
277        cam_frame_len_offset_t thumb_offset;
278        memset(&thumb_offset, 0, sizeof(cam_frame_len_offset_t));
279        thumb_stream->getFrameOffset(thumb_offset);
280        encode_parm.num_tmb_bufs = pStreamMem->getCnt();
281        for (int i = 0; i < pStreamMem->getCnt(); i++) {
282            if (pStreamMem != NULL) {
283                encode_parm.src_thumb_buf[i].index = i;
284                encode_parm.src_thumb_buf[i].buf_size = pStreamMem->getSize(i);
285                encode_parm.src_thumb_buf[i].buf_vaddr = (uint8_t *)pStreamMem->getPtr(i);
286                encode_parm.src_thumb_buf[i].fd = pStreamMem->getFd(i);
287                encode_parm.src_thumb_buf[i].format = MM_JPEG_FMT_YUV;
288                encode_parm.src_thumb_buf[i].offset = thumb_offset;
289            }
290        }
291    }
292
293    //Pass output jpeg buffer info to encoder.
294    //mJpegMem is allocated by framework.
295    encode_parm.num_dst_bufs = 1;
296    encode_parm.dest_buf[0].index = 0;
297    encode_parm.dest_buf[0].buf_size = mJpegMem->getSize(mJpegMemIndex);
298    encode_parm.dest_buf[0].buf_vaddr = (uint8_t *)mJpegMem->getPtr(mJpegMemIndex);
299    encode_parm.dest_buf[0].fd = mJpegMem->getFd(mJpegMemIndex);
300    encode_parm.dest_buf[0].format = MM_JPEG_FMT_YUV;
301    encode_parm.dest_buf[0].offset = main_offset;
302
303    ALOGV("%s : X", __func__);
304    return NO_ERROR;
305
306on_error:
307    if (m_pJpegExifObj != NULL) {
308        delete m_pJpegExifObj;
309        m_pJpegExifObj = NULL;
310    }
311    ALOGV("%s : X with error %d", __func__, ret);
312    return ret;
313}
314
315/*===========================================================================
316 * FUNCTION   : processData
317 *
318 * DESCRIPTION: enqueue data into dataProc thread
319 *
320 * PARAMETERS :
321 *   @frame   : process frame received from mm-camera-interface
322 *
323 * RETURN     : int32_t type of status
324 *              NO_ERROR  -- success
325 *              none-zero failure code
326 *
327 * NOTE       : depends on if offline reprocess is needed, received frame will
328 *              be sent to either input queue of postprocess or jpeg encoding
329 *==========================================================================*/
330int32_t QCamera3PostProcessor::processData(mm_camera_super_buf_t *frame)
331{
332    ALOGD("%s: no need offline reprocess, sending to jpeg encoding", __func__);
333    qcamera_jpeg_data_t *jpeg_job =
334        (qcamera_jpeg_data_t *)malloc(sizeof(qcamera_jpeg_data_t));
335    if (jpeg_job == NULL) {
336        ALOGE("%s: No memory for jpeg job", __func__);
337        return NO_MEMORY;
338    }
339
340    memset(jpeg_job, 0, sizeof(qcamera_jpeg_data_t));
341    jpeg_job->src_frame = frame;
342
343    // enqueu to jpeg input queue
344    m_inputJpegQ.enqueue((void *)jpeg_job);
345    m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_DO_NEXT_JOB, FALSE, FALSE);
346
347    return NO_ERROR;
348}
349
350/*===========================================================================
351 * FUNCTION   : processRawData
352 *
353 * DESCRIPTION: enqueue raw data into dataProc thread
354 *
355 * PARAMETERS :
356 *   @frame   : process frame received from mm-camera-interface
357 *
358 * RETURN     : int32_t type of status
359 *              NO_ERROR  -- success
360 *              none-zero failure code
361 *==========================================================================*/
362int32_t QCamera3PostProcessor::processRawData(mm_camera_super_buf_t *frame)
363{
364    // enqueu to raw input queue
365    m_inputRawQ.enqueue((void *)frame);
366    m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_DO_NEXT_JOB, FALSE, FALSE);
367    return NO_ERROR;
368}
369
370/*===========================================================================
371 * FUNCTION   : processPPData
372 *
373 * DESCRIPTION: process received frame after reprocess.
374 *
375 * PARAMETERS :
376 *   @frame   : received frame from reprocess channel.
377 *
378 * RETURN     : int32_t type of status
379 *              NO_ERROR  -- success
380 *              none-zero failure code
381 *
382 * NOTE       : The frame after reprocess need to send to jpeg encoding.
383 *==========================================================================*/
384int32_t QCamera3PostProcessor::processPPData(mm_camera_super_buf_t *frame)
385{
386    qcamera_pp_data_t *job = (qcamera_pp_data_t *)m_ongoingPPQ.dequeue();
387
388    if (job == NULL || job->src_frame == NULL) {
389        ALOGE("%s: Cannot find reprocess job", __func__);
390        return BAD_VALUE;
391    }
392
393    qcamera_jpeg_data_t *jpeg_job =
394        (qcamera_jpeg_data_t *)malloc(sizeof(qcamera_jpeg_data_t));
395    if (jpeg_job == NULL) {
396        ALOGE("%s: No memory for jpeg job", __func__);
397        return NO_MEMORY;
398    }
399
400    memset(jpeg_job, 0, sizeof(qcamera_jpeg_data_t));
401    jpeg_job->src_frame = frame;
402    jpeg_job->src_reproc_frame = job->src_frame;
403
404    // free pp job buf
405    free(job);
406
407    // enqueu reprocessed frame to jpeg input queue
408    m_inputJpegQ.enqueue((void *)jpeg_job);
409
410    // wait up data proc thread
411    m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_DO_NEXT_JOB, FALSE, FALSE);
412
413    return NO_ERROR;
414}
415
416/*===========================================================================
417 * FUNCTION   : findJpegJobByJobId
418 *
419 * DESCRIPTION: find a jpeg job from ongoing Jpeg queue by its job ID
420 *
421 * PARAMETERS :
422 *   @jobId   : job Id of the job
423 *
424 * RETURN     : ptr to a jpeg job struct. NULL if not found.
425 *
426 * NOTE       : Currently only one job is sending to mm-jpeg-interface for jpeg
427 *              encoding. Therefore simply dequeue from the ongoing Jpeg Queue
428 *              will serve the purpose to find the jpeg job.
429 *==========================================================================*/
430qcamera_jpeg_data_t *QCamera3PostProcessor::findJpegJobByJobId(uint32_t jobId)
431{
432    qcamera_jpeg_data_t * job = NULL;
433    if (jobId == 0) {
434        ALOGE("%s: not a valid jpeg jobId", __func__);
435        return NULL;
436    }
437
438    // currely only one jpeg job ongoing, so simply dequeue the head
439    job = (qcamera_jpeg_data_t *)m_ongoingJpegQ.dequeue();
440    return job;
441}
442
443/*===========================================================================
444 * FUNCTION   : releasePPInputData
445 *
446 * DESCRIPTION: callback function to release post process input data node
447 *
448 * PARAMETERS :
449 *   @data      : ptr to post process input data
450 *   @user_data : user data ptr (QCamera3Reprocessor)
451 *
452 * RETURN     : None
453 *==========================================================================*/
454void QCamera3PostProcessor::releasePPInputData(void *data, void *user_data)
455{
456    QCamera3PostProcessor *pme = (QCamera3PostProcessor *)user_data;
457    if (NULL != pme) {
458        pme->releaseSuperBuf((mm_camera_super_buf_t *)data);
459    }
460}
461
462/*===========================================================================
463 * FUNCTION   : releaseJpegData
464 *
465 * DESCRIPTION: callback function to release jpeg job node
466 *
467 * PARAMETERS :
468 *   @data      : ptr to ongoing jpeg job data
469 *   @user_data : user data ptr (QCamera3Reprocessor)
470 *
471 * RETURN     : None
472 *==========================================================================*/
473void QCamera3PostProcessor::releaseJpegData(void *data, void *user_data)
474{
475    QCamera3PostProcessor *pme = (QCamera3PostProcessor *)user_data;
476    if (NULL != pme) {
477        pme->releaseJpegJobData((qcamera_jpeg_data_t *)data);
478    }
479}
480
481/*===========================================================================
482 * FUNCTION   : releaseOngoingPPData
483 *
484 * DESCRIPTION: callback function to release ongoing postprocess job node
485 *
486 * PARAMETERS :
487 *   @data      : ptr to onging postprocess job
488 *   @user_data : user data ptr (QCamera3Reprocessor)
489 *
490 * RETURN     : None
491 *==========================================================================*/
492void QCamera3PostProcessor::releaseOngoingPPData(void *data, void *user_data)
493{
494    QCamera3PostProcessor *pme = (QCamera3PostProcessor *)user_data;
495    if (NULL != pme) {
496        qcamera_pp_data_t *pp_job = (qcamera_pp_data_t *)data;
497        if (NULL != pp_job->src_frame) {
498            pme->releaseSuperBuf(pp_job->src_frame);
499            free(pp_job->src_frame);
500            pp_job->src_frame = NULL;
501        }
502    }
503}
504
505/*===========================================================================
506 * FUNCTION   : releaseSuperBuf
507 *
508 * DESCRIPTION: function to release a superbuf frame by returning back to kernel
509 *
510 * PARAMETERS :
511 *   @super_buf : ptr to the superbuf frame
512 *
513 * RETURN     : None
514 *==========================================================================*/
515void QCamera3PostProcessor::releaseSuperBuf(mm_camera_super_buf_t *super_buf)
516{
517    if (NULL != super_buf) {
518        if (m_parent != NULL) {
519            m_parent->bufDone(super_buf);
520        }
521    }
522}
523
524/*===========================================================================
525 * FUNCTION   : releaseJpegJobData
526 *
527 * DESCRIPTION: function to release internal resources in jpeg job struct
528 *
529 * PARAMETERS :
530 *   @job     : ptr to jpeg job struct
531 *
532 * RETURN     : None
533 *
534 * NOTE       : original source frame need to be queued back to kernel for
535 *              future use. Output buf of jpeg job need to be released since
536 *              it's allocated for each job. Exif object need to be deleted.
537 *==========================================================================*/
538void QCamera3PostProcessor::releaseJpegJobData(qcamera_jpeg_data_t *job)
539{
540    ALOGV("%s: E", __func__);
541    if (NULL != job) {
542        if (NULL != job->src_reproc_frame) {
543            releaseSuperBuf(job->src_reproc_frame);
544            free(job->src_reproc_frame);
545            job->src_reproc_frame = NULL;
546        }
547
548        if (NULL != job->src_frame) {
549            free(job->src_frame);
550            job->src_frame = NULL;
551        }
552        mJpegMem = NULL;
553    }
554    ALOGV("%s: X", __func__);
555}
556
557/*===========================================================================
558 * FUNCTION   : getColorfmtFromImgFmt
559 *
560 * DESCRIPTION: function to return jpeg color format based on its image format
561 *
562 * PARAMETERS :
563 *   @img_fmt : image format
564 *
565 * RETURN     : jpeg color format that can be understandable by omx lib
566 *==========================================================================*/
567mm_jpeg_color_format QCamera3PostProcessor::getColorfmtFromImgFmt(cam_format_t img_fmt)
568{
569    switch (img_fmt) {
570    case CAM_FORMAT_YUV_420_NV21:
571        return MM_JPEG_COLOR_FORMAT_YCRCBLP_H2V2;
572    case CAM_FORMAT_YUV_420_NV21_ADRENO:
573        return MM_JPEG_COLOR_FORMAT_YCRCBLP_H2V2;
574    case CAM_FORMAT_YUV_420_NV12:
575        return MM_JPEG_COLOR_FORMAT_YCBCRLP_H2V2;
576    case CAM_FORMAT_YUV_420_YV12:
577        return MM_JPEG_COLOR_FORMAT_YCBCRLP_H2V2;
578    case CAM_FORMAT_YUV_422_NV61:
579        return MM_JPEG_COLOR_FORMAT_YCRCBLP_H2V1;
580    case CAM_FORMAT_YUV_422_NV16:
581        return MM_JPEG_COLOR_FORMAT_YCBCRLP_H2V1;
582    default:
583        return MM_JPEG_COLOR_FORMAT_YCRCBLP_H2V2;
584    }
585}
586
587/*===========================================================================
588 * FUNCTION   : getJpegImgTypeFromImgFmt
589 *
590 * DESCRIPTION: function to return jpeg encode image type based on its image format
591 *
592 * PARAMETERS :
593 *   @img_fmt : image format
594 *
595 * RETURN     : return jpeg source image format (YUV or Bitstream)
596 *==========================================================================*/
597mm_jpeg_format_t QCamera3PostProcessor::getJpegImgTypeFromImgFmt(cam_format_t img_fmt)
598{
599    switch (img_fmt) {
600    case CAM_FORMAT_YUV_420_NV21:
601    case CAM_FORMAT_YUV_420_NV21_ADRENO:
602    case CAM_FORMAT_YUV_420_NV12:
603    case CAM_FORMAT_YUV_420_YV12:
604    case CAM_FORMAT_YUV_422_NV61:
605    case CAM_FORMAT_YUV_422_NV16:
606        return MM_JPEG_FMT_YUV;
607    default:
608        return MM_JPEG_FMT_YUV;
609    }
610}
611
612/*===========================================================================
613 * FUNCTION   : encodeData
614 *
615 * DESCRIPTION: function to prepare encoding job information and send to
616 *              mm-jpeg-interface to do the encoding job
617 *
618 * PARAMETERS :
619 *   @jpeg_job_data : ptr to a struct saving job related information
620 *   @needNewSess   : flag to indicate if a new jpeg encoding session need
621 *                    to be created. After creation, this flag will be toggled
622 *
623 * RETURN     : int32_t type of status
624 *              NO_ERROR  -- success
625 *              none-zero failure code
626 *==========================================================================*/
627int32_t QCamera3PostProcessor::encodeData(qcamera_jpeg_data_t *jpeg_job_data,
628                                         uint8_t &needNewSess)
629{
630    ALOGV("%s : E", __func__);
631    int32_t ret = NO_ERROR;
632    mm_jpeg_job_t jpg_job;
633    uint32_t jobId = 0;
634    QCamera3Stream *main_stream = NULL;
635    mm_camera_buf_def_t *main_frame = NULL;
636    QCamera3Stream *thumb_stream = NULL;
637    mm_camera_buf_def_t *thumb_frame = NULL;
638    mm_camera_super_buf_t *recvd_frame = jpeg_job_data->src_frame;
639
640    // find channel
641    QCamera3Channel *pChannel = m_parent;
642    // check reprocess channel if not found
643    if (pChannel == NULL) {
644        ALOGE("%s: No corresponding channel (ch_id = %d) exist, return here",
645              __func__, recvd_frame->ch_id);
646        return BAD_VALUE;
647    }
648
649    // find snapshot frame and thumnail frame
650    //Note: In this version we will receive only snapshot frame.
651    for (int i = 0; i < recvd_frame->num_bufs; i++) {
652        QCamera3Stream *pStream =
653            pChannel->getStreamByHandle(recvd_frame->bufs[i]->stream_id);
654        if (pStream != NULL) {
655            if (pStream->isTypeOf(CAM_STREAM_TYPE_SNAPSHOT) ||
656                pStream->isTypeOf(CAM_STREAM_TYPE_OFFLINE_PROC)) {
657                main_stream = pStream;
658                main_frame = recvd_frame->bufs[i];
659            } else if (pStream->isTypeOf(CAM_STREAM_TYPE_PREVIEW) ||
660                       pStream->isTypeOf(CAM_STREAM_TYPE_POSTVIEW)) {
661                thumb_stream = pStream;
662                thumb_frame = recvd_frame->bufs[i];
663            }
664        }
665    }
666
667    if(NULL == main_frame){
668       ALOGE("%s : Main frame is NULL", __func__);
669       return BAD_VALUE;
670    }
671
672    QCamera3Memory *memObj = (QCamera3Memory *)main_frame->mem_info;
673    if (NULL == memObj) {
674        ALOGE("%s : Memeory Obj of main frame is NULL", __func__);
675        return NO_MEMORY;
676    }
677
678    // clean and invalidate cache ops through mem obj of the frame
679    memObj->cleanInvalidateCache(main_frame->buf_idx);
680
681    if (thumb_frame != NULL) {
682        QCamera3Memory *thumb_memObj = (QCamera3Memory *)thumb_frame->mem_info;
683        if (NULL != thumb_memObj) {
684            // clean and invalidate cache ops through mem obj of the frame
685            thumb_memObj->cleanInvalidateCache(thumb_frame->buf_idx);
686        }
687    }
688
689    if (mJpegClientHandle <= 0) {
690        ALOGE("%s: Error: bug here, mJpegClientHandle is 0", __func__);
691        return UNKNOWN_ERROR;
692    }
693
694    ALOGD("%s: Need new session?:%d",__func__, needNewSess);
695    if (needNewSess) {
696        //creating a new session, so we must destroy the old one
697        if ( 0 < mJpegSessionId ) {
698            ret = mJpegHandle.destroy_session(mJpegSessionId);
699            if (ret != NO_ERROR) {
700                ALOGE("%s: Error destroying an old jpeg encoding session, id = %d",
701                      __func__, mJpegSessionId);
702                return ret;
703            }
704            mJpegSessionId = 0;
705        }
706        // create jpeg encoding session
707        mm_jpeg_encode_params_t encodeParam;
708        memset(&encodeParam, 0, sizeof(mm_jpeg_encode_params_t));
709
710        getJpegEncodingConfig(encodeParam, main_stream, thumb_stream);
711        ALOGD("%s: #src bufs:%d # tmb bufs:%d #dst_bufs:%d", __func__,
712                     encodeParam.num_src_bufs,encodeParam.num_tmb_bufs,encodeParam.num_dst_bufs);
713        ret = mJpegHandle.create_session(mJpegClientHandle, &encodeParam, &mJpegSessionId);
714        if (ret != NO_ERROR) {
715            ALOGE("%s: Error creating a new jpeg encoding session, ret = %d", __func__, ret);
716            return ret;
717        }
718        needNewSess = FALSE;
719    }
720
721    // Fill in new job
722    memset(&jpg_job, 0, sizeof(mm_jpeg_job_t));
723    jpg_job.job_type = JPEG_JOB_TYPE_ENCODE;
724    jpg_job.encode_job.session_id = mJpegSessionId;
725    jpg_job.encode_job.src_index = main_frame->buf_idx;
726    jpg_job.encode_job.dst_index = 0;
727
728    cam_rect_t crop;
729    memset(&crop, 0, sizeof(cam_rect_t));
730    //TBD_later - Zoom event removed in stream
731    //main_stream->getCropInfo(crop);
732
733    cam_dimension_t src_dim;
734    memset(&src_dim, 0, sizeof(cam_dimension_t));
735    main_stream->getFrameDimension(src_dim);
736
737    // main dim
738    jpg_job.encode_job.main_dim.src_dim = src_dim;
739    jpg_job.encode_job.main_dim.dst_dim = src_dim;
740    jpg_job.encode_job.main_dim.crop = crop;
741
742    // thumbnail dim
743    ALOGD("%s: Thumbnail needed:%d",__func__, m_bThumbnailNeeded);
744    if (m_bThumbnailNeeded == TRUE) {
745        if (thumb_stream == NULL) {
746            // need jpeg thumbnail, but no postview/preview stream exists
747            // we use the main stream/frame to encode thumbnail
748            thumb_stream = main_stream;
749            thumb_frame = main_frame;
750        }
751        memset(&crop, 0, sizeof(cam_rect_t));
752        //TBD_later - Zoom event removed in stream
753        //thumb_stream->getCropInfo(crop);
754        memset(&src_dim, 0, sizeof(cam_dimension_t));
755        thumb_stream->getFrameDimension(src_dim);
756        jpg_job.encode_job.thumb_dim.src_dim = src_dim;
757        m_parent->getThumbnailSize(jpg_job.encode_job.thumb_dim.dst_dim);
758        jpg_job.encode_job.thumb_dim.crop = crop;
759        jpg_job.encode_job.thumb_index = thumb_frame->buf_idx;
760    }
761
762    // set rotation only when no online rotation or offline pp rotation is done before
763
764    if (!m_parent->needOnlineRotation()) {
765        jpg_job.encode_job.rotation = m_parent->getJpegRotation();
766    }
767    ALOGV("%s: jpeg rotation is set to %d", __func__, jpg_job.encode_job.rotation);
768
769    // Find meta data frame. Meta data frame contains additional exif info
770    // which will be extracted and filled in by encoder.
771    //Note: In this version meta data will be null
772    //as we don't support bundling of snapshot and metadata streams.
773
774    mm_camera_buf_def_t *meta_frame = NULL;
775    for (int i = 0; i < jpeg_job_data->src_frame->num_bufs; i++) {
776        // look through input superbuf
777        if (jpeg_job_data->src_frame->bufs[i]->stream_type == CAM_STREAM_TYPE_METADATA) {
778            meta_frame = jpeg_job_data->src_frame->bufs[i];
779            break;
780        }
781    }
782    if (meta_frame == NULL && jpeg_job_data->src_reproc_frame != NULL) {
783        // look through reprocess source superbuf
784        for (int i = 0; i < jpeg_job_data->src_reproc_frame->num_bufs; i++) {
785            if (jpeg_job_data->src_reproc_frame->bufs[i]->stream_type == CAM_STREAM_TYPE_METADATA) {
786                meta_frame = jpeg_job_data->src_reproc_frame->bufs[i];
787                break;
788            }
789        }
790    }
791    if (meta_frame != NULL) {
792        // fill in meta data frame ptr
793        jpg_job.encode_job.p_metadata = (cam_metadata_info_t *)meta_frame->buffer;
794    }
795
796    //Start jpeg encoding
797    ret = mJpegHandle.start_job(&jpg_job, &jobId);
798    if (ret == NO_ERROR) {
799        // remember job info
800        jpeg_job_data->jobId = jobId;
801    }
802
803    ALOGV("%s : X", __func__);
804    return ret;
805}
806
807/*===========================================================================
808 * FUNCTION   : dataProcessRoutine
809 *
810 * DESCRIPTION: data process routine that handles input data either from input
811 *              Jpeg Queue to do jpeg encoding, or from input PP Queue to do
812 *              reprocess.
813 *
814 * PARAMETERS :
815 *   @data    : user data ptr (QCamera3PostProcessor)
816 *
817 * RETURN     : None
818 *==========================================================================*/
819void *QCamera3PostProcessor::dataProcessRoutine(void *data)
820{
821    int running = 1;
822    int ret;
823    uint8_t is_active = FALSE;
824    uint8_t needNewSess = TRUE;
825    ALOGV("%s: E", __func__);
826    QCamera3PostProcessor *pme = (QCamera3PostProcessor *)data;
827    QCameraCmdThread *cmdThread = &pme->m_dataProcTh;
828
829    do {
830        do {
831            ret = cam_sem_wait(&cmdThread->cmd_sem);
832            if (ret != 0 && errno != EINVAL) {
833                ALOGE("%s: cam_sem_wait error (%s)",
834                           __func__, strerror(errno));
835                return NULL;
836            }
837        } while (ret != 0);
838
839        // we got notified about new cmd avail in cmd queue
840        camera_cmd_type_t cmd = cmdThread->getCmd();
841        switch (cmd) {
842        case CAMERA_CMD_TYPE_START_DATA_PROC:
843            ALOGD("%s: start data proc", __func__);
844            is_active = TRUE;
845            needNewSess = TRUE;
846            break;
847        case CAMERA_CMD_TYPE_STOP_DATA_PROC:
848            {
849                ALOGD("%s: stop data proc", __func__);
850                is_active = FALSE;
851
852                // cancel all ongoing jpeg jobs
853                qcamera_jpeg_data_t *jpeg_job =
854                    (qcamera_jpeg_data_t *)pme->m_ongoingJpegQ.dequeue();
855                while (jpeg_job != NULL) {
856                    pme->mJpegHandle.abort_job(jpeg_job->jobId);
857
858                    pme->releaseJpegJobData(jpeg_job);
859                    free(jpeg_job);
860
861                    jpeg_job = (qcamera_jpeg_data_t *)pme->m_ongoingJpegQ.dequeue();
862                }
863
864                // destroy jpeg encoding session
865                if ( 0 < pme->mJpegSessionId ) {
866                    pme->mJpegHandle.destroy_session(pme->mJpegSessionId);
867                    pme->mJpegSessionId = 0;
868                }
869
870                // free jpeg exif obj
871                if (pme->m_pJpegExifObj != NULL) {
872                    delete pme->m_pJpegExifObj;
873                    pme->m_pJpegExifObj = NULL;
874                }
875                needNewSess = TRUE;
876
877                // flush ongoing postproc Queue
878                pme->m_ongoingPPQ.flush();
879
880                // flush input jpeg Queue
881                pme->m_inputJpegQ.flush();
882
883                // flush input Postproc Queue
884                pme->m_inputPPQ.flush();
885
886                // flush input raw Queue
887                pme->m_inputRawQ.flush();
888
889                // signal cmd is completed
890                cam_sem_post(&cmdThread->sync_sem);
891            }
892            break;
893        case CAMERA_CMD_TYPE_DO_NEXT_JOB:
894            {
895                ALOGD("%s: Do next job, active is %d", __func__, is_active);
896                if (is_active == TRUE) {
897                    // check if there is any ongoing jpeg jobs
898                    if (pme->m_ongoingJpegQ.isEmpty()) {
899                        // no ongoing jpeg job, we are fine to send jpeg encoding job
900                        qcamera_jpeg_data_t *jpeg_job =
901                            (qcamera_jpeg_data_t *)pme->m_inputJpegQ.dequeue();
902
903                        if (NULL != jpeg_job) {
904                            //TBD_later - play shutter sound
905                            //pme->m_parent->playShutter();
906
907                            // add into ongoing jpeg job Q
908                            pme->m_ongoingJpegQ.enqueue((void *)jpeg_job);
909                            ret = pme->encodeData(jpeg_job, needNewSess);
910                            if (NO_ERROR != ret) {
911                                // dequeue the last one
912                                pme->m_ongoingJpegQ.dequeue(false);
913
914                                pme->releaseJpegJobData(jpeg_job);
915                                free(jpeg_job);
916                            }
917                        }
918                    }
919
920                    mm_camera_super_buf_t *pp_frame =
921                        (mm_camera_super_buf_t *)pme->m_inputPPQ.dequeue();
922                    if (NULL != pp_frame) {
923                        qcamera_pp_data_t *pp_job =
924                            (qcamera_pp_data_t *)malloc(sizeof(qcamera_pp_data_t));
925                        if (pp_job != NULL) {
926                            memset(pp_job, 0, sizeof(qcamera_pp_data_t));
927                        } else {
928                            ALOGE("%s: no mem for qcamera_pp_data_t", __func__);
929                            ret = -1;
930                        }
931
932                        if (0 != ret) {
933                            // free pp_job
934                            if (pp_job != NULL) {
935                                free(pp_job);
936                            }
937                            // free frame
938                            if (pp_frame != NULL) {
939                                pme->releaseSuperBuf(pp_frame);
940                                free(pp_frame);
941                            }
942                        }
943                    }
944                } else {
945                    // not active, simply return buf and do no op
946                    mm_camera_super_buf_t *super_buf =
947                        (mm_camera_super_buf_t *)pme->m_inputJpegQ.dequeue();
948                    if (NULL != super_buf) {
949                        pme->releaseSuperBuf(super_buf);
950                        free(super_buf);
951                    }
952                    super_buf = (mm_camera_super_buf_t *)pme->m_inputRawQ.dequeue();
953                    if (NULL != super_buf) {
954                        pme->releaseSuperBuf(super_buf);
955                        free(super_buf);
956                    }
957                    super_buf = (mm_camera_super_buf_t *)pme->m_inputPPQ.dequeue();
958                    if (NULL != super_buf) {
959                        pme->releaseSuperBuf(super_buf);
960                        free(super_buf);
961                    }
962                }
963            }
964            break;
965        case CAMERA_CMD_TYPE_EXIT:
966            running = 0;
967            break;
968        default:
969            break;
970        }
971    } while (running);
972    ALOGV("%s: X", __func__);
973    return NULL;
974}
975
976/*===========================================================================
977 * FUNCTION   : QCamera3Exif
978 *
979 * DESCRIPTION: constructor of QCamera3Exif
980 *
981 * PARAMETERS : None
982 *
983 * RETURN     : None
984 *==========================================================================*/
985QCamera3Exif::QCamera3Exif()
986    : m_nNumEntries(0)
987{
988    memset(m_Entries, 0, sizeof(m_Entries));
989}
990
991/*===========================================================================
992 * FUNCTION   : ~QCamera3Exif
993 *
994 * DESCRIPTION: deconstructor of QCamera3Exif. Will release internal memory ptr.
995 *
996 * PARAMETERS : None
997 *
998 * RETURN     : None
999 *==========================================================================*/
1000QCamera3Exif::~QCamera3Exif()
1001{
1002    for (uint32_t i = 0; i < m_nNumEntries; i++) {
1003        switch (m_Entries[i].tag_entry.type) {
1004            case EXIF_BYTE:
1005                {
1006                    if (m_Entries[i].tag_entry.count > 1 &&
1007                            m_Entries[i].tag_entry.data._bytes != NULL) {
1008                        free(m_Entries[i].tag_entry.data._bytes);
1009                        m_Entries[i].tag_entry.data._bytes = NULL;
1010                    }
1011                }
1012                break;
1013            case EXIF_ASCII:
1014                {
1015                    if (m_Entries[i].tag_entry.data._ascii != NULL) {
1016                        free(m_Entries[i].tag_entry.data._ascii);
1017                        m_Entries[i].tag_entry.data._ascii = NULL;
1018                    }
1019                }
1020                break;
1021            case EXIF_SHORT:
1022                {
1023                    if (m_Entries[i].tag_entry.count > 1 &&
1024                            m_Entries[i].tag_entry.data._shorts != NULL) {
1025                        free(m_Entries[i].tag_entry.data._shorts);
1026                        m_Entries[i].tag_entry.data._shorts = NULL;
1027                    }
1028                }
1029                break;
1030            case EXIF_LONG:
1031                {
1032                    if (m_Entries[i].tag_entry.count > 1 &&
1033                            m_Entries[i].tag_entry.data._longs != NULL) {
1034                        free(m_Entries[i].tag_entry.data._longs);
1035                        m_Entries[i].tag_entry.data._longs = NULL;
1036                    }
1037                }
1038                break;
1039            case EXIF_RATIONAL:
1040                {
1041                    if (m_Entries[i].tag_entry.count > 1 &&
1042                            m_Entries[i].tag_entry.data._rats != NULL) {
1043                        free(m_Entries[i].tag_entry.data._rats);
1044                        m_Entries[i].tag_entry.data._rats = NULL;
1045                    }
1046                }
1047                break;
1048            case EXIF_UNDEFINED:
1049                {
1050                    if (m_Entries[i].tag_entry.data._undefined != NULL) {
1051                        free(m_Entries[i].tag_entry.data._undefined);
1052                        m_Entries[i].tag_entry.data._undefined = NULL;
1053                    }
1054                }
1055                break;
1056            case EXIF_SLONG:
1057                {
1058                    if (m_Entries[i].tag_entry.count > 1 &&
1059                            m_Entries[i].tag_entry.data._slongs != NULL) {
1060                        free(m_Entries[i].tag_entry.data._slongs);
1061                        m_Entries[i].tag_entry.data._slongs = NULL;
1062                    }
1063                }
1064                break;
1065            case EXIF_SRATIONAL:
1066                {
1067                    if (m_Entries[i].tag_entry.count > 1 &&
1068                            m_Entries[i].tag_entry.data._srats != NULL) {
1069                        free(m_Entries[i].tag_entry.data._srats);
1070                        m_Entries[i].tag_entry.data._srats = NULL;
1071                    }
1072                }
1073                break;
1074            default:
1075                ALOGE("%s: Error, Unknown type",__func__);
1076                break;
1077        }
1078    }
1079}
1080
1081/*===========================================================================
1082 * FUNCTION   : addEntry
1083 *
1084 * DESCRIPTION: function to add an entry to exif data
1085 *
1086 * PARAMETERS :
1087 *   @tagid   : exif tag ID
1088 *   @type    : data type
1089 *   @count   : number of data in uint of its type
1090 *   @data    : input data ptr
1091 *
1092 * RETURN     : int32_t type of status
1093 *              NO_ERROR  -- success
1094 *              none-zero failure code
1095 *==========================================================================*/
1096int32_t QCamera3Exif::addEntry(exif_tag_id_t tagid,
1097                              exif_tag_type_t type,
1098                              uint32_t count,
1099                              void *data)
1100{
1101    int32_t rc = NO_ERROR;
1102    if(m_nNumEntries >= MAX_EXIF_TABLE_ENTRIES) {
1103        ALOGE("%s: Number of entries exceeded limit", __func__);
1104        return NO_MEMORY;
1105    }
1106
1107    m_Entries[m_nNumEntries].tag_id = tagid;
1108    m_Entries[m_nNumEntries].tag_entry.type = type;
1109    m_Entries[m_nNumEntries].tag_entry.count = count;
1110    m_Entries[m_nNumEntries].tag_entry.copy = 1;
1111    switch (type) {
1112        case EXIF_BYTE:
1113            {
1114                if (count > 1) {
1115                    uint8_t *values = (uint8_t *)malloc(count);
1116                    if (values == NULL) {
1117                        ALOGE("%s: No memory for byte array", __func__);
1118                        rc = NO_MEMORY;
1119                    } else {
1120                        memcpy(values, data, count);
1121                        m_Entries[m_nNumEntries].tag_entry.data._bytes = values;
1122                    }
1123                } else {
1124                    m_Entries[m_nNumEntries].tag_entry.data._byte =
1125                        *(uint8_t *)data;
1126                }
1127            }
1128            break;
1129        case EXIF_ASCII:
1130            {
1131                char *str = NULL;
1132                str = (char *)malloc(count + 1);
1133                if (str == NULL) {
1134                    ALOGE("%s: No memory for ascii string", __func__);
1135                    rc = NO_MEMORY;
1136                } else {
1137                    memset(str, 0, count + 1);
1138                    memcpy(str, data, count);
1139                    m_Entries[m_nNumEntries].tag_entry.data._ascii = str;
1140                }
1141            }
1142            break;
1143        case EXIF_SHORT:
1144            {
1145                if (count > 1) {
1146                    uint16_t *values =
1147                        (uint16_t *)malloc(count * sizeof(uint16_t));
1148                    if (values == NULL) {
1149                        ALOGE("%s: No memory for short array", __func__);
1150                        rc = NO_MEMORY;
1151                    } else {
1152                        memcpy(values, data, count * sizeof(uint16_t));
1153                        m_Entries[m_nNumEntries].tag_entry.data._shorts =values;
1154                    }
1155                } else {
1156                    m_Entries[m_nNumEntries].tag_entry.data._short =
1157                        *(uint16_t *)data;
1158                }
1159            }
1160            break;
1161        case EXIF_LONG:
1162            {
1163                if (count > 1) {
1164                    uint32_t *values =
1165                        (uint32_t *)malloc(count * sizeof(uint32_t));
1166                    if (values == NULL) {
1167                        ALOGE("%s: No memory for long array", __func__);
1168                        rc = NO_MEMORY;
1169                    } else {
1170                        memcpy(values, data, count * sizeof(uint32_t));
1171                        m_Entries[m_nNumEntries].tag_entry.data._longs = values;
1172                    }
1173                } else {
1174                    m_Entries[m_nNumEntries].tag_entry.data._long =
1175                        *(uint32_t *)data;
1176                }
1177            }
1178            break;
1179        case EXIF_RATIONAL:
1180            {
1181                if (count > 1) {
1182                    rat_t *values = (rat_t *)malloc(count * sizeof(rat_t));
1183                    if (values == NULL) {
1184                        ALOGE("%s: No memory for rational array", __func__);
1185                        rc = NO_MEMORY;
1186                    } else {
1187                        memcpy(values, data, count * sizeof(rat_t));
1188                        m_Entries[m_nNumEntries].tag_entry.data._rats = values;
1189                    }
1190                } else {
1191                    m_Entries[m_nNumEntries].tag_entry.data._rat =
1192                        *(rat_t *)data;
1193                }
1194            }
1195            break;
1196        case EXIF_UNDEFINED:
1197            {
1198                uint8_t *values = (uint8_t *)malloc(count);
1199                if (values == NULL) {
1200                    ALOGE("%s: No memory for undefined array", __func__);
1201                    rc = NO_MEMORY;
1202                } else {
1203                    memcpy(values, data, count);
1204                    m_Entries[m_nNumEntries].tag_entry.data._undefined = values;
1205                }
1206            }
1207            break;
1208        case EXIF_SLONG:
1209            {
1210                if (count > 1) {
1211                    int32_t *values =
1212                        (int32_t *)malloc(count * sizeof(int32_t));
1213                    if (values == NULL) {
1214                        ALOGE("%s: No memory for signed long array", __func__);
1215                        rc = NO_MEMORY;
1216                    } else {
1217                        memcpy(values, data, count * sizeof(int32_t));
1218                        m_Entries[m_nNumEntries].tag_entry.data._slongs =values;
1219                    }
1220                } else {
1221                    m_Entries[m_nNumEntries].tag_entry.data._slong =
1222                        *(int32_t *)data;
1223                }
1224            }
1225            break;
1226        case EXIF_SRATIONAL:
1227            {
1228                if (count > 1) {
1229                    srat_t *values = (srat_t *)malloc(count * sizeof(srat_t));
1230                    if (values == NULL) {
1231                        ALOGE("%s: No memory for sign rational array",__func__);
1232                        rc = NO_MEMORY;
1233                    } else {
1234                        memcpy(values, data, count * sizeof(srat_t));
1235                        m_Entries[m_nNumEntries].tag_entry.data._srats = values;
1236                    }
1237                } else {
1238                    m_Entries[m_nNumEntries].tag_entry.data._srat =
1239                        *(srat_t *)data;
1240                }
1241            }
1242            break;
1243        default:
1244            ALOGE("%s: Error, Unknown type",__func__);
1245            break;
1246    }
1247
1248    // Increase number of entries
1249    m_nNumEntries++;
1250    return rc;
1251}
1252
1253}; // namespace qcamera
1254