1 /* Copyright (c) 2012-2014, 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 <fcntl.h>
33 #include <stdlib.h>
34 #include <utils/Errors.h>
35 
36 #include "QCamera2HWI.h"
37 #include "QCameraPostProc.h"
38 
39 namespace qcamera {
40 
41 const char *QCameraPostProcessor::STORE_LOCATION = "/sdcard/img_%d.jpg";
42 
43 #define FREE_JPEG_OUTPUT_BUFFER(ptr,cnt)     \
44     int jpeg_bufs; \
45     for (jpeg_bufs = 0; jpeg_bufs < (int)cnt; jpeg_bufs++)  { \
46       if (ptr[jpeg_bufs] != NULL) { \
47           free(ptr[jpeg_bufs]); \
48           ptr[jpeg_bufs] = NULL; \
49       } \
50     }
51 
52 /*===========================================================================
53  * FUNCTION   : QCameraPostProcessor
54  *
55  * DESCRIPTION: constructor of QCameraPostProcessor.
56  *
57  * PARAMETERS :
58  *   @cam_ctrl : ptr to HWI object
59  *
60  * RETURN     : None
61  *==========================================================================*/
QCameraPostProcessor(QCamera2HardwareInterface * cam_ctrl)62 QCameraPostProcessor::QCameraPostProcessor(QCamera2HardwareInterface *cam_ctrl)
63     : m_parent(cam_ctrl),
64       mJpegCB(NULL),
65       mJpegUserData(NULL),
66       mJpegClientHandle(0),
67       mJpegSessionId(0),
68       m_pJpegExifObj(NULL),
69       m_bThumbnailNeeded(TRUE),
70       m_pReprocChannel(NULL),
71       m_bInited(FALSE),
72       m_inputPPQ(releasePPInputData, this),
73       m_ongoingPPQ(releaseOngoingPPData, this),
74       m_inputJpegQ(releaseJpegData, this),
75       m_ongoingJpegQ(releaseJpegData, this),
76       m_inputRawQ(releaseRawData, this),
77       mSaveFrmCnt(0),
78       mUseSaveProc(false),
79       mUseJpegBurst(false),
80       mJpegMemOpt(true),
81       m_JpegOutputMemCount(0),
82       mNewJpegSessionNeeded(true)
83 {
84     memset(&mJpegHandle, 0, sizeof(mJpegHandle));
85     memset(&m_pJpegOutputMem, 0, sizeof(m_pJpegOutputMem));
86 }
87 
88 /*===========================================================================
89  * FUNCTION   : ~QCameraPostProcessor
90  *
91  * DESCRIPTION: deconstructor of QCameraPostProcessor.
92  *
93  * PARAMETERS : None
94  *
95  * RETURN     : None
96  *==========================================================================*/
~QCameraPostProcessor()97 QCameraPostProcessor::~QCameraPostProcessor()
98 {
99     FREE_JPEG_OUTPUT_BUFFER(m_pJpegOutputMem,m_JpegOutputMemCount);
100     if (m_pJpegExifObj != NULL) {
101         delete m_pJpegExifObj;
102         m_pJpegExifObj = NULL;
103     }
104     if (m_pReprocChannel != NULL) {
105         m_pReprocChannel->stop();
106         delete m_pReprocChannel;
107         m_pReprocChannel = NULL;
108     }
109 }
110 
111 /*===========================================================================
112  * FUNCTION   : init
113  *
114  * DESCRIPTION: initialization of postprocessor
115  *
116  * PARAMETERS :
117  *   @jpeg_cb      : callback to handle jpeg event from mm-camera-interface
118  *   @user_data    : user data ptr for jpeg callback
119  *
120  * RETURN     : int32_t type of status
121  *              NO_ERROR  -- success
122  *              none-zero failure code
123  *==========================================================================*/
init(jpeg_encode_callback_t jpeg_cb,void * user_data)124 int32_t QCameraPostProcessor::init(jpeg_encode_callback_t jpeg_cb, void *user_data)
125 {
126     mJpegCB = jpeg_cb;
127     mJpegUserData = user_data;
128     mm_dimension max_size;
129 
130     //set max pic size
131     memset(&max_size, 0, sizeof(mm_dimension));
132     max_size.w = m_parent->m_max_pic_width;
133     max_size.h = m_parent->m_max_pic_height;
134 
135     mJpegClientHandle = jpeg_open(&mJpegHandle, max_size);
136     if(!mJpegClientHandle) {
137         ALOGE("%s : jpeg_open did not work", __func__);
138         return UNKNOWN_ERROR;
139     }
140 
141     m_dataProcTh.launch(dataProcessRoutine, this);
142     m_saveProcTh.launch(dataSaveRoutine, this);
143 
144     m_bInited = TRUE;
145     return NO_ERROR;
146 }
147 
148 /*===========================================================================
149  * FUNCTION   : deinit
150  *
151  * DESCRIPTION: de-initialization of postprocessor
152  *
153  * PARAMETERS : None
154  *
155  * RETURN     : int32_t type of status
156  *              NO_ERROR  -- success
157  *              none-zero failure code
158  *==========================================================================*/
deinit()159 int32_t QCameraPostProcessor::deinit()
160 {
161     if (m_bInited == TRUE) {
162         m_dataProcTh.exit();
163         m_saveProcTh.exit();
164 
165         if(mJpegClientHandle > 0) {
166             int rc = mJpegHandle.close(mJpegClientHandle);
167             CDBG_HIGH("%s: Jpeg closed, rc = %d, mJpegClientHandle = %x",
168                   __func__, rc, mJpegClientHandle);
169             mJpegClientHandle = 0;
170             memset(&mJpegHandle, 0, sizeof(mJpegHandle));
171         }
172         m_bInited = FALSE;
173     }
174     return NO_ERROR;
175 }
176 
177 /*===========================================================================
178  * FUNCTION   : start
179  *
180  * DESCRIPTION: start postprocessor. Data process thread and data notify thread
181  *              will be launched.
182  *
183  * PARAMETERS :
184  *   @pSrcChannel : source channel obj ptr that possibly needs reprocess
185  *
186  * RETURN     : int32_t type of status
187  *              NO_ERROR  -- success
188  *              none-zero failure code
189  *
190  * NOTE       : if any reprocess is needed, a reprocess channel/stream
191  *              will be started.
192  *==========================================================================*/
start(QCameraChannel * pSrcChannel)193 int32_t QCameraPostProcessor::start(QCameraChannel *pSrcChannel)
194 {
195     char prop[PROPERTY_VALUE_MAX];
196     int32_t rc = NO_ERROR;
197     if (m_bInited == FALSE) {
198         ALOGE("%s: postproc not initialized yet", __func__);
199         return UNKNOWN_ERROR;
200     }
201 
202     if (m_parent->needReprocess()) {
203         if (m_pReprocChannel != NULL) {
204             delete m_pReprocChannel;
205             m_pReprocChannel = NULL;
206         }
207         // if reprocess is needed, start reprocess channel
208         m_pReprocChannel = m_parent->addReprocChannel(pSrcChannel);
209         if (m_pReprocChannel == NULL) {
210             ALOGE("%s: cannot add reprocess channel", __func__);
211             return UNKNOWN_ERROR;
212         }
213 
214         rc = m_pReprocChannel->start();
215         if (rc != 0) {
216             ALOGE("%s: cannot start reprocess channel", __func__);
217             delete m_pReprocChannel;
218             m_pReprocChannel = NULL;
219             return rc;
220         }
221     }
222 
223     property_get("persist.camera.longshot.save", prop, "0");
224     mUseSaveProc = atoi(prop) > 0 ? true : false;
225 
226     m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_START_DATA_PROC, TRUE, FALSE);
227     m_parent->m_cbNotifier.startSnapshots();
228 
229     // Create Jpeg session
230     if ( !m_parent->mParameters.getRecordingHintValue() &&
231             !m_parent->isLongshotEnabled() &&
232             !m_parent->isZSLMode()) {
233 
234         QCameraChannel *pChannel = NULL;
235         pChannel = m_parent->needReprocess() ? m_pReprocChannel : pSrcChannel;
236         QCameraStream *pSnapshotStream = NULL;
237         QCameraStream *pThumbStream = NULL;
238 
239         for (int i = 0; i < pChannel->getNumOfStreams(); ++i) {
240             QCameraStream *pStream = pChannel->getStreamByIndex(i);
241 
242             if ( NULL == pStream ) {
243                 break;
244             }
245 
246             if (pStream->isTypeOf(CAM_STREAM_TYPE_SNAPSHOT) ||
247                     pStream->isOrignalTypeOf(CAM_STREAM_TYPE_SNAPSHOT)) {
248                 pSnapshotStream = pStream;
249             }
250 
251             if (pStream->isTypeOf(CAM_STREAM_TYPE_POSTVIEW) ||
252                     pStream->isOrignalTypeOf(CAM_STREAM_TYPE_POSTVIEW)) {
253                 pThumbStream = pStream;
254             }
255         }
256 
257         // If thumbnail is not part of the reprocess channel, then
258         // try to get it from the source channel
259         if ((NULL == pThumbStream) && (pChannel == m_pReprocChannel)) {
260             for (int i = 0; i < pSrcChannel->getNumOfStreams(); ++i) {
261                 QCameraStream *pStream = pSrcChannel->getStreamByIndex(i);
262 
263                 if ( NULL == pStream ) {
264                     break;
265                 }
266 
267                 if (pStream->isTypeOf(CAM_STREAM_TYPE_POSTVIEW) ||
268                     pStream->isOrignalTypeOf(CAM_STREAM_TYPE_POSTVIEW)) {
269                     pThumbStream = pStream;
270                 }
271             }
272         }
273 
274         if (m_parent->mParameters.generateThumbFromMain()) {
275             pThumbStream = NULL;
276         }
277 
278         if ( NULL != pSnapshotStream ) {
279             mm_jpeg_encode_params_t encodeParam;
280             memset(&encodeParam, 0, sizeof(mm_jpeg_encode_params_t));
281             getJpegEncodingConfig(encodeParam, pSnapshotStream, pThumbStream);
282             CDBG_HIGH("[KPI Perf] %s : call jpeg create_session", __func__);
283 
284             rc = mJpegHandle.create_session(mJpegClientHandle,
285                     &encodeParam,
286                     &mJpegSessionId);
287             if (rc != NO_ERROR) {
288                 ALOGE("%s: error creating a new jpeg encoding session", __func__);
289                 return rc;
290             }
291             mNewJpegSessionNeeded = false;
292         }
293     }
294 
295     return rc;
296 }
297 
298 /*===========================================================================
299  * FUNCTION   : stop
300  *
301  * DESCRIPTION: stop postprocessor. Data process and notify thread will be stopped.
302  *
303  * PARAMETERS : None
304  *
305  * RETURN     : int32_t type of status
306  *              NO_ERROR  -- success
307  *              none-zero failure code
308  *
309  * NOTE       : reprocess channel will be stopped and deleted if there is any
310  *==========================================================================*/
stop()311 int32_t QCameraPostProcessor::stop()
312 {
313     if (m_bInited == TRUE) {
314         m_parent->m_cbNotifier.stopSnapshots();
315         // dataProc Thread need to process "stop" as sync call because abort jpeg job should be a sync call
316         m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_STOP_DATA_PROC, TRUE, TRUE);
317     }
318 
319     return NO_ERROR;
320 }
321 
322 /*===========================================================================
323  * FUNCTION   : getJpegEncodingConfig
324  *
325  * DESCRIPTION: function to prepare encoding job information
326  *
327  * PARAMETERS :
328  *   @encode_parm   : param to be filled with encoding configuration
329  *
330  * RETURN     : int32_t type of status
331  *              NO_ERROR  -- success
332  *              none-zero failure code
333  *==========================================================================*/
getJpegEncodingConfig(mm_jpeg_encode_params_t & encode_parm,QCameraStream * main_stream,QCameraStream * thumb_stream)334 int32_t QCameraPostProcessor::getJpegEncodingConfig(mm_jpeg_encode_params_t& encode_parm,
335                                                     QCameraStream *main_stream,
336                                                     QCameraStream *thumb_stream)
337 {
338     CDBG("%s : E", __func__);
339     int32_t ret = NO_ERROR;
340     uint32_t out_size;
341 
342     char prop[PROPERTY_VALUE_MAX];
343     property_get("persist.camera.jpeg_burst", prop, "0");
344     mUseJpegBurst = (atoi(prop) > 0) && !mUseSaveProc;
345     encode_parm.burst_mode = mUseJpegBurst;
346 
347     cam_rect_t crop;
348     memset(&crop, 0, sizeof(cam_rect_t));
349     main_stream->getCropInfo(crop);
350 
351     cam_dimension_t src_dim, dst_dim;
352     memset(&src_dim, 0, sizeof(cam_dimension_t));
353     memset(&dst_dim, 0, sizeof(cam_dimension_t));
354     main_stream->getFrameDimension(src_dim);
355 
356     bool hdr_output_crop = m_parent->mParameters.isHDROutputCropEnabled();
357     if (hdr_output_crop && crop.height) {
358         dst_dim.height = crop.height;
359     } else {
360         dst_dim.height = src_dim.height;
361     }
362     if (hdr_output_crop && crop.width) {
363         dst_dim.width = crop.width;
364     } else {
365         dst_dim.width = src_dim.width;
366     }
367 
368     // set rotation only when no online rotation or offline pp rotation is done before
369     if (!m_parent->needRotationReprocess()) {
370         encode_parm.rotation = m_parent->getJpegRotation();
371     }
372 
373     encode_parm.main_dim.src_dim = src_dim;
374     encode_parm.main_dim.dst_dim = dst_dim;
375 
376     encode_parm.jpeg_cb = mJpegCB;
377     encode_parm.userdata = mJpegUserData;
378 
379     m_bThumbnailNeeded = TRUE; // need encode thumbnail by default
380     cam_dimension_t thumbnailSize;
381     memset(&thumbnailSize, 0, sizeof(cam_dimension_t));
382     m_parent->getThumbnailSize(thumbnailSize);
383     if (thumbnailSize.width == 0 || thumbnailSize.height == 0) {
384         // (0,0) means no thumbnail
385         m_bThumbnailNeeded = FALSE;
386     }
387     encode_parm.encode_thumbnail = m_bThumbnailNeeded;
388 
389     // get color format
390     cam_format_t img_fmt = CAM_FORMAT_YUV_420_NV12;
391     main_stream->getFormat(img_fmt);
392     encode_parm.color_format = getColorfmtFromImgFmt(img_fmt);
393 
394     // get jpeg quality
395     encode_parm.quality = m_parent->getJpegQuality();
396     if (encode_parm.quality <= 0) {
397         encode_parm.quality = 85;
398     }
399     cam_frame_len_offset_t main_offset;
400     memset(&main_offset, 0, sizeof(cam_frame_len_offset_t));
401     main_stream->getFrameOffset(main_offset);
402 
403     // src buf config
404     QCameraMemory *pStreamMem = main_stream->getStreamBufs();
405     if (pStreamMem == NULL) {
406         ALOGE("%s: cannot get stream bufs from main stream", __func__);
407         ret = BAD_VALUE;
408         goto on_error;
409     }
410     encode_parm.num_src_bufs = pStreamMem->getCnt();
411     for (uint32_t i = 0; i < encode_parm.num_src_bufs; i++) {
412         camera_memory_t *stream_mem = pStreamMem->getMemory(i, false);
413         if (stream_mem != NULL) {
414             encode_parm.src_main_buf[i].index = i;
415             encode_parm.src_main_buf[i].buf_size = stream_mem->size;
416             encode_parm.src_main_buf[i].buf_vaddr = (uint8_t *)stream_mem->data;
417             encode_parm.src_main_buf[i].fd = pStreamMem->getFd(i);
418             encode_parm.src_main_buf[i].format = MM_JPEG_FMT_YUV;
419             encode_parm.src_main_buf[i].offset = main_offset;
420         }
421     }
422 
423     if (m_bThumbnailNeeded == TRUE) {
424         bool need_thumb_rotate = true;
425         int jpeg_rotation = m_parent->getJpegRotation();
426         m_parent->getThumbnailSize(encode_parm.thumb_dim.dst_dim);
427 
428         if (thumb_stream == NULL) {
429             thumb_stream = main_stream;
430             need_thumb_rotate = false;
431         }
432         pStreamMem = thumb_stream->getStreamBufs();
433         if (pStreamMem == NULL) {
434             ALOGE("%s: cannot get stream bufs from thumb stream", __func__);
435             ret = BAD_VALUE;
436             goto on_error;
437         }
438         cam_frame_len_offset_t thumb_offset;
439         memset(&thumb_offset, 0, sizeof(cam_frame_len_offset_t));
440         thumb_stream->getFrameOffset(thumb_offset);
441         encode_parm.num_tmb_bufs =  pStreamMem->getCnt();
442         for (int i = 0; i < pStreamMem->getCnt(); i++) {
443             camera_memory_t *stream_mem = pStreamMem->getMemory(i, false);
444             if (stream_mem != NULL) {
445                 encode_parm.src_thumb_buf[i].index = i;
446                 encode_parm.src_thumb_buf[i].buf_size = stream_mem->size;
447                 encode_parm.src_thumb_buf[i].buf_vaddr = (uint8_t *)stream_mem->data;
448                 encode_parm.src_thumb_buf[i].fd = pStreamMem->getFd(i);
449                 encode_parm.src_thumb_buf[i].format = MM_JPEG_FMT_YUV;
450                 encode_parm.src_thumb_buf[i].offset = thumb_offset;
451             }
452         }
453         cam_format_t img_fmt_thumb = CAM_FORMAT_YUV_420_NV12;
454         thumb_stream->getFormat(img_fmt_thumb);
455         encode_parm.thumb_color_format = getColorfmtFromImgFmt(img_fmt_thumb);
456 
457         // crop is the same if frame is the same
458         if (thumb_stream != main_stream) {
459             memset(&crop, 0, sizeof(cam_rect_t));
460             thumb_stream->getCropInfo(crop);
461         }
462 
463         memset(&src_dim, 0, sizeof(cam_dimension_t));
464         thumb_stream->getFrameDimension(src_dim);
465         encode_parm.thumb_dim.src_dim = src_dim;
466 
467         if (!m_parent->needRotationReprocess() || need_thumb_rotate) {
468             encode_parm.thumb_rotation = jpeg_rotation;
469         } else if ((90 == jpeg_rotation) || (270 == jpeg_rotation)) {
470             // swap thumbnail dimensions
471             cam_dimension_t tmp_dim = encode_parm.thumb_dim.dst_dim;
472             encode_parm.thumb_dim.dst_dim.width = tmp_dim.height;
473             encode_parm.thumb_dim.dst_dim.height = tmp_dim.width;
474         }
475         encode_parm.thumb_dim.crop = crop;
476     }
477 
478     encode_parm.num_dst_bufs = 1;
479     if (mUseJpegBurst) {
480         encode_parm.num_dst_bufs = MAX_JPEG_BURST;
481     }
482     encode_parm.get_memory = NULL;
483     out_size = main_offset.frame_len;
484     if (mJpegMemOpt) {
485         encode_parm.get_memory = getJpegMemory;
486         out_size = sizeof(omx_jpeg_ouput_buf_t);
487         encode_parm.num_dst_bufs = encode_parm.num_src_bufs;
488     }
489     m_JpegOutputMemCount = encode_parm.num_dst_bufs;
490     for (int i = 0; i < (int)m_JpegOutputMemCount; i++) {
491         if (m_pJpegOutputMem[i] != NULL)
492           free(m_pJpegOutputMem[i]);
493         omx_jpeg_ouput_buf_t omx_out_buf;
494         omx_out_buf.handle = this;
495         // allocate output buf for jpeg encoding
496         m_pJpegOutputMem[i] = malloc(out_size);
497 
498         if (NULL == m_pJpegOutputMem[i]) {
499           ret = NO_MEMORY;
500           ALOGE("%s : initHeapMem for jpeg, ret = NO_MEMORY", __func__);
501           goto on_error;
502         }
503 
504         if (mJpegMemOpt) {
505             memcpy(m_pJpegOutputMem[i], &omx_out_buf, sizeof(omx_out_buf));
506         }
507 
508 
509         encode_parm.dest_buf[i].index = i;
510         encode_parm.dest_buf[i].buf_size = main_offset.frame_len;
511         encode_parm.dest_buf[i].buf_vaddr = (uint8_t *)m_pJpegOutputMem[i];
512         encode_parm.dest_buf[i].fd = 0;
513         encode_parm.dest_buf[i].format = MM_JPEG_FMT_YUV;
514         encode_parm.dest_buf[i].offset = main_offset;
515     }
516 
517 
518     CDBG("%s : X", __func__);
519     return NO_ERROR;
520 
521 on_error:
522     FREE_JPEG_OUTPUT_BUFFER(m_pJpegOutputMem, m_JpegOutputMemCount);
523 
524     CDBG("%s : X with error %d", __func__, ret);
525     return ret;
526 }
527 
528 /*===========================================================================
529  * FUNCTION   : sendEvtNotify
530  *
531  * DESCRIPTION: send event notify through notify callback registered by upper layer
532  *
533  * PARAMETERS :
534  *   @msg_type: msg type of notify
535  *   @ext1    : extension
536  *   @ext2    : extension
537  *
538  * RETURN     : int32_t type of status
539  *              NO_ERROR  -- success
540  *              none-zero failure code
541  *==========================================================================*/
sendEvtNotify(int32_t msg_type,int32_t ext1,int32_t ext2)542 int32_t QCameraPostProcessor::sendEvtNotify(int32_t msg_type,
543                                             int32_t ext1,
544                                             int32_t ext2)
545 {
546     return m_parent->sendEvtNotify(msg_type, ext1, ext2);
547 }
548 
549 /*===========================================================================
550  * FUNCTION   : sendDataNotify
551  *
552  * DESCRIPTION: enqueue data into dataNotify thread
553  *
554  * PARAMETERS :
555  *   @msg_type: data callback msg type
556  *   @data    : ptr to data memory struct
557  *   @index   : index to data buffer
558  *   @metadata: ptr to meta data buffer if there is any
559  *   @release_data : ptr to struct indicating if data need to be released
560  *                   after notify
561  *
562  * RETURN     : int32_t type of status
563  *              NO_ERROR  -- success
564  *              none-zero failure code
565  *==========================================================================*/
sendDataNotify(int32_t msg_type,camera_memory_t * data,uint8_t index,camera_frame_metadata_t * metadata,qcamera_release_data_t * release_data)566 int32_t QCameraPostProcessor::sendDataNotify(int32_t msg_type,
567                                              camera_memory_t *data,
568                                              uint8_t index,
569                                              camera_frame_metadata_t *metadata,
570                                              qcamera_release_data_t *release_data)
571 {
572     qcamera_data_argm_t *data_cb = (qcamera_data_argm_t *)malloc(sizeof(qcamera_data_argm_t));
573     if (NULL == data_cb) {
574         ALOGE("%s: no mem for acamera_data_argm_t", __func__);
575         return NO_MEMORY;
576     }
577     memset(data_cb, 0, sizeof(qcamera_data_argm_t));
578     data_cb->msg_type = msg_type;
579     data_cb->data = data;
580     data_cb->index = index;
581     data_cb->metadata = metadata;
582     if (release_data != NULL) {
583         data_cb->release_data = *release_data;
584     }
585 
586     qcamera_callback_argm_t cbArg;
587     memset(&cbArg, 0, sizeof(qcamera_callback_argm_t));
588     cbArg.cb_type = QCAMERA_DATA_SNAPSHOT_CALLBACK;
589     cbArg.msg_type = msg_type;
590     cbArg.data = data;
591     cbArg.metadata = metadata;
592     cbArg.user_data = data_cb;
593     cbArg.cookie = this;
594     cbArg.release_cb = releaseNotifyData;
595     int rc = m_parent->m_cbNotifier.notifyCallback(cbArg);
596     if ( NO_ERROR != rc ) {
597         ALOGE("%s: Error enqueuing jpeg data into notify queue", __func__);
598         releaseNotifyData(data_cb, this, UNKNOWN_ERROR);
599         return UNKNOWN_ERROR;
600     }
601 
602     return rc;
603 }
604 
605 /*===========================================================================
606  * FUNCTION   : processData
607  *
608  * DESCRIPTION: enqueue data into dataProc thread
609  *
610  * PARAMETERS :
611  *   @frame   : process frame received from mm-camera-interface
612  *
613  * RETURN     : int32_t type of status
614  *              NO_ERROR  -- success
615  *              none-zero failure code
616  *
617  * NOTE       : depends on if offline reprocess is needed, received frame will
618  *              be sent to either input queue of postprocess or jpeg encoding
619  *==========================================================================*/
processData(mm_camera_super_buf_t * frame)620 int32_t QCameraPostProcessor::processData(mm_camera_super_buf_t *frame)
621 {
622     if (m_bInited == FALSE) {
623         ALOGE("%s: postproc not initialized yet", __func__);
624         return UNKNOWN_ERROR;
625     }
626 
627     if (m_parent->needReprocess()) {
628         if ((!m_parent->isLongshotEnabled() &&
629              !m_parent->m_stateMachine.isNonZSLCaptureRunning()) ||
630             (m_parent->isLongshotEnabled() &&
631              m_parent->isCaptureShutterEnabled())) {
632             //play shutter sound
633             m_parent->playShutter();
634         }
635 
636         CDBG_HIGH("%s: need reprocess", __func__);
637         // enqueu to post proc input queue
638         m_inputPPQ.enqueue((void *)frame);
639     } else if (m_parent->mParameters.isNV16PictureFormat() ||
640         m_parent->mParameters.isNV21PictureFormat()) {
641         //check if raw frame information is needed.
642         if(m_parent->mParameters.isYUVFrameInfoNeeded())
643             setYUVFrameInfo(frame);
644 
645         processRawData(frame);
646     } else {
647         //play shutter sound
648         if(!m_parent->m_stateMachine.isNonZSLCaptureRunning() &&
649            !m_parent->mLongshotEnabled)
650            m_parent->playShutter();
651 
652         CDBG_HIGH("%s: no need offline reprocess, sending to jpeg encoding", __func__);
653         qcamera_jpeg_data_t *jpeg_job =
654             (qcamera_jpeg_data_t *)malloc(sizeof(qcamera_jpeg_data_t));
655         if (jpeg_job == NULL) {
656             ALOGE("%s: No memory for jpeg job", __func__);
657             return NO_MEMORY;
658         }
659 
660         memset(jpeg_job, 0, sizeof(qcamera_jpeg_data_t));
661         jpeg_job->src_frame = frame;
662 
663         // find meta data frame
664         mm_camera_buf_def_t *meta_frame = NULL;
665         for (int i = 0; i < frame->num_bufs; i++) {
666             // look through input superbuf
667             if (frame->bufs[i]->stream_type == CAM_STREAM_TYPE_METADATA) {
668                 meta_frame = frame->bufs[i];
669                 break;
670             }
671         }
672 
673         if (meta_frame != NULL) {
674             // fill in meta data frame ptr
675             jpeg_job->metadata = (metadata_buffer_t *)meta_frame->buffer;
676         }
677 
678         // enqueu to jpeg input queue
679         m_inputJpegQ.enqueue((void *)jpeg_job);
680     }
681     m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_DO_NEXT_JOB, FALSE, FALSE);
682 
683     return NO_ERROR;
684 }
685 
686 /*===========================================================================
687  * FUNCTION   : processRawData
688  *
689  * DESCRIPTION: enqueue raw data into dataProc thread
690  *
691  * PARAMETERS :
692  *   @frame   : process frame received from mm-camera-interface
693  *
694  * RETURN     : int32_t type of status
695  *              NO_ERROR  -- success
696  *              none-zero failure code
697  *==========================================================================*/
processRawData(mm_camera_super_buf_t * frame)698 int32_t QCameraPostProcessor::processRawData(mm_camera_super_buf_t *frame)
699 {
700     if (m_bInited == FALSE) {
701         ALOGE("%s: postproc not initialized yet", __func__);
702         return UNKNOWN_ERROR;
703     }
704 
705     // enqueu to raw input queue
706     m_inputRawQ.enqueue((void *)frame);
707     m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_DO_NEXT_JOB, FALSE, FALSE);
708     return NO_ERROR;
709 }
710 
711 /*===========================================================================
712  * FUNCTION   : processJpegEvt
713  *
714  * DESCRIPTION: process jpeg event from mm-jpeg-interface.
715  *
716  * PARAMETERS :
717  *   @evt     : payload of jpeg event, including information about jpeg encoding
718  *              status, jpeg size and so on.
719  *
720  * RETURN     : int32_t type of status
721  *              NO_ERROR  -- success
722  *              none-zero failure code
723  *
724  * NOTE       : This event will also trigger DataProc thread to move to next job
725  *              processing (i.e., send a new jpeg encoding job to mm-jpeg-interface
726  *              if there is any pending job in jpeg input queue)
727  *==========================================================================*/
processJpegEvt(qcamera_jpeg_evt_payload_t * evt)728 int32_t QCameraPostProcessor::processJpegEvt(qcamera_jpeg_evt_payload_t *evt)
729 {
730     if (m_bInited == FALSE) {
731         ALOGE("%s: postproc not initialized yet", __func__);
732         return UNKNOWN_ERROR;
733     }
734 
735     int32_t rc = NO_ERROR;
736     camera_memory_t *jpeg_mem = NULL;
737     omx_jpeg_ouput_buf_t *jpeg_out = NULL;
738 
739     if (mUseSaveProc && m_parent->isLongshotEnabled()) {
740         qcamera_jpeg_evt_payload_t *saveData = ( qcamera_jpeg_evt_payload_t * ) malloc(sizeof(qcamera_jpeg_evt_payload_t));
741         if ( NULL == saveData ) {
742             ALOGE("%s: Can not allocate save data message!", __func__);
743             return NO_MEMORY;
744         }
745         *saveData = *evt;
746         m_inputSaveQ.enqueue((void *) saveData);
747         m_saveProcTh.sendCmd(CAMERA_CMD_TYPE_DO_NEXT_JOB, FALSE, FALSE);
748     } else {
749         // Release jpeg job data
750         m_ongoingJpegQ.flushNodes(matchJobId, (void*)&evt->jobId);
751 
752         CDBG_HIGH("[KPI Perf] %s : jpeg job %d", __func__, evt->jobId);
753 
754         if (m_parent->mDataCb == NULL ||
755             m_parent->msgTypeEnabledWithLock(CAMERA_MSG_COMPRESSED_IMAGE) == 0 ) {
756             CDBG_HIGH("%s: No dataCB or CAMERA_MSG_COMPRESSED_IMAGE not enabled",
757                   __func__);
758             rc = NO_ERROR;
759             goto end;
760         }
761 
762         if(evt->status == JPEG_JOB_STATUS_ERROR) {
763             ALOGE("%s: Error event handled from jpeg, status = %d",
764                   __func__, evt->status);
765             rc = FAILED_TRANSACTION;
766             goto end;
767         }
768 
769         m_parent->dumpJpegToFile(evt->out_data.buf_vaddr,
770                                   evt->out_data.buf_filled_len,
771                                   evt->jobId);
772         CDBG_HIGH("%s: Dump jpeg_size=%d", __func__, evt->out_data.buf_filled_len);
773 
774         /* check if the all the captures are done */
775         if (m_parent->mParameters.isUbiRefocus() &&
776             (m_parent->getOutputImageCount() <
777             m_parent->mParameters.UfOutputCount())) {
778             jpeg_out  = (omx_jpeg_ouput_buf_t*) evt->out_data.buf_vaddr;
779             jpeg_mem = (camera_memory_t *)jpeg_out->mem_hdl;
780             if (NULL != jpeg_mem) {
781                 jpeg_mem->release(jpeg_mem);
782                 jpeg_mem = NULL;
783             }
784             goto end;
785         }
786 
787         if (!mJpegMemOpt) {
788             // alloc jpeg memory to pass to upper layer
789             jpeg_mem = m_parent->mGetMemory(-1, evt->out_data.buf_filled_len,
790                 1, m_parent->mCallbackCookie);
791             if (NULL == jpeg_mem) {
792                 rc = NO_MEMORY;
793                 ALOGE("%s : getMemory for jpeg, ret = NO_MEMORY", __func__);
794                 goto end;
795             }
796             memcpy(jpeg_mem->data, evt->out_data.buf_vaddr, evt->out_data.buf_filled_len);
797         } else {
798             jpeg_out  = (omx_jpeg_ouput_buf_t*) evt->out_data.buf_vaddr;
799             jpeg_mem = (camera_memory_t *)jpeg_out->mem_hdl;
800         }
801 
802         CDBG_HIGH("%s : Calling upperlayer callback to store JPEG image", __func__);
803         qcamera_release_data_t release_data;
804         memset(&release_data, 0, sizeof(qcamera_release_data_t));
805         release_data.data = jpeg_mem;
806         CDBG_HIGH("[KPI Perf] %s: PROFILE_JPEG_CB ",__func__);
807         rc = sendDataNotify(CAMERA_MSG_COMPRESSED_IMAGE,
808                             jpeg_mem,
809                             0,
810                             NULL,
811                             &release_data);
812 
813 end:
814         if (rc != NO_ERROR) {
815             // send error msg to upper layer
816             sendEvtNotify(CAMERA_MSG_ERROR,
817                           UNKNOWN_ERROR,
818                           0);
819 
820             if (NULL != jpeg_mem) {
821                 jpeg_mem->release(jpeg_mem);
822                 jpeg_mem = NULL;
823             }
824         }
825     }
826 
827     // wait up data proc thread to do next job,
828     // if previous request is blocked due to ongoing jpeg job
829     m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_DO_NEXT_JOB, FALSE, FALSE);
830 
831     return rc;
832 }
833 
834 /*===========================================================================
835  * FUNCTION   : processPPData
836  *
837  * DESCRIPTION: process received frame after reprocess.
838  *
839  * PARAMETERS :
840  *   @frame   : received frame from reprocess channel.
841  *
842  * RETURN     : int32_t type of status
843  *              NO_ERROR  -- success
844  *              none-zero failure code
845  *
846  * NOTE       : The frame after reprocess need to send to jpeg encoding.
847  *==========================================================================*/
processPPData(mm_camera_super_buf_t * frame)848 int32_t QCameraPostProcessor::processPPData(mm_camera_super_buf_t *frame)
849 {
850     bool needSuperBufMatch = m_parent->mParameters.generateThumbFromMain();
851     if (m_bInited == FALSE) {
852         ALOGE("%s: postproc not initialized yet", __func__);
853         return UNKNOWN_ERROR;
854     }
855 
856     qcamera_pp_data_t *job = (qcamera_pp_data_t *)m_ongoingPPQ.dequeue();
857 
858     if (!needSuperBufMatch && (job == NULL || job->src_frame == NULL) ) {
859         ALOGE("%s: Cannot find reprocess job", __func__);
860         return BAD_VALUE;
861     }
862 
863     if (!needSuperBufMatch && (m_parent->mParameters.isNV16PictureFormat() ||
864         m_parent->mParameters.isNV21PictureFormat())) {
865         releaseSuperBuf(job->src_frame);
866         free(job->src_frame);
867         free(job);
868 
869         if(m_parent->mParameters.isYUVFrameInfoNeeded())
870             setYUVFrameInfo(frame);
871         return processRawData(frame);
872     }
873 
874     if (m_parent->isLongshotEnabled() &&
875             !m_parent->isCaptureShutterEnabled()) {
876         // play shutter sound for longshot
877         // after reprocess is done
878         // TODO: Move this after CAC done event
879         m_parent->playShutter();
880     }
881 
882     qcamera_jpeg_data_t *jpeg_job =
883         (qcamera_jpeg_data_t *)malloc(sizeof(qcamera_jpeg_data_t));
884     if (jpeg_job == NULL) {
885         ALOGE("%s: No memory for jpeg job", __func__);
886         return NO_MEMORY;
887     }
888 
889     memset(jpeg_job, 0, sizeof(qcamera_jpeg_data_t));
890     jpeg_job->src_frame = frame;
891     jpeg_job->src_reproc_frame = job ? job->src_frame : NULL;
892     jpeg_job->src_reproc_bufs = job ? job->src_reproc_bufs : NULL;
893     jpeg_job->reproc_frame_release = job ? job->reproc_frame_release : false;
894 
895     // find meta data frame
896     mm_camera_buf_def_t *meta_frame = NULL;
897     for (int i = 0; job && (i < job->src_frame->num_bufs); i++) {
898         // look through input superbuf
899         if (job->src_frame->bufs[i]->stream_type == CAM_STREAM_TYPE_METADATA) {
900             meta_frame = job->src_frame->bufs[i];
901             break;
902         }
903     }
904 
905     if (meta_frame == NULL) {
906         // look through reprocess superbuf
907         for (int i = 0; i < frame->num_bufs; i++) {
908             if (frame->bufs[i]->stream_type == CAM_STREAM_TYPE_METADATA) {
909                 meta_frame = frame->bufs[i];
910                 break;
911             }
912         }
913     }
914 
915     if (meta_frame != NULL) {
916         // fill in meta data frame ptr
917         jpeg_job->metadata = (metadata_buffer_t *)meta_frame->buffer;
918     }
919 
920     // free pp job buf
921     if (job) {
922         free(job);
923     }
924 
925     // enqueu reprocessed frame to jpeg input queue
926     m_inputJpegQ.enqueue((void *)jpeg_job);
927 
928     ALOGD("%s: %d] ", __func__, __LINE__);
929     // wait up data proc thread
930     m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_DO_NEXT_JOB, FALSE, FALSE);
931 
932     return NO_ERROR;
933 }
934 
935 /*===========================================================================
936  * FUNCTION   : findJpegJobByJobId
937  *
938  * DESCRIPTION: find a jpeg job from ongoing Jpeg queue by its job ID
939  *
940  * PARAMETERS :
941  *   @jobId   : job Id of the job
942  *
943  * RETURN     : ptr to a jpeg job struct. NULL if not found.
944  *
945  * NOTE       : Currently only one job is sending to mm-jpeg-interface for jpeg
946  *              encoding. Therefore simply dequeue from the ongoing Jpeg Queue
947  *              will serve the purpose to find the jpeg job.
948  *==========================================================================*/
findJpegJobByJobId(uint32_t jobId)949 qcamera_jpeg_data_t *QCameraPostProcessor::findJpegJobByJobId(uint32_t jobId)
950 {
951     qcamera_jpeg_data_t * job = NULL;
952     if (jobId == 0) {
953         ALOGE("%s: not a valid jpeg jobId", __func__);
954         return NULL;
955     }
956 
957     // currely only one jpeg job ongoing, so simply dequeue the head
958     job = (qcamera_jpeg_data_t *)m_ongoingJpegQ.dequeue();
959     return job;
960 }
961 
962 /*===========================================================================
963  * FUNCTION   : releasePPInputData
964  *
965  * DESCRIPTION: callback function to release post process input data node
966  *
967  * PARAMETERS :
968  *   @data      : ptr to post process input data
969  *   @user_data : user data ptr (QCameraReprocessor)
970  *
971  * RETURN     : None
972  *==========================================================================*/
releasePPInputData(void * data,void * user_data)973 void QCameraPostProcessor::releasePPInputData(void *data, void *user_data)
974 {
975     QCameraPostProcessor *pme = (QCameraPostProcessor *)user_data;
976     if (NULL != pme) {
977         pme->releaseSuperBuf((mm_camera_super_buf_t *)data);
978     }
979 }
980 
981 /*===========================================================================
982  * FUNCTION   : releaseJpegData
983  *
984  * DESCRIPTION: callback function to release jpeg job node
985  *
986  * PARAMETERS :
987  *   @data      : ptr to ongoing jpeg job data
988  *   @user_data : user data ptr (QCameraReprocessor)
989  *
990  * RETURN     : None
991  *==========================================================================*/
releaseJpegData(void * data,void * user_data)992 void QCameraPostProcessor::releaseJpegData(void *data, void *user_data)
993 {
994     QCameraPostProcessor *pme = (QCameraPostProcessor *)user_data;
995     if (NULL != pme) {
996         pme->releaseJpegJobData((qcamera_jpeg_data_t *)data);
997         CDBG_HIGH("%s : Rleased job ID %u", __func__,
998             ((qcamera_jpeg_data_t *)data)->jobId);
999     }
1000 }
1001 
1002 /*===========================================================================
1003  * FUNCTION   : releaseOngoingPPData
1004  *
1005  * DESCRIPTION: callback function to release ongoing postprocess job node
1006  *
1007  * PARAMETERS :
1008  *   @data      : ptr to onging postprocess job
1009  *   @user_data : user data ptr (QCameraReprocessor)
1010  *
1011  * RETURN     : None
1012  *==========================================================================*/
releaseOngoingPPData(void * data,void * user_data)1013 void QCameraPostProcessor::releaseOngoingPPData(void *data, void *user_data)
1014 {
1015     QCameraPostProcessor *pme = (QCameraPostProcessor *)user_data;
1016     if (NULL != pme) {
1017         qcamera_pp_data_t *pp_job = (qcamera_pp_data_t *)data;
1018         if (NULL != pp_job->src_frame) {
1019             if (!pp_job->reproc_frame_release) {
1020                 pme->releaseSuperBuf(pp_job->src_frame);
1021             }
1022             free(pp_job->src_frame);
1023             pp_job->src_frame = NULL;
1024         }
1025     }
1026 }
1027 
1028 /*===========================================================================
1029  * FUNCTION   : releaseNotifyData
1030  *
1031  * DESCRIPTION: function to release internal resources in notify data struct
1032  *
1033  * PARAMETERS :
1034  *   @user_data  : ptr user data
1035  *   @cookie     : callback cookie
1036  *   @cb_status  : callback status
1037  *
1038  * RETURN     : None
1039  *
1040  * NOTE       : deallocate jpeg heap memory if it's not NULL
1041  *==========================================================================*/
releaseNotifyData(void * user_data,void * cookie,int32_t cb_status)1042 void QCameraPostProcessor::releaseNotifyData(void *user_data,
1043                                              void *cookie,
1044                                              int32_t cb_status)
1045 {
1046     qcamera_data_argm_t *app_cb = ( qcamera_data_argm_t * ) user_data;
1047     QCameraPostProcessor *postProc = ( QCameraPostProcessor * ) cookie;
1048     if ( ( NULL != app_cb ) && ( NULL != postProc ) ) {
1049 
1050         if ( postProc->mUseSaveProc &&
1051              app_cb->release_data.unlinkFile &&
1052              ( NO_ERROR != cb_status ) ) {
1053 
1054             String8 unlinkPath((const char *) app_cb->release_data.data->data,
1055                                 app_cb->release_data.data->size);
1056             int rc = unlink(unlinkPath.string());
1057             CDBG_HIGH("%s : Unlinking stored file rc = %d",
1058                   __func__,
1059                   rc);
1060         }
1061 
1062         if (app_cb && NULL != app_cb->release_data.data) {
1063             app_cb->release_data.data->release(app_cb->release_data.data);
1064             app_cb->release_data.data = NULL;
1065         }
1066         if (app_cb && NULL != app_cb->release_data.frame) {
1067             postProc->releaseSuperBuf(app_cb->release_data.frame);
1068             free(app_cb->release_data.frame);
1069             app_cb->release_data.frame = NULL;
1070         }
1071         if (app_cb && NULL != app_cb->release_data.streamBufs) {
1072             app_cb->release_data.streamBufs->deallocate();
1073             delete app_cb->release_data.streamBufs;
1074             app_cb->release_data.streamBufs = NULL;
1075         }
1076         free(app_cb);
1077     }
1078 }
1079 
1080 /*===========================================================================
1081  * FUNCTION   : releaseSuperBuf
1082  *
1083  * DESCRIPTION: function to release a superbuf frame by returning back to kernel
1084  *
1085  * PARAMETERS :
1086  *   @super_buf : ptr to the superbuf frame
1087  *
1088  * RETURN     : None
1089  *==========================================================================*/
releaseSuperBuf(mm_camera_super_buf_t * super_buf)1090 void QCameraPostProcessor::releaseSuperBuf(mm_camera_super_buf_t *super_buf)
1091 {
1092     QCameraChannel *pChannel = NULL;
1093 
1094     if (NULL != super_buf) {
1095         pChannel = m_parent->getChannelByHandle(super_buf->ch_id);
1096 
1097         if ( NULL == pChannel ) {
1098             if (m_pReprocChannel != NULL &&
1099                 m_pReprocChannel->getMyHandle() == super_buf->ch_id) {
1100                 pChannel = m_pReprocChannel;
1101             }
1102         }
1103 
1104         if (pChannel != NULL) {
1105             pChannel->bufDone(super_buf);
1106         } else {
1107             ALOGE(" %s : Channel id %d not found!!",
1108                   __func__,
1109                   super_buf->ch_id);
1110         }
1111     }
1112 }
1113 
1114 /*===========================================================================
1115  * FUNCTION   : releaseJpegJobData
1116  *
1117  * DESCRIPTION: function to release internal resources in jpeg job struct
1118  *
1119  * PARAMETERS :
1120  *   @job     : ptr to jpeg job struct
1121  *
1122  * RETURN     : None
1123  *
1124  * NOTE       : original source frame need to be queued back to kernel for
1125  *              future use. Output buf of jpeg job need to be released since
1126  *              it's allocated for each job. Exif object need to be deleted.
1127  *==========================================================================*/
releaseJpegJobData(qcamera_jpeg_data_t * job)1128 void QCameraPostProcessor::releaseJpegJobData(qcamera_jpeg_data_t *job)
1129 {
1130     CDBG("%s: E", __func__);
1131     if (NULL != job) {
1132         if (NULL != job->src_reproc_frame) {
1133             if (!job->reproc_frame_release) {
1134                 releaseSuperBuf(job->src_reproc_frame);
1135             }
1136             free(job->src_reproc_frame);
1137             job->src_reproc_frame = NULL;
1138         }
1139 
1140         if (NULL != job->src_frame) {
1141             releaseSuperBuf(job->src_frame);
1142             free(job->src_frame);
1143             job->src_frame = NULL;
1144         }
1145 
1146         if (NULL != job->pJpegExifObj) {
1147             delete job->pJpegExifObj;
1148             job->pJpegExifObj = NULL;
1149         }
1150 
1151         if (NULL != job->src_reproc_bufs) {
1152             delete [] job->src_reproc_bufs;
1153         }
1154 
1155     }
1156     CDBG("%s: X", __func__);
1157 }
1158 
1159 /*===========================================================================
1160  * FUNCTION   : releaseSaveJobData
1161  *
1162  * DESCRIPTION: function to release internal resources in store jobs
1163  *
1164  * PARAMETERS :
1165  *   @job     : ptr to save job struct
1166  *
1167  * RETURN     : None
1168  *
1169  *==========================================================================*/
releaseSaveJobData(void * data,void * user_data)1170 void QCameraPostProcessor::releaseSaveJobData(void *data, void *user_data)
1171 {
1172     CDBG("%s: E", __func__);
1173 
1174     QCameraPostProcessor *pme = (QCameraPostProcessor *) user_data;
1175     if (NULL == pme) {
1176         ALOGE("%s: Invalid postproc handle", __func__);
1177         return;
1178     }
1179 
1180     qcamera_jpeg_evt_payload_t *job_data = (qcamera_jpeg_evt_payload_t *) data;
1181     if (job_data == NULL) {
1182         ALOGE("%s: Invalid jpeg event data", __func__);
1183         return;
1184     }
1185 
1186     // find job by jobId
1187     qcamera_jpeg_data_t *job = pme->findJpegJobByJobId(job_data->jobId);
1188 
1189     if (NULL != job) {
1190         pme->releaseJpegJobData(job);
1191         free(job);
1192     } else {
1193         ALOGE("%s : Invalid jpeg job", __func__);
1194     }
1195 
1196     CDBG("%s: X", __func__);
1197 }
1198 
1199 /*===========================================================================
1200  * FUNCTION   : releaseRawData
1201  *
1202  * DESCRIPTION: function to release internal resources in store jobs
1203  *
1204  * PARAMETERS :
1205  *   @job     : ptr to save job struct
1206  *
1207  * RETURN     : None
1208  *
1209  *==========================================================================*/
releaseRawData(void * data,void * user_data)1210 void QCameraPostProcessor::releaseRawData(void *data, void *user_data)
1211 {
1212     CDBG("%s: E", __func__);
1213 
1214     QCameraPostProcessor *pme = (QCameraPostProcessor *) user_data;
1215     if (NULL == pme) {
1216         ALOGE("%s: Invalid postproc handle", __func__);
1217         return;
1218     }
1219     mm_camera_super_buf_t *super_buf = (mm_camera_super_buf_t *) data;
1220     pme->releaseSuperBuf(super_buf);
1221 
1222     CDBG("%s: X", __func__);
1223 }
1224 
1225 
1226 /*===========================================================================
1227  * FUNCTION   : getColorfmtFromImgFmt
1228  *
1229  * DESCRIPTION: function to return jpeg color format based on its image format
1230  *
1231  * PARAMETERS :
1232  *   @img_fmt : image format
1233  *
1234  * RETURN     : jpeg color format that can be understandable by omx lib
1235  *==========================================================================*/
getColorfmtFromImgFmt(cam_format_t img_fmt)1236 mm_jpeg_color_format QCameraPostProcessor::getColorfmtFromImgFmt(cam_format_t img_fmt)
1237 {
1238     switch (img_fmt) {
1239     case CAM_FORMAT_YUV_420_NV21:
1240         return MM_JPEG_COLOR_FORMAT_YCRCBLP_H2V2;
1241     case CAM_FORMAT_YUV_420_NV21_ADRENO:
1242         return MM_JPEG_COLOR_FORMAT_YCRCBLP_H2V2;
1243     case CAM_FORMAT_YUV_420_NV12:
1244         return MM_JPEG_COLOR_FORMAT_YCBCRLP_H2V2;
1245     case CAM_FORMAT_YUV_420_YV12:
1246         return MM_JPEG_COLOR_FORMAT_YCBCRLP_H2V2;
1247     case CAM_FORMAT_YUV_422_NV61:
1248         return MM_JPEG_COLOR_FORMAT_YCRCBLP_H2V1;
1249     case CAM_FORMAT_YUV_422_NV16:
1250         return MM_JPEG_COLOR_FORMAT_YCBCRLP_H2V1;
1251     default:
1252         return MM_JPEG_COLOR_FORMAT_YCRCBLP_H2V2;
1253     }
1254 }
1255 
1256 /*===========================================================================
1257  * FUNCTION   : getJpegImgTypeFromImgFmt
1258  *
1259  * DESCRIPTION: function to return jpeg encode image type based on its image format
1260  *
1261  * PARAMETERS :
1262  *   @img_fmt : image format
1263  *
1264  * RETURN     : return jpeg source image format (YUV or Bitstream)
1265  *==========================================================================*/
getJpegImgTypeFromImgFmt(cam_format_t img_fmt)1266 mm_jpeg_format_t QCameraPostProcessor::getJpegImgTypeFromImgFmt(cam_format_t img_fmt)
1267 {
1268     switch (img_fmt) {
1269     case CAM_FORMAT_YUV_420_NV21:
1270     case CAM_FORMAT_YUV_420_NV21_ADRENO:
1271     case CAM_FORMAT_YUV_420_NV12:
1272     case CAM_FORMAT_YUV_420_YV12:
1273     case CAM_FORMAT_YUV_422_NV61:
1274     case CAM_FORMAT_YUV_422_NV16:
1275         return MM_JPEG_FMT_YUV;
1276     default:
1277         return MM_JPEG_FMT_YUV;
1278     }
1279 }
1280 
1281 /*===========================================================================
1282  * FUNCTION   : queryStreams
1283  *
1284  * DESCRIPTION: utility method for retrieving main, thumbnail and reprocess
1285  *              streams and frame from bundled super buffer
1286  *
1287  * PARAMETERS :
1288  *   @main    : ptr to main stream if present
1289  *   @thumb   : ptr to thumbnail stream if present
1290  *   @reproc  : ptr to reprocess stream if present
1291  *   @main_image : ptr to main image if present
1292  *   @thumb_image: ptr to thumbnail image if present
1293  *   @frame   : bundled super buffer
1294  *   @reproc_frame : bundled source frame buffer
1295  *
1296  * RETURN     : int32_t type of status
1297  *              NO_ERROR  -- success
1298  *              none-zero failure code
1299  *==========================================================================*/
queryStreams(QCameraStream ** main,QCameraStream ** thumb,QCameraStream ** reproc,mm_camera_buf_def_t ** main_image,mm_camera_buf_def_t ** thumb_image,mm_camera_super_buf_t * frame,mm_camera_super_buf_t * reproc_frame)1300 int32_t QCameraPostProcessor::queryStreams(QCameraStream **main,
1301         QCameraStream **thumb,
1302         QCameraStream **reproc,
1303         mm_camera_buf_def_t **main_image,
1304         mm_camera_buf_def_t **thumb_image,
1305         mm_camera_super_buf_t *frame,
1306         mm_camera_super_buf_t *reproc_frame)
1307 {
1308     if (NULL == frame) {
1309         return NO_INIT;
1310     }
1311 
1312     QCameraChannel *pChannel = m_parent->getChannelByHandle(frame->ch_id);
1313     // check reprocess channel if not found
1314     if (pChannel == NULL) {
1315         if (m_pReprocChannel != NULL &&
1316             m_pReprocChannel->getMyHandle() == frame->ch_id) {
1317             pChannel = m_pReprocChannel;
1318         }
1319     }
1320     if (pChannel == NULL) {
1321         ALOGD("%s: No corresponding channel (ch_id = %d) exist, return here",
1322               __func__, frame->ch_id);
1323         return BAD_VALUE;
1324     }
1325 
1326     // Use snapshot stream to create thumbnail if snapshot and preview
1327     // flip settings doesn't match in ZSL mode.
1328     bool thumb_stream_needed = !m_parent->isZSLMode() ||
1329         (m_parent->mParameters.getFlipMode(CAM_STREAM_TYPE_SNAPSHOT) ==
1330          m_parent->mParameters.getFlipMode(CAM_STREAM_TYPE_PREVIEW));
1331 
1332     *main = *thumb = *reproc = NULL;
1333     *main_image = *thumb_image = NULL;
1334     // find snapshot frame and thumnail frame
1335     for (int i = 0; i < frame->num_bufs; i++) {
1336         QCameraStream *pStream =
1337                 pChannel->getStreamByHandle(frame->bufs[i]->stream_id);
1338         if (pStream != NULL) {
1339             if (pStream->isTypeOf(CAM_STREAM_TYPE_SNAPSHOT) ||
1340                 pStream->isOrignalTypeOf(CAM_STREAM_TYPE_SNAPSHOT)) {
1341                 *main= pStream;
1342                 *main_image = frame->bufs[i];
1343             } else if (thumb_stream_needed &&
1344                        (pStream->isTypeOf(CAM_STREAM_TYPE_PREVIEW) ||
1345                         pStream->isTypeOf(CAM_STREAM_TYPE_POSTVIEW) ||
1346                         pStream->isOrignalTypeOf(CAM_STREAM_TYPE_PREVIEW) ||
1347                         pStream->isOrignalTypeOf(CAM_STREAM_TYPE_POSTVIEW))) {
1348                 *thumb = pStream;
1349                 *thumb_image = frame->bufs[i];
1350             }
1351             if (pStream->isTypeOf(CAM_STREAM_TYPE_OFFLINE_PROC) ) {
1352                 *reproc = pStream;
1353             }
1354         }
1355     }
1356 
1357     if (thumb_stream_needed && *thumb_image == NULL && reproc_frame != NULL) {
1358         QCameraChannel *pSrcReprocChannel = NULL;
1359         pSrcReprocChannel = m_parent->getChannelByHandle(reproc_frame->ch_id);
1360         if (pSrcReprocChannel != NULL) {
1361             // find thumbnail frame
1362             for (int i = 0; i < reproc_frame->num_bufs; i++) {
1363                 QCameraStream *pStream =
1364                         pSrcReprocChannel->getStreamByHandle(
1365                                 reproc_frame->bufs[i]->stream_id);
1366                 if (pStream != NULL) {
1367                     if (pStream->isTypeOf(CAM_STREAM_TYPE_PREVIEW) ||
1368                         pStream->isTypeOf(CAM_STREAM_TYPE_POSTVIEW)) {
1369                         *thumb = pStream;
1370                         *thumb_image = reproc_frame->bufs[i];
1371                     }
1372                 }
1373             }
1374         }
1375     }
1376 
1377     if (m_parent->mParameters.generateThumbFromMain()) {
1378         *thumb = NULL;
1379         *thumb_image = NULL;
1380     }
1381 
1382     return NO_ERROR;
1383 }
1384 
1385 /*===========================================================================
1386 * FUNCTION   : syncStreamParams
1387 *
1388 * DESCRIPTION: Query the runtime parameters of all streams included
1389 *              in the main and reprocessed frames
1390 *
1391 * PARAMETERS :
1392 *   @frame : Main image super buffer
1393 *   @reproc_frame : Image supper buffer that got processed
1394 *
1395 * RETURN     : int32_t type of status
1396 *              NO_ERROR  -- success
1397 *              none-zero failure code
1398 *==========================================================================*/
syncStreamParams(mm_camera_super_buf_t * frame,mm_camera_super_buf_t * reproc_frame)1399 int32_t QCameraPostProcessor::syncStreamParams(mm_camera_super_buf_t *frame,
1400         mm_camera_super_buf_t *reproc_frame)
1401 {
1402     QCameraStream *reproc_stream = NULL;
1403     QCameraStream *main_stream = NULL;
1404     QCameraStream *thumb_stream = NULL;
1405     mm_camera_buf_def_t *main_frame = NULL;
1406     mm_camera_buf_def_t *thumb_frame = NULL;
1407     int32_t ret = NO_ERROR;
1408 
1409     ret = queryStreams(&main_stream,
1410             &thumb_stream,
1411             &reproc_stream,
1412             &main_frame,
1413             &thumb_frame,
1414             frame,
1415             reproc_frame);
1416     if (NO_ERROR != ret) {
1417         ALOGE("%s : Camera streams query from input frames failed %d",
1418                 __func__,
1419                 ret);
1420         return ret;
1421     }
1422 
1423     if (NULL != main_stream) {
1424         ret = main_stream->syncRuntimeParams();
1425         if (NO_ERROR != ret) {
1426             ALOGE("%s : Syncing of main stream runtime parameters failed %d",
1427                     __func__,
1428                     ret);
1429             return ret;
1430         }
1431     }
1432 
1433     if (NULL != thumb_stream) {
1434         ret = thumb_stream->syncRuntimeParams();
1435         if (NO_ERROR != ret) {
1436             ALOGE("%s : Syncing of thumb stream runtime parameters failed %d",
1437                     __func__,
1438                     ret);
1439             return ret;
1440         }
1441     }
1442 
1443     if ((NULL != reproc_stream) && (reproc_stream != main_stream)) {
1444         ret = reproc_stream->syncRuntimeParams();
1445         if (NO_ERROR != ret) {
1446             ALOGE("%s : Syncing of reproc stream runtime parameters failed %d",
1447                     __func__,
1448                     ret);
1449             return ret;
1450         }
1451     }
1452 
1453     return ret;
1454 }
1455 
1456 /*===========================================================================
1457  * FUNCTION   : encodeData
1458  *
1459  * DESCRIPTION: function to prepare encoding job information and send to
1460  *              mm-jpeg-interface to do the encoding job
1461  *
1462  * PARAMETERS :
1463  *   @jpeg_job_data : ptr to a struct saving job related information
1464  *   @needNewSess   : flag to indicate if a new jpeg encoding session need
1465  *                    to be created. After creation, this flag will be toggled
1466  *
1467  * RETURN     : int32_t type of status
1468  *              NO_ERROR  -- success
1469  *              none-zero failure code
1470  *==========================================================================*/
encodeData(qcamera_jpeg_data_t * jpeg_job_data,uint8_t & needNewSess)1471 int32_t QCameraPostProcessor::encodeData(qcamera_jpeg_data_t *jpeg_job_data,
1472                                          uint8_t &needNewSess)
1473 {
1474     CDBG("%s : E", __func__);
1475     int32_t ret = NO_ERROR;
1476     mm_jpeg_job_t jpg_job;
1477     uint32_t jobId = 0;
1478     QCameraStream *reproc_stream = NULL;
1479     QCameraStream *main_stream = NULL;
1480     mm_camera_buf_def_t *main_frame = NULL;
1481     QCameraStream *thumb_stream = NULL;
1482     mm_camera_buf_def_t *thumb_frame = NULL;
1483     mm_camera_super_buf_t *recvd_frame = jpeg_job_data->src_frame;
1484     cam_rect_t crop;
1485     cam_stream_parm_buffer_t param;
1486     cam_stream_img_prop_t imgProp;
1487 
1488     // find channel
1489     QCameraChannel *pChannel = m_parent->getChannelByHandle(recvd_frame->ch_id);
1490     // check reprocess channel if not found
1491     if (pChannel == NULL) {
1492         if (m_pReprocChannel != NULL &&
1493             m_pReprocChannel->getMyHandle() == recvd_frame->ch_id) {
1494             pChannel = m_pReprocChannel;
1495         }
1496     }
1497 
1498     if (pChannel == NULL) {
1499         ALOGE("%s:%d] No corresponding channel (ch_id = %d) exist, return here",
1500               __func__, __LINE__, recvd_frame->ch_id);
1501         return BAD_VALUE;
1502     }
1503 
1504     const int jpeg_rotation = m_parent->getJpegRotation();
1505 
1506     ret = queryStreams(&main_stream,
1507             &thumb_stream,
1508             &reproc_stream,
1509             &main_frame,
1510             &thumb_frame,
1511             recvd_frame,
1512             jpeg_job_data->src_reproc_frame);
1513     if (NO_ERROR != ret) {
1514         return ret;
1515     }
1516 
1517     if(NULL == main_frame){
1518        ALOGE("%s : Main frame is NULL", __func__);
1519        return BAD_VALUE;
1520     }
1521 
1522     if(NULL == thumb_frame){
1523        CDBG("%s : Thumbnail frame does not exist", __func__);
1524     }
1525 
1526     QCameraMemory *memObj = (QCameraMemory *)main_frame->mem_info;
1527     if (NULL == memObj) {
1528         ALOGE("%s : Memeory Obj of main frame is NULL", __func__);
1529         return NO_MEMORY;
1530     }
1531 
1532     // dump snapshot frame if enabled
1533     m_parent->dumpFrameToFile(main_stream, main_frame, QCAMERA_DUMP_FRM_SNAPSHOT);
1534 
1535     // send upperlayer callback for raw image
1536     camera_memory_t *mem = memObj->getMemory(main_frame->buf_idx, false);
1537     if (NULL != m_parent->mDataCb &&
1538         m_parent->msgTypeEnabledWithLock(CAMERA_MSG_RAW_IMAGE) > 0) {
1539         qcamera_callback_argm_t cbArg;
1540         memset(&cbArg, 0, sizeof(qcamera_callback_argm_t));
1541         cbArg.cb_type = QCAMERA_DATA_CALLBACK;
1542         cbArg.msg_type = CAMERA_MSG_RAW_IMAGE;
1543         cbArg.data = mem;
1544         cbArg.index = 1;
1545         m_parent->m_cbNotifier.notifyCallback(cbArg);
1546     }
1547     if (NULL != m_parent->mNotifyCb &&
1548         m_parent->msgTypeEnabledWithLock(CAMERA_MSG_RAW_IMAGE_NOTIFY) > 0) {
1549         qcamera_callback_argm_t cbArg;
1550         memset(&cbArg, 0, sizeof(qcamera_callback_argm_t));
1551         cbArg.cb_type = QCAMERA_NOTIFY_CALLBACK;
1552         cbArg.msg_type = CAMERA_MSG_RAW_IMAGE_NOTIFY;
1553         cbArg.ext1 = 0;
1554         cbArg.ext2 = 0;
1555         m_parent->m_cbNotifier.notifyCallback(cbArg);
1556     }
1557 
1558     if (thumb_frame != NULL) {
1559         // dump thumbnail frame if enabled
1560         m_parent->dumpFrameToFile(thumb_stream, thumb_frame, QCAMERA_DUMP_FRM_THUMBNAIL);
1561     }
1562 
1563     if (mJpegClientHandle <= 0) {
1564         ALOGE("%s: Error: bug here, mJpegClientHandle is 0", __func__);
1565         return UNKNOWN_ERROR;
1566     }
1567 
1568     if (needNewSess) {
1569         // create jpeg encoding session
1570         mm_jpeg_encode_params_t encodeParam;
1571         memset(&encodeParam, 0, sizeof(mm_jpeg_encode_params_t));
1572         getJpegEncodingConfig(encodeParam, main_stream, thumb_stream);
1573         CDBG_HIGH("[KPI Perf] %s : call jpeg create_session", __func__);
1574         ret = mJpegHandle.create_session(mJpegClientHandle, &encodeParam, &mJpegSessionId);
1575         if (ret != NO_ERROR) {
1576             ALOGE("%s: error creating a new jpeg encoding session", __func__);
1577             return ret;
1578         }
1579         needNewSess = FALSE;
1580     }
1581     // Fill in new job
1582     memset(&jpg_job, 0, sizeof(mm_jpeg_job_t));
1583     jpg_job.job_type = JPEG_JOB_TYPE_ENCODE;
1584     jpg_job.encode_job.session_id = mJpegSessionId;
1585     jpg_job.encode_job.src_index = main_frame->buf_idx;
1586     jpg_job.encode_job.dst_index = 0;
1587 
1588     if (mJpegMemOpt) {
1589         jpg_job.encode_job.dst_index = jpg_job.encode_job.src_index;
1590     } else if (mUseJpegBurst) {
1591         jpg_job.encode_job.dst_index = -1;
1592     }
1593 
1594     cam_dimension_t src_dim;
1595     memset(&src_dim, 0, sizeof(cam_dimension_t));
1596     main_stream->getFrameDimension(src_dim);
1597 
1598     bool hdr_output_crop = m_parent->mParameters.isHDROutputCropEnabled();
1599     bool img_feature_enabled =
1600       m_parent->mParameters.isUbiFocusEnabled() ||
1601       m_parent->mParameters.isChromaFlashEnabled() ||
1602       m_parent->mParameters.isOptiZoomEnabled();
1603 
1604     CDBG_HIGH("%s:%d] Crop needed %d", __func__, __LINE__, img_feature_enabled);
1605     crop.left = 0;
1606     crop.top = 0;
1607     crop.height = src_dim.height;
1608     crop.width = src_dim.width;
1609 
1610     param = main_stream->getOutputCrop();
1611     for (int i = 0; i < param.outputCrop.num_of_streams; i++) {
1612        if (param.outputCrop.crop_info[i].stream_id
1613            == main_stream->getMyServerID()) {
1614                crop = param.outputCrop.crop_info[i].crop;
1615                main_stream->setCropInfo(crop);
1616        }
1617     }
1618     if (img_feature_enabled) {
1619         memset(&param, 0, sizeof(cam_stream_parm_buffer_t));
1620 
1621         param = main_stream->getImgProp();
1622         imgProp = param.imgProp;
1623         main_stream->setCropInfo(imgProp.crop);
1624         crop = imgProp.crop;
1625         thumb_stream = NULL; /* use thumbnail from main image */
1626         if (imgProp.is_raw_image) {
1627            camera_memory_t *mem = memObj->getMemory(
1628                main_frame->buf_idx, false);
1629            ALOGE("%s:%d] Process raw image %p %d", __func__, __LINE__,
1630                mem, imgProp.size);
1631            /* dump image */
1632            if (mem && mem->data) {
1633                CAM_DUMP_TO_FILE("/data/local/ubifocus", "DepthMapImage",
1634                                 -1, "y",
1635                                 (uint8_t *)mem->data,
1636                                 imgProp.size);
1637            }
1638            return NO_ERROR;
1639         }
1640     }
1641 
1642     cam_dimension_t dst_dim;
1643 
1644     if (hdr_output_crop && crop.height) {
1645         dst_dim.height = crop.height;
1646     } else {
1647         dst_dim.height = src_dim.height;
1648     }
1649     if (hdr_output_crop && crop.width) {
1650         dst_dim.width = crop.width;
1651     } else {
1652         dst_dim.width = src_dim.width;
1653     }
1654 
1655     // main dim
1656     jpg_job.encode_job.main_dim.src_dim = src_dim;
1657     jpg_job.encode_job.main_dim.dst_dim = dst_dim;
1658     jpg_job.encode_job.main_dim.crop = crop;
1659 
1660     // get exif data
1661     QCameraExif *pJpegExifObj = m_parent->getExifData();
1662     jpeg_job_data->pJpegExifObj = pJpegExifObj;
1663     if (pJpegExifObj != NULL) {
1664         jpg_job.encode_job.exif_info.exif_data = pJpegExifObj->getEntries();
1665         jpg_job.encode_job.exif_info.numOfEntries =
1666             pJpegExifObj->getNumOfEntries();
1667     }
1668 
1669     // set rotation only when no online rotation or offline pp rotation is done before
1670     if (!m_parent->needRotationReprocess()) {
1671         jpg_job.encode_job.rotation = jpeg_rotation;
1672     }
1673     CDBG_HIGH("%s: jpeg rotation is set to %d", __func__, jpg_job.encode_job.rotation);
1674 
1675     // thumbnail dim
1676     if (m_bThumbnailNeeded == TRUE) {
1677         m_parent->getThumbnailSize(jpg_job.encode_job.thumb_dim.dst_dim);
1678 
1679         if (thumb_stream == NULL) {
1680             // need jpeg thumbnail, but no postview/preview stream exists
1681             // we use the main stream/frame to encode thumbnail
1682             thumb_stream = main_stream;
1683             thumb_frame = main_frame;
1684             if (m_parent->needRotationReprocess() &&
1685                 ((90 == jpeg_rotation) || (270 == jpeg_rotation))) {
1686                 // swap thumbnail dimensions
1687                 cam_dimension_t tmp_dim = jpg_job.encode_job.thumb_dim.dst_dim;
1688                 jpg_job.encode_job.thumb_dim.dst_dim.width = tmp_dim.height;
1689                 jpg_job.encode_job.thumb_dim.dst_dim.height = tmp_dim.width;
1690             }
1691         }
1692 
1693         memset(&src_dim, 0, sizeof(cam_dimension_t));
1694         thumb_stream->getFrameDimension(src_dim);
1695         jpg_job.encode_job.thumb_dim.src_dim = src_dim;
1696 
1697         // crop is the same if frame is the same
1698         if (thumb_frame != main_frame) {
1699             crop.left = 0;
1700             crop.top = 0;
1701             crop.height = src_dim.height;
1702             crop.width = src_dim.width;
1703 
1704             param = thumb_stream->getOutputCrop();
1705             for (int i = 0; i < param.outputCrop.num_of_streams; i++) {
1706                if (param.outputCrop.crop_info[i].stream_id
1707                    == thumb_stream->getMyServerID()) {
1708                        crop = param.outputCrop.crop_info[i].crop;
1709                        thumb_stream->setCropInfo(crop);
1710                }
1711            }
1712         }
1713 
1714         jpg_job.encode_job.thumb_dim.crop = crop;
1715         jpg_job.encode_job.thumb_index = thumb_frame->buf_idx;
1716         CDBG_HIGH("%s, thumbnail src w/h (%dx%d), dst w/h (%dx%d)", __func__,
1717             jpg_job.encode_job.thumb_dim.src_dim.width,
1718             jpg_job.encode_job.thumb_dim.src_dim.height,
1719             jpg_job.encode_job.thumb_dim.dst_dim.width,
1720             jpg_job.encode_job.thumb_dim.dst_dim.height);
1721     }
1722 
1723     if (jpeg_job_data->metadata != NULL) {
1724         // fill in meta data frame ptr
1725         jpg_job.encode_job.p_metadata = jpeg_job_data->metadata;
1726     }
1727 
1728     jpg_job.encode_job.hal_version = CAM_HAL_V1;
1729     jpg_job.encode_job.cam_exif_params = m_parent->mExifParams;
1730 
1731     /* Init the QTable */
1732     for (int i = 0; i < QTABLE_MAX; i++) {
1733         jpg_job.encode_job.qtable_set[i] = 0;
1734     }
1735 
1736     CDBG_HIGH("[KPI Perf] %s : PROFILE_JPEG_JOB_START", __func__);
1737     ret = mJpegHandle.start_job(&jpg_job, &jobId);
1738     if (ret == NO_ERROR) {
1739         // remember job info
1740         jpeg_job_data->jobId = jobId;
1741     }
1742 
1743     return ret;
1744 }
1745 
1746 /*===========================================================================
1747  * FUNCTION   : processRawImageImpl
1748  *
1749  * DESCRIPTION: function to send raw image to upper layer
1750  *
1751  * PARAMETERS :
1752  *   @recvd_frame   : frame to be encoded
1753  *
1754  * RETURN     : int32_t type of status
1755  *              NO_ERROR  -- success
1756  *              none-zero failure code
1757  *==========================================================================*/
processRawImageImpl(mm_camera_super_buf_t * recvd_frame)1758 int32_t QCameraPostProcessor::processRawImageImpl(mm_camera_super_buf_t *recvd_frame)
1759 {
1760     int32_t rc = NO_ERROR;
1761 
1762     QCameraChannel *pChannel = m_parent->getChannelByHandle(recvd_frame->ch_id);
1763     QCameraStream *pStream = NULL;
1764     mm_camera_buf_def_t *frame = NULL;
1765     // check reprocess channel if not found
1766     if (pChannel == NULL) {
1767         if (m_pReprocChannel != NULL &&
1768             m_pReprocChannel->getMyHandle() == recvd_frame->ch_id) {
1769             pChannel = m_pReprocChannel;
1770         }
1771     }
1772     if (pChannel == NULL) {
1773         ALOGE("%s:%d] No corresponding channel (ch_id = %d) exist, return here",
1774               __func__, __LINE__, recvd_frame->ch_id);
1775         return BAD_VALUE;
1776     }
1777 
1778     // find snapshot frame
1779     for (int i = 0; i < recvd_frame->num_bufs; i++) {
1780         QCameraStream *pCurStream =
1781             pChannel->getStreamByHandle(recvd_frame->bufs[i]->stream_id);
1782         if (pCurStream != NULL) {
1783             if (pCurStream->isTypeOf(CAM_STREAM_TYPE_SNAPSHOT) ||
1784                 pCurStream->isTypeOf(CAM_STREAM_TYPE_RAW) ||
1785                 pCurStream->isOrignalTypeOf(CAM_STREAM_TYPE_SNAPSHOT) ||
1786                 pCurStream->isOrignalTypeOf(CAM_STREAM_TYPE_RAW)) {
1787                 pStream = pCurStream;
1788                 frame = recvd_frame->bufs[i];
1789                 break;
1790             }
1791         }
1792     }
1793 
1794     if ( NULL == frame ) {
1795         ALOGE("%s: No valid raw buffer", __func__);
1796         return BAD_VALUE;
1797     }
1798 
1799     QCameraMemory *rawMemObj = (QCameraMemory *)frame->mem_info;
1800     bool zslChannelUsed = m_parent->isZSLMode() &&
1801             ( pChannel != m_pReprocChannel );
1802     camera_memory_t *raw_mem = NULL;
1803 
1804     if (rawMemObj != NULL) {
1805         if (zslChannelUsed) {
1806             raw_mem = rawMemObj->getMemory(frame->buf_idx, false);
1807         } else {
1808             raw_mem = m_parent->mGetMemory(-1,
1809                                            frame->frame_len,
1810                                            1,
1811                                            m_parent->mCallbackCookie);
1812             if (NULL == raw_mem) {
1813                 ALOGE("%s : Not enough memory for RAW cb ", __func__);
1814                 return NO_MEMORY;
1815             }
1816             memcpy(raw_mem->data, frame->buffer, frame->frame_len);
1817         }
1818     }
1819 
1820     if (NULL != rawMemObj && NULL != raw_mem) {
1821         // dump frame into file
1822         if (frame->stream_type == CAM_STREAM_TYPE_SNAPSHOT ||
1823             pStream->isOrignalTypeOf(CAM_STREAM_TYPE_SNAPSHOT)) {
1824             // for YUV422 NV16 case
1825             m_parent->dumpFrameToFile(pStream, frame, QCAMERA_DUMP_FRM_SNAPSHOT);
1826         } else {
1827             m_parent->dumpFrameToFile(pStream, frame, QCAMERA_DUMP_FRM_RAW);
1828         }
1829 
1830         // send data callback / notify for RAW_IMAGE
1831         if (NULL != m_parent->mDataCb &&
1832             m_parent->msgTypeEnabledWithLock(CAMERA_MSG_RAW_IMAGE) > 0) {
1833             qcamera_callback_argm_t cbArg;
1834             memset(&cbArg, 0, sizeof(qcamera_callback_argm_t));
1835             cbArg.cb_type = QCAMERA_DATA_CALLBACK;
1836             cbArg.msg_type = CAMERA_MSG_RAW_IMAGE;
1837             cbArg.data = raw_mem;
1838             cbArg.index = 0;
1839             m_parent->m_cbNotifier.notifyCallback(cbArg);
1840         }
1841         if (NULL != m_parent->mNotifyCb &&
1842             m_parent->msgTypeEnabledWithLock(CAMERA_MSG_RAW_IMAGE_NOTIFY) > 0) {
1843             qcamera_callback_argm_t cbArg;
1844             memset(&cbArg, 0, sizeof(qcamera_callback_argm_t));
1845             cbArg.cb_type = QCAMERA_NOTIFY_CALLBACK;
1846             cbArg.msg_type = CAMERA_MSG_RAW_IMAGE_NOTIFY;
1847             cbArg.ext1 = 0;
1848             cbArg.ext2 = 0;
1849             m_parent->m_cbNotifier.notifyCallback(cbArg);
1850         }
1851 
1852         if ((m_parent->mDataCb != NULL) &&
1853             m_parent->msgTypeEnabledWithLock(CAMERA_MSG_COMPRESSED_IMAGE) > 0) {
1854             qcamera_release_data_t release_data;
1855             memset(&release_data, 0, sizeof(qcamera_release_data_t));
1856             if ( zslChannelUsed ) {
1857                 release_data.frame = recvd_frame;
1858             } else {
1859                 release_data.data = raw_mem;
1860             }
1861             rc = sendDataNotify(CAMERA_MSG_COMPRESSED_IMAGE,
1862                                 raw_mem,
1863                                 0,
1864                                 NULL,
1865                                 &release_data);
1866         } else {
1867             raw_mem->release(raw_mem);
1868         }
1869     } else {
1870         ALOGE("%s: Cannot get raw mem", __func__);
1871         rc = UNKNOWN_ERROR;
1872     }
1873 
1874     return rc;
1875 }
1876 
1877 /*===========================================================================
1878  * FUNCTION   : dataSaveRoutine
1879  *
1880  * DESCRIPTION: data saving routine
1881  *
1882  * PARAMETERS :
1883  *   @data    : user data ptr (QCameraPostProcessor)
1884  *
1885  * RETURN     : None
1886  *==========================================================================*/
dataSaveRoutine(void * data)1887 void *QCameraPostProcessor::dataSaveRoutine(void *data)
1888 {
1889     int running = 1;
1890     int ret;
1891     uint8_t is_active = FALSE;
1892     QCameraPostProcessor *pme = (QCameraPostProcessor *)data;
1893     QCameraCmdThread *cmdThread = &pme->m_saveProcTh;
1894     char saveName[PROPERTY_VALUE_MAX];
1895 
1896     CDBG_HIGH("%s: E", __func__);
1897     do {
1898         do {
1899             ret = cam_sem_wait(&cmdThread->cmd_sem);
1900             if (ret != 0 && errno != EINVAL) {
1901                 ALOGE("%s: cam_sem_wait error (%s)",
1902                            __func__, strerror(errno));
1903                 return NULL;
1904             }
1905         } while (ret != 0);
1906 
1907         // we got notified about new cmd avail in cmd queue
1908         camera_cmd_type_t cmd = cmdThread->getCmd();
1909         switch (cmd) {
1910         case CAMERA_CMD_TYPE_START_DATA_PROC:
1911             CDBG_HIGH("%s: start data proc", __func__);
1912             is_active = TRUE;
1913             pme->m_inputSaveQ.init();
1914             break;
1915         case CAMERA_CMD_TYPE_STOP_DATA_PROC:
1916             {
1917                 CDBG_HIGH("%s: stop data proc", __func__);
1918                 is_active = FALSE;
1919 
1920                 // flush input save Queue
1921                 pme->m_inputSaveQ.flush();
1922 
1923                 // signal cmd is completed
1924                 cam_sem_post(&cmdThread->sync_sem);
1925             }
1926             break;
1927         case CAMERA_CMD_TYPE_DO_NEXT_JOB:
1928             {
1929                 CDBG_HIGH("%s: Do next job, active is %d", __func__, is_active);
1930 
1931                 qcamera_jpeg_evt_payload_t *job_data = (qcamera_jpeg_evt_payload_t *) pme->m_inputSaveQ.dequeue();
1932                 if (job_data == NULL) {
1933                     ALOGE("%s: Invalid jpeg event data", __func__);
1934                     continue;
1935                 }
1936 
1937                 pme->m_ongoingJpegQ.flushNodes(matchJobId, (void*)&job_data->jobId);
1938 
1939                 CDBG_HIGH("[KPI Perf] %s : jpeg job %d", __func__, job_data->jobId);
1940 
1941                 if (is_active == TRUE) {
1942                     memset(saveName, '\0', sizeof(saveName));
1943                     snprintf(saveName,
1944                              sizeof(saveName),
1945                              QCameraPostProcessor::STORE_LOCATION,
1946                              pme->mSaveFrmCnt);
1947 
1948                     int file_fd = open(saveName, O_RDWR | O_CREAT, 0655);
1949                     if (file_fd > 0) {
1950                         size_t written_len = write(file_fd,
1951                                                 job_data->out_data.buf_vaddr,
1952                                                 job_data->out_data.buf_filled_len);
1953                         if ( job_data->out_data.buf_filled_len != written_len ) {
1954                             ALOGE("%s: Failed save complete data %d bytes written instead of %d bytes!",
1955                                   __func__,
1956                                   written_len,
1957                                   job_data->out_data.buf_filled_len);
1958                         } else {
1959                             CDBG_HIGH("%s: written number of bytes %d\n", __func__, written_len);
1960                         }
1961 
1962                         close(file_fd);
1963                     } else {
1964                         ALOGE("%s: fail t open file for saving", __func__);
1965                     }
1966                     pme->mSaveFrmCnt++;
1967 
1968                     camera_memory_t* jpeg_mem = pme->m_parent->mGetMemory(-1,
1969                                                          strlen(saveName),
1970                                                          1,
1971                                                          pme->m_parent->mCallbackCookie);
1972                     if (NULL == jpeg_mem) {
1973                         ret = NO_MEMORY;
1974                         ALOGE("%s : getMemory for jpeg, ret = NO_MEMORY", __func__);
1975                         goto end;
1976                     }
1977                     memcpy(jpeg_mem->data, saveName, strlen(saveName));
1978 
1979                     CDBG_HIGH("%s : Calling upperlayer callback to store JPEG image", __func__);
1980                     qcamera_release_data_t release_data;
1981                     memset(&release_data, 0, sizeof(qcamera_release_data_t));
1982                     release_data.data = jpeg_mem;
1983                     release_data.unlinkFile = true;
1984                     CDBG_HIGH("[KPI Perf] %s: PROFILE_JPEG_CB ",__func__);
1985                     ret = pme->sendDataNotify(CAMERA_MSG_COMPRESSED_IMAGE,
1986                                         jpeg_mem,
1987                                         0,
1988                                         NULL,
1989                                         &release_data);
1990                 }
1991 
1992 end:
1993                 free(job_data);
1994             }
1995             break;
1996         case CAMERA_CMD_TYPE_EXIT:
1997             CDBG_HIGH("%s : save thread exit", __func__);
1998             running = 0;
1999             break;
2000         default:
2001             break;
2002         }
2003     } while (running);
2004     CDBG_HIGH("%s: X", __func__);
2005     return NULL;
2006 }
2007 
2008 /*===========================================================================
2009  * FUNCTION   : dataProcessRoutine
2010  *
2011  * DESCRIPTION: data process routine that handles input data either from input
2012  *              Jpeg Queue to do jpeg encoding, or from input PP Queue to do
2013  *              reprocess.
2014  *
2015  * PARAMETERS :
2016  *   @data    : user data ptr (QCameraPostProcessor)
2017  *
2018  * RETURN     : None
2019  *==========================================================================*/
dataProcessRoutine(void * data)2020 void *QCameraPostProcessor::dataProcessRoutine(void *data)
2021 {
2022     int running = 1;
2023     int ret;
2024     uint8_t is_active = FALSE;
2025     QCameraPostProcessor *pme = (QCameraPostProcessor *)data;
2026     QCameraCmdThread *cmdThread = &pme->m_dataProcTh;
2027 
2028     CDBG_HIGH("%s: E", __func__);
2029     do {
2030         do {
2031             ret = cam_sem_wait(&cmdThread->cmd_sem);
2032             if (ret != 0 && errno != EINVAL) {
2033                 ALOGE("%s: cam_sem_wait error (%s)",
2034                            __func__, strerror(errno));
2035                 return NULL;
2036             }
2037         } while (ret != 0);
2038 
2039         // we got notified about new cmd avail in cmd queue
2040         camera_cmd_type_t cmd = cmdThread->getCmd();
2041         switch (cmd) {
2042         case CAMERA_CMD_TYPE_START_DATA_PROC:
2043             CDBG_HIGH("%s: start data proc", __func__);
2044             is_active = TRUE;
2045 
2046             pme->m_ongoingPPQ.init();
2047             pme->m_inputJpegQ.init();
2048             pme->m_inputPPQ.init();
2049             pme->m_inputRawQ.init();
2050 
2051             pme->m_saveProcTh.sendCmd(CAMERA_CMD_TYPE_START_DATA_PROC,
2052                                       FALSE,
2053                                       FALSE);
2054 
2055             // signal cmd is completed
2056             cam_sem_post(&cmdThread->sync_sem);
2057 
2058             break;
2059         case CAMERA_CMD_TYPE_STOP_DATA_PROC:
2060             {
2061                 CDBG_HIGH("%s: stop data proc", __func__);
2062                 is_active = FALSE;
2063 
2064                 pme->m_saveProcTh.sendCmd(CAMERA_CMD_TYPE_STOP_DATA_PROC,
2065                                            TRUE,
2066                                            TRUE);
2067                 // cancel all ongoing jpeg jobs
2068                 qcamera_jpeg_data_t *jpeg_job =
2069                     (qcamera_jpeg_data_t *)pme->m_ongoingJpegQ.dequeue();
2070                 while (jpeg_job != NULL) {
2071                     pme->mJpegHandle.abort_job(jpeg_job->jobId);
2072 
2073                     pme->releaseJpegJobData(jpeg_job);
2074                     free(jpeg_job);
2075 
2076                     jpeg_job = (qcamera_jpeg_data_t *)pme->m_ongoingJpegQ.dequeue();
2077                 }
2078 
2079                 // destroy jpeg encoding session
2080                 if ( 0 < pme->mJpegSessionId ) {
2081                     pme->mJpegHandle.destroy_session(pme->mJpegSessionId);
2082                     pme->mJpegSessionId = 0;
2083                 }
2084 
2085                 // free jpeg out buf and exif obj
2086                 FREE_JPEG_OUTPUT_BUFFER(pme->m_pJpegOutputMem,
2087                     pme->m_JpegOutputMemCount);
2088 
2089                 if (pme->m_pJpegExifObj != NULL) {
2090                     delete pme->m_pJpegExifObj;
2091                     pme->m_pJpegExifObj = NULL;
2092                 }
2093 
2094                 // stop reproc channel if exists
2095                 if (pme->m_pReprocChannel != NULL) {
2096                     pme->m_pReprocChannel->stop();
2097                     delete pme->m_pReprocChannel;
2098                     pme->m_pReprocChannel = NULL;
2099                 }
2100 
2101                 // flush ongoing postproc Queue
2102                 pme->m_ongoingPPQ.flush();
2103 
2104                 // flush input jpeg Queue
2105                 pme->m_inputJpegQ.flush();
2106 
2107                 // flush input Postproc Queue
2108                 pme->m_inputPPQ.flush();
2109 
2110                 // flush input raw Queue
2111                 pme->m_inputRawQ.flush();
2112 
2113                 // signal cmd is completed
2114                 cam_sem_post(&cmdThread->sync_sem);
2115 
2116                 pme->mNewJpegSessionNeeded = true;
2117             }
2118             break;
2119         case CAMERA_CMD_TYPE_DO_NEXT_JOB:
2120             {
2121                 CDBG_HIGH("%s: Do next job, active is %d", __func__, is_active);
2122                 if (is_active == TRUE) {
2123                     qcamera_jpeg_data_t *jpeg_job =
2124                         (qcamera_jpeg_data_t *)pme->m_inputJpegQ.dequeue();
2125 
2126                     if (NULL != jpeg_job) {
2127                         // To avoid any race conditions,
2128                         // sync any stream specific parameters here.
2129                         pme->syncStreamParams(jpeg_job->src_frame, NULL);
2130 
2131                         // add into ongoing jpeg job Q
2132                         pme->m_ongoingJpegQ.enqueue((void *)jpeg_job);
2133                         ret = pme->encodeData(jpeg_job,
2134                                   pme->mNewJpegSessionNeeded);
2135                         if (NO_ERROR != ret) {
2136                             // dequeue the last one
2137                             pme->m_ongoingJpegQ.dequeue(false);
2138                             pme->releaseJpegJobData(jpeg_job);
2139                             free(jpeg_job);
2140                             pme->sendEvtNotify(CAMERA_MSG_ERROR, UNKNOWN_ERROR, 0);
2141                         }
2142                     }
2143 
2144 
2145                     // process raw data if any
2146                     mm_camera_super_buf_t *super_buf =
2147                         (mm_camera_super_buf_t *)pme->m_inputRawQ.dequeue();
2148 
2149                     if (NULL != super_buf) {
2150                         //play shutter sound
2151                         pme->m_parent->playShutter();
2152                         ret = pme->processRawImageImpl(super_buf);
2153                         if (NO_ERROR != ret) {
2154                             pme->releaseSuperBuf(super_buf);
2155                             free(super_buf);
2156                             pme->sendEvtNotify(CAMERA_MSG_ERROR, UNKNOWN_ERROR, 0);
2157                         }
2158                     }
2159 
2160                     mm_camera_super_buf_t *pp_frame =
2161                         (mm_camera_super_buf_t *)pme->m_inputPPQ.dequeue();
2162                     if (NULL != pp_frame) {
2163                         qcamera_pp_data_t *pp_job =
2164                             (qcamera_pp_data_t *)malloc(sizeof(qcamera_pp_data_t));
2165                         if (pp_job != NULL) {
2166                             pme->syncStreamParams(pp_frame, NULL);
2167                             memset(pp_job, 0, sizeof(qcamera_pp_data_t));
2168                             if (pme->m_pReprocChannel != NULL) {
2169                                 // add into ongoing PP job Q
2170                                 pp_job->src_frame = pp_frame;
2171                                 ret = pme->reprocess(pp_job);
2172                                 if (NO_ERROR == ret) {
2173                                     pme->stopCapture();
2174                                 }
2175                             } else {
2176                                 ALOGE("%s: Reprocess channel is NULL", __func__);
2177                                 ret = -1;
2178                             }
2179                         } else {
2180                             ALOGE("%s: no mem for qcamera_pp_data_t", __func__);
2181                             ret = -1;
2182                         }
2183 
2184                         if (0 != ret) {
2185                             // free pp_job
2186                             if (pp_job != NULL) {
2187                                 free(pp_job);
2188                             }
2189                             // free frame
2190                             if (pp_frame != NULL) {
2191                                 pme->releaseSuperBuf(pp_frame);
2192                                 free(pp_frame);
2193                             }
2194                             // send error notify
2195                             pme->sendEvtNotify(CAMERA_MSG_ERROR, UNKNOWN_ERROR, 0);
2196                         }
2197                     }
2198                 } else {
2199                     // not active, simply return buf and do no op
2200                     qcamera_jpeg_data_t *jpeg_data =
2201                         (qcamera_jpeg_data_t *)pme->m_inputJpegQ.dequeue();
2202                     if (NULL != jpeg_data) {
2203                         pme->releaseJpegJobData(jpeg_data);
2204                         free(jpeg_data);
2205                     }
2206                     mm_camera_super_buf_t *super_buf =
2207                         (mm_camera_super_buf_t *)pme->m_inputRawQ.dequeue();
2208                     if (NULL != super_buf) {
2209                         pme->releaseSuperBuf(super_buf);
2210                         free(super_buf);
2211                     }
2212                     super_buf = (mm_camera_super_buf_t *)pme->m_inputPPQ.dequeue();
2213                     if (NULL != super_buf) {
2214                         pme->releaseSuperBuf(super_buf);
2215                         free(super_buf);
2216                     }
2217                 }
2218             }
2219             break;
2220         case CAMERA_CMD_TYPE_EXIT:
2221             running = 0;
2222             break;
2223         default:
2224             break;
2225         }
2226     } while (running);
2227     CDBG_HIGH("%s: X", __func__);
2228     return NULL;
2229 }
2230 
2231 /*===========================================================================
2232  * FUNCTION   : reprocess
2233  *
2234  * DESCRIPTION: Trigger reprocessing
2235  *
2236  * PARAMETERS :
2237  *   @pp_job  : Postproc job
2238  *
2239  * RETURN     : int32_t type of status
2240  *              NO_ERROR  -- success
2241  *              none-zero failure code
2242  *==========================================================================*/
reprocess(qcamera_pp_data_t * pp_job)2243 int32_t QCameraPostProcessor::reprocess(qcamera_pp_data_t *pp_job)
2244 {
2245     int rc = NO_ERROR;
2246 
2247     if (NULL == pp_job) {
2248         return BAD_VALUE;
2249     }
2250 
2251     if (m_parent->isRegularCapture()) {
2252        if ((NULL != pp_job->src_frame) &&
2253            (0 < pp_job->src_frame->num_bufs)) {
2254            mm_camera_buf_def_t *bufs = NULL;
2255            uint8_t num_bufs = -1;
2256            num_bufs = pp_job->src_frame->num_bufs;
2257            bufs = new mm_camera_buf_def_t[num_bufs];
2258            if (NULL == bufs) {
2259                ALOGE("%s:Unable to allocate cached buffers",
2260                      __func__);
2261                return NO_MEMORY;
2262            }
2263 
2264            for (int i = 0; i < num_bufs; i++) {
2265                bufs[i] = *pp_job->src_frame->bufs[i];
2266                pp_job->src_frame->bufs[i] = &bufs[i];
2267            }
2268            pp_job->src_reproc_bufs = bufs;
2269        }
2270 
2271        // Don't release source frame after encoding
2272        // at this point the source channel will not exist.
2273        pp_job->reproc_frame_release = true;
2274        m_ongoingPPQ.enqueue((void *)pp_job);
2275        rc = m_pReprocChannel->doReprocessOffline(pp_job->src_frame);
2276     } else {
2277         m_ongoingPPQ.enqueue((void *)pp_job);
2278         rc = m_pReprocChannel->doReprocess(pp_job->src_frame);
2279     }
2280 
2281     if (NO_ERROR != rc) {
2282         // remove from ongoing PP job Q
2283         m_ongoingPPQ.dequeue(false);
2284     }
2285 
2286     return rc;
2287 }
2288 
2289 /*===========================================================================
2290  * FUNCTION   : stopCapture
2291  *
2292  * DESCRIPTION: Trigger image capture stop
2293  *
2294  * PARAMETERS :
2295  * None
2296  *
2297  * RETURN     : int32_t type of status
2298  *              NO_ERROR  -- success
2299  *              none-zero failure code
2300  *==========================================================================*/
stopCapture()2301 int32_t QCameraPostProcessor::stopCapture()
2302 {
2303      int rc = NO_ERROR;
2304 
2305      if (m_parent->isRegularCapture()) {
2306         rc = m_parent->processAPI(
2307                         QCAMERA_SM_EVT_STOP_CAPTURE_CHANNEL,
2308                         NULL);
2309      }
2310 
2311      return rc;
2312 }
2313 
2314 /*===========================================================================
2315  * FUNCTION   : getJpegPaddingReq
2316  *
2317  * DESCRIPTION: function to add an entry to exif data
2318  *
2319  * PARAMETERS :
2320  *   @padding_info : jpeg specific padding requirement
2321  *
2322  * RETURN     : int32_t type of status
2323  *              NO_ERROR  -- success
2324  *              none-zero failure code
2325  *==========================================================================*/
getJpegPaddingReq(cam_padding_info_t & padding_info)2326 int32_t QCameraPostProcessor::getJpegPaddingReq(cam_padding_info_t &padding_info)
2327 {
2328     // TODO: hardcode for now, needs to query from mm-jpeg-interface
2329     padding_info.width_padding  = CAM_PAD_NONE;
2330     padding_info.height_padding  = CAM_PAD_TO_16;
2331     padding_info.plane_padding  = CAM_PAD_TO_WORD;
2332     return NO_ERROR;
2333 }
2334 
2335 /*===========================================================================
2336  * FUNCTION   : setYUVFrameInfo
2337  *
2338  * DESCRIPTION: set Raw YUV frame data info for up-layer
2339  *
2340  * PARAMETERS :
2341  *   @frame   : process frame received from mm-camera-interface
2342  *
2343  * RETURN     : int32_t type of status
2344  *              NO_ERROR  -- success
2345  *              none-zero failure code
2346  *
2347  * NOTE       : currently we return frame len, y offset, cbcr offset and frame format
2348  *==========================================================================*/
setYUVFrameInfo(mm_camera_super_buf_t * recvd_frame)2349 int32_t QCameraPostProcessor::setYUVFrameInfo(mm_camera_super_buf_t *recvd_frame)
2350 {
2351     QCameraChannel *pChannel = m_parent->getChannelByHandle(recvd_frame->ch_id);
2352     // check reprocess channel if not found
2353     if (pChannel == NULL) {
2354         if (m_pReprocChannel != NULL &&
2355             m_pReprocChannel->getMyHandle() == recvd_frame->ch_id) {
2356             pChannel = m_pReprocChannel;
2357         }
2358     }
2359 
2360     if (pChannel == NULL) {
2361         ALOGE("%s:%d] No corresponding channel (ch_id = %d) exist, return here",
2362               __func__, __LINE__, recvd_frame->ch_id);
2363         return BAD_VALUE;
2364     }
2365 
2366     // find snapshot frame
2367     for (int i = 0; i < recvd_frame->num_bufs; i++) {
2368         QCameraStream *pStream =
2369             pChannel->getStreamByHandle(recvd_frame->bufs[i]->stream_id);
2370         if (pStream != NULL) {
2371             if (pStream->isTypeOf(CAM_STREAM_TYPE_SNAPSHOT) ||
2372                 pStream->isOrignalTypeOf(CAM_STREAM_TYPE_SNAPSHOT)) {
2373                 //get the main frame, use stream info
2374                 cam_frame_len_offset_t frame_offset;
2375                 cam_dimension_t frame_dim;
2376                 cam_format_t frame_fmt;
2377                 const char *fmt_string;
2378                 pStream->getFrameDimension(frame_dim);
2379                 pStream->getFrameOffset(frame_offset);
2380                 pStream->getFormat(frame_fmt);
2381                 fmt_string = m_parent->mParameters.getFrameFmtString(frame_fmt);
2382 
2383                 int cbcr_offset = frame_offset.mp[0].len - frame_dim.width * frame_dim.height;
2384                 m_parent->mParameters.set("snapshot-framelen", frame_offset.frame_len);
2385                 m_parent->mParameters.set("snapshot-yoff", frame_offset.mp[0].offset);
2386                 m_parent->mParameters.set("snapshot-cbcroff", cbcr_offset);
2387                 if(fmt_string != NULL){
2388                     m_parent->mParameters.set("snapshot-format", fmt_string);
2389                 }else{
2390                     m_parent->mParameters.set("snapshot-format", "");
2391                 }
2392 
2393                 CDBG_HIGH("%s: frame width=%d, height=%d, yoff=%d, cbcroff=%d, fmt_string=%s", __func__,
2394                         frame_dim.width, frame_dim.height, frame_offset.mp[0].offset, cbcr_offset, fmt_string);
2395                 return NO_ERROR;
2396             }
2397         }
2398     }
2399 
2400     return BAD_VALUE;
2401 }
2402 
matchJobId(void * data,void *,void * match_data)2403 bool QCameraPostProcessor::matchJobId(void *data, void *, void *match_data)
2404 {
2405   qcamera_jpeg_data_t * job = (qcamera_jpeg_data_t *) data;
2406   uint32_t job_id = *((uint32_t *) match_data);
2407   return job->jobId == job_id;
2408 }
2409 
2410 /*===========================================================================
2411  * FUNCTION   : getJpegMemory
2412  *
2413  * DESCRIPTION: buffer allocation function
2414  *   to pass to jpeg interface
2415  *
2416  * PARAMETERS :
2417  *   @out_buf : buffer descriptor struct
2418  *
2419  * RETURN     : int32_t type of status
2420  *              NO_ERROR  -- success
2421  *              none-zero failure code
2422  *==========================================================================*/
getJpegMemory(omx_jpeg_ouput_buf_t * out_buf)2423 int QCameraPostProcessor::getJpegMemory(omx_jpeg_ouput_buf_t *out_buf)
2424 {
2425     CDBG_HIGH("%s: Allocating jpeg out buffer of size: %d", __func__, out_buf->size);
2426     QCameraPostProcessor *procInst = (QCameraPostProcessor *) out_buf->handle;
2427     camera_memory_t *cam_mem = procInst->m_parent->mGetMemory(-1, out_buf->size,
2428         1, procInst->m_parent->mCallbackCookie);
2429     out_buf->mem_hdl = cam_mem;
2430     out_buf->vaddr = cam_mem->data;
2431 
2432     return 0;
2433 }
2434 
2435 /*===========================================================================
2436  * FUNCTION   : QCameraExif
2437  *
2438  * DESCRIPTION: constructor of QCameraExif
2439  *
2440  * PARAMETERS : None
2441  *
2442  * RETURN     : None
2443  *==========================================================================*/
QCameraExif()2444 QCameraExif::QCameraExif()
2445     : m_nNumEntries(0)
2446 {
2447     memset(m_Entries, 0, sizeof(m_Entries));
2448 }
2449 
2450 /*===========================================================================
2451  * FUNCTION   : ~QCameraExif
2452  *
2453  * DESCRIPTION: deconstructor of QCameraExif. Will release internal memory ptr.
2454  *
2455  * PARAMETERS : None
2456  *
2457  * RETURN     : None
2458  *==========================================================================*/
~QCameraExif()2459 QCameraExif::~QCameraExif()
2460 {
2461     for (uint32_t i = 0; i < m_nNumEntries; i++) {
2462         switch (m_Entries[i].tag_entry.type) {
2463         case EXIF_BYTE:
2464             {
2465                 if (m_Entries[i].tag_entry.count > 1 &&
2466                     m_Entries[i].tag_entry.data._bytes != NULL) {
2467                     free(m_Entries[i].tag_entry.data._bytes);
2468                     m_Entries[i].tag_entry.data._bytes = NULL;
2469                 }
2470             }
2471             break;
2472         case EXIF_ASCII:
2473             {
2474                 if (m_Entries[i].tag_entry.data._ascii != NULL) {
2475                     free(m_Entries[i].tag_entry.data._ascii);
2476                     m_Entries[i].tag_entry.data._ascii = NULL;
2477                 }
2478             }
2479             break;
2480         case EXIF_SHORT:
2481             {
2482                 if (m_Entries[i].tag_entry.count > 1 &&
2483                     m_Entries[i].tag_entry.data._shorts != NULL) {
2484                     free(m_Entries[i].tag_entry.data._shorts);
2485                     m_Entries[i].tag_entry.data._shorts = NULL;
2486                 }
2487             }
2488             break;
2489         case EXIF_LONG:
2490             {
2491                 if (m_Entries[i].tag_entry.count > 1 &&
2492                     m_Entries[i].tag_entry.data._longs != NULL) {
2493                     free(m_Entries[i].tag_entry.data._longs);
2494                     m_Entries[i].tag_entry.data._longs = NULL;
2495                 }
2496             }
2497             break;
2498         case EXIF_RATIONAL:
2499             {
2500                 if (m_Entries[i].tag_entry.count > 1 &&
2501                     m_Entries[i].tag_entry.data._rats != NULL) {
2502                     free(m_Entries[i].tag_entry.data._rats);
2503                     m_Entries[i].tag_entry.data._rats = NULL;
2504                 }
2505             }
2506             break;
2507         case EXIF_UNDEFINED:
2508             {
2509                 if (m_Entries[i].tag_entry.data._undefined != NULL) {
2510                     free(m_Entries[i].tag_entry.data._undefined);
2511                     m_Entries[i].tag_entry.data._undefined = NULL;
2512                 }
2513             }
2514             break;
2515         case EXIF_SLONG:
2516             {
2517                 if (m_Entries[i].tag_entry.count > 1 &&
2518                     m_Entries[i].tag_entry.data._slongs != NULL) {
2519                     free(m_Entries[i].tag_entry.data._slongs);
2520                     m_Entries[i].tag_entry.data._slongs = NULL;
2521                 }
2522             }
2523             break;
2524         case EXIF_SRATIONAL:
2525             {
2526                 if (m_Entries[i].tag_entry.count > 1 &&
2527                     m_Entries[i].tag_entry.data._srats != NULL) {
2528                     free(m_Entries[i].tag_entry.data._srats);
2529                     m_Entries[i].tag_entry.data._srats = NULL;
2530                 }
2531             }
2532             break;
2533         }
2534     }
2535 }
2536 
2537 /*===========================================================================
2538  * FUNCTION   : addEntry
2539  *
2540  * DESCRIPTION: function to add an entry to exif data
2541  *
2542  * PARAMETERS :
2543  *   @tagid   : exif tag ID
2544  *   @type    : data type
2545  *   @count   : number of data in uint of its type
2546  *   @data    : input data ptr
2547  *
2548  * RETURN     : int32_t type of status
2549  *              NO_ERROR  -- success
2550  *              none-zero failure code
2551  *==========================================================================*/
addEntry(exif_tag_id_t tagid,exif_tag_type_t type,uint32_t count,void * data)2552 int32_t QCameraExif::addEntry(exif_tag_id_t tagid,
2553                               exif_tag_type_t type,
2554                               uint32_t count,
2555                               void *data)
2556 {
2557     int32_t rc = NO_ERROR;
2558     if(m_nNumEntries >= MAX_EXIF_TABLE_ENTRIES) {
2559         ALOGE("%s: Number of entries exceeded limit", __func__);
2560         return NO_MEMORY;
2561     }
2562 
2563     m_Entries[m_nNumEntries].tag_id = tagid;
2564     m_Entries[m_nNumEntries].tag_entry.type = type;
2565     m_Entries[m_nNumEntries].tag_entry.count = count;
2566     m_Entries[m_nNumEntries].tag_entry.copy = 1;
2567     switch (type) {
2568     case EXIF_BYTE:
2569         {
2570             if (count > 1) {
2571                 uint8_t *values = (uint8_t *)malloc(count);
2572                 if (values == NULL) {
2573                     ALOGE("%s: No memory for byte array", __func__);
2574                     rc = NO_MEMORY;
2575                 } else {
2576                     memcpy(values, data, count);
2577                     m_Entries[m_nNumEntries].tag_entry.data._bytes = values;
2578                 }
2579             } else {
2580                 m_Entries[m_nNumEntries].tag_entry.data._byte = *(uint8_t *)data;
2581             }
2582         }
2583         break;
2584     case EXIF_ASCII:
2585         {
2586             char *str = NULL;
2587             str = (char *)malloc(count + 1);
2588             if (str == NULL) {
2589                 ALOGE("%s: No memory for ascii string", __func__);
2590                 rc = NO_MEMORY;
2591             } else {
2592                 memset(str, 0, count + 1);
2593                 memcpy(str, data, count);
2594                 m_Entries[m_nNumEntries].tag_entry.data._ascii = str;
2595             }
2596         }
2597         break;
2598     case EXIF_SHORT:
2599         {
2600             if (count > 1) {
2601                 uint16_t *values = (uint16_t *)malloc(count * sizeof(uint16_t));
2602                 if (values == NULL) {
2603                     ALOGE("%s: No memory for short array", __func__);
2604                     rc = NO_MEMORY;
2605                 } else {
2606                     memcpy(values, data, count * sizeof(uint16_t));
2607                     m_Entries[m_nNumEntries].tag_entry.data._shorts = values;
2608                 }
2609             } else {
2610                 m_Entries[m_nNumEntries].tag_entry.data._short = *(uint16_t *)data;
2611             }
2612         }
2613         break;
2614     case EXIF_LONG:
2615         {
2616             if (count > 1) {
2617                 uint32_t *values = (uint32_t *)malloc(count * sizeof(uint32_t));
2618                 if (values == NULL) {
2619                     ALOGE("%s: No memory for long array", __func__);
2620                     rc = NO_MEMORY;
2621                 } else {
2622                     memcpy(values, data, count * sizeof(uint32_t));
2623                     m_Entries[m_nNumEntries].tag_entry.data._longs = values;
2624                 }
2625             } else {
2626                 m_Entries[m_nNumEntries].tag_entry.data._long = *(uint32_t *)data;
2627             }
2628         }
2629         break;
2630     case EXIF_RATIONAL:
2631         {
2632             if (count > 1) {
2633                 rat_t *values = (rat_t *)malloc(count * sizeof(rat_t));
2634                 if (values == NULL) {
2635                     ALOGE("%s: No memory for rational array", __func__);
2636                     rc = NO_MEMORY;
2637                 } else {
2638                     memcpy(values, data, count * sizeof(rat_t));
2639                     m_Entries[m_nNumEntries].tag_entry.data._rats = values;
2640                 }
2641             } else {
2642                 m_Entries[m_nNumEntries].tag_entry.data._rat = *(rat_t *)data;
2643             }
2644         }
2645         break;
2646     case EXIF_UNDEFINED:
2647         {
2648             uint8_t *values = (uint8_t *)malloc(count);
2649             if (values == NULL) {
2650                 ALOGE("%s: No memory for undefined array", __func__);
2651                 rc = NO_MEMORY;
2652             } else {
2653                 memcpy(values, data, count);
2654                 m_Entries[m_nNumEntries].tag_entry.data._undefined = values;
2655             }
2656         }
2657         break;
2658     case EXIF_SLONG:
2659         {
2660             if (count > 1) {
2661                 int32_t *values = (int32_t *)malloc(count * sizeof(int32_t));
2662                 if (values == NULL) {
2663                     ALOGE("%s: No memory for signed long array", __func__);
2664                     rc = NO_MEMORY;
2665                 } else {
2666                     memcpy(values, data, count * sizeof(int32_t));
2667                     m_Entries[m_nNumEntries].tag_entry.data._slongs = values;
2668                 }
2669             } else {
2670                 m_Entries[m_nNumEntries].tag_entry.data._slong = *(int32_t *)data;
2671             }
2672         }
2673         break;
2674     case EXIF_SRATIONAL:
2675         {
2676             if (count > 1) {
2677                 srat_t *values = (srat_t *)malloc(count * sizeof(srat_t));
2678                 if (values == NULL) {
2679                     ALOGE("%s: No memory for signed rational array", __func__);
2680                     rc = NO_MEMORY;
2681                 } else {
2682                     memcpy(values, data, count * sizeof(srat_t));
2683                     m_Entries[m_nNumEntries].tag_entry.data._srats = values;
2684                 }
2685             } else {
2686                 m_Entries[m_nNumEntries].tag_entry.data._srat = *(srat_t *)data;
2687             }
2688         }
2689         break;
2690     }
2691 
2692     // Increase number of entries
2693     m_nNumEntries++;
2694     return rc;
2695 }
2696 
2697 }; // namespace qcamera
2698