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