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 
38 namespace 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  *==========================================================================*/
QCameraPostProcessor(QCamera2HardwareInterface * cam_ctrl)50 QCameraPostProcessor::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  *==========================================================================*/
~QCameraPostProcessor()78 QCameraPostProcessor::~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  *==========================================================================*/
init(jpeg_encode_callback_t jpeg_cb,void * user_data)109 int32_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  *==========================================================================*/
deinit()136 int32_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  *==========================================================================*/
start(QCameraChannel * pSrcChannel)167 int32_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  *==========================================================================*/
stop()210 int32_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  *==========================================================================*/
getJpegEncodingConfig(mm_jpeg_encode_params_t & encode_parm,QCameraStream * main_stream,QCameraStream * thumb_stream)231 int32_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 
361 on_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  *==========================================================================*/
sendEvtNotify(int32_t msg_type,int32_t ext1,int32_t ext2)389 int32_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  *==========================================================================*/
sendDataNotify(int32_t msg_type,camera_memory_t * data,uint8_t index,camera_frame_metadata_t * metadata,qcamera_release_data_t * release_data)413 int32_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  *==========================================================================*/
processData(mm_camera_super_buf_t * frame)467 int32_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  *==========================================================================*/
processRawData(mm_camera_super_buf_t * frame)507 int32_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  *==========================================================================*/
processJpegEvt(qcamera_jpeg_evt_payload_t * evt)532 int32_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 
588 end:
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  *==========================================================================*/
processPPData(mm_camera_super_buf_t * frame)628 int32_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  *==========================================================================*/
findJpegJobByJobId(uint32_t jobId)681 qcamera_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  *==========================================================================*/
releasePPInputData(void * data,void * user_data)705 void 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  *==========================================================================*/
releaseJpegData(void * data,void * user_data)724 void 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  *==========================================================================*/
releaseOngoingPPData(void * data,void * user_data)743 void 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  *==========================================================================*/
releaseNotifyData(void * user_data,void * cookie)769 void 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  *==========================================================================*/
releaseSuperBuf(mm_camera_super_buf_t * super_buf)797 void 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  *==========================================================================*/
releaseJpegJobData(qcamera_jpeg_data_t * job)835 void 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  *==========================================================================*/
getColorfmtFromImgFmt(cam_format_t img_fmt)864 mm_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  *==========================================================================*/
getJpegImgTypeFromImgFmt(cam_format_t img_fmt)894 mm_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  *==========================================================================*/
encodeData(qcamera_jpeg_data_t * jpeg_job_data,uint8_t & needNewSess)924 int32_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 = (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  *==========================================================================*/
processRawImageImpl(mm_camera_super_buf_t * recvd_frame)1133 int32_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  *==========================================================================*/
dataProcessRoutine(void * data)1216 void *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  *==========================================================================*/
getJpegPaddingReq(cam_padding_info_t & padding_info)1429 int32_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  *==========================================================================*/
QCameraExif()1447 QCameraExif::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  *==========================================================================*/
~QCameraExif()1462 QCameraExif::~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  *==========================================================================*/
addEntry(exif_tag_id_t tagid,exif_tag_type_t type,uint32_t count,void * data)1555 int32_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