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