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