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