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