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