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