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