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