• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Copyright (c) 2012-2016, The Linux Foundation. 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 "QCamera3PostProc"
31 
32 // To remove
33 #include <cutils/properties.h>
34 
35 // System dependencies
36 #include <stdio.h>
37 
38 // Camera dependencies
39 #include "QCamera3Channel.h"
40 #include "QCamera3HWI.h"
41 #include "QCamera3PostProc.h"
42 #include "QCamera3Stream.h"
43 #include "QCameraTrace.h"
44 
45 extern "C" {
46 #include "mm_camera_dbg.h"
47 }
48 
49 
50 namespace qcamera {
51 
52 static const char ExifAsciiPrefix[] =
53     { 0x41, 0x53, 0x43, 0x49, 0x49, 0x0, 0x0, 0x0 };          // "ASCII\0\0\0"
54 
55 __unused
56 static const char ExifUndefinedPrefix[] =
57     { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };   // "\0\0\0\0\0\0\0\0"
58 
59 #define EXIF_ASCII_PREFIX_SIZE           8   //(sizeof(ExifAsciiPrefix))
60 #define FOCAL_LENGTH_DECIMAL_PRECISION   1000
61 
62 /*===========================================================================
63  * FUNCTION   : QCamera3PostProcessor
64  *
65  * DESCRIPTION: constructor of QCamera3PostProcessor.
66  *
67  * PARAMETERS :
68  *   @cam_ctrl : ptr to HWI object
69  *
70  * RETURN     : None
71  *==========================================================================*/
QCamera3PostProcessor(QCamera3ProcessingChannel * ch_ctrl)72 QCamera3PostProcessor::QCamera3PostProcessor(QCamera3ProcessingChannel* ch_ctrl)
73     : m_parent(ch_ctrl),
74       mJpegCB(NULL),
75       mJpegUserData(NULL),
76       mJpegClientHandle(0),
77       mJpegSessionId(0),
78       m_bThumbnailNeeded(TRUE),
79       m_pReprocChannel(NULL),
80       m_inputPPQ(releasePPInputData, this),
81       m_inputFWKPPQ(NULL, this),
82       m_ongoingPPQ(releaseOngoingPPData, this),
83       m_inputJpegQ(releaseJpegData, this),
84       m_ongoingJpegQ(releaseJpegData, this),
85       m_inputMetaQ(releaseMetadata, this),
86       m_jpegSettingsQ(NULL, this)
87 {
88     memset(&mJpegHandle, 0, sizeof(mJpegHandle));
89     memset(&mJpegMetadata, 0, sizeof(mJpegMetadata));
90     pthread_mutex_init(&mReprocJobLock, NULL);
91 }
92 
93 /*===========================================================================
94  * FUNCTION   : ~QCamera3PostProcessor
95  *
96  * DESCRIPTION: deconstructor of QCamera3PostProcessor.
97  *
98  * PARAMETERS : None
99  *
100  * RETURN     : None
101  *==========================================================================*/
~QCamera3PostProcessor()102 QCamera3PostProcessor::~QCamera3PostProcessor()
103 {
104     pthread_mutex_destroy(&mReprocJobLock);
105 }
106 
107 /*===========================================================================
108  * FUNCTION   : init
109  *
110  * DESCRIPTION: initialization of postprocessor
111  *
112  * PARAMETERS :
113  *   @memory              : output buffer memory
114  *
115  * RETURN     : int32_t type of status
116  *              NO_ERROR  -- success
117  *              none-zero failure code
118  *==========================================================================*/
init(QCamera3StreamMem * memory)119 int32_t QCamera3PostProcessor::init(QCamera3StreamMem *memory)
120 {
121     ATRACE_CAMSCOPE_CALL(CAMSCOPE_HAL3_PPROC_INIT);
122     mOutputMem = memory;
123     m_dataProcTh.launch(dataProcessRoutine, this);
124 
125     return NO_ERROR;
126 }
127 
128 /*===========================================================================
129  * FUNCTION   : deinit
130  *
131  * DESCRIPTION: de-initialization of postprocessor
132  *
133  * PARAMETERS : None
134  *
135  * RETURN     : int32_t type of status
136  *              NO_ERROR  -- success
137  *              none-zero failure code
138  *==========================================================================*/
deinit()139 int32_t QCamera3PostProcessor::deinit()
140 {
141     int rc = NO_ERROR;
142     m_dataProcTh.exit();
143 
144     if (m_pReprocChannel != NULL) {
145         m_pReprocChannel->stop();
146         delete m_pReprocChannel;
147         m_pReprocChannel = NULL;
148     }
149 
150     if(mJpegClientHandle > 0) {
151         rc = mJpegHandle.close(mJpegClientHandle);
152         LOGH("Jpeg closed, rc = %d, mJpegClientHandle = %x",
153                rc, mJpegClientHandle);
154         mJpegClientHandle = 0;
155         memset(&mJpegHandle, 0, sizeof(mJpegHandle));
156     }
157 
158     mOutputMem = NULL;
159     return rc;
160 }
161 
162 /*===========================================================================
163  * FUNCTION   : initJpeg
164  *
165  * DESCRIPTION: initialization of jpeg through postprocessor
166  *
167  * PARAMETERS :
168  *   @jpeg_cb      : callback to handle jpeg event from mm-camera-interface
169  *   @max_pic_dim  : max picture dimensions
170  *   @user_data    : user data ptr for jpeg callback
171  *
172  * RETURN     : int32_t type of status
173  *              NO_ERROR  -- success
174  *              none-zero failure code
175  *==========================================================================*/
initJpeg(jpeg_encode_callback_t jpeg_cb,cam_dimension_t * max_pic_dim,void * user_data)176 int32_t QCamera3PostProcessor::initJpeg(jpeg_encode_callback_t jpeg_cb,
177         cam_dimension_t* max_pic_dim,
178         void *user_data)
179 {
180     ATRACE_CAMSCOPE_CALL(CAMSCOPE_HAL3_PPROC_INIT_JPEG);
181     mJpegCB = jpeg_cb;
182     mJpegUserData = user_data;
183     mm_dimension max_size;
184 
185     if ((0 > max_pic_dim->width) || (0 > max_pic_dim->height)) {
186         LOGE("Negative dimension %dx%d",
187                 max_pic_dim->width, max_pic_dim->height);
188         return BAD_VALUE;
189     }
190 
191     // set max pic size
192     memset(&max_size, 0, sizeof(mm_dimension));
193     max_size.w =  max_pic_dim->width;
194     max_size.h =  max_pic_dim->height;
195 
196     // Pass OTP calibration data to JPEG
197     QCamera3HardwareInterface* hal_obj = (QCamera3HardwareInterface*)m_parent->mUserData;
198     mJpegMetadata.default_sensor_flip = FLIP_NONE;
199     mJpegMetadata.sensor_mount_angle = hal_obj->getSensorMountAngle();
200     memcpy(&mJpegMetadata.otp_calibration_data,
201             hal_obj->getRelatedCalibrationData(),
202             sizeof(cam_related_system_calibration_data_t));
203     mJpegClientHandle = jpeg_open(&mJpegHandle, NULL, max_size, &mJpegMetadata);
204 
205     if (!mJpegClientHandle) {
206         LOGE("jpeg_open did not work");
207         return UNKNOWN_ERROR;
208     }
209     return NO_ERROR;
210 }
211 
212 /*===========================================================================
213  * FUNCTION   : start
214  *
215  * DESCRIPTION: start postprocessor. Data process thread and data notify thread
216  *              will be launched.
217  *
218  * PARAMETERS :
219  *   @config        : reprocess configuration
220  *
221  * RETURN     : int32_t type of status
222  *              NO_ERROR  -- success
223  *              none-zero failure code
224  *
225  * NOTE       : if any reprocess is needed, a reprocess channel/stream
226  *              will be started.
227  *==========================================================================*/
start(const reprocess_config_t & config)228 int32_t QCamera3PostProcessor::start(const reprocess_config_t &config)
229 {
230     int32_t rc = NO_ERROR;
231     QCamera3HardwareInterface* hal_obj = (QCamera3HardwareInterface*)m_parent->mUserData;
232 
233     if (config.reprocess_type != REPROCESS_TYPE_NONE) {
234         if (m_pReprocChannel != NULL) {
235             m_pReprocChannel->stop();
236             delete m_pReprocChannel;
237             m_pReprocChannel = NULL;
238         }
239 
240         // if reprocess is needed, start reprocess channel
241         LOGD("Setting input channel as pInputChannel");
242         m_pReprocChannel = hal_obj->addOfflineReprocChannel(config, m_parent);
243         if (m_pReprocChannel == NULL) {
244             LOGE("cannot add reprocess channel");
245             return UNKNOWN_ERROR;
246         }
247         /*start the reprocess channel only if buffers are already allocated, thus
248           only start it in an intermediate reprocess type, defer it for others*/
249         if (config.reprocess_type == REPROCESS_TYPE_JPEG) {
250             rc = m_pReprocChannel->start();
251             if (rc != 0) {
252                 LOGE("cannot start reprocess channel");
253                 delete m_pReprocChannel;
254                 m_pReprocChannel = NULL;
255                 return rc;
256             }
257         }
258     }
259     m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_START_DATA_PROC, TRUE, FALSE);
260 
261     return rc;
262 }
263 
264 /*===========================================================================
265  * FUNCTION   : flush
266  *
267  * DESCRIPTION: stop ongoing postprocess and jpeg jobs
268  *
269  * PARAMETERS : None
270  *
271  * RETURN     : int32_t type of status
272  *              NO_ERROR  -- success
273  *              none-zero failure code
274  *
275  *==========================================================================*/
flush()276 int32_t QCamera3PostProcessor::flush()
277 {
278     int32_t rc = NO_ERROR;
279     qcamera_hal3_jpeg_data_t *jpeg_job =
280             (qcamera_hal3_jpeg_data_t *)m_ongoingJpegQ.dequeue();
281     while (jpeg_job != NULL) {
282         rc = mJpegHandle.abort_job(jpeg_job->jobId);
283         releaseJpegJobData(jpeg_job);
284         free(jpeg_job);
285 
286         jpeg_job = (qcamera_hal3_jpeg_data_t *)m_ongoingJpegQ.dequeue();
287     }
288     rc = releaseOfflineBuffers(true);
289     return rc;
290 }
291 
292 /*===========================================================================
293  * FUNCTION   : stop
294  *
295  * DESCRIPTION: stop postprocessor. Data process and notify thread will be stopped.
296  *
297  * PARAMETERS : None
298  *
299  * RETURN     : int32_t type of status
300  *              NO_ERROR  -- success
301  *              none-zero failure code
302  *
303  * NOTE       : reprocess channel will be stopped and deleted if there is any
304  *==========================================================================*/
stop()305 int32_t QCamera3PostProcessor::stop()
306 {
307     m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_STOP_DATA_PROC, TRUE, TRUE);
308 
309     if (m_pReprocChannel != NULL) {
310         m_pReprocChannel->stop();
311         delete m_pReprocChannel;
312         m_pReprocChannel = NULL;
313     }
314 
315     return NO_ERROR;
316 }
317 
318 /*===========================================================================
319  * FUNCTION   : getFWKJpegEncodeConfig
320  *
321  * DESCRIPTION: function to prepare encoding job information
322  *
323  * PARAMETERS :
324  *   @encode_parm   : param to be filled with encoding configuration
325  *   @frame         : framework input buffer
326  *   @jpeg_settings : jpeg settings to be applied for encoding
327  *
328  * RETURN     : int32_t type of status
329  *              NO_ERROR  -- success
330  *              none-zero failure code
331  *==========================================================================*/
getFWKJpegEncodeConfig(mm_jpeg_encode_params_t & encode_parm,qcamera_fwk_input_pp_data_t * frame,jpeg_settings_t * jpeg_settings)332 int32_t QCamera3PostProcessor::getFWKJpegEncodeConfig(
333         mm_jpeg_encode_params_t& encode_parm,
334         qcamera_fwk_input_pp_data_t *frame,
335         jpeg_settings_t *jpeg_settings)
336 {
337     LOGD("E");
338     int32_t ret = NO_ERROR;
339 
340     if ((NULL == frame) || (NULL == jpeg_settings)) {
341         return BAD_VALUE;
342     }
343 
344     ssize_t bufSize = mOutputMem->getSize(jpeg_settings->out_buf_index);
345     if (BAD_INDEX == bufSize) {
346         LOGE("cannot retrieve buffer size for buffer %u",
347                 jpeg_settings->out_buf_index);
348         return BAD_VALUE;
349     }
350 
351     encode_parm.jpeg_cb = mJpegCB;
352     encode_parm.userdata = mJpegUserData;
353 
354     if (jpeg_settings->thumbnail_size.width > 0 &&
355             jpeg_settings->thumbnail_size.height > 0)
356         m_bThumbnailNeeded = TRUE;
357     else
358         m_bThumbnailNeeded = FALSE;
359     encode_parm.encode_thumbnail = m_bThumbnailNeeded;
360 
361     // get color format
362     cam_format_t img_fmt = frame->reproc_config.stream_format;
363     encode_parm.color_format = getColorfmtFromImgFmt(img_fmt);
364 
365     // get jpeg quality
366     encode_parm.quality = jpeg_settings->jpeg_quality;
367     if (encode_parm.quality <= 0) {
368         encode_parm.quality = 85;
369     }
370 
371     // get jpeg thumbnail quality
372     encode_parm.thumb_quality = jpeg_settings->jpeg_thumb_quality;
373 
374     cam_frame_len_offset_t main_offset =
375             frame->reproc_config.input_stream_plane_info.plane_info;
376 
377     encode_parm.num_src_bufs = 1;
378     encode_parm.src_main_buf[0].index = 0;
379     encode_parm.src_main_buf[0].buf_size = frame->input_buffer.frame_len;
380     encode_parm.src_main_buf[0].buf_vaddr = (uint8_t *) frame->input_buffer.buffer;
381     encode_parm.src_main_buf[0].fd = frame->input_buffer.fd;
382     encode_parm.src_main_buf[0].format = MM_JPEG_FMT_YUV;
383     encode_parm.src_main_buf[0].offset = main_offset;
384 
385     //Pass input thumbnail buffer info to encoder.
386     //Note: Use main buffer to encode thumbnail
387     if (m_bThumbnailNeeded == TRUE) {
388         encode_parm.num_tmb_bufs = 1;
389         encode_parm.src_thumb_buf[0] = encode_parm.src_main_buf[0];
390     }
391 
392     //Pass output jpeg buffer info to encoder.
393     //mOutputMem is allocated by framework.
394     encode_parm.num_dst_bufs = 1;
395     encode_parm.dest_buf[0].index = 0;
396     encode_parm.dest_buf[0].buf_size = (size_t)bufSize;
397     encode_parm.dest_buf[0].buf_vaddr = (uint8_t *)mOutputMem->getPtr(
398             jpeg_settings->out_buf_index);
399     encode_parm.dest_buf[0].fd = mOutputMem->getFd(
400             jpeg_settings->out_buf_index);
401     encode_parm.dest_buf[0].format = MM_JPEG_FMT_YUV;
402     encode_parm.dest_buf[0].offset = main_offset;
403 
404     LOGD("X");
405     return NO_ERROR;
406 
407     LOGD("X with error %d", ret);
408     return ret;
409 }
410 
411 /*===========================================================================
412  * FUNCTION   : getJpegEncodeConfig
413  *
414  * DESCRIPTION: function to prepare encoding job information
415  *
416  * PARAMETERS :
417  *   @encode_parm   : param to be filled with encoding configuration
418  *   #main_stream   : stream object where the input buffer comes from
419  *   @jpeg_settings : jpeg settings to be applied for encoding
420  *
421  * RETURN     : int32_t type of status
422  *              NO_ERROR  -- success
423  *              none-zero failure code
424  *==========================================================================*/
getJpegEncodeConfig(mm_jpeg_encode_params_t & encode_parm,QCamera3Stream * main_stream,jpeg_settings_t * jpeg_settings)425 int32_t QCamera3PostProcessor::getJpegEncodeConfig(
426                 mm_jpeg_encode_params_t& encode_parm,
427                 QCamera3Stream *main_stream,
428                 jpeg_settings_t *jpeg_settings)
429 {
430     LOGD("E");
431     int32_t ret = NO_ERROR;
432     ssize_t bufSize = 0;
433 
434     encode_parm.jpeg_cb = mJpegCB;
435     encode_parm.userdata = mJpegUserData;
436 
437     if (jpeg_settings->thumbnail_size.width > 0 &&
438             jpeg_settings->thumbnail_size.height > 0)
439         m_bThumbnailNeeded = TRUE;
440     else
441         m_bThumbnailNeeded = FALSE;
442     encode_parm.encode_thumbnail = m_bThumbnailNeeded;
443 
444     // get color format
445     cam_format_t img_fmt = CAM_FORMAT_YUV_420_NV12;  //default value
446     main_stream->getFormat(img_fmt);
447     encode_parm.color_format = getColorfmtFromImgFmt(img_fmt);
448 
449     // get jpeg quality
450     encode_parm.quality = jpeg_settings->jpeg_quality;
451     if (encode_parm.quality <= 0) {
452         encode_parm.quality = 85;
453     }
454 
455     // get jpeg thumbnail quality
456     encode_parm.thumb_quality = jpeg_settings->jpeg_thumb_quality;
457 
458     cam_frame_len_offset_t main_offset;
459     memset(&main_offset, 0, sizeof(cam_frame_len_offset_t));
460     main_stream->getFrameOffset(main_offset);
461 
462     // src buf config
463     //Pass input main image buffer info to encoder.
464     QCamera3StreamMem *pStreamMem = main_stream->getStreamBufs();
465     if (pStreamMem == NULL) {
466         LOGE("cannot get stream bufs from main stream");
467         ret = BAD_VALUE;
468         goto on_error;
469     }
470     encode_parm.num_src_bufs = MIN(pStreamMem->getCnt(), MM_JPEG_MAX_BUF);
471     for (uint32_t i = 0; i < encode_parm.num_src_bufs; i++) {
472         if (pStreamMem != NULL) {
473             encode_parm.src_main_buf[i].index = i;
474             bufSize = pStreamMem->getSize(i);
475             if (BAD_INDEX == bufSize) {
476                 LOGE("cannot retrieve buffer size for buffer %u", i);
477                 ret = BAD_VALUE;
478                 goto on_error;
479             }
480             encode_parm.src_main_buf[i].buf_size = (size_t)bufSize;
481             encode_parm.src_main_buf[i].buf_vaddr = (uint8_t *)pStreamMem->getPtr(i);
482             encode_parm.src_main_buf[i].fd = pStreamMem->getFd(i);
483             encode_parm.src_main_buf[i].format = MM_JPEG_FMT_YUV;
484             encode_parm.src_main_buf[i].offset = main_offset;
485         }
486     }
487 
488     //Pass input thumbnail buffer info to encoder.
489     //Note: Use main buffer to encode thumbnail
490     if (m_bThumbnailNeeded == TRUE) {
491         pStreamMem = main_stream->getStreamBufs();
492         if (pStreamMem == NULL) {
493             LOGE("cannot get stream bufs from thumb stream");
494             ret = BAD_VALUE;
495             goto on_error;
496         }
497         cam_frame_len_offset_t thumb_offset;
498         memset(&thumb_offset, 0, sizeof(cam_frame_len_offset_t));
499         main_stream->getFrameOffset(thumb_offset);
500         encode_parm.num_tmb_bufs = MIN(pStreamMem->getCnt(), MM_JPEG_MAX_BUF);
501         for (uint32_t i = 0; i < encode_parm.num_tmb_bufs; i++) {
502             if (pStreamMem != NULL) {
503                 encode_parm.src_thumb_buf[i].index = i;
504                 bufSize = pStreamMem->getSize(i);
505                 if (BAD_INDEX == bufSize) {
506                     LOGE("cannot retrieve buffer size for buffer %u", i);
507                     ret = BAD_VALUE;
508                     goto on_error;
509                 }
510                 encode_parm.src_thumb_buf[i].buf_size = (uint32_t)bufSize;
511                 encode_parm.src_thumb_buf[i].buf_vaddr = (uint8_t *)pStreamMem->getPtr(i);
512                 encode_parm.src_thumb_buf[i].fd = pStreamMem->getFd(i);
513                 encode_parm.src_thumb_buf[i].format = MM_JPEG_FMT_YUV;
514                 encode_parm.src_thumb_buf[i].offset = thumb_offset;
515             }
516         }
517     }
518 
519     //Pass output jpeg buffer info to encoder.
520     //mJpegMem is allocated by framework.
521     bufSize = mOutputMem->getSize(jpeg_settings->out_buf_index);
522     if (BAD_INDEX == bufSize) {
523         LOGE("cannot retrieve buffer size for buffer %u",
524                 jpeg_settings->out_buf_index);
525         ret = BAD_VALUE;
526         goto on_error;
527     }
528     encode_parm.num_dst_bufs = 1;
529     encode_parm.dest_buf[0].index = 0;
530     encode_parm.dest_buf[0].buf_size = (size_t)bufSize;
531     encode_parm.dest_buf[0].buf_vaddr = (uint8_t *)mOutputMem->getPtr(
532             jpeg_settings->out_buf_index);
533     encode_parm.dest_buf[0].fd = mOutputMem->getFd(
534             jpeg_settings->out_buf_index);
535     encode_parm.dest_buf[0].format = MM_JPEG_FMT_YUV;
536     encode_parm.dest_buf[0].offset = main_offset;
537 
538     LOGD("X");
539     return NO_ERROR;
540 
541 on_error:
542     LOGD("X with error %d", ret);
543     return ret;
544 }
545 
processData(mm_camera_super_buf_t * input)546 int32_t QCamera3PostProcessor::processData(mm_camera_super_buf_t *input) {
547     return processData(input, NULL, 0);
548 }
549 
550 /*===========================================================================
551  * FUNCTION   : processData
552  *
553  * DESCRIPTION: enqueue data into dataProc thread
554  *
555  * PARAMETERS :
556  *   @frame   : process input frame
557  *   @output  : process output frame
558  *
559  * RETURN     : int32_t type of status
560  *              NO_ERROR  -- success
561  *              none-zero failure code
562  *
563  * NOTE       : depends on if offline reprocess is needed, received frame will
564  *              be sent to either input queue of postprocess or jpeg encoding
565  *==========================================================================*/
processData(mm_camera_super_buf_t * input,buffer_handle_t * output,uint32_t frameNumber)566 int32_t QCamera3PostProcessor::processData(mm_camera_super_buf_t *input,
567         buffer_handle_t *output, uint32_t frameNumber)
568 {
569     LOGD("E");
570     pthread_mutex_lock(&mReprocJobLock);
571 
572     // enqueue to post proc input queue
573     qcamera_hal3_pp_buffer_t *pp_buffer = (qcamera_hal3_pp_buffer_t *)malloc(
574             sizeof(qcamera_hal3_pp_buffer_t));
575     if (NULL == pp_buffer) {
576         LOGE("out of memory");
577         return NO_MEMORY;
578     }
579     memset(pp_buffer, 0, sizeof(*pp_buffer));
580     pp_buffer->input = input;
581     pp_buffer->output = output;
582     pp_buffer->frameNumber = frameNumber;
583     m_inputPPQ.enqueue((void *)pp_buffer);
584     if (!(m_inputMetaQ.isEmpty())) {
585         LOGD("meta queue is not empty, do next job");
586         m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_DO_NEXT_JOB, FALSE, FALSE);
587     } else
588         LOGD("metadata queue is empty");
589     pthread_mutex_unlock(&mReprocJobLock);
590 
591     return NO_ERROR;
592 }
593 
594 /*===========================================================================
595  * FUNCTION   : needsReprocess
596  *
597  * DESCRIPTION: Determine if reprocess is needed.
598  *
599  * PARAMETERS :
600  *   @frame   : process frame
601  *
602  * RETURN     :
603  *  TRUE if frame needs to be reprocessed
604  *  FALSE is frame does not need to be reprocessed
605  *
606  *==========================================================================*/
needsReprocess(qcamera_fwk_input_pp_data_t * frame)607 bool QCamera3PostProcessor::needsReprocess(qcamera_fwk_input_pp_data_t *frame)
608 {
609     metadata_buffer_t* meta = (metadata_buffer_t *) frame->metadata_buffer.buffer;
610     bool edgeModeOn = FALSE;
611     bool noiseRedModeOn = FALSE;
612     bool reproNotDone = TRUE;
613 
614     if (frame->reproc_config.reprocess_type == REPROCESS_TYPE_NONE) {
615         return FALSE;
616     }
617 
618     // edge detection
619     IF_META_AVAILABLE(cam_edge_application_t, edgeMode,
620             CAM_INTF_META_EDGE_MODE, meta) {
621         edgeModeOn = (CAM_EDGE_MODE_OFF != edgeMode->edge_mode);
622     }
623 
624     // noise reduction
625     IF_META_AVAILABLE(uint32_t, noiseRedMode,
626             CAM_INTF_META_NOISE_REDUCTION_MODE, meta) {
627         noiseRedModeOn = (CAM_NOISE_REDUCTION_MODE_OFF != *noiseRedMode);
628     }
629 
630     IF_META_AVAILABLE(uint8_t, reprocess_flags,
631             CAM_INTF_META_REPROCESS_FLAGS, meta) {
632         reproNotDone = FALSE;
633     }
634 
635     return (edgeModeOn || noiseRedModeOn || reproNotDone);
636 }
637 
638 /*===========================================================================
639  * FUNCTION   : processData
640  *
641  * DESCRIPTION: enqueue data into dataProc thread
642  *
643  * PARAMETERS :
644  *   @frame   : process frame
645  *
646  * RETURN     : int32_t type of status
647  *              NO_ERROR  -- success
648  *              none-zero failure code
649  *
650  * NOTE       : depends on if offline reprocess is needed, received frame will
651  *              be sent to either input queue of postprocess or jpeg encoding
652  *==========================================================================*/
processData(qcamera_fwk_input_pp_data_t * frame)653 int32_t QCamera3PostProcessor::processData(qcamera_fwk_input_pp_data_t *frame)
654 {
655     if (needsReprocess(frame)) {
656         ATRACE_INT("Camera:Reprocess", 1);
657         LOGH("scheduling framework reprocess");
658         pthread_mutex_lock(&mReprocJobLock);
659         // enqueu to post proc input queue
660         m_inputFWKPPQ.enqueue((void *)frame);
661         m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_DO_NEXT_JOB, FALSE, FALSE);
662         pthread_mutex_unlock(&mReprocJobLock);
663     } else {
664         jpeg_settings_t *jpeg_settings = (jpeg_settings_t *)m_jpegSettingsQ.dequeue();
665 
666         if (jpeg_settings == NULL) {
667             LOGE("Cannot find jpeg settings");
668             return BAD_VALUE;
669         }
670 
671         LOGH("no need offline reprocess, sending to jpeg encoding");
672         qcamera_hal3_jpeg_data_t *jpeg_job =
673             (qcamera_hal3_jpeg_data_t *)malloc(sizeof(qcamera_hal3_jpeg_data_t));
674         if (jpeg_job == NULL) {
675             LOGE("No memory for jpeg job");
676             return NO_MEMORY;
677         }
678 
679         memset(jpeg_job, 0, sizeof(qcamera_hal3_jpeg_data_t));
680         jpeg_job->fwk_frame = frame;
681         jpeg_job->jpeg_settings = jpeg_settings;
682         jpeg_job->metadata =
683                 (metadata_buffer_t *) frame->metadata_buffer.buffer;
684 
685         // enqueu to jpeg input queue
686         m_inputJpegQ.enqueue((void *)jpeg_job);
687         m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_DO_NEXT_JOB, FALSE, FALSE);
688     }
689 
690     return NO_ERROR;
691 }
692 
693 /*===========================================================================
694  * FUNCTION   : processPPMetadata
695  *
696  * DESCRIPTION: enqueue data into dataProc thread
697  *
698  * PARAMETERS :
699  *   @frame   : process metadata frame received from pic channel
700  *
701  * RETURN     : int32_t type of status
702  *              NO_ERROR  -- success
703  *              none-zero failure code
704  *
705  *==========================================================================*/
processPPMetadata(mm_camera_super_buf_t * reproc_meta)706 int32_t QCamera3PostProcessor::processPPMetadata(mm_camera_super_buf_t *reproc_meta)
707 {
708     LOGD("E");
709     pthread_mutex_lock(&mReprocJobLock);
710     // enqueue to metadata input queue
711     m_inputMetaQ.enqueue((void *)reproc_meta);
712     if (!(m_inputPPQ.isEmpty())) {
713        LOGD("pp queue is not empty, do next job");
714        m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_DO_NEXT_JOB, FALSE, FALSE);
715     } else {
716        LOGD("pp queue is empty, not calling do next job");
717     }
718     pthread_mutex_unlock(&mReprocJobLock);
719     return NO_ERROR;
720 }
721 
722 /*===========================================================================
723  * FUNCTION   : processJpegSettingData
724  *
725  * DESCRIPTION: enqueue jpegSetting into dataProc thread
726  *
727  * PARAMETERS :
728  *   @jpeg_settings : jpeg settings data received from pic channel
729  *
730  * RETURN     : int32_t type of status
731  *              NO_ERROR  -- success
732  *              none-zero failure code
733  *
734  *==========================================================================*/
processJpegSettingData(jpeg_settings_t * jpeg_settings)735 int32_t QCamera3PostProcessor::processJpegSettingData(
736         jpeg_settings_t *jpeg_settings)
737 {
738     if (!jpeg_settings) {
739         LOGE("invalid jpeg settings pointer");
740         return -EINVAL;
741     }
742     return m_jpegSettingsQ.enqueue((void *)jpeg_settings);
743 }
744 
745 /*===========================================================================
746  * FUNCTION   : processPPData
747  *
748  * DESCRIPTION: process received frame after reprocess.
749  *
750  * PARAMETERS :
751  *   @frame   : received frame from reprocess channel.
752  *
753  * RETURN     : int32_t type of status
754  *              NO_ERROR  -- success
755  *              none-zero failure code
756  *
757  * NOTE       : The frame after reprocess need to send to jpeg encoding.
758  *==========================================================================*/
processPPData(mm_camera_super_buf_t * frame)759 int32_t QCamera3PostProcessor::processPPData(mm_camera_super_buf_t *frame)
760 {
761     qcamera_hal3_pp_data_t *job = (qcamera_hal3_pp_data_t *)m_ongoingPPQ.dequeue();
762     ATRACE_INT("Camera:Reprocess", 0);
763     if (job == NULL || ((NULL == job->src_frame) && (NULL == job->fwk_src_frame))) {
764         LOGE("Cannot find reprocess job");
765         return BAD_VALUE;
766     }
767     if (job->jpeg_settings == NULL) {
768         LOGE("Cannot find jpeg settings");
769         return BAD_VALUE;
770     }
771 
772     qcamera_hal3_jpeg_data_t *jpeg_job =
773         (qcamera_hal3_jpeg_data_t *)malloc(sizeof(qcamera_hal3_jpeg_data_t));
774     if (jpeg_job == NULL) {
775         LOGE("No memory for jpeg job");
776         return NO_MEMORY;
777     }
778 
779     memset(jpeg_job, 0, sizeof(qcamera_hal3_jpeg_data_t));
780     jpeg_job->src_frame = frame;
781     if(frame != job->src_frame)
782         jpeg_job->src_reproc_frame = job->src_frame;
783     if (NULL == job->fwk_src_frame) {
784         jpeg_job->metadata = job->metadata;
785     } else {
786         jpeg_job->metadata =
787                 (metadata_buffer_t *) job->fwk_src_frame->metadata_buffer.buffer;
788         jpeg_job->fwk_src_buffer = job->fwk_src_frame;
789     }
790     jpeg_job->src_metadata = job->src_metadata;
791     jpeg_job->jpeg_settings = job->jpeg_settings;
792 
793     // free pp job buf
794     free(job);
795 
796     // enqueu reprocessed frame to jpeg input queue
797     m_inputJpegQ.enqueue((void *)jpeg_job);
798 
799     // wait up data proc thread
800     m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_DO_NEXT_JOB, FALSE, FALSE);
801 
802     return NO_ERROR;
803 }
804 
805 /*===========================================================================
806  * FUNCTION   : dequeuePPJob
807  *
808  * DESCRIPTION: find a postprocessing job from ongoing pp queue by frame number
809  *
810  * PARAMETERS :
811  *   @frameNumber : frame number for the pp job
812  *
813  * RETURN     : ptr to a pp job struct. NULL if not found.
814  *==========================================================================*/
dequeuePPJob(uint32_t frameNumber)815 qcamera_hal3_pp_data_t *QCamera3PostProcessor::dequeuePPJob(uint32_t frameNumber) {
816     qcamera_hal3_pp_data_t *pp_job = NULL;
817     pp_job = (qcamera_hal3_pp_data_t *)m_ongoingPPQ.dequeue();
818 
819     if (pp_job == NULL) {
820         LOGE("Fatal: ongoing PP queue is empty");
821         return NULL;
822     }
823     if (pp_job->fwk_src_frame &&
824             (pp_job->fwk_src_frame->frameNumber != frameNumber)) {
825         LOGE("head of pp queue doesn't match requested frame number");
826     }
827     return pp_job;
828 }
829 
830 /*===========================================================================
831  * FUNCTION   : findJpegJobByJobId
832  *
833  * DESCRIPTION: find a jpeg job from ongoing Jpeg queue by its job ID
834  *
835  * PARAMETERS :
836  *   @jobId   : job Id of the job
837  *
838  * RETURN     : ptr to a jpeg job struct. NULL if not found.
839  *
840  * NOTE       : Currently only one job is sending to mm-jpeg-interface for jpeg
841  *              encoding. Therefore simply dequeue from the ongoing Jpeg Queue
842  *              will serve the purpose to find the jpeg job.
843  *==========================================================================*/
findJpegJobByJobId(uint32_t jobId)844 qcamera_hal3_jpeg_data_t *QCamera3PostProcessor::findJpegJobByJobId(uint32_t jobId)
845 {
846     qcamera_hal3_jpeg_data_t * job = NULL;
847     if (jobId == 0) {
848         LOGE("not a valid jpeg jobId");
849         return NULL;
850     }
851 
852     // currely only one jpeg job ongoing, so simply dequeue the head
853     job = (qcamera_hal3_jpeg_data_t *)m_ongoingJpegQ.dequeue();
854     return job;
855 }
856 
857 /*===========================================================================
858  * FUNCTION   : releasePPInputData
859  *
860  * DESCRIPTION: callback function to release post process input data node
861  *
862  * PARAMETERS :
863  *   @data      : ptr to post process input data
864  *   @user_data : user data ptr (QCamera3Reprocessor)
865  *
866  * RETURN     : None
867  *==========================================================================*/
releasePPInputData(void * data,void * user_data)868 void QCamera3PostProcessor::releasePPInputData(void *data, void *user_data)
869 {
870     QCamera3PostProcessor *pme = (QCamera3PostProcessor *)user_data;
871     if (NULL != pme) {
872         qcamera_hal3_pp_buffer_t *buf = (qcamera_hal3_pp_buffer_t *)data;
873         if (NULL != buf) {
874             if (buf->input) {
875                 pme->releaseSuperBuf(buf->input);
876                 free(buf->input);
877                 buf->input = NULL;
878             }
879         }
880     }
881 }
882 
883 /*===========================================================================
884  * FUNCTION   : releaseMetaData
885  *
886  * DESCRIPTION: callback function to release metadata camera buffer
887  *
888  * PARAMETERS :
889  *   @data      : ptr to post process input data
890  *   @user_data : user data ptr (QCamera3Reprocessor)
891  *
892  * RETURN     : None
893  *==========================================================================*/
releaseMetadata(void * data,void * user_data)894 void QCamera3PostProcessor::releaseMetadata(void *data, void *user_data)
895 {
896     QCamera3PostProcessor *pme = (QCamera3PostProcessor *)user_data;
897     if (NULL != pme) {
898         pme->m_parent->metadataBufDone((mm_camera_super_buf_t *)data);
899     }
900 }
901 
902 /*===========================================================================
903  * FUNCTION   : releaseJpegData
904  *
905  * DESCRIPTION: callback function to release jpeg job node
906  *
907  * PARAMETERS :
908  *   @data      : ptr to ongoing jpeg job data
909  *   @user_data : user data ptr (QCamera3Reprocessor)
910  *
911  * RETURN     : None
912  *==========================================================================*/
releaseJpegData(void * data,void * user_data)913 void QCamera3PostProcessor::releaseJpegData(void *data, void *user_data)
914 {
915     QCamera3PostProcessor *pme = (QCamera3PostProcessor *)user_data;
916     if (NULL != pme) {
917         pme->releaseJpegJobData((qcamera_hal3_jpeg_data_t *)data);
918     }
919 }
920 
921 /*===========================================================================
922  * FUNCTION   : releaseOngoingPPData
923  *
924  * DESCRIPTION: callback function to release ongoing postprocess job node
925  *
926  * PARAMETERS :
927  *   @data      : ptr to onging postprocess job
928  *   @user_data : user data ptr (QCamera3Reprocessor)
929  *
930  * RETURN     : None
931  *==========================================================================*/
releaseOngoingPPData(void * data,void * user_data)932 void QCamera3PostProcessor::releaseOngoingPPData(void *data, void *user_data)
933 {
934     QCamera3PostProcessor *pme = (QCamera3PostProcessor *)user_data;
935     if (NULL != pme) {
936         qcamera_hal3_pp_data_t *pp_data = (qcamera_hal3_pp_data_t *)data;
937 
938         if (pp_data && pp_data->src_frame)
939           pme->releaseSuperBuf(pp_data->src_frame);
940 
941         pme->releasePPJobData(pp_data);
942 
943     }
944 }
945 
946 /*===========================================================================
947  * FUNCTION   : releaseSuperBuf
948  *
949  * DESCRIPTION: function to release a superbuf frame by returning back to kernel
950  *
951  * PARAMETERS :
952  *   @super_buf : ptr to the superbuf frame
953  *
954  * RETURN     : None
955  *==========================================================================*/
releaseSuperBuf(mm_camera_super_buf_t * super_buf)956 void QCamera3PostProcessor::releaseSuperBuf(mm_camera_super_buf_t *super_buf)
957 {
958     if (NULL != super_buf) {
959         if (m_parent != NULL) {
960             m_parent->bufDone(super_buf);
961         }
962     }
963 }
964 
965 /*===========================================================================
966  * FUNCTION   : releaseOfflineBuffers
967  *
968  * DESCRIPTION: function to release/unmap offline buffers if any
969  *
970  * PARAMETERS :
971  * @allBuffers : flag that asks to release all buffers or only one
972  *
973  * RETURN     : int32_t type of status
974  *              NO_ERROR  -- success
975  *              none-zero failure code
976  *==========================================================================*/
releaseOfflineBuffers(bool allBuffers)977 int32_t QCamera3PostProcessor::releaseOfflineBuffers(bool allBuffers)
978 {
979     int32_t rc = NO_ERROR;
980 
981     if(NULL != m_pReprocChannel) {
982         rc = m_pReprocChannel->unmapOfflineBuffers(allBuffers);
983     }
984 
985     return rc;
986 }
987 
988 /*===========================================================================
989  * FUNCTION   : releaseJpegJobData
990  *
991  * DESCRIPTION: function to release internal resources in jpeg job struct
992  *
993  * PARAMETERS :
994  *   @job     : ptr to jpeg job struct
995  *
996  * RETURN     : None
997  *
998  * NOTE       : original source frame need to be queued back to kernel for
999  *              future use. Output buf of jpeg job need to be released since
1000  *              it's allocated for each job. Exif object need to be deleted.
1001  *==========================================================================*/
releaseJpegJobData(qcamera_hal3_jpeg_data_t * job)1002 void QCamera3PostProcessor::releaseJpegJobData(qcamera_hal3_jpeg_data_t *job)
1003 {
1004     ATRACE_CAMSCOPE_CALL(CAMSCOPE_HAL3_PPROC_REL_JPEG_JOB_DATA);
1005     int32_t rc = NO_ERROR;
1006     LOGD("E");
1007     if (NULL != job) {
1008         if (NULL != job->src_reproc_frame) {
1009             free(job->src_reproc_frame);
1010             job->src_reproc_frame = NULL;
1011         }
1012 
1013         if (NULL != job->src_frame) {
1014             if (NULL != m_pReprocChannel) {
1015                 rc = m_pReprocChannel->bufDone(job->src_frame);
1016                 if (NO_ERROR != rc)
1017                     LOGE("bufDone error: %d", rc);
1018             }
1019             free(job->src_frame);
1020             job->src_frame = NULL;
1021         }
1022 
1023         if (NULL != job->fwk_src_buffer) {
1024             free(job->fwk_src_buffer);
1025             job->fwk_src_buffer = NULL;
1026         } else if (NULL != job->src_metadata) {
1027             m_parent->metadataBufDone(job->src_metadata);
1028             free(job->src_metadata);
1029             job->src_metadata = NULL;
1030         }
1031 
1032         if (NULL != job->fwk_frame) {
1033             free(job->fwk_frame);
1034             job->fwk_frame = NULL;
1035         }
1036 
1037         if (NULL != job->pJpegExifObj) {
1038             delete job->pJpegExifObj;
1039             job->pJpegExifObj = NULL;
1040         }
1041 
1042         if (NULL != job->jpeg_settings) {
1043             free(job->jpeg_settings);
1044             job->jpeg_settings = NULL;
1045         }
1046     }
1047     /* Additional trigger to process any pending jobs in the input queue */
1048     m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_DO_NEXT_JOB, FALSE, FALSE);
1049     LOGD("X");
1050 }
1051 
1052 /*===========================================================================
1053  * FUNCTION   : releasePPJobData
1054  *
1055  * DESCRIPTION: function to release internal resources in p pjob struct
1056  *
1057  * PARAMETERS :
1058  *   @job     : ptr to pp job struct
1059  *
1060  * RETURN     : None
1061  *
1062  * NOTE       : Original source metadata buffer needs to be released and
1063  *              queued back to kernel for future use. src_frame, src_metadata,
1064  *              and fwk_src_frame structures need to be freed.
1065  *==========================================================================*/
releasePPJobData(qcamera_hal3_pp_data_t * pp_job)1066 void QCamera3PostProcessor::releasePPJobData(qcamera_hal3_pp_data_t *pp_job)
1067 {
1068     ATRACE_CAMSCOPE_CALL(CAMSCOPE_HAL3_PPROC_REL_PP_JOB_DATA);
1069     LOGD("E");
1070     if (NULL != pp_job) {
1071         if (NULL != pp_job->src_frame) {
1072             free(pp_job->src_frame);
1073             if (NULL != pp_job->src_metadata) {
1074                 m_parent->metadataBufDone(pp_job->src_metadata);
1075                 free(pp_job->src_metadata);
1076             }
1077             pp_job->src_frame = NULL;
1078             pp_job->metadata = NULL;
1079         }
1080 
1081         if (NULL != pp_job->fwk_src_frame) {
1082             free(pp_job->fwk_src_frame);
1083             pp_job->fwk_src_frame = NULL;
1084         }
1085     }
1086 
1087     /* Additional trigger to process any pending jobs in the input queue */
1088     m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_DO_NEXT_JOB, FALSE, FALSE);
1089     LOGD("X");
1090 }
1091 
1092 /*===========================================================================
1093  * FUNCTION   : getColorfmtFromImgFmt
1094  *
1095  * DESCRIPTION: function to return jpeg color format based on its image format
1096  *
1097  * PARAMETERS :
1098  *   @img_fmt : image format
1099  *
1100  * RETURN     : jpeg color format that can be understandable by omx lib
1101  *==========================================================================*/
getColorfmtFromImgFmt(cam_format_t img_fmt)1102 mm_jpeg_color_format QCamera3PostProcessor::getColorfmtFromImgFmt(cam_format_t img_fmt)
1103 {
1104     switch (img_fmt) {
1105     case CAM_FORMAT_YUV_420_NV21:
1106     case CAM_FORMAT_YUV_420_NV21_VENUS:
1107         return MM_JPEG_COLOR_FORMAT_YCRCBLP_H2V2;
1108     case CAM_FORMAT_YUV_420_NV21_ADRENO:
1109         return MM_JPEG_COLOR_FORMAT_YCRCBLP_H2V2;
1110     case CAM_FORMAT_YUV_420_NV12:
1111     case CAM_FORMAT_YUV_420_NV12_VENUS:
1112         return MM_JPEG_COLOR_FORMAT_YCBCRLP_H2V2;
1113     case CAM_FORMAT_YUV_420_YV12:
1114         return MM_JPEG_COLOR_FORMAT_YCBCRLP_H2V2;
1115     case CAM_FORMAT_YUV_422_NV61:
1116         return MM_JPEG_COLOR_FORMAT_YCRCBLP_H2V1;
1117     case CAM_FORMAT_YUV_422_NV16:
1118         return MM_JPEG_COLOR_FORMAT_YCBCRLP_H2V1;
1119     default:
1120         return MM_JPEG_COLOR_FORMAT_YCRCBLP_H2V2;
1121     }
1122 }
1123 
1124 /*===========================================================================
1125  * FUNCTION   : getJpegImgTypeFromImgFmt
1126  *
1127  * DESCRIPTION: function to return jpeg encode image type based on its image format
1128  *
1129  * PARAMETERS :
1130  *   @img_fmt : image format
1131  *
1132  * RETURN     : return jpeg source image format (YUV or Bitstream)
1133  *==========================================================================*/
getJpegImgTypeFromImgFmt(cam_format_t img_fmt)1134 mm_jpeg_format_t QCamera3PostProcessor::getJpegImgTypeFromImgFmt(cam_format_t img_fmt)
1135 {
1136     switch (img_fmt) {
1137     case CAM_FORMAT_YUV_420_NV21:
1138     case CAM_FORMAT_YUV_420_NV21_ADRENO:
1139     case CAM_FORMAT_YUV_420_NV12:
1140     case CAM_FORMAT_YUV_420_NV12_VENUS:
1141     case CAM_FORMAT_YUV_420_NV21_VENUS:
1142     case CAM_FORMAT_YUV_420_YV12:
1143     case CAM_FORMAT_YUV_422_NV61:
1144     case CAM_FORMAT_YUV_422_NV16:
1145         return MM_JPEG_FMT_YUV;
1146     default:
1147         return MM_JPEG_FMT_YUV;
1148     }
1149 }
1150 
1151 /*===========================================================================
1152  * FUNCTION   : encodeFWKData
1153  *
1154  * DESCRIPTION: function to prepare encoding job information and send to
1155  *              mm-jpeg-interface to do the encoding job
1156  *
1157  * PARAMETERS :
1158  *   @jpeg_job_data : ptr to a struct saving job related information
1159  *   @needNewSess   : flag to indicate if a new jpeg encoding session need
1160  *                    to be created. After creation, this flag will be toggled
1161  *
1162  * RETURN     : int32_t type of status
1163  *              NO_ERROR  -- success
1164  *              none-zero failure code
1165  *==========================================================================*/
encodeFWKData(qcamera_hal3_jpeg_data_t * jpeg_job_data,uint8_t & needNewSess)1166 int32_t QCamera3PostProcessor::encodeFWKData(qcamera_hal3_jpeg_data_t *jpeg_job_data,
1167         uint8_t &needNewSess)
1168 {
1169     LOGD("E");
1170     int32_t ret = NO_ERROR;
1171     mm_jpeg_job_t jpg_job;
1172     uint32_t jobId = 0;
1173     qcamera_fwk_input_pp_data_t *recvd_frame = NULL;
1174     metadata_buffer_t *metadata = NULL;
1175     jpeg_settings_t *jpeg_settings = NULL;
1176     QCamera3HardwareInterface* hal_obj = NULL;
1177     mm_jpeg_debug_exif_params_t *exif_debug_params = NULL;
1178     bool needJpegExifRotation = false;
1179 
1180     if (NULL == jpeg_job_data) {
1181         LOGE("Invalid jpeg job");
1182         return BAD_VALUE;
1183     }
1184 
1185     recvd_frame = jpeg_job_data->fwk_frame;
1186     if (NULL == recvd_frame) {
1187         LOGE("Invalid input buffer");
1188         return BAD_VALUE;
1189     }
1190 
1191     metadata = jpeg_job_data->metadata;
1192     if (NULL == metadata) {
1193         LOGE("Invalid metadata buffer");
1194         return BAD_VALUE;
1195     }
1196 
1197     jpeg_settings = jpeg_job_data->jpeg_settings;
1198     if (NULL == jpeg_settings) {
1199         LOGE("Invalid jpeg settings buffer");
1200         return BAD_VALUE;
1201     }
1202 
1203     if ((NULL != jpeg_job_data->fwk_frame) && (NULL != jpeg_job_data->src_frame)) {
1204         LOGE("Unsupported case both framework and camera source buffers are invalid!");
1205         return BAD_VALUE;
1206     }
1207 
1208     hal_obj = (QCamera3HardwareInterface*)m_parent->mUserData;
1209     if (hal_obj == NULL) {
1210         LOGE("hal_obj is NULL, Error");
1211         return BAD_VALUE;
1212     }
1213 
1214     if (mJpegClientHandle <= 0) {
1215         LOGE("Error: bug here, mJpegClientHandle is 0");
1216         return UNKNOWN_ERROR;
1217     }
1218 
1219     cam_dimension_t src_dim;
1220     memset(&src_dim, 0, sizeof(cam_dimension_t));
1221     src_dim.width = recvd_frame->reproc_config.input_stream_dim.width;
1222     src_dim.height = recvd_frame->reproc_config.input_stream_dim.height;
1223 
1224     cam_dimension_t dst_dim;
1225     memset(&dst_dim, 0, sizeof(cam_dimension_t));
1226     dst_dim.width = recvd_frame->reproc_config.output_stream_dim.width;
1227     dst_dim.height = recvd_frame->reproc_config.output_stream_dim.height;
1228 
1229     cam_rect_t crop;
1230     memset(&crop, 0, sizeof(cam_rect_t));
1231     //TBD_later - Zoom event removed in stream
1232     //main_stream->getCropInfo(crop);
1233 
1234     // Set JPEG encode crop in reprocess frame metadata
1235     // If this JPEG crop info exist, encoder should do cropping
1236     IF_META_AVAILABLE(cam_stream_crop_info_t, jpeg_crop,
1237             CAM_INTF_PARM_JPEG_ENCODE_CROP, metadata) {
1238         memcpy(&crop, &(jpeg_crop->crop), sizeof(cam_rect_t));
1239     }
1240 
1241     // Set JPEG encode crop in reprocess frame metadata
1242     // If this JPEG scale info exist, encoder should do scaling
1243     IF_META_AVAILABLE(cam_dimension_t, scale_dim,
1244             CAM_INTF_PARM_JPEG_SCALE_DIMENSION, metadata) {
1245         if (scale_dim->width != 0 && scale_dim->height != 0) {
1246             dst_dim.width = scale_dim->width;
1247             dst_dim.height = scale_dim->height;
1248         }
1249     }
1250 
1251     needJpegExifRotation = (hal_obj->needJpegExifRotation() || !needsReprocess(recvd_frame));
1252 
1253     // If EXIF rotation metadata is added and used to match the JPEG orientation,
1254     // it means CPP rotation is not involved, whether it is because CPP does not
1255     // support rotation, or the reprocessed frame is not sent to CPP.
1256     // Override CAM_INTF_PARM_ROTATION to 0 to avoid wrong CPP rotation info
1257     // to be filled in to JPEG metadata.
1258     if (needJpegExifRotation) {
1259         cam_rotation_info_t rotation_info;
1260         memset(&rotation_info, 0, sizeof(rotation_info));
1261         rotation_info.rotation = ROTATE_0;
1262         rotation_info.streamId = 0;
1263         ADD_SET_PARAM_ENTRY_TO_BATCH(metadata, CAM_INTF_PARM_ROTATION, rotation_info);
1264     }
1265 
1266     LOGH("Need new session?:%d", needNewSess);
1267     if (needNewSess) {
1268         //creating a new session, so we must destroy the old one
1269         if ( 0 < mJpegSessionId ) {
1270             ret = mJpegHandle.destroy_session(mJpegSessionId);
1271             if (ret != NO_ERROR) {
1272                 LOGE("Error destroying an old jpeg encoding session, id = %d",
1273                        mJpegSessionId);
1274                 return ret;
1275             }
1276             mJpegSessionId = 0;
1277         }
1278         // create jpeg encoding session
1279         mm_jpeg_encode_params_t encodeParam;
1280         memset(&encodeParam, 0, sizeof(mm_jpeg_encode_params_t));
1281         getFWKJpegEncodeConfig(encodeParam, recvd_frame, jpeg_settings);
1282         QCamera3StreamMem *memObj = (QCamera3StreamMem *)(recvd_frame->input_buffer.mem_info);
1283         if (NULL == memObj) {
1284             LOGE("Memeory Obj of main frame is NULL");
1285             return NO_MEMORY;
1286         }
1287         // clean and invalidate cache ops through mem obj of the frame
1288         memObj->cleanInvalidateCache(recvd_frame->input_buffer.buf_idx);
1289 
1290         LOGH("#src bufs:%d # tmb bufs:%d #dst_bufs:%d",
1291                      encodeParam.num_src_bufs,encodeParam.num_tmb_bufs,encodeParam.num_dst_bufs);
1292         if (!needJpegExifRotation &&
1293             (jpeg_settings->jpeg_orientation == 90 ||
1294             jpeg_settings->jpeg_orientation == 270)) {
1295             // swap src width and height, stride and scanline due to rotation
1296             encodeParam.main_dim.src_dim.width = src_dim.height;
1297             encodeParam.main_dim.src_dim.height = src_dim.width;
1298             encodeParam.thumb_dim.src_dim.width = src_dim.height;
1299             encodeParam.thumb_dim.src_dim.height = src_dim.width;
1300 
1301             int32_t temp = encodeParam.src_main_buf[0].offset.mp[0].stride;
1302             encodeParam.src_main_buf[0].offset.mp[0].stride =
1303                 encodeParam.src_main_buf[0].offset.mp[0].scanline;
1304             encodeParam.src_main_buf[0].offset.mp[0].scanline = temp;
1305 
1306             temp = encodeParam.src_thumb_buf[0].offset.mp[0].stride;
1307             encodeParam.src_thumb_buf[0].offset.mp[0].stride =
1308                 encodeParam.src_thumb_buf[0].offset.mp[0].scanline;
1309             encodeParam.src_thumb_buf[0].offset.mp[0].scanline = temp;
1310         } else {
1311             encodeParam.main_dim.src_dim = src_dim;
1312             encodeParam.thumb_dim.src_dim = src_dim;
1313         }
1314         encodeParam.main_dim.dst_dim = dst_dim;
1315         encodeParam.thumb_dim.dst_dim = jpeg_settings->thumbnail_size;
1316 
1317         LOGI("Src Buffer cnt = %d, res = %dX%d len = %d rot = %d "
1318             "src_dim = %dX%d dst_dim = %dX%d",
1319             encodeParam.num_src_bufs,
1320             encodeParam.src_main_buf[0].offset.mp[0].stride,
1321             encodeParam.src_main_buf[0].offset.mp[0].scanline,
1322             encodeParam.src_main_buf[0].offset.frame_len,
1323             encodeParam.rotation,
1324             src_dim.width, src_dim.height,
1325             dst_dim.width, dst_dim.height);
1326         LOGI("Src THUMB buf_cnt = %d, res = %dX%d len = %d rot = %d "
1327             "src_dim = %dX%d, dst_dim = %dX%d",
1328             encodeParam.num_tmb_bufs,
1329             encodeParam.src_thumb_buf[0].offset.mp[0].stride,
1330             encodeParam.src_thumb_buf[0].offset.mp[0].scanline,
1331             encodeParam.src_thumb_buf[0].offset.frame_len,
1332             encodeParam.thumb_rotation,
1333             encodeParam.thumb_dim.src_dim.width,
1334             encodeParam.thumb_dim.src_dim.height,
1335             encodeParam.thumb_dim.dst_dim.width,
1336             encodeParam.thumb_dim.dst_dim.height);
1337 
1338         LOGH("#src bufs:%d # tmb bufs:%d #dst_bufs:%d",
1339                      encodeParam.num_src_bufs,encodeParam.num_tmb_bufs,encodeParam.num_dst_bufs);
1340 
1341         ret = mJpegHandle.create_session(mJpegClientHandle, &encodeParam, &mJpegSessionId);
1342         if (ret != NO_ERROR) {
1343             LOGE("Error creating a new jpeg encoding session, ret = %d", ret);
1344             return ret;
1345         }
1346         needNewSess = FALSE;
1347     }
1348 
1349     // Fill in new job
1350     memset(&jpg_job, 0, sizeof(mm_jpeg_job_t));
1351     jpg_job.job_type = JPEG_JOB_TYPE_ENCODE;
1352     jpg_job.encode_job.session_id = mJpegSessionId;
1353     jpg_job.encode_job.src_index = 0;
1354     jpg_job.encode_job.dst_index = 0;
1355 
1356     // Set main dim job parameters and handle rotation
1357     if (!needJpegExifRotation && (jpeg_settings->jpeg_orientation == 90 ||
1358             jpeg_settings->jpeg_orientation == 270)) {
1359 
1360         jpg_job.encode_job.main_dim.src_dim.width = src_dim.height;
1361         jpg_job.encode_job.main_dim.src_dim.height = src_dim.width;
1362 
1363         jpg_job.encode_job.main_dim.dst_dim.width = dst_dim.height;
1364         jpg_job.encode_job.main_dim.dst_dim.height = dst_dim.width;
1365 
1366         jpg_job.encode_job.main_dim.crop.width = crop.height;
1367         jpg_job.encode_job.main_dim.crop.height = crop.width;
1368         jpg_job.encode_job.main_dim.crop.left = crop.top;
1369         jpg_job.encode_job.main_dim.crop.top = crop.left;
1370     } else {
1371         jpg_job.encode_job.main_dim.src_dim = src_dim;
1372         jpg_job.encode_job.main_dim.dst_dim = dst_dim;
1373         jpg_job.encode_job.main_dim.crop = crop;
1374     }
1375 
1376     // get 3a sw version info
1377     cam_q3a_version_t sw_version;
1378     memset(&sw_version, 0, sizeof(sw_version));
1379     if (hal_obj)
1380         hal_obj->get3AVersion(sw_version);
1381 
1382     // get exif data
1383     QCamera3Exif *pJpegExifObj = getExifData(metadata, jpeg_settings, needJpegExifRotation);
1384     jpeg_job_data->pJpegExifObj = pJpegExifObj;
1385     if (pJpegExifObj != NULL) {
1386         jpg_job.encode_job.exif_info.exif_data = pJpegExifObj->getEntries();
1387         jpg_job.encode_job.exif_info.numOfEntries =
1388             pJpegExifObj->getNumOfEntries();
1389         jpg_job.encode_job.exif_info.debug_data.sw_3a_version[0] =
1390             sw_version.major_version;
1391         jpg_job.encode_job.exif_info.debug_data.sw_3a_version[1] =
1392             sw_version.minor_version;
1393         jpg_job.encode_job.exif_info.debug_data.sw_3a_version[2] =
1394             sw_version.patch_version;
1395         jpg_job.encode_job.exif_info.debug_data.sw_3a_version[3] =
1396             sw_version.new_feature_des;
1397     }
1398 
1399     // thumbnail dim
1400     LOGH("Thumbnail needed:%d", m_bThumbnailNeeded);
1401     if (m_bThumbnailNeeded == TRUE) {
1402         jpg_job.encode_job.thumb_dim.dst_dim =
1403                 jpeg_settings->thumbnail_size;
1404 
1405         if (!needJpegExifRotation && (jpeg_settings->jpeg_orientation == 90 ||
1406                 jpeg_settings->jpeg_orientation == 270)) {
1407             //swap the thumbnail destination width and height if it has
1408             //already been rotated
1409             int temp = jpg_job.encode_job.thumb_dim.dst_dim.width;
1410             jpg_job.encode_job.thumb_dim.dst_dim.width =
1411                     jpg_job.encode_job.thumb_dim.dst_dim.height;
1412             jpg_job.encode_job.thumb_dim.dst_dim.height = temp;
1413 
1414             jpg_job.encode_job.thumb_dim.src_dim.width = src_dim.height;
1415             jpg_job.encode_job.thumb_dim.src_dim.height = src_dim.width;
1416 
1417             jpg_job.encode_job.thumb_dim.crop.width = crop.height;
1418             jpg_job.encode_job.thumb_dim.crop.height = crop.width;
1419             jpg_job.encode_job.thumb_dim.crop.left = crop.top;
1420             jpg_job.encode_job.thumb_dim.crop.top = crop.left;
1421         } else {
1422         jpg_job.encode_job.thumb_dim.src_dim = src_dim;
1423         jpg_job.encode_job.thumb_dim.crop = crop;
1424         }
1425         jpg_job.encode_job.thumb_index = 0;
1426     }
1427 
1428     jpg_job.encode_job.cam_exif_params = hal_obj->get3AExifParams();
1429     exif_debug_params = jpg_job.encode_job.cam_exif_params.debug_params;
1430     // Fill in exif debug data
1431     // Allocate for a local copy of debug parameters
1432     jpg_job.encode_job.cam_exif_params.debug_params =
1433             (mm_jpeg_debug_exif_params_t *) malloc (sizeof(mm_jpeg_debug_exif_params_t));
1434     if (!jpg_job.encode_job.cam_exif_params.debug_params) {
1435         LOGE("Out of Memory. Allocation failed for 3A debug exif params");
1436         return NO_MEMORY;
1437     }
1438 
1439     jpg_job.encode_job.mobicat_mask = hal_obj->getMobicatMask();
1440 
1441     if (metadata != NULL) {
1442         // Fill in the metadata passed as parameter
1443         jpg_job.encode_job.p_metadata = metadata;
1444 
1445        jpg_job.encode_job.p_metadata->is_mobicat_aec_params_valid =
1446                 jpg_job.encode_job.cam_exif_params.cam_3a_params_valid;
1447 
1448        if (jpg_job.encode_job.cam_exif_params.cam_3a_params_valid) {
1449             jpg_job.encode_job.p_metadata->mobicat_aec_params =
1450                 jpg_job.encode_job.cam_exif_params.cam_3a_params;
1451        }
1452 
1453         if (exif_debug_params) {
1454             // Copy debug parameters locally.
1455            memcpy(jpg_job.encode_job.cam_exif_params.debug_params,
1456                    exif_debug_params, (sizeof(mm_jpeg_debug_exif_params_t)));
1457            /* Save a copy of 3A debug params */
1458             jpg_job.encode_job.p_metadata->is_statsdebug_ae_params_valid =
1459                     jpg_job.encode_job.cam_exif_params.debug_params->ae_debug_params_valid;
1460             jpg_job.encode_job.p_metadata->is_statsdebug_awb_params_valid =
1461                     jpg_job.encode_job.cam_exif_params.debug_params->awb_debug_params_valid;
1462             jpg_job.encode_job.p_metadata->is_statsdebug_af_params_valid =
1463                     jpg_job.encode_job.cam_exif_params.debug_params->af_debug_params_valid;
1464             jpg_job.encode_job.p_metadata->is_statsdebug_asd_params_valid =
1465                     jpg_job.encode_job.cam_exif_params.debug_params->asd_debug_params_valid;
1466             jpg_job.encode_job.p_metadata->is_statsdebug_stats_params_valid =
1467                     jpg_job.encode_job.cam_exif_params.debug_params->stats_debug_params_valid;
1468             jpg_job.encode_job.p_metadata->is_statsdebug_bestats_params_valid =
1469                     jpg_job.encode_job.cam_exif_params.debug_params->bestats_debug_params_valid;
1470             jpg_job.encode_job.p_metadata->is_statsdebug_bhist_params_valid =
1471                     jpg_job.encode_job.cam_exif_params.debug_params->bhist_debug_params_valid;
1472             jpg_job.encode_job.p_metadata->is_statsdebug_3a_tuning_params_valid =
1473                     jpg_job.encode_job.cam_exif_params.debug_params->q3a_tuning_debug_params_valid;
1474 
1475             if (jpg_job.encode_job.cam_exif_params.debug_params->ae_debug_params_valid) {
1476                 jpg_job.encode_job.p_metadata->statsdebug_ae_data =
1477                         jpg_job.encode_job.cam_exif_params.debug_params->ae_debug_params;
1478             }
1479             if (jpg_job.encode_job.cam_exif_params.debug_params->awb_debug_params_valid) {
1480                 jpg_job.encode_job.p_metadata->statsdebug_awb_data =
1481                         jpg_job.encode_job.cam_exif_params.debug_params->awb_debug_params;
1482             }
1483             if (jpg_job.encode_job.cam_exif_params.debug_params->af_debug_params_valid) {
1484                 jpg_job.encode_job.p_metadata->statsdebug_af_data =
1485                         jpg_job.encode_job.cam_exif_params.debug_params->af_debug_params;
1486             }
1487             if (jpg_job.encode_job.cam_exif_params.debug_params->asd_debug_params_valid) {
1488                 jpg_job.encode_job.p_metadata->statsdebug_asd_data =
1489                         jpg_job.encode_job.cam_exif_params.debug_params->asd_debug_params;
1490             }
1491             if (jpg_job.encode_job.cam_exif_params.debug_params->stats_debug_params_valid) {
1492                 jpg_job.encode_job.p_metadata->statsdebug_stats_buffer_data =
1493                         jpg_job.encode_job.cam_exif_params.debug_params->stats_debug_params;
1494             }
1495             if (jpg_job.encode_job.cam_exif_params.debug_params->bestats_debug_params_valid) {
1496                 jpg_job.encode_job.p_metadata->statsdebug_bestats_buffer_data =
1497                         jpg_job.encode_job.cam_exif_params.debug_params->bestats_debug_params;
1498             }
1499             if (jpg_job.encode_job.cam_exif_params.debug_params->bhist_debug_params_valid) {
1500                 jpg_job.encode_job.p_metadata->statsdebug_bhist_data =
1501                         jpg_job.encode_job.cam_exif_params.debug_params->bhist_debug_params;
1502             }
1503             if (jpg_job.encode_job.cam_exif_params.debug_params->q3a_tuning_debug_params_valid) {
1504                 jpg_job.encode_job.p_metadata->statsdebug_3a_tuning_data =
1505                         jpg_job.encode_job.cam_exif_params.debug_params->q3a_tuning_debug_params;
1506             }
1507         }
1508     } else {
1509        LOGW("Metadata is null");
1510     }
1511 
1512     // Multi image info
1513     if (hal_obj->isDeviceLinked() == TRUE) {
1514         jpg_job.encode_job.multi_image_info.type = MM_JPEG_TYPE_JPEG;
1515         jpg_job.encode_job.multi_image_info.num_of_images = 1;
1516         jpg_job.encode_job.multi_image_info.enable_metadata = 1;
1517         if (hal_obj->isMainCamera() == TRUE) {
1518             jpg_job.encode_job.multi_image_info.is_primary = 1;
1519         } else {
1520             jpg_job.encode_job.multi_image_info.is_primary = 0;
1521         }
1522     }
1523 
1524     jpg_job.encode_job.hal_version = CAM_HAL_V3;
1525 
1526     //Start jpeg encoding
1527     ret = mJpegHandle.start_job(&jpg_job, &jobId);
1528     if (jpg_job.encode_job.cam_exif_params.debug_params) {
1529         free(jpg_job.encode_job.cam_exif_params.debug_params);
1530     }
1531     if (ret == NO_ERROR) {
1532         // remember job info
1533         jpeg_job_data->jobId = jobId;
1534     }
1535 
1536     LOGD("X");
1537     return ret;
1538 }
1539 
1540 /*===========================================================================
1541  * FUNCTION   : encodeData
1542  *
1543  * DESCRIPTION: function to prepare encoding job information and send to
1544  *              mm-jpeg-interface to do the encoding job
1545  *
1546  * PARAMETERS :
1547  *   @jpeg_job_data : ptr to a struct saving job related information
1548  *   @needNewSess   : flag to indicate if a new jpeg encoding session need
1549  *                    to be created. After creation, this flag will be toggled
1550  *
1551  * RETURN     : int32_t type of status
1552  *              NO_ERROR  -- success
1553  *              none-zero failure code
1554  *==========================================================================*/
encodeData(qcamera_hal3_jpeg_data_t * jpeg_job_data,uint8_t & needNewSess)1555 int32_t QCamera3PostProcessor::encodeData(qcamera_hal3_jpeg_data_t *jpeg_job_data,
1556                           uint8_t &needNewSess)
1557 {
1558     ATRACE_CAMSCOPE_CALL(CAMSCOPE_HAL3_PPROC_ENCODEDATA);
1559     LOGD("E");
1560     int32_t ret = NO_ERROR;
1561     mm_jpeg_job_t jpg_job;
1562     uint32_t jobId = 0;
1563     QCamera3Stream *main_stream = NULL;
1564     mm_camera_buf_def_t *main_frame = NULL;
1565     QCamera3Channel *srcChannel = NULL;
1566     mm_camera_super_buf_t *recvd_frame = NULL;
1567     metadata_buffer_t *metadata = NULL;
1568     jpeg_settings_t *jpeg_settings = NULL;
1569     QCamera3HardwareInterface* hal_obj = NULL;
1570     mm_jpeg_debug_exif_params_t *exif_debug_params = NULL;
1571     if (m_parent != NULL) {
1572         hal_obj = (QCamera3HardwareInterface*)m_parent->mUserData;
1573         if (hal_obj == NULL) {
1574             LOGE("hal_obj is NULL, Error");
1575             return BAD_VALUE;
1576         }
1577     } else {
1578         LOGE("m_parent is NULL, Error");
1579         return BAD_VALUE;
1580     }
1581     bool needJpegExifRotation = false;
1582 
1583     recvd_frame = jpeg_job_data->src_frame;
1584     metadata = jpeg_job_data->metadata;
1585     jpeg_settings = jpeg_job_data->jpeg_settings;
1586 
1587     LOGD("encoding bufIndex: %u",
1588         jpeg_job_data->src_frame->bufs[0]->buf_idx);
1589 
1590     QCamera3Channel *pChannel = NULL;
1591     // first check picture channel
1592     if (m_parent->getMyHandle() == recvd_frame->ch_id) {
1593         pChannel = m_parent;
1594     }
1595     // check reprocess channel if not found
1596     if (pChannel == NULL) {
1597         if (m_pReprocChannel != NULL &&
1598             m_pReprocChannel->getMyHandle() == recvd_frame->ch_id) {
1599             pChannel = m_pReprocChannel;
1600         }
1601     }
1602 
1603     srcChannel = pChannel;
1604 
1605     if (srcChannel == NULL) {
1606         LOGE("No corresponding channel (ch_id = %d) exist, return here",
1607                recvd_frame->ch_id);
1608         return BAD_VALUE;
1609     }
1610 
1611     // find snapshot frame and thumnail frame
1612     //Note: In this version we will receive only snapshot frame.
1613     for (uint32_t i = 0; i < recvd_frame->num_bufs; i++) {
1614         QCamera3Stream *srcStream =
1615             srcChannel->getStreamByHandle(recvd_frame->bufs[i]->stream_id);
1616         if (srcStream != NULL) {
1617             switch (srcStream->getMyType()) {
1618             case CAM_STREAM_TYPE_SNAPSHOT:
1619             case CAM_STREAM_TYPE_OFFLINE_PROC:
1620                 main_stream = srcStream;
1621                 main_frame = recvd_frame->bufs[i];
1622                 break;
1623             default:
1624                 break;
1625             }
1626         }
1627     }
1628 
1629     if(NULL == main_frame){
1630        LOGE("Main frame is NULL");
1631        return BAD_VALUE;
1632     }
1633 
1634     QCamera3StreamMem *memObj = (QCamera3StreamMem *)main_frame->mem_info;
1635     if (NULL == memObj) {
1636         LOGE("Memeory Obj of main frame is NULL");
1637         return NO_MEMORY;
1638     }
1639 
1640     // clean and invalidate cache ops through mem obj of the frame
1641     memObj->cleanInvalidateCache(main_frame->buf_idx);
1642 
1643     if (mJpegClientHandle <= 0) {
1644         LOGE("Error: bug here, mJpegClientHandle is 0");
1645         return UNKNOWN_ERROR;
1646     }
1647     cam_dimension_t src_dim;
1648     memset(&src_dim, 0, sizeof(cam_dimension_t));
1649     main_stream->getFrameDimension(src_dim);
1650 
1651     cam_dimension_t dst_dim;
1652     memset(&dst_dim, 0, sizeof(cam_dimension_t));
1653     if (NO_ERROR != m_parent->getStreamSize(dst_dim)) {
1654         LOGE("Failed to get size of the JPEG stream");
1655         return UNKNOWN_ERROR;
1656     }
1657 
1658     needJpegExifRotation = hal_obj->needJpegExifRotation();
1659     IF_META_AVAILABLE(cam_rotation_info_t, rotation_info, CAM_INTF_PARM_ROTATION, metadata) {
1660         if (jpeg_settings->jpeg_orientation != 0 && rotation_info->rotation == ROTATE_0) {
1661             needJpegExifRotation = TRUE;
1662             LOGH("Need EXIF JPEG ROTATION");
1663         }
1664     }
1665 
1666     // Although in HAL3, legacy flip mode is not advertised
1667     // default value of CAM_INTF_PARM_FLIP is still added here
1668     // for jpge metadata
1669     int32_t flipMode = 0; // no flip
1670     ADD_SET_PARAM_ENTRY_TO_BATCH(metadata, CAM_INTF_PARM_FLIP, flipMode);
1671 
1672     LOGH("Need new session?:%d", needNewSess);
1673     if (needNewSess) {
1674         //creating a new session, so we must destroy the old one
1675         if ( 0 < mJpegSessionId ) {
1676             ret = mJpegHandle.destroy_session(mJpegSessionId);
1677             if (ret != NO_ERROR) {
1678                 LOGE("Error destroying an old jpeg encoding session, id = %d",
1679                        mJpegSessionId);
1680                 return ret;
1681             }
1682             mJpegSessionId = 0;
1683         }
1684         // create jpeg encoding session
1685         mm_jpeg_encode_params_t encodeParam;
1686         memset(&encodeParam, 0, sizeof(mm_jpeg_encode_params_t));
1687         getJpegEncodeConfig(encodeParam, main_stream, jpeg_settings);
1688         LOGH("#src bufs:%d # tmb bufs:%d #dst_bufs:%d",
1689                      encodeParam.num_src_bufs,encodeParam.num_tmb_bufs,encodeParam.num_dst_bufs);
1690         if (!needJpegExifRotation &&
1691             (jpeg_settings->jpeg_orientation == 90 ||
1692             jpeg_settings->jpeg_orientation == 270)) {
1693            //swap src width and height, stride and scanline due to rotation
1694            encodeParam.main_dim.src_dim.width = src_dim.height;
1695            encodeParam.main_dim.src_dim.height = src_dim.width;
1696            encodeParam.thumb_dim.src_dim.width = src_dim.height;
1697            encodeParam.thumb_dim.src_dim.height = src_dim.width;
1698 
1699            int32_t temp = encodeParam.src_main_buf[0].offset.mp[0].stride;
1700            encodeParam.src_main_buf[0].offset.mp[0].stride =
1701               encodeParam.src_main_buf[0].offset.mp[0].scanline;
1702            encodeParam.src_main_buf[0].offset.mp[0].scanline = temp;
1703 
1704            temp = encodeParam.src_thumb_buf[0].offset.mp[0].stride;
1705            encodeParam.src_thumb_buf[0].offset.mp[0].stride =
1706               encodeParam.src_thumb_buf[0].offset.mp[0].scanline;
1707            encodeParam.src_thumb_buf[0].offset.mp[0].scanline = temp;
1708         } else {
1709            encodeParam.main_dim.src_dim  = src_dim;
1710            encodeParam.thumb_dim.src_dim = src_dim;
1711         }
1712         encodeParam.main_dim.dst_dim = dst_dim;
1713         encodeParam.thumb_dim.dst_dim = jpeg_settings->thumbnail_size;
1714 
1715         LOGI("Src Buffer cnt = %d, res = %dX%d len = %d rot = %d "
1716             "src_dim = %dX%d dst_dim = %dX%d",
1717             encodeParam.num_src_bufs,
1718             encodeParam.src_main_buf[0].offset.mp[0].stride,
1719             encodeParam.src_main_buf[0].offset.mp[0].scanline,
1720             encodeParam.src_main_buf[0].offset.frame_len,
1721             encodeParam.rotation,
1722             src_dim.width, src_dim.height,
1723             dst_dim.width, dst_dim.height);
1724         LOGI("Src THUMB buf_cnt = %d, res = %dX%d len = %d rot = %d "
1725             "src_dim = %dX%d, dst_dim = %dX%d",
1726             encodeParam.num_tmb_bufs,
1727             encodeParam.src_thumb_buf[0].offset.mp[0].stride,
1728             encodeParam.src_thumb_buf[0].offset.mp[0].scanline,
1729             encodeParam.src_thumb_buf[0].offset.frame_len,
1730             encodeParam.thumb_rotation,
1731             encodeParam.thumb_dim.src_dim.width,
1732             encodeParam.thumb_dim.src_dim.height,
1733             encodeParam.thumb_dim.dst_dim.width,
1734             encodeParam.thumb_dim.dst_dim.height);
1735         ret = mJpegHandle.create_session(mJpegClientHandle, &encodeParam, &mJpegSessionId);
1736         if (ret != NO_ERROR) {
1737             LOGE("Error creating a new jpeg encoding session, ret = %d", ret);
1738             return ret;
1739         }
1740         needNewSess = FALSE;
1741     }
1742 
1743     // Fill in new job
1744     memset(&jpg_job, 0, sizeof(mm_jpeg_job_t));
1745     jpg_job.job_type = JPEG_JOB_TYPE_ENCODE;
1746     jpg_job.encode_job.session_id = mJpegSessionId;
1747     jpg_job.encode_job.src_index = (int32_t)main_frame->buf_idx;
1748     jpg_job.encode_job.dst_index = 0;
1749 
1750     cam_rect_t crop;
1751     memset(&crop, 0, sizeof(cam_rect_t));
1752     //TBD_later - Zoom event removed in stream
1753     //main_stream->getCropInfo(crop);
1754 
1755     // Set main dim job parameters and handle rotation
1756     if (!needJpegExifRotation && (jpeg_settings->jpeg_orientation == 90 ||
1757             jpeg_settings->jpeg_orientation == 270)) {
1758 
1759         jpg_job.encode_job.main_dim.src_dim.width = src_dim.height;
1760         jpg_job.encode_job.main_dim.src_dim.height = src_dim.width;
1761 
1762         jpg_job.encode_job.main_dim.dst_dim.width = dst_dim.height;
1763         jpg_job.encode_job.main_dim.dst_dim.height = dst_dim.width;
1764 
1765         jpg_job.encode_job.main_dim.crop.width = crop.height;
1766         jpg_job.encode_job.main_dim.crop.height = crop.width;
1767         jpg_job.encode_job.main_dim.crop.left = crop.top;
1768         jpg_job.encode_job.main_dim.crop.top = crop.left;
1769     } else {
1770         jpg_job.encode_job.main_dim.src_dim = src_dim;
1771         jpg_job.encode_job.main_dim.dst_dim = dst_dim;
1772         jpg_job.encode_job.main_dim.crop = crop;
1773     }
1774 
1775     // get 3a sw version info
1776     cam_q3a_version_t sw_version;
1777     memset(&sw_version, 0, sizeof(sw_version));
1778 
1779     if (hal_obj)
1780         hal_obj->get3AVersion(sw_version);
1781 
1782     // get exif data
1783     QCamera3Exif *pJpegExifObj = getExifData(metadata, jpeg_settings, needJpegExifRotation);
1784     jpeg_job_data->pJpegExifObj = pJpegExifObj;
1785     if (pJpegExifObj != NULL) {
1786         jpg_job.encode_job.exif_info.exif_data = pJpegExifObj->getEntries();
1787         jpg_job.encode_job.exif_info.numOfEntries =
1788             pJpegExifObj->getNumOfEntries();
1789         jpg_job.encode_job.exif_info.debug_data.sw_3a_version[0] =
1790             sw_version.major_version;
1791         jpg_job.encode_job.exif_info.debug_data.sw_3a_version[1] =
1792             sw_version.minor_version;
1793         jpg_job.encode_job.exif_info.debug_data.sw_3a_version[2] =
1794             sw_version.patch_version;
1795         jpg_job.encode_job.exif_info.debug_data.sw_3a_version[3] =
1796             sw_version.new_feature_des;
1797     }
1798 
1799     // thumbnail dim
1800     LOGH("Thumbnail needed:%d", m_bThumbnailNeeded);
1801     if (m_bThumbnailNeeded == TRUE) {
1802         jpg_job.encode_job.thumb_dim.dst_dim =
1803                 jpeg_settings->thumbnail_size;
1804 
1805       if (!needJpegExifRotation &&
1806           (jpeg_settings->jpeg_orientation  == 90 ||
1807            jpeg_settings->jpeg_orientation == 270)) {
1808             //swap the thumbnail destination width and height if it has
1809             //already been rotated
1810             int temp = jpg_job.encode_job.thumb_dim.dst_dim.width;
1811             jpg_job.encode_job.thumb_dim.dst_dim.width =
1812                     jpg_job.encode_job.thumb_dim.dst_dim.height;
1813             jpg_job.encode_job.thumb_dim.dst_dim.height = temp;
1814 
1815             jpg_job.encode_job.thumb_dim.src_dim.width = src_dim.height;
1816             jpg_job.encode_job.thumb_dim.src_dim.height = src_dim.width;
1817 
1818             jpg_job.encode_job.thumb_dim.crop.width = crop.height;
1819             jpg_job.encode_job.thumb_dim.crop.height = crop.width;
1820             jpg_job.encode_job.thumb_dim.crop.left = crop.top;
1821             jpg_job.encode_job.thumb_dim.crop.top = crop.left;
1822         } else {
1823            jpg_job.encode_job.thumb_dim.src_dim = src_dim;
1824            jpg_job.encode_job.thumb_dim.crop = crop;
1825         }
1826         jpg_job.encode_job.thumb_index = main_frame->buf_idx;
1827         LOGI("Thumbnail idx = %d src w/h (%dx%d), dst w/h (%dx%d)",
1828                 jpg_job.encode_job.thumb_index,
1829                 jpg_job.encode_job.thumb_dim.src_dim.width,
1830                 jpg_job.encode_job.thumb_dim.src_dim.height,
1831                 jpg_job.encode_job.thumb_dim.dst_dim.width,
1832                 jpg_job.encode_job.thumb_dim.dst_dim.height);
1833     }
1834     LOGI("Main image idx = %d src w/h (%dx%d), dst w/h (%dx%d)",
1835             jpg_job.encode_job.src_index,
1836             jpg_job.encode_job.main_dim.src_dim.width,
1837             jpg_job.encode_job.main_dim.src_dim.height,
1838             jpg_job.encode_job.main_dim.dst_dim.width,
1839             jpg_job.encode_job.main_dim.dst_dim.height);
1840 
1841     jpg_job.encode_job.cam_exif_params = hal_obj->get3AExifParams();
1842     exif_debug_params = jpg_job.encode_job.cam_exif_params.debug_params;
1843 
1844     // Allocate for a local copy of debug parameters
1845     jpg_job.encode_job.cam_exif_params.debug_params =
1846             (mm_jpeg_debug_exif_params_t *) malloc (sizeof(mm_jpeg_debug_exif_params_t));
1847     if (!jpg_job.encode_job.cam_exif_params.debug_params) {
1848         LOGE("Out of Memory. Allocation failed for 3A debug exif params");
1849         return NO_MEMORY;
1850     }
1851 
1852     jpg_job.encode_job.mobicat_mask = hal_obj->getMobicatMask();
1853 
1854     if (metadata != NULL) {
1855        //Fill in the metadata passed as parameter
1856        jpg_job.encode_job.p_metadata = metadata;
1857 
1858        jpg_job.encode_job.p_metadata->is_mobicat_aec_params_valid =
1859                 jpg_job.encode_job.cam_exif_params.cam_3a_params_valid;
1860 
1861        if (jpg_job.encode_job.cam_exif_params.cam_3a_params_valid) {
1862             jpg_job.encode_job.p_metadata->mobicat_aec_params =
1863                 jpg_job.encode_job.cam_exif_params.cam_3a_params;
1864        }
1865 
1866        if (exif_debug_params) {
1867             // Copy debug parameters locally.
1868            memcpy(jpg_job.encode_job.cam_exif_params.debug_params,
1869                    exif_debug_params, (sizeof(mm_jpeg_debug_exif_params_t)));
1870            /* Save a copy of 3A debug params */
1871             jpg_job.encode_job.p_metadata->is_statsdebug_ae_params_valid =
1872                     jpg_job.encode_job.cam_exif_params.debug_params->ae_debug_params_valid;
1873             jpg_job.encode_job.p_metadata->is_statsdebug_awb_params_valid =
1874                     jpg_job.encode_job.cam_exif_params.debug_params->awb_debug_params_valid;
1875             jpg_job.encode_job.p_metadata->is_statsdebug_af_params_valid =
1876                     jpg_job.encode_job.cam_exif_params.debug_params->af_debug_params_valid;
1877             jpg_job.encode_job.p_metadata->is_statsdebug_asd_params_valid =
1878                     jpg_job.encode_job.cam_exif_params.debug_params->asd_debug_params_valid;
1879             jpg_job.encode_job.p_metadata->is_statsdebug_stats_params_valid =
1880                     jpg_job.encode_job.cam_exif_params.debug_params->stats_debug_params_valid;
1881             jpg_job.encode_job.p_metadata->is_statsdebug_bestats_params_valid =
1882                     jpg_job.encode_job.cam_exif_params.debug_params->bestats_debug_params_valid;
1883             jpg_job.encode_job.p_metadata->is_statsdebug_bhist_params_valid =
1884                     jpg_job.encode_job.cam_exif_params.debug_params->bhist_debug_params_valid;
1885             jpg_job.encode_job.p_metadata->is_statsdebug_3a_tuning_params_valid =
1886                     jpg_job.encode_job.cam_exif_params.debug_params->q3a_tuning_debug_params_valid;
1887 
1888             if (jpg_job.encode_job.cam_exif_params.debug_params->ae_debug_params_valid) {
1889                 jpg_job.encode_job.p_metadata->statsdebug_ae_data =
1890                         jpg_job.encode_job.cam_exif_params.debug_params->ae_debug_params;
1891             }
1892             if (jpg_job.encode_job.cam_exif_params.debug_params->awb_debug_params_valid) {
1893                 jpg_job.encode_job.p_metadata->statsdebug_awb_data =
1894                         jpg_job.encode_job.cam_exif_params.debug_params->awb_debug_params;
1895             }
1896             if (jpg_job.encode_job.cam_exif_params.debug_params->af_debug_params_valid) {
1897                 jpg_job.encode_job.p_metadata->statsdebug_af_data =
1898                         jpg_job.encode_job.cam_exif_params.debug_params->af_debug_params;
1899             }
1900             if (jpg_job.encode_job.cam_exif_params.debug_params->asd_debug_params_valid) {
1901                 jpg_job.encode_job.p_metadata->statsdebug_asd_data =
1902                         jpg_job.encode_job.cam_exif_params.debug_params->asd_debug_params;
1903             }
1904             if (jpg_job.encode_job.cam_exif_params.debug_params->stats_debug_params_valid) {
1905                 jpg_job.encode_job.p_metadata->statsdebug_stats_buffer_data =
1906                         jpg_job.encode_job.cam_exif_params.debug_params->stats_debug_params;
1907             }
1908             if (jpg_job.encode_job.cam_exif_params.debug_params->bestats_debug_params_valid) {
1909                 jpg_job.encode_job.p_metadata->statsdebug_bestats_buffer_data =
1910                         jpg_job.encode_job.cam_exif_params.debug_params->bestats_debug_params;
1911             }
1912             if (jpg_job.encode_job.cam_exif_params.debug_params->bhist_debug_params_valid) {
1913                 jpg_job.encode_job.p_metadata->statsdebug_bhist_data =
1914                         jpg_job.encode_job.cam_exif_params.debug_params->bhist_debug_params;
1915             }
1916             if (jpg_job.encode_job.cam_exif_params.debug_params->q3a_tuning_debug_params_valid) {
1917                 jpg_job.encode_job.p_metadata->statsdebug_3a_tuning_data =
1918                         jpg_job.encode_job.cam_exif_params.debug_params->q3a_tuning_debug_params;
1919             }
1920         }
1921     } else {
1922        LOGW("Metadata is null");
1923     }
1924 
1925     // Multi image info
1926     if (hal_obj->isDeviceLinked() == TRUE) {
1927         jpg_job.encode_job.multi_image_info.type = MM_JPEG_TYPE_JPEG;
1928         jpg_job.encode_job.multi_image_info.num_of_images = 1;
1929         jpg_job.encode_job.multi_image_info.enable_metadata = 1;
1930         if (hal_obj->isMainCamera() == TRUE) {
1931             jpg_job.encode_job.multi_image_info.is_primary = 1;
1932         } else {
1933             jpg_job.encode_job.multi_image_info.is_primary = 0;
1934         }
1935     }
1936 
1937     jpg_job.encode_job.hal_version = CAM_HAL_V3;
1938 
1939     //Start jpeg encoding
1940     ret = mJpegHandle.start_job(&jpg_job, &jobId);
1941     if (jpg_job.encode_job.cam_exif_params.debug_params) {
1942         free(jpg_job.encode_job.cam_exif_params.debug_params);
1943     }
1944     if (ret == NO_ERROR) {
1945         // remember job info
1946         jpeg_job_data->jobId = jobId;
1947     }
1948 
1949     LOGD("X");
1950     return ret;
1951 }
1952 
1953 /*===========================================================================
1954  * FUNCTION   : dataProcessRoutine
1955  *
1956  * DESCRIPTION: data process routine that handles input data either from input
1957  *              Jpeg Queue to do jpeg encoding, or from input PP Queue to do
1958  *              reprocess.
1959  *
1960  * PARAMETERS :
1961  *   @data    : user data ptr (QCamera3PostProcessor)
1962  *
1963  * RETURN     : None
1964  *==========================================================================*/
dataProcessRoutine(void * data)1965 void *QCamera3PostProcessor::dataProcessRoutine(void *data)
1966 {
1967     int running = 1;
1968     int ret;
1969     uint8_t is_active = FALSE;
1970     uint8_t needNewSess = TRUE;
1971     mm_camera_super_buf_t *meta_buffer = NULL;
1972     LOGD("E");
1973     QCamera3PostProcessor *pme = (QCamera3PostProcessor *)data;
1974     QCameraCmdThread *cmdThread = &pme->m_dataProcTh;
1975     cmdThread->setName("cam_data_proc");
1976 
1977     do {
1978         do {
1979             ret = cam_sem_wait(&cmdThread->cmd_sem);
1980             if (ret != 0 && errno != EINVAL) {
1981                 LOGE("cam_sem_wait error (%s)",
1982                             strerror(errno));
1983                 return NULL;
1984             }
1985         } while (ret != 0);
1986 
1987         // we got notified about new cmd avail in cmd queue
1988         camera_cmd_type_t cmd = cmdThread->getCmd();
1989         switch (cmd) {
1990         case CAMERA_CMD_TYPE_START_DATA_PROC:
1991             LOGH("start data proc");
1992             is_active = TRUE;
1993             needNewSess = TRUE;
1994 
1995             pme->m_ongoingPPQ.init();
1996             pme->m_inputJpegQ.init();
1997             pme->m_inputPPQ.init();
1998             pme->m_inputFWKPPQ.init();
1999             pme->m_inputMetaQ.init();
2000             cam_sem_post(&cmdThread->sync_sem);
2001 
2002             break;
2003         case CAMERA_CMD_TYPE_STOP_DATA_PROC:
2004             {
2005                 LOGH("stop data proc");
2006                 is_active = FALSE;
2007 
2008                 // cancel all ongoing jpeg jobs
2009                 qcamera_hal3_jpeg_data_t *jpeg_job =
2010                     (qcamera_hal3_jpeg_data_t *)pme->m_ongoingJpegQ.dequeue();
2011                 while (jpeg_job != NULL) {
2012                     pme->mJpegHandle.abort_job(jpeg_job->jobId);
2013 
2014                     pme->releaseJpegJobData(jpeg_job);
2015                     free(jpeg_job);
2016 
2017                     jpeg_job = (qcamera_hal3_jpeg_data_t *)pme->m_ongoingJpegQ.dequeue();
2018                 }
2019 
2020                 // destroy jpeg encoding session
2021                 if ( 0 < pme->mJpegSessionId ) {
2022                     pme->mJpegHandle.destroy_session(pme->mJpegSessionId);
2023                     pme->mJpegSessionId = 0;
2024                 }
2025 
2026                 needNewSess = TRUE;
2027 
2028                 // flush ongoing postproc Queue
2029                 pme->m_ongoingPPQ.flush();
2030 
2031                 // flush input jpeg Queue
2032                 pme->m_inputJpegQ.flush();
2033 
2034                 // flush input Postproc Queue
2035                 pme->m_inputPPQ.flush();
2036 
2037                 // flush framework input Postproc Queue
2038                 pme->m_inputFWKPPQ.flush();
2039 
2040                 pme->m_inputMetaQ.flush();
2041 
2042                 // signal cmd is completed
2043                 cam_sem_post(&cmdThread->sync_sem);
2044             }
2045             break;
2046         case CAMERA_CMD_TYPE_DO_NEXT_JOB:
2047             {
2048                 LOGH("Do next job, active is %d", is_active);
2049                 /* needNewSess is set to TRUE as postproc is not re-STARTed
2050                  * anymore for every captureRequest */
2051                 needNewSess = TRUE;
2052                 if (is_active == TRUE) {
2053                     // check if there is any ongoing jpeg jobs
2054                     if (pme->m_ongoingJpegQ.isEmpty()) {
2055                         LOGD("ongoing jpeg queue is empty so doing the jpeg job");
2056                         // no ongoing jpeg job, we are fine to send jpeg encoding job
2057                         qcamera_hal3_jpeg_data_t *jpeg_job =
2058                             (qcamera_hal3_jpeg_data_t *)pme->m_inputJpegQ.dequeue();
2059 
2060                         if (NULL != jpeg_job) {
2061                             // add into ongoing jpeg job Q
2062                             pme->m_ongoingJpegQ.enqueue((void *)jpeg_job);
2063 
2064                             if (jpeg_job->fwk_frame) {
2065                                 ret = pme->encodeFWKData(jpeg_job, needNewSess);
2066                             } else {
2067                                 ret = pme->encodeData(jpeg_job, needNewSess);
2068                             }
2069                             if (NO_ERROR != ret) {
2070                                 // dequeue the last one
2071                                 pme->m_ongoingJpegQ.dequeue(false);
2072 
2073                                 pme->releaseJpegJobData(jpeg_job);
2074                                 free(jpeg_job);
2075                             }
2076                         }
2077                     }
2078 
2079                     // check if there are any framework pp jobs
2080                     if (!pme->m_inputFWKPPQ.isEmpty()) {
2081                         qcamera_fwk_input_pp_data_t *fwk_frame =
2082                                 (qcamera_fwk_input_pp_data_t *) pme->m_inputFWKPPQ.dequeue();
2083                         if (NULL != fwk_frame) {
2084                             qcamera_hal3_pp_data_t *pp_job =
2085                                     (qcamera_hal3_pp_data_t *)malloc(sizeof(qcamera_hal3_pp_data_t));
2086                             jpeg_settings_t *jpeg_settings =
2087                                     (jpeg_settings_t *)pme->m_jpegSettingsQ.dequeue();
2088                             if (pp_job != NULL) {
2089                                 memset(pp_job, 0, sizeof(qcamera_hal3_pp_data_t));
2090                                 pp_job->jpeg_settings = jpeg_settings;
2091                                 if (pme->m_pReprocChannel != NULL) {
2092                                     if (NO_ERROR != pme->m_pReprocChannel->overrideFwkMetadata(fwk_frame)) {
2093                                         LOGE("Failed to extract output crop");
2094                                     }
2095                                     // add into ongoing PP job Q
2096                                     pp_job->fwk_src_frame = fwk_frame;
2097                                     pme->m_ongoingPPQ.enqueue((void *)pp_job);
2098                                     ret = pme->m_pReprocChannel->doReprocessOffline(fwk_frame);
2099                                     if (NO_ERROR != ret) {
2100                                         // remove from ongoing PP job Q
2101                                         pme->m_ongoingPPQ.dequeue(false);
2102                                     }
2103                                 } else {
2104                                     LOGE("Reprocess channel is NULL");
2105                                     ret = -1;
2106                                 }
2107                             } else {
2108                                 LOGE("no mem for qcamera_hal3_pp_data_t");
2109                                 ret = -1;
2110                             }
2111 
2112                             if (0 != ret) {
2113                                 // free pp_job
2114                                 if (pp_job != NULL) {
2115                                     free(pp_job);
2116                                 }
2117                                 // free frame
2118                                 if (fwk_frame != NULL) {
2119                                     free(fwk_frame);
2120                                 }
2121                             }
2122                         }
2123                     }
2124 
2125                     LOGH("dequeuing pp frame");
2126                     pthread_mutex_lock(&pme->mReprocJobLock);
2127                     if(!pme->m_inputPPQ.isEmpty() && !pme->m_inputMetaQ.isEmpty()) {
2128                         qcamera_hal3_pp_buffer_t *pp_buffer =
2129                             (qcamera_hal3_pp_buffer_t *)pme->m_inputPPQ.dequeue();
2130                         meta_buffer =
2131                             (mm_camera_super_buf_t *)pme->m_inputMetaQ.dequeue();
2132                         jpeg_settings_t *jpeg_settings =
2133                            (jpeg_settings_t *)pme->m_jpegSettingsQ.dequeue();
2134                         pthread_mutex_unlock(&pme->mReprocJobLock);
2135                         qcamera_hal3_pp_data_t *pp_job =
2136                             (qcamera_hal3_pp_data_t *)malloc(sizeof(qcamera_hal3_pp_data_t));
2137                         if (pp_job == NULL) {
2138                             LOGE("no mem for qcamera_hal3_pp_data_t");
2139                             ret = -1;
2140                         } else if (meta_buffer == NULL) {
2141                             LOGE("failed to dequeue from m_inputMetaQ");
2142                             ret = -1;
2143                         } else if (pp_buffer == NULL) {
2144                             LOGE("failed to dequeue from m_inputPPQ");
2145                             ret = -1;
2146                         } else if (pp_buffer != NULL){
2147                             memset(pp_job, 0, sizeof(qcamera_hal3_pp_data_t));
2148                             pp_job->src_frame = pp_buffer->input;
2149                             pp_job->src_metadata = meta_buffer;
2150                             if (meta_buffer->bufs[0] != NULL) {
2151                                 pp_job->metadata = (metadata_buffer_t *)
2152                                         meta_buffer->bufs[0]->buffer;
2153                             }
2154                             pp_job->jpeg_settings = jpeg_settings;
2155                             pme->m_ongoingPPQ.enqueue((void *)pp_job);
2156                             if (pme->m_pReprocChannel != NULL) {
2157                                 mm_camera_buf_def_t *meta_buffer_arg = NULL;
2158                                 meta_buffer_arg = meta_buffer->bufs[0];
2159                                 qcamera_fwk_input_pp_data_t fwk_frame;
2160                                 memset(&fwk_frame, 0, sizeof(qcamera_fwk_input_pp_data_t));
2161                                 fwk_frame.frameNumber = pp_buffer->frameNumber;
2162                                 ret = pme->m_pReprocChannel->overrideMetadata(
2163                                         pp_buffer, meta_buffer_arg,
2164                                         pp_job->jpeg_settings,
2165                                         fwk_frame);
2166                                 if (NO_ERROR == ret) {
2167                                     // add into ongoing PP job Q
2168                                     ret = pme->m_pReprocChannel->doReprocessOffline(
2169                                             &fwk_frame, true);
2170                                     if (NO_ERROR != ret) {
2171                                         // remove from ongoing PP job Q
2172                                         pme->m_ongoingPPQ.dequeue(false);
2173                                     }
2174                                 }
2175                             } else {
2176                                 LOGE("No reprocess. Calling processPPData directly");
2177                                 ret = pme->processPPData(pp_buffer->input);
2178                             }
2179                         }
2180 
2181                         if (0 != ret) {
2182                             // free pp_job
2183                             if (pp_job != NULL) {
2184                                 free(pp_job);
2185                             }
2186                             // free frame
2187                             if (pp_buffer != NULL) {
2188                                 if (pp_buffer->input) {
2189                                     pme->releaseSuperBuf(pp_buffer->input);
2190                                     free(pp_buffer->input);
2191                                 }
2192                                 free(pp_buffer);
2193                             }
2194                             //free metadata
2195                             if (NULL != meta_buffer) {
2196                                 pme->m_parent->metadataBufDone(meta_buffer);
2197                                 free(meta_buffer);
2198                             }
2199                         } else {
2200                             if (pp_buffer != NULL) {
2201                                 free(pp_buffer);
2202                             }
2203                         }
2204                     } else {
2205                         pthread_mutex_unlock(&pme->mReprocJobLock);
2206                     }
2207                 } else {
2208                     // not active, simply return buf and do no op
2209                     qcamera_hal3_jpeg_data_t *jpeg_job =
2210                         (qcamera_hal3_jpeg_data_t *)pme->m_inputJpegQ.dequeue();
2211                     if (NULL != jpeg_job) {
2212                         free(jpeg_job);
2213                     }
2214 
2215                     qcamera_hal3_pp_buffer_t* pp_buf =
2216                             (qcamera_hal3_pp_buffer_t *)pme->m_inputPPQ.dequeue();
2217                     if (NULL != pp_buf) {
2218                         if (pp_buf->input) {
2219                             pme->releaseSuperBuf(pp_buf->input);
2220                             free(pp_buf->input);
2221                             pp_buf->input = NULL;
2222                         }
2223                         free(pp_buf);
2224                     }
2225                     mm_camera_super_buf_t *metadata = (mm_camera_super_buf_t *)pme->m_inputMetaQ.dequeue();
2226                     if (metadata != NULL) {
2227                         pme->m_parent->metadataBufDone(metadata);
2228                         free(metadata);
2229                     }
2230                     qcamera_fwk_input_pp_data_t *fwk_frame =
2231                             (qcamera_fwk_input_pp_data_t *) pme->m_inputFWKPPQ.dequeue();
2232                     if (NULL != fwk_frame) {
2233                         free(fwk_frame);
2234                     }
2235                 }
2236             }
2237             break;
2238         case CAMERA_CMD_TYPE_EXIT:
2239             running = 0;
2240             break;
2241         default:
2242             break;
2243         }
2244     } while (running);
2245     LOGD("X");
2246     return NULL;
2247 }
2248 
2249 /* EXIF related helper methods */
2250 
2251 /*===========================================================================
2252  * FUNCTION   : getRational
2253  *
2254  * DESCRIPTION: compose rational struct
2255  *
2256  * PARAMETERS :
2257  *   @rat     : ptr to struct to store rational info
2258  *   @num     :num of the rational
2259  *   @denom   : denom of the rational
2260  *
2261  * RETURN     : int32_t type of status
2262  *              NO_ERROR  -- success
2263  *              none-zero failure code
2264  *==========================================================================*/
getRational(rat_t * rat,int num,int denom)2265 int32_t getRational(rat_t *rat, int num, int denom)
2266 {
2267     if ((0 > num) || (0 >= denom)) {
2268         LOGE("Negative values");
2269         return BAD_VALUE;
2270     }
2271     if (NULL == rat) {
2272         LOGE("NULL rat input");
2273         return BAD_VALUE;
2274     }
2275     rat->num = (uint32_t)num;
2276     rat->denom = (uint32_t)denom;
2277     return NO_ERROR;
2278 }
2279 
2280 /*===========================================================================
2281  * FUNCTION   : parseGPSCoordinate
2282  *
2283  * DESCRIPTION: parse GPS coordinate string
2284  *
2285  * PARAMETERS :
2286  *   @coord_str : [input] coordinate string
2287  *   @coord     : [output]  ptr to struct to store coordinate
2288  *
2289  * RETURN     : int32_t type of status
2290  *              NO_ERROR  -- success
2291  *              none-zero failure code
2292  *==========================================================================*/
parseGPSCoordinate(const char * coord_str,rat_t * coord)2293 int parseGPSCoordinate(const char *coord_str, rat_t* coord)
2294 {
2295     if(coord == NULL) {
2296         LOGE("error, invalid argument coord == NULL");
2297         return BAD_VALUE;
2298     }
2299     double degF = atof(coord_str);
2300     if (degF < 0) {
2301         degF = -degF;
2302     }
2303     double minF = (degF - (int) degF) * 60;
2304     double secF = (minF - (int) minF) * 60;
2305 
2306     getRational(&coord[0], (int)degF, 1);
2307     getRational(&coord[1], (int)minF, 1);
2308     getRational(&coord[2], (int)(secF * 10000), 10000);
2309     return NO_ERROR;
2310 }
2311 
2312 /*===========================================================================
2313  * FUNCTION   : getExifDateTime
2314  *
2315  * DESCRIPTION: query exif date time
2316  *
2317  * PARAMETERS :
2318  *   @dateTime   : string to store exif date time
2319  *   @subsecTime : string to store exif subsec time
2320  *
2321  * RETURN     : int32_t type of status
2322  *              NO_ERROR  -- success
2323  *              none-zero failure code
2324  *==========================================================================*/
getExifDateTime(String8 & dateTime,String8 & subsecTime)2325 int32_t getExifDateTime(String8 &dateTime, String8 &subsecTime)
2326 {
2327     int32_t ret = NO_ERROR;
2328 
2329     //get time and date from system
2330     struct timeval tv;
2331     struct tm timeinfo_data;
2332 
2333     int res = gettimeofday(&tv, NULL);
2334     if (0 == res) {
2335         struct tm *timeinfo = localtime_r(&tv.tv_sec, &timeinfo_data);
2336         if (NULL != timeinfo) {
2337             //Write datetime according to EXIF Spec
2338             //"YYYY:MM:DD HH:MM:SS" (20 chars including \0)
2339             dateTime = String8::format("%04d:%02d:%02d %02d:%02d:%02d",
2340                     timeinfo->tm_year + 1900, timeinfo->tm_mon + 1,
2341                     timeinfo->tm_mday, timeinfo->tm_hour,
2342                     timeinfo->tm_min, timeinfo->tm_sec);
2343             //Write subsec according to EXIF Sepc
2344             subsecTime = String8::format("%06ld", tv.tv_usec);
2345         } else {
2346             LOGE("localtime_r() error");
2347             ret = UNKNOWN_ERROR;
2348         }
2349     } else if (-1 == res) {
2350         LOGE("gettimeofday() error: %s", strerror(errno));
2351         ret = UNKNOWN_ERROR;
2352     } else {
2353         LOGE("gettimeofday() unexpected return code: %d", res);
2354         ret = UNKNOWN_ERROR;
2355     }
2356 
2357     return ret;
2358 }
2359 
2360 /*===========================================================================
2361  * FUNCTION   : getExifFocalLength
2362  *
2363  * DESCRIPTION: get exif focal length
2364  *
2365  * PARAMETERS :
2366  *   @focalLength : ptr to rational struct to store focal length
2367  *   @value       : focal length value
2368  *
2369  * RETURN     : int32_t type of status
2370  *              NO_ERROR  -- success
2371  *              none-zero failure code
2372  *==========================================================================*/
getExifFocalLength(rat_t * focalLength,float value)2373 int32_t getExifFocalLength(rat_t *focalLength, float value)
2374 {
2375     int focalLengthValue =
2376         (int)(value * FOCAL_LENGTH_DECIMAL_PRECISION);
2377     return getRational(focalLength, focalLengthValue, FOCAL_LENGTH_DECIMAL_PRECISION);
2378 }
2379 
2380 /*===========================================================================
2381   * FUNCTION   : getExifExpTimeInfo
2382   *
2383   * DESCRIPTION: get exif exposure time information
2384   *
2385   * PARAMETERS :
2386   *   @expoTimeInfo     : rational exposure time value
2387   *   @value            : exposure time value
2388   * RETURN     : nt32_t type of status
2389   *              NO_ERROR  -- success
2390   *              none-zero failure code
2391   *==========================================================================*/
getExifExpTimeInfo(rat_t * expoTimeInfo,int64_t value)2392 int32_t getExifExpTimeInfo(rat_t *expoTimeInfo, int64_t value)
2393 {
2394 
2395     int64_t cal_exposureTime;
2396     if (value != 0)
2397         cal_exposureTime = value;
2398     else
2399         cal_exposureTime = 60;
2400 
2401     return getRational(expoTimeInfo, 1, (int)cal_exposureTime);
2402 }
2403 
2404 /*===========================================================================
2405  * FUNCTION   : getExifGpsProcessingMethod
2406  *
2407  * DESCRIPTION: get GPS processing method
2408  *
2409  * PARAMETERS :
2410  *   @gpsProcessingMethod : string to store GPS process method
2411  *   @count               : length of the string
2412  *   @value               : the value of the processing method
2413  *
2414  * RETURN     : int32_t type of status
2415  *              NO_ERROR  -- success
2416  *              none-zero failure code
2417  *==========================================================================*/
getExifGpsProcessingMethod(char * gpsProcessingMethod,uint32_t & count,char * value)2418 int32_t getExifGpsProcessingMethod(char *gpsProcessingMethod,
2419         uint32_t &count, char* value)
2420 {
2421     if(value != NULL) {
2422         memcpy(gpsProcessingMethod, ExifAsciiPrefix, EXIF_ASCII_PREFIX_SIZE);
2423         count = EXIF_ASCII_PREFIX_SIZE;
2424         strlcpy(gpsProcessingMethod + EXIF_ASCII_PREFIX_SIZE,
2425                 value,
2426                 GPS_PROCESSING_METHOD_SIZE);
2427         count += (uint32_t)strlen(value);
2428         gpsProcessingMethod[count++] = '\0'; // increase 1 for the last NULL char
2429         return NO_ERROR;
2430     } else {
2431         return BAD_VALUE;
2432     }
2433 }
2434 
2435 /*===========================================================================
2436  * FUNCTION   : getExifLatitude
2437  *
2438  * DESCRIPTION: get exif latitude
2439  *
2440  * PARAMETERS :
2441  *   @latitude : ptr to rational struct to store latitude info
2442  *   @latRef   : character to indicate latitude reference
2443  *   @value    : value of the latitude
2444  *
2445  * RETURN     : int32_t type of status
2446  *              NO_ERROR  -- success
2447  *              none-zero failure code
2448  *==========================================================================*/
getExifLatitude(rat_t * latitude,char * latRef,double value)2449 int32_t getExifLatitude(rat_t *latitude, char *latRef, double value)
2450 {
2451     char str[30];
2452     snprintf(str, sizeof(str), "%f", value);
2453     if(str[0] != '\0') {
2454         parseGPSCoordinate(str, latitude);
2455 
2456         //set Latitude Ref
2457         float latitudeValue = strtof(str, 0);
2458         if(latitudeValue < 0.0f) {
2459             latRef[0] = 'S';
2460         } else {
2461             latRef[0] = 'N';
2462         }
2463         latRef[1] = '\0';
2464         return NO_ERROR;
2465     }else{
2466         return BAD_VALUE;
2467     }
2468 }
2469 
2470 /*===========================================================================
2471  * FUNCTION   : getExifLongitude
2472  *
2473  * DESCRIPTION: get exif longitude
2474  *
2475  * PARAMETERS :
2476  *   @longitude : ptr to rational struct to store longitude info
2477  *   @lonRef    : character to indicate longitude reference
2478  *   @value     : value of the longitude
2479  *
2480  * RETURN     : int32_t type of status
2481  *              NO_ERROR  -- success
2482  *              none-zero failure code
2483  *==========================================================================*/
getExifLongitude(rat_t * longitude,char * lonRef,double value)2484 int32_t getExifLongitude(rat_t *longitude, char *lonRef, double value)
2485 {
2486     char str[30];
2487     snprintf(str, sizeof(str), "%f", value);
2488     if(str[0] != '\0') {
2489         parseGPSCoordinate(str, longitude);
2490 
2491         //set Longitude Ref
2492         float longitudeValue = strtof(str, 0);
2493         if(longitudeValue < 0.0f) {
2494             lonRef[0] = 'W';
2495         } else {
2496             lonRef[0] = 'E';
2497         }
2498         lonRef[1] = '\0';
2499         return NO_ERROR;
2500     }else{
2501         return BAD_VALUE;
2502     }
2503 }
2504 
2505 /*===========================================================================
2506  * FUNCTION   : getExifAltitude
2507  *
2508  * DESCRIPTION: get exif altitude
2509  *
2510  * PARAMETERS :
2511  *   @altitude : ptr to rational struct to store altitude info
2512  *   @altRef   : character to indicate altitude reference
2513  *   @argValue : altitude value
2514  *
2515  * RETURN     : int32_t type of status
2516  *              NO_ERROR  -- success
2517  *              none-zero failure code
2518  *==========================================================================*/
getExifAltitude(rat_t * altitude,char * altRef,double argValue)2519 int32_t getExifAltitude(rat_t *altitude, char *altRef, double argValue)
2520 {
2521     char str[30];
2522     snprintf(str, sizeof(str), "%f", argValue);
2523     if (str[0] != '\0') {
2524         double value = atof(str);
2525         *altRef = 0;
2526         if(value < 0){
2527             *altRef = 1;
2528             value = -value;
2529         }
2530         return getRational(altitude, (int)(value * 1000), 1000);
2531     } else {
2532         return BAD_VALUE;
2533     }
2534 }
2535 
2536 /*===========================================================================
2537  * FUNCTION   : getExifGpsDateTimeStamp
2538  *
2539  * DESCRIPTION: get exif GPS date time stamp
2540  *
2541  * PARAMETERS :
2542  *   @gpsDateStamp : GPS date time stamp string
2543  *   @bufLen       : length of the string
2544  *   @gpsTimeStamp : ptr to rational struct to store time stamp info
2545  *   @value        : timestamp value
2546  *
2547  * RETURN     : int32_t type of status
2548  *              NO_ERROR  -- success
2549  *              none-zero failure code
2550  *==========================================================================*/
getExifGpsDateTimeStamp(char * gpsDateStamp,uint32_t bufLen,rat_t * gpsTimeStamp,int64_t value)2551 int32_t getExifGpsDateTimeStamp(char *gpsDateStamp, uint32_t bufLen,
2552         rat_t *gpsTimeStamp, int64_t value)
2553 {
2554     char str[30];
2555     snprintf(str, sizeof(str), "%lld", (long long int)value);
2556     if(str[0] != '\0') {
2557         time_t unixTime = (time_t)atol(str);
2558         struct tm *UTCTimestamp = gmtime(&unixTime);
2559         if (UTCTimestamp != NULL && gpsDateStamp != NULL
2560                 && gpsTimeStamp != NULL) {
2561             strftime(gpsDateStamp, bufLen, "%Y:%m:%d", UTCTimestamp);
2562 
2563             getRational(&gpsTimeStamp[0], UTCTimestamp->tm_hour, 1);
2564             getRational(&gpsTimeStamp[1], UTCTimestamp->tm_min, 1);
2565             getRational(&gpsTimeStamp[2], UTCTimestamp->tm_sec, 1);
2566             return NO_ERROR;
2567         } else {
2568             LOGE("Could not get the timestamp");
2569             return BAD_VALUE;
2570         }
2571     } else {
2572         return BAD_VALUE;
2573     }
2574 }
2575 
2576 /*===========================================================================
2577  * FUNCTION   : getExifExposureValue
2578  *
2579  * DESCRIPTION: get exif GPS date time stamp
2580  *
2581  * PARAMETERS :
2582  *   @exposure_val        : rational exposure value
2583  *   @exposure_comp       : exposure compensation
2584  *   @step                : exposure step
2585  *
2586  * RETURN     : int32_t type of status
2587  *              NO_ERROR  -- success
2588  *              none-zero failure code
2589  *==========================================================================*/
getExifExposureValue(srat_t * exposure_val,int32_t exposure_comp,cam_rational_type_t step)2590 int32_t getExifExposureValue(srat_t* exposure_val, int32_t exposure_comp,
2591         cam_rational_type_t step)
2592 {
2593     exposure_val->num = exposure_comp * step.numerator;
2594     exposure_val->denom = step.denominator;
2595     return 0;
2596 }
2597 
2598 /*===========================================================================
2599  * FUNCTION   : getExifData
2600  *
2601  * DESCRIPTION: get exif data to be passed into jpeg encoding
2602  *
2603  * PARAMETERS :
2604  * @metadata      : metadata of the encoding request
2605  * @jpeg_settings : jpeg_settings for encoding
2606  * @needJpegExifRotation: check if rotation need to added in EXIF
2607  *
2608  * RETURN     : exif data from user setting and GPS
2609  *==========================================================================*/
getExifData(metadata_buffer_t * metadata,jpeg_settings_t * jpeg_settings,bool needJpegExifRotation)2610 QCamera3Exif *QCamera3PostProcessor::getExifData(metadata_buffer_t *metadata,
2611         jpeg_settings_t *jpeg_settings, bool needJpegExifRotation)
2612 {
2613     QCamera3Exif *exif = new QCamera3Exif();
2614     if (exif == NULL) {
2615         LOGE("No memory for QCamera3Exif");
2616         return NULL;
2617     }
2618     QCamera3HardwareInterface* hal_obj = NULL;
2619     if (m_parent != NULL) {
2620         hal_obj = (QCamera3HardwareInterface*)m_parent->mUserData;
2621     } else {
2622         LOGE("m_parent is NULL, Error");
2623         return NULL;
2624     }
2625 
2626     int32_t rc = NO_ERROR;
2627     uint32_t count = 0;
2628 
2629     // add exif entries
2630     String8 dateTime;
2631     String8 subsecTime;
2632     rc = getExifDateTime(dateTime, subsecTime);
2633     if (rc == NO_ERROR) {
2634         exif->addEntry(EXIFTAGID_DATE_TIME, EXIF_ASCII,
2635                 (uint32_t)(dateTime.length() + 1), (void *)dateTime.string());
2636         exif->addEntry(EXIFTAGID_EXIF_DATE_TIME_ORIGINAL, EXIF_ASCII,
2637                 (uint32_t)(dateTime.length() + 1), (void *)dateTime.string());
2638         exif->addEntry(EXIFTAGID_EXIF_DATE_TIME_DIGITIZED, EXIF_ASCII,
2639                 (uint32_t)(dateTime.length() + 1), (void *)dateTime.string());
2640         exif->addEntry(EXIFTAGID_SUBSEC_TIME, EXIF_ASCII,
2641                 (uint32_t)(subsecTime.length() + 1), (void *)subsecTime.string());
2642         exif->addEntry(EXIFTAGID_SUBSEC_TIME_ORIGINAL, EXIF_ASCII,
2643                 (uint32_t)(subsecTime.length() + 1), (void *)subsecTime.string());
2644         exif->addEntry(EXIFTAGID_SUBSEC_TIME_DIGITIZED, EXIF_ASCII,
2645                 (uint32_t)(subsecTime.length() + 1), (void *)subsecTime.string());
2646     } else {
2647         LOGW("getExifDateTime failed");
2648     }
2649 
2650 
2651     if (metadata != NULL) {
2652         IF_META_AVAILABLE(float, focal_length, CAM_INTF_META_LENS_FOCAL_LENGTH, metadata) {
2653             rat_t focalLength;
2654             rc = getExifFocalLength(&focalLength, *focal_length);
2655             if (rc == NO_ERROR) {
2656                 exif->addEntry(EXIFTAGID_FOCAL_LENGTH,
2657                         EXIF_RATIONAL,
2658                         1,
2659                         (void *)&(focalLength));
2660             } else {
2661                 LOGW("getExifFocalLength failed");
2662             }
2663         }
2664 
2665         IF_META_AVAILABLE(int32_t, isoSpeed, CAM_INTF_META_SENSOR_SENSITIVITY, metadata) {
2666             int16_t fwk_isoSpeed = (int16_t) *isoSpeed;
2667             exif->addEntry(EXIFTAGID_ISO_SPEED_RATING, EXIF_SHORT, 1, (void *) &(fwk_isoSpeed));
2668         }
2669 
2670 
2671         IF_META_AVAILABLE(int64_t, sensor_exposure_time,
2672                 CAM_INTF_META_SENSOR_EXPOSURE_TIME, metadata) {
2673             rat_t sensorExpTime;
2674             rc = getExifExpTimeInfo(&sensorExpTime, *sensor_exposure_time);
2675             if (rc == NO_ERROR){
2676                 exif->addEntry(EXIFTAGID_EXPOSURE_TIME,
2677                         EXIF_RATIONAL,
2678                         1,
2679                         (void *)&(sensorExpTime));
2680             } else {
2681                 LOGW("getExifExpTimeInfo failed");
2682             }
2683         }
2684 
2685         char* jpeg_gps_processing_method = jpeg_settings->gps_processing_method;
2686         if (strlen(jpeg_gps_processing_method) > 0) {
2687             char gpsProcessingMethod[EXIF_ASCII_PREFIX_SIZE +
2688                     GPS_PROCESSING_METHOD_SIZE];
2689             count = 0;
2690             rc = getExifGpsProcessingMethod(gpsProcessingMethod,
2691                     count,
2692                     jpeg_gps_processing_method);
2693             if(rc == NO_ERROR) {
2694                 exif->addEntry(EXIFTAGID_GPS_PROCESSINGMETHOD,
2695                         EXIF_ASCII,
2696                         count,
2697                         (void *)gpsProcessingMethod);
2698             } else {
2699                 LOGW("getExifGpsProcessingMethod failed");
2700             }
2701         }
2702 
2703         if (jpeg_settings->gps_coordinates_valid) {
2704 
2705             //latitude
2706             rat_t latitude[3];
2707             char latRef[2];
2708             rc = getExifLatitude(latitude, latRef,
2709                     jpeg_settings->gps_coordinates[0]);
2710             if(rc == NO_ERROR) {
2711                 exif->addEntry(EXIFTAGID_GPS_LATITUDE,
2712                         EXIF_RATIONAL,
2713                         3,
2714                         (void *)latitude);
2715                 exif->addEntry(EXIFTAGID_GPS_LATITUDE_REF,
2716                         EXIF_ASCII,
2717                         2,
2718                         (void *)latRef);
2719             } else {
2720                 LOGW("getExifLatitude failed");
2721             }
2722 
2723             //longitude
2724             rat_t longitude[3];
2725             char lonRef[2];
2726             rc = getExifLongitude(longitude, lonRef,
2727                     jpeg_settings->gps_coordinates[1]);
2728             if(rc == NO_ERROR) {
2729                 exif->addEntry(EXIFTAGID_GPS_LONGITUDE,
2730                         EXIF_RATIONAL,
2731                         3,
2732                         (void *)longitude);
2733 
2734                 exif->addEntry(EXIFTAGID_GPS_LONGITUDE_REF,
2735                         EXIF_ASCII,
2736                         2,
2737                         (void *)lonRef);
2738             } else {
2739                 LOGW("getExifLongitude failed");
2740             }
2741 
2742             //altitude
2743             rat_t altitude;
2744             char altRef;
2745             rc = getExifAltitude(&altitude, &altRef,
2746                     jpeg_settings->gps_coordinates[2]);
2747             if(rc == NO_ERROR) {
2748                 exif->addEntry(EXIFTAGID_GPS_ALTITUDE,
2749                         EXIF_RATIONAL,
2750                         1,
2751                         (void *)&(altitude));
2752 
2753                 exif->addEntry(EXIFTAGID_GPS_ALTITUDE_REF,
2754                         EXIF_BYTE,
2755                         1,
2756                         (void *)&altRef);
2757             } else {
2758                 LOGW("getExifAltitude failed");
2759             }
2760         }
2761 
2762         if (jpeg_settings->gps_timestamp_valid) {
2763 
2764             char gpsDateStamp[20];
2765             rat_t gpsTimeStamp[3];
2766             rc = getExifGpsDateTimeStamp(gpsDateStamp, 20, gpsTimeStamp,
2767                     jpeg_settings->gps_timestamp);
2768             if(rc == NO_ERROR) {
2769                 exif->addEntry(EXIFTAGID_GPS_DATESTAMP, EXIF_ASCII,
2770                         (uint32_t)(strlen(gpsDateStamp) + 1),
2771                         (void *)gpsDateStamp);
2772 
2773                 exif->addEntry(EXIFTAGID_GPS_TIMESTAMP,
2774                         EXIF_RATIONAL,
2775                         3,
2776                         (void *)gpsTimeStamp);
2777             } else {
2778                 LOGW("getExifGpsDataTimeStamp failed");
2779             }
2780         }
2781 
2782         IF_META_AVAILABLE(int32_t, exposure_comp, CAM_INTF_PARM_EXPOSURE_COMPENSATION, metadata) {
2783             IF_META_AVAILABLE(cam_rational_type_t, comp_step, CAM_INTF_PARM_EV_STEP, metadata) {
2784                 srat_t exposure_val;
2785                 rc = getExifExposureValue(&exposure_val, *exposure_comp, *comp_step);
2786                 if(rc == NO_ERROR) {
2787                     exif->addEntry(EXIFTAGID_EXPOSURE_BIAS_VALUE,
2788                             EXIF_SRATIONAL,
2789                             1,
2790                             (void *)(&exposure_val));
2791                 } else {
2792                     LOGW("getExifExposureValue failed ");
2793                 }
2794             }
2795         }
2796     } else {
2797         LOGW("no metadata provided ");
2798     }
2799 
2800 #ifdef ENABLE_MODEL_INFO_EXIF
2801 
2802     char value[PROPERTY_VALUE_MAX];
2803     if (property_get("ro.product.manufacturer", value, "QCOM-AA") > 0) {
2804         exif->addEntry(EXIFTAGID_MAKE, EXIF_ASCII,
2805                 (uint32_t)(strlen(value) + 1), (void *)value);
2806     } else {
2807         LOGW("getExifMaker failed");
2808     }
2809 
2810     if (property_get("ro.product.model", value, "QCAM-AA") > 0) {
2811         exif->addEntry(EXIFTAGID_MODEL, EXIF_ASCII,
2812                 (uint32_t)(strlen(value) + 1), (void *)value);
2813     } else {
2814         LOGW("getExifModel failed");
2815     }
2816 
2817     if (property_get("ro.build.description", value, "QCAM-AA") > 0) {
2818         exif->addEntry(EXIFTAGID_SOFTWARE, EXIF_ASCII,
2819                 (uint32_t)(strlen(value) + 1), (void *)value);
2820     } else {
2821         LOGW("getExifSoftware failed");
2822     }
2823 
2824 #endif
2825 
2826     if (jpeg_settings->image_desc_valid) {
2827         if (exif->addEntry(EXIFTAGID_IMAGE_DESCRIPTION, EXIF_ASCII,
2828                 strlen(jpeg_settings->image_desc)+1,
2829                 (void *)jpeg_settings->image_desc)) {
2830             LOGW("Adding IMAGE_DESCRIPTION tag failed");
2831         }
2832     }
2833 
2834     if (needJpegExifRotation) {
2835         int16_t orientation;
2836         switch (jpeg_settings->jpeg_orientation) {
2837             case 0:
2838                 orientation = 1;
2839                 break;
2840             case 90:
2841                 orientation = 6;
2842                 break;
2843             case 180:
2844                 orientation = 3;
2845                 break;
2846             case 270:
2847                 orientation = 8;
2848                 break;
2849             default:
2850                 orientation = 1;
2851                 break;
2852         }
2853         exif->addEntry(EXIFTAGID_ORIENTATION,
2854                        EXIF_SHORT,
2855                        1,
2856                        (void *)&orientation);
2857         exif->addEntry(EXIFTAGID_TN_ORIENTATION,
2858                        EXIF_SHORT,
2859                        1,
2860                        (void *)&orientation);
2861 
2862     }
2863 
2864     return exif;
2865 }
2866 
2867 /*===========================================================================
2868  * FUNCTION   : QCamera3Exif
2869  *
2870  * DESCRIPTION: constructor of QCamera3Exif
2871  *
2872  * PARAMETERS : None
2873  *
2874  * RETURN     : None
2875  *==========================================================================*/
QCamera3Exif()2876 QCamera3Exif::QCamera3Exif()
2877     : m_nNumEntries(0)
2878 {
2879     memset(m_Entries, 0, sizeof(m_Entries));
2880 }
2881 
2882 /*===========================================================================
2883  * FUNCTION   : ~QCamera3Exif
2884  *
2885  * DESCRIPTION: deconstructor of QCamera3Exif. Will release internal memory ptr.
2886  *
2887  * PARAMETERS : None
2888  *
2889  * RETURN     : None
2890  *==========================================================================*/
~QCamera3Exif()2891 QCamera3Exif::~QCamera3Exif()
2892 {
2893     for (uint32_t i = 0; i < m_nNumEntries; i++) {
2894         switch (m_Entries[i].tag_entry.type) {
2895             case EXIF_BYTE:
2896                 {
2897                     if (m_Entries[i].tag_entry.count > 1 &&
2898                             m_Entries[i].tag_entry.data._bytes != NULL) {
2899                         free(m_Entries[i].tag_entry.data._bytes);
2900                         m_Entries[i].tag_entry.data._bytes = NULL;
2901                     }
2902                 }
2903                 break;
2904             case EXIF_ASCII:
2905                 {
2906                     if (m_Entries[i].tag_entry.data._ascii != NULL) {
2907                         free(m_Entries[i].tag_entry.data._ascii);
2908                         m_Entries[i].tag_entry.data._ascii = NULL;
2909                     }
2910                 }
2911                 break;
2912             case EXIF_SHORT:
2913                 {
2914                     if (m_Entries[i].tag_entry.count > 1 &&
2915                             m_Entries[i].tag_entry.data._shorts != NULL) {
2916                         free(m_Entries[i].tag_entry.data._shorts);
2917                         m_Entries[i].tag_entry.data._shorts = NULL;
2918                     }
2919                 }
2920                 break;
2921             case EXIF_LONG:
2922                 {
2923                     if (m_Entries[i].tag_entry.count > 1 &&
2924                             m_Entries[i].tag_entry.data._longs != NULL) {
2925                         free(m_Entries[i].tag_entry.data._longs);
2926                         m_Entries[i].tag_entry.data._longs = NULL;
2927                     }
2928                 }
2929                 break;
2930             case EXIF_RATIONAL:
2931                 {
2932                     if (m_Entries[i].tag_entry.count > 1 &&
2933                             m_Entries[i].tag_entry.data._rats != NULL) {
2934                         free(m_Entries[i].tag_entry.data._rats);
2935                         m_Entries[i].tag_entry.data._rats = NULL;
2936                     }
2937                 }
2938                 break;
2939             case EXIF_UNDEFINED:
2940                 {
2941                     if (m_Entries[i].tag_entry.data._undefined != NULL) {
2942                         free(m_Entries[i].tag_entry.data._undefined);
2943                         m_Entries[i].tag_entry.data._undefined = NULL;
2944                     }
2945                 }
2946                 break;
2947             case EXIF_SLONG:
2948                 {
2949                     if (m_Entries[i].tag_entry.count > 1 &&
2950                             m_Entries[i].tag_entry.data._slongs != NULL) {
2951                         free(m_Entries[i].tag_entry.data._slongs);
2952                         m_Entries[i].tag_entry.data._slongs = NULL;
2953                     }
2954                 }
2955                 break;
2956             case EXIF_SRATIONAL:
2957                 {
2958                     if (m_Entries[i].tag_entry.count > 1 &&
2959                             m_Entries[i].tag_entry.data._srats != NULL) {
2960                         free(m_Entries[i].tag_entry.data._srats);
2961                         m_Entries[i].tag_entry.data._srats = NULL;
2962                     }
2963                 }
2964                 break;
2965             default:
2966                 LOGW("Error, Unknown type");
2967                 break;
2968         }
2969     }
2970 }
2971 
2972 /*===========================================================================
2973  * FUNCTION   : addEntry
2974  *
2975  * DESCRIPTION: function to add an entry to exif data
2976  *
2977  * PARAMETERS :
2978  *   @tagid   : exif tag ID
2979  *   @type    : data type
2980  *   @count   : number of data in uint of its type
2981  *   @data    : input data ptr
2982  *
2983  * RETURN     : int32_t type of status
2984  *              NO_ERROR  -- success
2985  *              none-zero failure code
2986  *==========================================================================*/
addEntry(exif_tag_id_t tagid,exif_tag_type_t type,uint32_t count,void * data)2987 int32_t QCamera3Exif::addEntry(exif_tag_id_t tagid,
2988                               exif_tag_type_t type,
2989                               uint32_t count,
2990                               void *data)
2991 {
2992     int32_t rc = NO_ERROR;
2993     if(m_nNumEntries >= MAX_HAL3_EXIF_TABLE_ENTRIES) {
2994         LOGE("Number of entries exceeded limit");
2995         return NO_MEMORY;
2996     }
2997 
2998     m_Entries[m_nNumEntries].tag_id = tagid;
2999     m_Entries[m_nNumEntries].tag_entry.type = type;
3000     m_Entries[m_nNumEntries].tag_entry.count = count;
3001     m_Entries[m_nNumEntries].tag_entry.copy = 1;
3002     switch (type) {
3003         case EXIF_BYTE:
3004             {
3005                 if (count > 1) {
3006                     uint8_t *values = (uint8_t *)malloc(count);
3007                     if (values == NULL) {
3008                         LOGE("No memory for byte array");
3009                         rc = NO_MEMORY;
3010                     } else {
3011                         memcpy(values, data, count);
3012                         m_Entries[m_nNumEntries].tag_entry.data._bytes = values;
3013                     }
3014                 } else {
3015                     m_Entries[m_nNumEntries].tag_entry.data._byte =
3016                         *(uint8_t *)data;
3017                 }
3018             }
3019             break;
3020         case EXIF_ASCII:
3021             {
3022                 char *str = NULL;
3023                 str = (char *)malloc(count + 1);
3024                 if (str == NULL) {
3025                     LOGE("No memory for ascii string");
3026                     rc = NO_MEMORY;
3027                 } else {
3028                     memset(str, 0, count + 1);
3029                     memcpy(str, data, count);
3030                     m_Entries[m_nNumEntries].tag_entry.data._ascii = str;
3031                 }
3032             }
3033             break;
3034         case EXIF_SHORT:
3035             {
3036                 uint16_t *exif_data = (uint16_t *)data;
3037                 if (count > 1) {
3038                     uint16_t *values =
3039                         (uint16_t *)malloc(count * sizeof(uint16_t));
3040                     if (values == NULL) {
3041                         LOGE("No memory for short array");
3042                         rc = NO_MEMORY;
3043                     } else {
3044                         memcpy(values, exif_data, count * sizeof(uint16_t));
3045                         m_Entries[m_nNumEntries].tag_entry.data._shorts = values;
3046                     }
3047                 } else {
3048                     m_Entries[m_nNumEntries].tag_entry.data._short =
3049                         *(uint16_t *)data;
3050                 }
3051             }
3052             break;
3053         case EXIF_LONG:
3054             {
3055                 uint32_t *exif_data = (uint32_t *)data;
3056                 if (count > 1) {
3057                     uint32_t *values =
3058                         (uint32_t *)malloc(count * sizeof(uint32_t));
3059                     if (values == NULL) {
3060                         LOGE("No memory for long array");
3061                         rc = NO_MEMORY;
3062                     } else {
3063                         memcpy(values, exif_data, count * sizeof(uint32_t));
3064                         m_Entries[m_nNumEntries].tag_entry.data._longs = values;
3065                     }
3066                 } else {
3067                     m_Entries[m_nNumEntries].tag_entry.data._long =
3068                         *(uint32_t *)data;
3069                 }
3070             }
3071             break;
3072         case EXIF_RATIONAL:
3073             {
3074                 rat_t *exif_data = (rat_t *)data;
3075                 if (count > 1) {
3076                     rat_t *values = (rat_t *)malloc(count * sizeof(rat_t));
3077                     if (values == NULL) {
3078                         LOGE("No memory for rational array");
3079                         rc = NO_MEMORY;
3080                     } else {
3081                         memcpy(values, exif_data, count * sizeof(rat_t));
3082                         m_Entries[m_nNumEntries].tag_entry.data._rats = values;
3083                     }
3084                 } else {
3085                     m_Entries[m_nNumEntries].tag_entry.data._rat =
3086                         *(rat_t *)data;
3087                 }
3088             }
3089             break;
3090         case EXIF_UNDEFINED:
3091             {
3092                 uint8_t *values = (uint8_t *)malloc(count);
3093                 if (values == NULL) {
3094                     LOGE("No memory for undefined array");
3095                     rc = NO_MEMORY;
3096                 } else {
3097                     memcpy(values, data, count);
3098                     m_Entries[m_nNumEntries].tag_entry.data._undefined = values;
3099                 }
3100             }
3101             break;
3102         case EXIF_SLONG:
3103             {
3104                 int32_t *exif_data = (int32_t *)data;
3105                 if (count > 1) {
3106                     int32_t *values =
3107                         (int32_t *)malloc(count * sizeof(int32_t));
3108                     if (values == NULL) {
3109                         LOGE("No memory for signed long array");
3110                         rc = NO_MEMORY;
3111                     } else {
3112                         memcpy(values, exif_data, count * sizeof(int32_t));
3113                         m_Entries[m_nNumEntries].tag_entry.data._slongs =values;
3114                     }
3115                 } else {
3116                     m_Entries[m_nNumEntries].tag_entry.data._slong =
3117                         *(int32_t *)data;
3118                 }
3119             }
3120             break;
3121         case EXIF_SRATIONAL:
3122             {
3123                 srat_t *exif_data = (srat_t *)data;
3124                 if (count > 1) {
3125                     srat_t *values = (srat_t *)malloc(count * sizeof(srat_t));
3126                     if (values == NULL) {
3127                         LOGE("No memory for sign rational array");
3128                         rc = NO_MEMORY;
3129                     } else {
3130                         memcpy(values, exif_data, count * sizeof(srat_t));
3131                         m_Entries[m_nNumEntries].tag_entry.data._srats = values;
3132                     }
3133                 } else {
3134                     m_Entries[m_nNumEntries].tag_entry.data._srat =
3135                         *(srat_t *)data;
3136                 }
3137             }
3138             break;
3139         default:
3140             LOGE("Error, Unknown type");
3141             break;
3142     }
3143 
3144     // Increase number of entries
3145     m_nNumEntries++;
3146     return rc;
3147 }
3148 
3149 }; // namespace qcamera
3150