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