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