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